Merge pull request #5959 from royalharsh/master

DocFixit: Add instructions to install protobuf3 in python readme files
diff --git a/.gitignore b/.gitignore
index 502483f..ca61bda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,7 @@
 *.egg
 
 # Node installation output
-node_modules/
+^node_modules
 src/node/extension_binary/
 
 # gcov coverage data
diff --git a/BUILD b/BUILD
index 514aea8..b69c940 100644
--- a/BUILD
+++ b/BUILD
@@ -41,65 +41,66 @@
 
 
 
+
 cc_library(
   name = "gpr",
   srcs = [
-    "src/core/profiling/timers.h",
-    "src/core/support/backoff.h",
-    "src/core/support/block_annotate.h",
-    "src/core/support/env.h",
-    "src/core/support/load_file.h",
-    "src/core/support/murmur_hash.h",
-    "src/core/support/stack_lockfree.h",
-    "src/core/support/string.h",
-    "src/core/support/string_win32.h",
-    "src/core/support/thd_internal.h",
-    "src/core/support/time_precise.h",
-    "src/core/support/tmpfile.h",
-    "src/core/profiling/basic_timers.c",
-    "src/core/profiling/stap_timers.c",
-    "src/core/support/alloc.c",
-    "src/core/support/avl.c",
-    "src/core/support/backoff.c",
-    "src/core/support/cmdline.c",
-    "src/core/support/cpu_iphone.c",
-    "src/core/support/cpu_linux.c",
-    "src/core/support/cpu_posix.c",
-    "src/core/support/cpu_windows.c",
-    "src/core/support/env_linux.c",
-    "src/core/support/env_posix.c",
-    "src/core/support/env_win32.c",
-    "src/core/support/histogram.c",
-    "src/core/support/host_port.c",
-    "src/core/support/load_file.c",
-    "src/core/support/log.c",
-    "src/core/support/log_android.c",
-    "src/core/support/log_linux.c",
-    "src/core/support/log_posix.c",
-    "src/core/support/log_win32.c",
-    "src/core/support/murmur_hash.c",
-    "src/core/support/slice.c",
-    "src/core/support/slice_buffer.c",
-    "src/core/support/stack_lockfree.c",
-    "src/core/support/string.c",
-    "src/core/support/string_posix.c",
-    "src/core/support/string_win32.c",
-    "src/core/support/subprocess_posix.c",
-    "src/core/support/subprocess_windows.c",
-    "src/core/support/sync.c",
-    "src/core/support/sync_posix.c",
-    "src/core/support/sync_win32.c",
-    "src/core/support/thd.c",
-    "src/core/support/thd_posix.c",
-    "src/core/support/thd_win32.c",
-    "src/core/support/time.c",
-    "src/core/support/time_posix.c",
-    "src/core/support/time_precise.c",
-    "src/core/support/time_win32.c",
-    "src/core/support/tls_pthread.c",
-    "src/core/support/tmpfile_posix.c",
-    "src/core/support/tmpfile_win32.c",
-    "src/core/support/wrap_memcpy.c",
+    "src/core/lib/profiling/timers.h",
+    "src/core/lib/support/backoff.h",
+    "src/core/lib/support/block_annotate.h",
+    "src/core/lib/support/env.h",
+    "src/core/lib/support/load_file.h",
+    "src/core/lib/support/murmur_hash.h",
+    "src/core/lib/support/stack_lockfree.h",
+    "src/core/lib/support/string.h",
+    "src/core/lib/support/string_win32.h",
+    "src/core/lib/support/thd_internal.h",
+    "src/core/lib/support/time_precise.h",
+    "src/core/lib/support/tmpfile.h",
+    "src/core/lib/profiling/basic_timers.c",
+    "src/core/lib/profiling/stap_timers.c",
+    "src/core/lib/support/alloc.c",
+    "src/core/lib/support/avl.c",
+    "src/core/lib/support/backoff.c",
+    "src/core/lib/support/cmdline.c",
+    "src/core/lib/support/cpu_iphone.c",
+    "src/core/lib/support/cpu_linux.c",
+    "src/core/lib/support/cpu_posix.c",
+    "src/core/lib/support/cpu_windows.c",
+    "src/core/lib/support/env_linux.c",
+    "src/core/lib/support/env_posix.c",
+    "src/core/lib/support/env_win32.c",
+    "src/core/lib/support/histogram.c",
+    "src/core/lib/support/host_port.c",
+    "src/core/lib/support/load_file.c",
+    "src/core/lib/support/log.c",
+    "src/core/lib/support/log_android.c",
+    "src/core/lib/support/log_linux.c",
+    "src/core/lib/support/log_posix.c",
+    "src/core/lib/support/log_win32.c",
+    "src/core/lib/support/murmur_hash.c",
+    "src/core/lib/support/slice.c",
+    "src/core/lib/support/slice_buffer.c",
+    "src/core/lib/support/stack_lockfree.c",
+    "src/core/lib/support/string.c",
+    "src/core/lib/support/string_posix.c",
+    "src/core/lib/support/string_win32.c",
+    "src/core/lib/support/subprocess_posix.c",
+    "src/core/lib/support/subprocess_windows.c",
+    "src/core/lib/support/sync.c",
+    "src/core/lib/support/sync_posix.c",
+    "src/core/lib/support/sync_win32.c",
+    "src/core/lib/support/thd.c",
+    "src/core/lib/support/thd_posix.c",
+    "src/core/lib/support/thd_win32.c",
+    "src/core/lib/support/time.c",
+    "src/core/lib/support/time_posix.c",
+    "src/core/lib/support/time_precise.c",
+    "src/core/lib/support/time_win32.c",
+    "src/core/lib/support/tls_pthread.c",
+    "src/core/lib/support/tmpfile_posix.c",
+    "src/core/lib/support/tmpfile_win32.c",
+    "src/core/lib/support/wrap_memcpy.c",
   ],
   hdrs = [
     "include/grpc/support/alloc.h",
@@ -154,316 +155,306 @@
 )
 
 
+
 cc_library(
   name = "grpc",
   srcs = [
-    "src/core/census/grpc_filter.h",
-    "src/core/census/grpc_plugin.h",
-    "src/core/channel/channel_args.h",
-    "src/core/channel/channel_stack.h",
-    "src/core/channel/channel_stack_builder.h",
-    "src/core/channel/client_channel.h",
-    "src/core/channel/client_uchannel.h",
-    "src/core/channel/compress_filter.h",
-    "src/core/channel/connected_channel.h",
-    "src/core/channel/context.h",
-    "src/core/channel/http_client_filter.h",
-    "src/core/channel/http_server_filter.h",
-    "src/core/channel/subchannel_call_holder.h",
-    "src/core/client_config/client_config.h",
-    "src/core/client_config/connector.h",
-    "src/core/client_config/initial_connect_string.h",
-    "src/core/client_config/lb_policies/load_balancer_api.h",
-    "src/core/client_config/lb_policies/pick_first.h",
-    "src/core/client_config/lb_policies/round_robin.h",
-    "src/core/client_config/lb_policy.h",
-    "src/core/client_config/lb_policy_factory.h",
-    "src/core/client_config/lb_policy_registry.h",
-    "src/core/client_config/resolver.h",
-    "src/core/client_config/resolver_factory.h",
-    "src/core/client_config/resolver_registry.h",
-    "src/core/client_config/resolvers/dns_resolver.h",
-    "src/core/client_config/resolvers/sockaddr_resolver.h",
-    "src/core/client_config/subchannel.h",
-    "src/core/client_config/subchannel_factory.h",
-    "src/core/client_config/subchannel_index.h",
-    "src/core/client_config/uri_parser.h",
-    "src/core/compression/algorithm_metadata.h",
-    "src/core/compression/message_compress.h",
-    "src/core/debug/trace.h",
-    "src/core/httpcli/format_request.h",
-    "src/core/httpcli/httpcli.h",
-    "src/core/httpcli/parser.h",
-    "src/core/iomgr/closure.h",
-    "src/core/iomgr/endpoint.h",
-    "src/core/iomgr/endpoint_pair.h",
-    "src/core/iomgr/exec_ctx.h",
-    "src/core/iomgr/executor.h",
-    "src/core/iomgr/fd_posix.h",
-    "src/core/iomgr/iocp_windows.h",
-    "src/core/iomgr/iomgr.h",
-    "src/core/iomgr/iomgr_internal.h",
-    "src/core/iomgr/iomgr_posix.h",
-    "src/core/iomgr/pollset.h",
-    "src/core/iomgr/pollset_posix.h",
-    "src/core/iomgr/pollset_set.h",
-    "src/core/iomgr/pollset_set_posix.h",
-    "src/core/iomgr/pollset_set_windows.h",
-    "src/core/iomgr/pollset_windows.h",
-    "src/core/iomgr/resolve_address.h",
-    "src/core/iomgr/sockaddr.h",
-    "src/core/iomgr/sockaddr_posix.h",
-    "src/core/iomgr/sockaddr_utils.h",
-    "src/core/iomgr/sockaddr_win32.h",
-    "src/core/iomgr/socket_utils_posix.h",
-    "src/core/iomgr/socket_windows.h",
-    "src/core/iomgr/tcp_client.h",
-    "src/core/iomgr/tcp_posix.h",
-    "src/core/iomgr/tcp_server.h",
-    "src/core/iomgr/tcp_windows.h",
-    "src/core/iomgr/time_averaged_stats.h",
-    "src/core/iomgr/timer.h",
-    "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/udp_server.h",
-    "src/core/iomgr/wakeup_fd_pipe.h",
-    "src/core/iomgr/wakeup_fd_posix.h",
-    "src/core/iomgr/workqueue.h",
-    "src/core/iomgr/workqueue_posix.h",
-    "src/core/iomgr/workqueue_windows.h",
-    "src/core/json/json.h",
-    "src/core/json/json_common.h",
-    "src/core/json/json_reader.h",
-    "src/core/json/json_writer.h",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
-    "src/core/statistics/census_interface.h",
-    "src/core/statistics/census_rpc_stats.h",
-    "src/core/surface/api_trace.h",
-    "src/core/surface/call.h",
-    "src/core/surface/call_test_only.h",
-    "src/core/surface/channel.h",
-    "src/core/surface/channel_init.h",
-    "src/core/surface/channel_stack_type.h",
-    "src/core/surface/completion_queue.h",
-    "src/core/surface/event_string.h",
-    "src/core/surface/init.h",
-    "src/core/surface/lame_client.h",
-    "src/core/surface/server.h",
-    "src/core/surface/surface_trace.h",
-    "src/core/transport/byte_stream.h",
-    "src/core/transport/chttp2/alpn.h",
-    "src/core/transport/chttp2/bin_encoder.h",
-    "src/core/transport/chttp2/frame.h",
-    "src/core/transport/chttp2/frame_data.h",
-    "src/core/transport/chttp2/frame_goaway.h",
-    "src/core/transport/chttp2/frame_ping.h",
-    "src/core/transport/chttp2/frame_rst_stream.h",
-    "src/core/transport/chttp2/frame_settings.h",
-    "src/core/transport/chttp2/frame_window_update.h",
-    "src/core/transport/chttp2/hpack_encoder.h",
-    "src/core/transport/chttp2/hpack_parser.h",
-    "src/core/transport/chttp2/hpack_table.h",
-    "src/core/transport/chttp2/http2_errors.h",
-    "src/core/transport/chttp2/huffsyms.h",
-    "src/core/transport/chttp2/incoming_metadata.h",
-    "src/core/transport/chttp2/internal.h",
-    "src/core/transport/chttp2/status_conversion.h",
-    "src/core/transport/chttp2/stream_map.h",
-    "src/core/transport/chttp2/timeout_encoding.h",
-    "src/core/transport/chttp2/varint.h",
-    "src/core/transport/chttp2_transport.h",
-    "src/core/transport/connectivity_state.h",
-    "src/core/transport/metadata.h",
-    "src/core/transport/metadata_batch.h",
-    "src/core/transport/static_metadata.h",
-    "src/core/transport/transport.h",
-    "src/core/transport/transport_impl.h",
-    "src/core/security/auth_filters.h",
-    "src/core/security/b64.h",
-    "src/core/security/credentials.h",
-    "src/core/security/handshake.h",
-    "src/core/security/json_token.h",
-    "src/core/security/jwt_verifier.h",
-    "src/core/security/secure_endpoint.h",
-    "src/core/security/security_connector.h",
-    "src/core/security/security_context.h",
-    "src/core/tsi/fake_transport_security.h",
-    "src/core/tsi/ssl_transport_security.h",
-    "src/core/tsi/ssl_types.h",
-    "src/core/tsi/transport_security.h",
-    "src/core/tsi/transport_security_interface.h",
-    "src/core/census/aggregation.h",
-    "src/core/census/mlog.h",
-    "src/core/census/rpc_metric_id.h",
-    "third_party/nanopb/pb.h",
-    "third_party/nanopb/pb_common.h",
-    "third_party/nanopb/pb_decode.h",
-    "third_party/nanopb/pb_encode.h",
-    "src/core/census/grpc_context.c",
-    "src/core/census/grpc_filter.c",
-    "src/core/census/grpc_plugin.c",
-    "src/core/channel/channel_args.c",
-    "src/core/channel/channel_stack.c",
-    "src/core/channel/channel_stack_builder.c",
-    "src/core/channel/client_channel.c",
-    "src/core/channel/client_uchannel.c",
-    "src/core/channel/compress_filter.c",
-    "src/core/channel/connected_channel.c",
-    "src/core/channel/http_client_filter.c",
-    "src/core/channel/http_server_filter.c",
-    "src/core/channel/subchannel_call_holder.c",
-    "src/core/client_config/client_config.c",
-    "src/core/client_config/connector.c",
-    "src/core/client_config/default_initial_connect_string.c",
-    "src/core/client_config/initial_connect_string.c",
-    "src/core/client_config/lb_policies/load_balancer_api.c",
-    "src/core/client_config/lb_policies/pick_first.c",
-    "src/core/client_config/lb_policies/round_robin.c",
-    "src/core/client_config/lb_policy.c",
-    "src/core/client_config/lb_policy_factory.c",
-    "src/core/client_config/lb_policy_registry.c",
-    "src/core/client_config/resolver.c",
-    "src/core/client_config/resolver_factory.c",
-    "src/core/client_config/resolver_registry.c",
-    "src/core/client_config/resolvers/dns_resolver.c",
-    "src/core/client_config/resolvers/sockaddr_resolver.c",
-    "src/core/client_config/subchannel.c",
-    "src/core/client_config/subchannel_factory.c",
-    "src/core/client_config/subchannel_index.c",
-    "src/core/client_config/uri_parser.c",
-    "src/core/compression/compression_algorithm.c",
-    "src/core/compression/message_compress.c",
-    "src/core/debug/trace.c",
-    "src/core/httpcli/format_request.c",
-    "src/core/httpcli/httpcli.c",
-    "src/core/httpcli/parser.c",
-    "src/core/iomgr/closure.c",
-    "src/core/iomgr/endpoint.c",
-    "src/core/iomgr/endpoint_pair_posix.c",
-    "src/core/iomgr/endpoint_pair_windows.c",
-    "src/core/iomgr/exec_ctx.c",
-    "src/core/iomgr/executor.c",
-    "src/core/iomgr/fd_posix.c",
-    "src/core/iomgr/iocp_windows.c",
-    "src/core/iomgr/iomgr.c",
-    "src/core/iomgr/iomgr_posix.c",
-    "src/core/iomgr/iomgr_windows.c",
-    "src/core/iomgr/pollset_multipoller_with_epoll.c",
-    "src/core/iomgr/pollset_multipoller_with_poll_posix.c",
-    "src/core/iomgr/pollset_posix.c",
-    "src/core/iomgr/pollset_set_posix.c",
-    "src/core/iomgr/pollset_set_windows.c",
-    "src/core/iomgr/pollset_windows.c",
-    "src/core/iomgr/resolve_address_posix.c",
-    "src/core/iomgr/resolve_address_windows.c",
-    "src/core/iomgr/sockaddr_utils.c",
-    "src/core/iomgr/socket_utils_common_posix.c",
-    "src/core/iomgr/socket_utils_linux.c",
-    "src/core/iomgr/socket_utils_posix.c",
-    "src/core/iomgr/socket_windows.c",
-    "src/core/iomgr/tcp_client_posix.c",
-    "src/core/iomgr/tcp_client_windows.c",
-    "src/core/iomgr/tcp_posix.c",
-    "src/core/iomgr/tcp_server_posix.c",
-    "src/core/iomgr/tcp_server_windows.c",
-    "src/core/iomgr/tcp_windows.c",
-    "src/core/iomgr/time_averaged_stats.c",
-    "src/core/iomgr/timer.c",
-    "src/core/iomgr/timer_heap.c",
-    "src/core/iomgr/udp_server.c",
-    "src/core/iomgr/wakeup_fd_eventfd.c",
-    "src/core/iomgr/wakeup_fd_nospecial.c",
-    "src/core/iomgr/wakeup_fd_pipe.c",
-    "src/core/iomgr/wakeup_fd_posix.c",
-    "src/core/iomgr/workqueue_posix.c",
-    "src/core/iomgr/workqueue_windows.c",
-    "src/core/json/json.c",
-    "src/core/json/json_reader.c",
-    "src/core/json/json_string.c",
-    "src/core/json/json_writer.c",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
-    "src/core/surface/alarm.c",
-    "src/core/surface/api_trace.c",
-    "src/core/surface/byte_buffer.c",
-    "src/core/surface/byte_buffer_reader.c",
-    "src/core/surface/call.c",
-    "src/core/surface/call_details.c",
-    "src/core/surface/call_log_batch.c",
-    "src/core/surface/channel.c",
-    "src/core/surface/channel_connectivity.c",
-    "src/core/surface/channel_create.c",
-    "src/core/surface/channel_init.c",
-    "src/core/surface/channel_ping.c",
-    "src/core/surface/channel_stack_type.c",
-    "src/core/surface/completion_queue.c",
-    "src/core/surface/event_string.c",
-    "src/core/surface/init.c",
-    "src/core/surface/lame_client.c",
-    "src/core/surface/metadata_array.c",
-    "src/core/surface/server.c",
-    "src/core/surface/server_chttp2.c",
-    "src/core/surface/validate_metadata.c",
-    "src/core/surface/version.c",
-    "src/core/transport/byte_stream.c",
-    "src/core/transport/chttp2/alpn.c",
-    "src/core/transport/chttp2/bin_encoder.c",
-    "src/core/transport/chttp2/frame_data.c",
-    "src/core/transport/chttp2/frame_goaway.c",
-    "src/core/transport/chttp2/frame_ping.c",
-    "src/core/transport/chttp2/frame_rst_stream.c",
-    "src/core/transport/chttp2/frame_settings.c",
-    "src/core/transport/chttp2/frame_window_update.c",
-    "src/core/transport/chttp2/hpack_encoder.c",
-    "src/core/transport/chttp2/hpack_parser.c",
-    "src/core/transport/chttp2/hpack_table.c",
-    "src/core/transport/chttp2/huffsyms.c",
-    "src/core/transport/chttp2/incoming_metadata.c",
-    "src/core/transport/chttp2/parsing.c",
-    "src/core/transport/chttp2/status_conversion.c",
-    "src/core/transport/chttp2/stream_lists.c",
-    "src/core/transport/chttp2/stream_map.c",
-    "src/core/transport/chttp2/timeout_encoding.c",
-    "src/core/transport/chttp2/varint.c",
-    "src/core/transport/chttp2/writing.c",
-    "src/core/transport/chttp2_transport.c",
-    "src/core/transport/connectivity_state.c",
-    "src/core/transport/metadata.c",
-    "src/core/transport/metadata_batch.c",
-    "src/core/transport/static_metadata.c",
-    "src/core/transport/transport.c",
-    "src/core/transport/transport_op_string.c",
-    "src/core/httpcli/httpcli_security_connector.c",
-    "src/core/security/b64.c",
-    "src/core/security/client_auth_filter.c",
-    "src/core/security/credentials.c",
-    "src/core/security/credentials_metadata.c",
-    "src/core/security/credentials_posix.c",
-    "src/core/security/credentials_win32.c",
-    "src/core/security/google_default_credentials.c",
-    "src/core/security/handshake.c",
-    "src/core/security/json_token.c",
-    "src/core/security/jwt_verifier.c",
-    "src/core/security/secure_endpoint.c",
-    "src/core/security/security_connector.c",
-    "src/core/security/security_context.c",
-    "src/core/security/server_auth_filter.c",
-    "src/core/security/server_secure_chttp2.c",
-    "src/core/surface/init_secure.c",
-    "src/core/surface/secure_channel_create.c",
-    "src/core/tsi/fake_transport_security.c",
-    "src/core/tsi/ssl_transport_security.c",
-    "src/core/tsi/transport_security.c",
-    "src/core/census/context.c",
-    "src/core/census/initialize.c",
-    "src/core/census/mlog.c",
-    "src/core/census/operation.c",
-    "src/core/census/placeholders.c",
-    "src/core/census/tracing.c",
-    "third_party/nanopb/pb_common.c",
-    "third_party/nanopb/pb_decode.c",
-    "third_party/nanopb/pb_encode.c",
+    "src/core/lib/channel/channel_args.h",
+    "src/core/lib/channel/channel_stack.h",
+    "src/core/lib/channel/channel_stack_builder.h",
+    "src/core/lib/channel/compress_filter.h",
+    "src/core/lib/channel/connected_channel.h",
+    "src/core/lib/channel/context.h",
+    "src/core/lib/channel/http_client_filter.h",
+    "src/core/lib/channel/http_server_filter.h",
+    "src/core/lib/compression/algorithm_metadata.h",
+    "src/core/lib/compression/message_compress.h",
+    "src/core/lib/debug/trace.h",
+    "src/core/lib/http/format_request.h",
+    "src/core/lib/http/httpcli.h",
+    "src/core/lib/http/parser.h",
+    "src/core/lib/iomgr/closure.h",
+    "src/core/lib/iomgr/endpoint.h",
+    "src/core/lib/iomgr/endpoint_pair.h",
+    "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
+    "src/core/lib/iomgr/ev_posix.h",
+    "src/core/lib/iomgr/exec_ctx.h",
+    "src/core/lib/iomgr/executor.h",
+    "src/core/lib/iomgr/iocp_windows.h",
+    "src/core/lib/iomgr/iomgr.h",
+    "src/core/lib/iomgr/iomgr_internal.h",
+    "src/core/lib/iomgr/iomgr_posix.h",
+    "src/core/lib/iomgr/pollset.h",
+    "src/core/lib/iomgr/pollset_set.h",
+    "src/core/lib/iomgr/pollset_set_windows.h",
+    "src/core/lib/iomgr/pollset_windows.h",
+    "src/core/lib/iomgr/resolve_address.h",
+    "src/core/lib/iomgr/sockaddr.h",
+    "src/core/lib/iomgr/sockaddr_posix.h",
+    "src/core/lib/iomgr/sockaddr_utils.h",
+    "src/core/lib/iomgr/sockaddr_win32.h",
+    "src/core/lib/iomgr/socket_utils_posix.h",
+    "src/core/lib/iomgr/socket_windows.h",
+    "src/core/lib/iomgr/tcp_client.h",
+    "src/core/lib/iomgr/tcp_posix.h",
+    "src/core/lib/iomgr/tcp_server.h",
+    "src/core/lib/iomgr/tcp_windows.h",
+    "src/core/lib/iomgr/time_averaged_stats.h",
+    "src/core/lib/iomgr/timer.h",
+    "src/core/lib/iomgr/timer_heap.h",
+    "src/core/lib/iomgr/udp_server.h",
+    "src/core/lib/iomgr/unix_sockets_posix.h",
+    "src/core/lib/iomgr/wakeup_fd_pipe.h",
+    "src/core/lib/iomgr/wakeup_fd_posix.h",
+    "src/core/lib/iomgr/workqueue.h",
+    "src/core/lib/iomgr/workqueue_posix.h",
+    "src/core/lib/iomgr/workqueue_windows.h",
+    "src/core/lib/json/json.h",
+    "src/core/lib/json/json_common.h",
+    "src/core/lib/json/json_reader.h",
+    "src/core/lib/json/json_writer.h",
+    "src/core/lib/surface/api_trace.h",
+    "src/core/lib/surface/call.h",
+    "src/core/lib/surface/call_test_only.h",
+    "src/core/lib/surface/channel.h",
+    "src/core/lib/surface/channel_init.h",
+    "src/core/lib/surface/channel_stack_type.h",
+    "src/core/lib/surface/completion_queue.h",
+    "src/core/lib/surface/event_string.h",
+    "src/core/lib/surface/init.h",
+    "src/core/lib/surface/lame_client.h",
+    "src/core/lib/surface/server.h",
+    "src/core/lib/surface/surface_trace.h",
+    "src/core/lib/transport/byte_stream.h",
+    "src/core/lib/transport/connectivity_state.h",
+    "src/core/lib/transport/metadata.h",
+    "src/core/lib/transport/metadata_batch.h",
+    "src/core/lib/transport/static_metadata.h",
+    "src/core/lib/transport/transport.h",
+    "src/core/lib/transport/transport_impl.h",
+    "src/core/ext/transport/chttp2/transport/bin_encoder.h",
+    "src/core/ext/transport/chttp2/transport/chttp2_transport.h",
+    "src/core/ext/transport/chttp2/transport/frame.h",
+    "src/core/ext/transport/chttp2/transport/frame_data.h",
+    "src/core/ext/transport/chttp2/transport/frame_goaway.h",
+    "src/core/ext/transport/chttp2/transport/frame_ping.h",
+    "src/core/ext/transport/chttp2/transport/frame_rst_stream.h",
+    "src/core/ext/transport/chttp2/transport/frame_settings.h",
+    "src/core/ext/transport/chttp2/transport/frame_window_update.h",
+    "src/core/ext/transport/chttp2/transport/hpack_encoder.h",
+    "src/core/ext/transport/chttp2/transport/hpack_parser.h",
+    "src/core/ext/transport/chttp2/transport/hpack_table.h",
+    "src/core/ext/transport/chttp2/transport/http2_errors.h",
+    "src/core/ext/transport/chttp2/transport/huffsyms.h",
+    "src/core/ext/transport/chttp2/transport/incoming_metadata.h",
+    "src/core/ext/transport/chttp2/transport/internal.h",
+    "src/core/ext/transport/chttp2/transport/status_conversion.h",
+    "src/core/ext/transport/chttp2/transport/stream_map.h",
+    "src/core/ext/transport/chttp2/transport/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/tsi/fake_transport_security.h",
+    "src/core/lib/tsi/ssl_transport_security.h",
+    "src/core/lib/tsi/ssl_types.h",
+    "src/core/lib/tsi/transport_security.h",
+    "src/core/lib/tsi/transport_security_interface.h",
+    "src/core/ext/client_config/client_channel.h",
+    "src/core/ext/client_config/client_channel_factory.h",
+    "src/core/ext/client_config/client_config.h",
+    "src/core/ext/client_config/connector.h",
+    "src/core/ext/client_config/initial_connect_string.h",
+    "src/core/ext/client_config/lb_policy.h",
+    "src/core/ext/client_config/lb_policy_factory.h",
+    "src/core/ext/client_config/lb_policy_registry.h",
+    "src/core/ext/client_config/parse_address.h",
+    "src/core/ext/client_config/resolver.h",
+    "src/core/ext/client_config/resolver_factory.h",
+    "src/core/ext/client_config/resolver_registry.h",
+    "src/core/ext/client_config/subchannel.h",
+    "src/core/ext/client_config/subchannel_call_holder.h",
+    "src/core/ext/client_config/subchannel_index.h",
+    "src/core/ext/client_config/uri_parser.h",
+    "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
+    "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h",
+    "src/core/ext/census/aggregation.h",
+    "src/core/ext/census/census_interface.h",
+    "src/core/ext/census/census_rpc_stats.h",
+    "src/core/ext/census/grpc_filter.h",
+    "src/core/ext/census/mlog.h",
+    "src/core/ext/census/rpc_metric_id.h",
+    "src/core/lib/surface/init.c",
+    "src/core/lib/channel/channel_args.c",
+    "src/core/lib/channel/channel_stack.c",
+    "src/core/lib/channel/channel_stack_builder.c",
+    "src/core/lib/channel/compress_filter.c",
+    "src/core/lib/channel/connected_channel.c",
+    "src/core/lib/channel/http_client_filter.c",
+    "src/core/lib/channel/http_server_filter.c",
+    "src/core/lib/compression/compression_algorithm.c",
+    "src/core/lib/compression/message_compress.c",
+    "src/core/lib/debug/trace.c",
+    "src/core/lib/http/format_request.c",
+    "src/core/lib/http/httpcli.c",
+    "src/core/lib/http/parser.c",
+    "src/core/lib/iomgr/closure.c",
+    "src/core/lib/iomgr/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_posix.c",
+    "src/core/lib/iomgr/exec_ctx.c",
+    "src/core/lib/iomgr/executor.c",
+    "src/core/lib/iomgr/iocp_windows.c",
+    "src/core/lib/iomgr/iomgr.c",
+    "src/core/lib/iomgr/iomgr_posix.c",
+    "src/core/lib/iomgr/iomgr_windows.c",
+    "src/core/lib/iomgr/pollset_set_windows.c",
+    "src/core/lib/iomgr/pollset_windows.c",
+    "src/core/lib/iomgr/resolve_address_posix.c",
+    "src/core/lib/iomgr/resolve_address_windows.c",
+    "src/core/lib/iomgr/sockaddr_utils.c",
+    "src/core/lib/iomgr/socket_utils_common_posix.c",
+    "src/core/lib/iomgr/socket_utils_linux.c",
+    "src/core/lib/iomgr/socket_utils_posix.c",
+    "src/core/lib/iomgr/socket_windows.c",
+    "src/core/lib/iomgr/tcp_client_posix.c",
+    "src/core/lib/iomgr/tcp_client_windows.c",
+    "src/core/lib/iomgr/tcp_posix.c",
+    "src/core/lib/iomgr/tcp_server_posix.c",
+    "src/core/lib/iomgr/tcp_server_windows.c",
+    "src/core/lib/iomgr/tcp_windows.c",
+    "src/core/lib/iomgr/time_averaged_stats.c",
+    "src/core/lib/iomgr/timer.c",
+    "src/core/lib/iomgr/timer_heap.c",
+    "src/core/lib/iomgr/udp_server.c",
+    "src/core/lib/iomgr/unix_sockets_posix.c",
+    "src/core/lib/iomgr/unix_sockets_posix_noop.c",
+    "src/core/lib/iomgr/wakeup_fd_eventfd.c",
+    "src/core/lib/iomgr/wakeup_fd_nospecial.c",
+    "src/core/lib/iomgr/wakeup_fd_pipe.c",
+    "src/core/lib/iomgr/wakeup_fd_posix.c",
+    "src/core/lib/iomgr/workqueue_posix.c",
+    "src/core/lib/iomgr/workqueue_windows.c",
+    "src/core/lib/json/json.c",
+    "src/core/lib/json/json_reader.c",
+    "src/core/lib/json/json_string.c",
+    "src/core/lib/json/json_writer.c",
+    "src/core/lib/surface/alarm.c",
+    "src/core/lib/surface/api_trace.c",
+    "src/core/lib/surface/byte_buffer.c",
+    "src/core/lib/surface/byte_buffer_reader.c",
+    "src/core/lib/surface/call.c",
+    "src/core/lib/surface/call_details.c",
+    "src/core/lib/surface/call_log_batch.c",
+    "src/core/lib/surface/channel.c",
+    "src/core/lib/surface/channel_init.c",
+    "src/core/lib/surface/channel_ping.c",
+    "src/core/lib/surface/channel_stack_type.c",
+    "src/core/lib/surface/completion_queue.c",
+    "src/core/lib/surface/event_string.c",
+    "src/core/lib/surface/lame_client.c",
+    "src/core/lib/surface/metadata_array.c",
+    "src/core/lib/surface/server.c",
+    "src/core/lib/surface/validate_metadata.c",
+    "src/core/lib/surface/version.c",
+    "src/core/lib/transport/byte_stream.c",
+    "src/core/lib/transport/connectivity_state.c",
+    "src/core/lib/transport/metadata.c",
+    "src/core/lib/transport/metadata_batch.c",
+    "src/core/lib/transport/static_metadata.c",
+    "src/core/lib/transport/transport.c",
+    "src/core/lib/transport/transport_op_string.c",
+    "src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c",
+    "src/core/ext/transport/chttp2/transport/bin_encoder.c",
+    "src/core/ext/transport/chttp2/transport/chttp2_plugin.c",
+    "src/core/ext/transport/chttp2/transport/chttp2_transport.c",
+    "src/core/ext/transport/chttp2/transport/frame_data.c",
+    "src/core/ext/transport/chttp2/transport/frame_goaway.c",
+    "src/core/ext/transport/chttp2/transport/frame_ping.c",
+    "src/core/ext/transport/chttp2/transport/frame_rst_stream.c",
+    "src/core/ext/transport/chttp2/transport/frame_settings.c",
+    "src/core/ext/transport/chttp2/transport/frame_window_update.c",
+    "src/core/ext/transport/chttp2/transport/hpack_encoder.c",
+    "src/core/ext/transport/chttp2/transport/hpack_parser.c",
+    "src/core/ext/transport/chttp2/transport/hpack_table.c",
+    "src/core/ext/transport/chttp2/transport/huffsyms.c",
+    "src/core/ext/transport/chttp2/transport/incoming_metadata.c",
+    "src/core/ext/transport/chttp2/transport/parsing.c",
+    "src/core/ext/transport/chttp2/transport/status_conversion.c",
+    "src/core/ext/transport/chttp2/transport/stream_lists.c",
+    "src/core/ext/transport/chttp2/transport/stream_map.c",
+    "src/core/ext/transport/chttp2/transport/timeout_encoding.c",
+    "src/core/ext/transport/chttp2/transport/varint.c",
+    "src/core/ext/transport/chttp2/transport/writing.c",
+    "src/core/ext/transport/chttp2/alpn/alpn.c",
+    "src/core/lib/http/httpcli_security_connector.c",
+    "src/core/lib/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/surface/init_secure.c",
+    "src/core/lib/tsi/fake_transport_security.c",
+    "src/core/lib/tsi/ssl_transport_security.c",
+    "src/core/lib/tsi/transport_security.c",
+    "src/core/ext/transport/chttp2/client/secure/secure_channel_create.c",
+    "src/core/ext/client_config/channel_connectivity.c",
+    "src/core/ext/client_config/client_channel.c",
+    "src/core/ext/client_config/client_channel_factory.c",
+    "src/core/ext/client_config/client_config.c",
+    "src/core/ext/client_config/client_config_plugin.c",
+    "src/core/ext/client_config/connector.c",
+    "src/core/ext/client_config/default_initial_connect_string.c",
+    "src/core/ext/client_config/initial_connect_string.c",
+    "src/core/ext/client_config/lb_policy.c",
+    "src/core/ext/client_config/lb_policy_factory.c",
+    "src/core/ext/client_config/lb_policy_registry.c",
+    "src/core/ext/client_config/parse_address.c",
+    "src/core/ext/client_config/resolver.c",
+    "src/core/ext/client_config/resolver_factory.c",
+    "src/core/ext/client_config/resolver_registry.c",
+    "src/core/ext/client_config/subchannel.c",
+    "src/core/ext/client_config/subchannel_call_holder.c",
+    "src/core/ext/client_config/subchannel_index.c",
+    "src/core/ext/client_config/uri_parser.c",
+    "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c",
+    "src/core/ext/transport/chttp2/client/insecure/channel_create.c",
+    "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
+    "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c",
+    "src/core/ext/lb_policy/pick_first/pick_first.c",
+    "src/core/ext/lb_policy/round_robin/round_robin.c",
+    "src/core/ext/resolver/dns/native/dns_resolver.c",
+    "src/core/ext/resolver/sockaddr/sockaddr_resolver.c",
+    "src/core/ext/census/context.c",
+    "src/core/ext/census/grpc_context.c",
+    "src/core/ext/census/grpc_filter.c",
+    "src/core/ext/census/grpc_plugin.c",
+    "src/core/ext/census/initialize.c",
+    "src/core/ext/census/mlog.c",
+    "src/core/ext/census/operation.c",
+    "src/core/ext/census/placeholders.c",
+    "src/core/ext/census/tracing.c",
+    "src/core/plugin_registry/grpc_plugin_registry.c",
   ],
   hdrs = [
-    "include/grpc/grpc_security.h",
     "include/grpc/byte_buffer.h",
     "include/grpc/byte_buffer_reader.h",
     "include/grpc/compression.h",
@@ -475,28 +466,6 @@
     "include/grpc/impl/codegen/grpc_types.h",
     "include/grpc/impl/codegen/propagation_bits.h",
     "include/grpc/impl/codegen/status.h",
-    "include/grpc/census.h",
-  ],
-  includes = [
-    "include",
-    ".",
-  ],
-  deps = [
-    "//external:libssl",
-    "//external:zlib",
-    ":gpr",
-  ],
-  copts = [
-    "-std=gnu99",
-  ],
-)
-
-
-cc_library(
-  name = "grpc_codegen_lib",
-  srcs = [
-  ],
-  hdrs = [
     "include/grpc/impl/codegen/alloc.h",
     "include/grpc/impl/codegen/atm.h",
     "include/grpc/impl/codegen/atm_gcc_atomic.h",
@@ -511,296 +480,290 @@
     "include/grpc/impl/codegen/sync_posix.h",
     "include/grpc/impl/codegen/sync_win32.h",
     "include/grpc/impl/codegen/time.h",
-    "include/grpc/impl/codegen/byte_buffer.h",
-    "include/grpc/impl/codegen/compression_types.h",
-    "include/grpc/impl/codegen/connectivity_state.h",
-    "include/grpc/impl/codegen/grpc_types.h",
-    "include/grpc/impl/codegen/propagation_bits.h",
-    "include/grpc/impl/codegen/status.h",
+    "include/grpc/grpc_security.h",
+    "include/grpc/grpc_security_constants.h",
+    "include/grpc/census.h",
   ],
   includes = [
     "include",
     ".",
   ],
   deps = [
-    "//external:protobuf_compiler",
+    "//external:libssl",
+    "//external:zlib",
+    ":gpr",
+    "//external:nanopb",
+  ],
+  copts = [
+    "-std=gnu99",
   ],
 )
 
 
+
 cc_library(
   name = "grpc_unsecure",
   srcs = [
-    "src/core/census/grpc_filter.h",
-    "src/core/census/grpc_plugin.h",
-    "src/core/channel/channel_args.h",
-    "src/core/channel/channel_stack.h",
-    "src/core/channel/channel_stack_builder.h",
-    "src/core/channel/client_channel.h",
-    "src/core/channel/client_uchannel.h",
-    "src/core/channel/compress_filter.h",
-    "src/core/channel/connected_channel.h",
-    "src/core/channel/context.h",
-    "src/core/channel/http_client_filter.h",
-    "src/core/channel/http_server_filter.h",
-    "src/core/channel/subchannel_call_holder.h",
-    "src/core/client_config/client_config.h",
-    "src/core/client_config/connector.h",
-    "src/core/client_config/initial_connect_string.h",
-    "src/core/client_config/lb_policies/load_balancer_api.h",
-    "src/core/client_config/lb_policies/pick_first.h",
-    "src/core/client_config/lb_policies/round_robin.h",
-    "src/core/client_config/lb_policy.h",
-    "src/core/client_config/lb_policy_factory.h",
-    "src/core/client_config/lb_policy_registry.h",
-    "src/core/client_config/resolver.h",
-    "src/core/client_config/resolver_factory.h",
-    "src/core/client_config/resolver_registry.h",
-    "src/core/client_config/resolvers/dns_resolver.h",
-    "src/core/client_config/resolvers/sockaddr_resolver.h",
-    "src/core/client_config/subchannel.h",
-    "src/core/client_config/subchannel_factory.h",
-    "src/core/client_config/subchannel_index.h",
-    "src/core/client_config/uri_parser.h",
-    "src/core/compression/algorithm_metadata.h",
-    "src/core/compression/message_compress.h",
-    "src/core/debug/trace.h",
-    "src/core/httpcli/format_request.h",
-    "src/core/httpcli/httpcli.h",
-    "src/core/httpcli/parser.h",
-    "src/core/iomgr/closure.h",
-    "src/core/iomgr/endpoint.h",
-    "src/core/iomgr/endpoint_pair.h",
-    "src/core/iomgr/exec_ctx.h",
-    "src/core/iomgr/executor.h",
-    "src/core/iomgr/fd_posix.h",
-    "src/core/iomgr/iocp_windows.h",
-    "src/core/iomgr/iomgr.h",
-    "src/core/iomgr/iomgr_internal.h",
-    "src/core/iomgr/iomgr_posix.h",
-    "src/core/iomgr/pollset.h",
-    "src/core/iomgr/pollset_posix.h",
-    "src/core/iomgr/pollset_set.h",
-    "src/core/iomgr/pollset_set_posix.h",
-    "src/core/iomgr/pollset_set_windows.h",
-    "src/core/iomgr/pollset_windows.h",
-    "src/core/iomgr/resolve_address.h",
-    "src/core/iomgr/sockaddr.h",
-    "src/core/iomgr/sockaddr_posix.h",
-    "src/core/iomgr/sockaddr_utils.h",
-    "src/core/iomgr/sockaddr_win32.h",
-    "src/core/iomgr/socket_utils_posix.h",
-    "src/core/iomgr/socket_windows.h",
-    "src/core/iomgr/tcp_client.h",
-    "src/core/iomgr/tcp_posix.h",
-    "src/core/iomgr/tcp_server.h",
-    "src/core/iomgr/tcp_windows.h",
-    "src/core/iomgr/time_averaged_stats.h",
-    "src/core/iomgr/timer.h",
-    "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/udp_server.h",
-    "src/core/iomgr/wakeup_fd_pipe.h",
-    "src/core/iomgr/wakeup_fd_posix.h",
-    "src/core/iomgr/workqueue.h",
-    "src/core/iomgr/workqueue_posix.h",
-    "src/core/iomgr/workqueue_windows.h",
-    "src/core/json/json.h",
-    "src/core/json/json_common.h",
-    "src/core/json/json_reader.h",
-    "src/core/json/json_writer.h",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
-    "src/core/statistics/census_interface.h",
-    "src/core/statistics/census_rpc_stats.h",
-    "src/core/surface/api_trace.h",
-    "src/core/surface/call.h",
-    "src/core/surface/call_test_only.h",
-    "src/core/surface/channel.h",
-    "src/core/surface/channel_init.h",
-    "src/core/surface/channel_stack_type.h",
-    "src/core/surface/completion_queue.h",
-    "src/core/surface/event_string.h",
-    "src/core/surface/init.h",
-    "src/core/surface/lame_client.h",
-    "src/core/surface/server.h",
-    "src/core/surface/surface_trace.h",
-    "src/core/transport/byte_stream.h",
-    "src/core/transport/chttp2/alpn.h",
-    "src/core/transport/chttp2/bin_encoder.h",
-    "src/core/transport/chttp2/frame.h",
-    "src/core/transport/chttp2/frame_data.h",
-    "src/core/transport/chttp2/frame_goaway.h",
-    "src/core/transport/chttp2/frame_ping.h",
-    "src/core/transport/chttp2/frame_rst_stream.h",
-    "src/core/transport/chttp2/frame_settings.h",
-    "src/core/transport/chttp2/frame_window_update.h",
-    "src/core/transport/chttp2/hpack_encoder.h",
-    "src/core/transport/chttp2/hpack_parser.h",
-    "src/core/transport/chttp2/hpack_table.h",
-    "src/core/transport/chttp2/http2_errors.h",
-    "src/core/transport/chttp2/huffsyms.h",
-    "src/core/transport/chttp2/incoming_metadata.h",
-    "src/core/transport/chttp2/internal.h",
-    "src/core/transport/chttp2/status_conversion.h",
-    "src/core/transport/chttp2/stream_map.h",
-    "src/core/transport/chttp2/timeout_encoding.h",
-    "src/core/transport/chttp2/varint.h",
-    "src/core/transport/chttp2_transport.h",
-    "src/core/transport/connectivity_state.h",
-    "src/core/transport/metadata.h",
-    "src/core/transport/metadata_batch.h",
-    "src/core/transport/static_metadata.h",
-    "src/core/transport/transport.h",
-    "src/core/transport/transport_impl.h",
-    "src/core/census/aggregation.h",
-    "src/core/census/mlog.h",
-    "src/core/census/rpc_metric_id.h",
-    "third_party/nanopb/pb.h",
-    "third_party/nanopb/pb_common.h",
-    "third_party/nanopb/pb_decode.h",
-    "third_party/nanopb/pb_encode.h",
-    "src/core/surface/init_unsecure.c",
-    "src/core/census/grpc_context.c",
-    "src/core/census/grpc_filter.c",
-    "src/core/census/grpc_plugin.c",
-    "src/core/channel/channel_args.c",
-    "src/core/channel/channel_stack.c",
-    "src/core/channel/channel_stack_builder.c",
-    "src/core/channel/client_channel.c",
-    "src/core/channel/client_uchannel.c",
-    "src/core/channel/compress_filter.c",
-    "src/core/channel/connected_channel.c",
-    "src/core/channel/http_client_filter.c",
-    "src/core/channel/http_server_filter.c",
-    "src/core/channel/subchannel_call_holder.c",
-    "src/core/client_config/client_config.c",
-    "src/core/client_config/connector.c",
-    "src/core/client_config/default_initial_connect_string.c",
-    "src/core/client_config/initial_connect_string.c",
-    "src/core/client_config/lb_policies/load_balancer_api.c",
-    "src/core/client_config/lb_policies/pick_first.c",
-    "src/core/client_config/lb_policies/round_robin.c",
-    "src/core/client_config/lb_policy.c",
-    "src/core/client_config/lb_policy_factory.c",
-    "src/core/client_config/lb_policy_registry.c",
-    "src/core/client_config/resolver.c",
-    "src/core/client_config/resolver_factory.c",
-    "src/core/client_config/resolver_registry.c",
-    "src/core/client_config/resolvers/dns_resolver.c",
-    "src/core/client_config/resolvers/sockaddr_resolver.c",
-    "src/core/client_config/subchannel.c",
-    "src/core/client_config/subchannel_factory.c",
-    "src/core/client_config/subchannel_index.c",
-    "src/core/client_config/uri_parser.c",
-    "src/core/compression/compression_algorithm.c",
-    "src/core/compression/message_compress.c",
-    "src/core/debug/trace.c",
-    "src/core/httpcli/format_request.c",
-    "src/core/httpcli/httpcli.c",
-    "src/core/httpcli/parser.c",
-    "src/core/iomgr/closure.c",
-    "src/core/iomgr/endpoint.c",
-    "src/core/iomgr/endpoint_pair_posix.c",
-    "src/core/iomgr/endpoint_pair_windows.c",
-    "src/core/iomgr/exec_ctx.c",
-    "src/core/iomgr/executor.c",
-    "src/core/iomgr/fd_posix.c",
-    "src/core/iomgr/iocp_windows.c",
-    "src/core/iomgr/iomgr.c",
-    "src/core/iomgr/iomgr_posix.c",
-    "src/core/iomgr/iomgr_windows.c",
-    "src/core/iomgr/pollset_multipoller_with_epoll.c",
-    "src/core/iomgr/pollset_multipoller_with_poll_posix.c",
-    "src/core/iomgr/pollset_posix.c",
-    "src/core/iomgr/pollset_set_posix.c",
-    "src/core/iomgr/pollset_set_windows.c",
-    "src/core/iomgr/pollset_windows.c",
-    "src/core/iomgr/resolve_address_posix.c",
-    "src/core/iomgr/resolve_address_windows.c",
-    "src/core/iomgr/sockaddr_utils.c",
-    "src/core/iomgr/socket_utils_common_posix.c",
-    "src/core/iomgr/socket_utils_linux.c",
-    "src/core/iomgr/socket_utils_posix.c",
-    "src/core/iomgr/socket_windows.c",
-    "src/core/iomgr/tcp_client_posix.c",
-    "src/core/iomgr/tcp_client_windows.c",
-    "src/core/iomgr/tcp_posix.c",
-    "src/core/iomgr/tcp_server_posix.c",
-    "src/core/iomgr/tcp_server_windows.c",
-    "src/core/iomgr/tcp_windows.c",
-    "src/core/iomgr/time_averaged_stats.c",
-    "src/core/iomgr/timer.c",
-    "src/core/iomgr/timer_heap.c",
-    "src/core/iomgr/udp_server.c",
-    "src/core/iomgr/wakeup_fd_eventfd.c",
-    "src/core/iomgr/wakeup_fd_nospecial.c",
-    "src/core/iomgr/wakeup_fd_pipe.c",
-    "src/core/iomgr/wakeup_fd_posix.c",
-    "src/core/iomgr/workqueue_posix.c",
-    "src/core/iomgr/workqueue_windows.c",
-    "src/core/json/json.c",
-    "src/core/json/json_reader.c",
-    "src/core/json/json_string.c",
-    "src/core/json/json_writer.c",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
-    "src/core/surface/alarm.c",
-    "src/core/surface/api_trace.c",
-    "src/core/surface/byte_buffer.c",
-    "src/core/surface/byte_buffer_reader.c",
-    "src/core/surface/call.c",
-    "src/core/surface/call_details.c",
-    "src/core/surface/call_log_batch.c",
-    "src/core/surface/channel.c",
-    "src/core/surface/channel_connectivity.c",
-    "src/core/surface/channel_create.c",
-    "src/core/surface/channel_init.c",
-    "src/core/surface/channel_ping.c",
-    "src/core/surface/channel_stack_type.c",
-    "src/core/surface/completion_queue.c",
-    "src/core/surface/event_string.c",
-    "src/core/surface/init.c",
-    "src/core/surface/lame_client.c",
-    "src/core/surface/metadata_array.c",
-    "src/core/surface/server.c",
-    "src/core/surface/server_chttp2.c",
-    "src/core/surface/validate_metadata.c",
-    "src/core/surface/version.c",
-    "src/core/transport/byte_stream.c",
-    "src/core/transport/chttp2/alpn.c",
-    "src/core/transport/chttp2/bin_encoder.c",
-    "src/core/transport/chttp2/frame_data.c",
-    "src/core/transport/chttp2/frame_goaway.c",
-    "src/core/transport/chttp2/frame_ping.c",
-    "src/core/transport/chttp2/frame_rst_stream.c",
-    "src/core/transport/chttp2/frame_settings.c",
-    "src/core/transport/chttp2/frame_window_update.c",
-    "src/core/transport/chttp2/hpack_encoder.c",
-    "src/core/transport/chttp2/hpack_parser.c",
-    "src/core/transport/chttp2/hpack_table.c",
-    "src/core/transport/chttp2/huffsyms.c",
-    "src/core/transport/chttp2/incoming_metadata.c",
-    "src/core/transport/chttp2/parsing.c",
-    "src/core/transport/chttp2/status_conversion.c",
-    "src/core/transport/chttp2/stream_lists.c",
-    "src/core/transport/chttp2/stream_map.c",
-    "src/core/transport/chttp2/timeout_encoding.c",
-    "src/core/transport/chttp2/varint.c",
-    "src/core/transport/chttp2/writing.c",
-    "src/core/transport/chttp2_transport.c",
-    "src/core/transport/connectivity_state.c",
-    "src/core/transport/metadata.c",
-    "src/core/transport/metadata_batch.c",
-    "src/core/transport/static_metadata.c",
-    "src/core/transport/transport.c",
-    "src/core/transport/transport_op_string.c",
-    "src/core/census/context.c",
-    "src/core/census/initialize.c",
-    "src/core/census/mlog.c",
-    "src/core/census/operation.c",
-    "src/core/census/placeholders.c",
-    "src/core/census/tracing.c",
-    "third_party/nanopb/pb_common.c",
-    "third_party/nanopb/pb_decode.c",
-    "third_party/nanopb/pb_encode.c",
+    "src/core/lib/channel/channel_args.h",
+    "src/core/lib/channel/channel_stack.h",
+    "src/core/lib/channel/channel_stack_builder.h",
+    "src/core/lib/channel/compress_filter.h",
+    "src/core/lib/channel/connected_channel.h",
+    "src/core/lib/channel/context.h",
+    "src/core/lib/channel/http_client_filter.h",
+    "src/core/lib/channel/http_server_filter.h",
+    "src/core/lib/compression/algorithm_metadata.h",
+    "src/core/lib/compression/message_compress.h",
+    "src/core/lib/debug/trace.h",
+    "src/core/lib/http/format_request.h",
+    "src/core/lib/http/httpcli.h",
+    "src/core/lib/http/parser.h",
+    "src/core/lib/iomgr/closure.h",
+    "src/core/lib/iomgr/endpoint.h",
+    "src/core/lib/iomgr/endpoint_pair.h",
+    "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
+    "src/core/lib/iomgr/ev_posix.h",
+    "src/core/lib/iomgr/exec_ctx.h",
+    "src/core/lib/iomgr/executor.h",
+    "src/core/lib/iomgr/iocp_windows.h",
+    "src/core/lib/iomgr/iomgr.h",
+    "src/core/lib/iomgr/iomgr_internal.h",
+    "src/core/lib/iomgr/iomgr_posix.h",
+    "src/core/lib/iomgr/pollset.h",
+    "src/core/lib/iomgr/pollset_set.h",
+    "src/core/lib/iomgr/pollset_set_windows.h",
+    "src/core/lib/iomgr/pollset_windows.h",
+    "src/core/lib/iomgr/resolve_address.h",
+    "src/core/lib/iomgr/sockaddr.h",
+    "src/core/lib/iomgr/sockaddr_posix.h",
+    "src/core/lib/iomgr/sockaddr_utils.h",
+    "src/core/lib/iomgr/sockaddr_win32.h",
+    "src/core/lib/iomgr/socket_utils_posix.h",
+    "src/core/lib/iomgr/socket_windows.h",
+    "src/core/lib/iomgr/tcp_client.h",
+    "src/core/lib/iomgr/tcp_posix.h",
+    "src/core/lib/iomgr/tcp_server.h",
+    "src/core/lib/iomgr/tcp_windows.h",
+    "src/core/lib/iomgr/time_averaged_stats.h",
+    "src/core/lib/iomgr/timer.h",
+    "src/core/lib/iomgr/timer_heap.h",
+    "src/core/lib/iomgr/udp_server.h",
+    "src/core/lib/iomgr/unix_sockets_posix.h",
+    "src/core/lib/iomgr/wakeup_fd_pipe.h",
+    "src/core/lib/iomgr/wakeup_fd_posix.h",
+    "src/core/lib/iomgr/workqueue.h",
+    "src/core/lib/iomgr/workqueue_posix.h",
+    "src/core/lib/iomgr/workqueue_windows.h",
+    "src/core/lib/json/json.h",
+    "src/core/lib/json/json_common.h",
+    "src/core/lib/json/json_reader.h",
+    "src/core/lib/json/json_writer.h",
+    "src/core/lib/surface/api_trace.h",
+    "src/core/lib/surface/call.h",
+    "src/core/lib/surface/call_test_only.h",
+    "src/core/lib/surface/channel.h",
+    "src/core/lib/surface/channel_init.h",
+    "src/core/lib/surface/channel_stack_type.h",
+    "src/core/lib/surface/completion_queue.h",
+    "src/core/lib/surface/event_string.h",
+    "src/core/lib/surface/init.h",
+    "src/core/lib/surface/lame_client.h",
+    "src/core/lib/surface/server.h",
+    "src/core/lib/surface/surface_trace.h",
+    "src/core/lib/transport/byte_stream.h",
+    "src/core/lib/transport/connectivity_state.h",
+    "src/core/lib/transport/metadata.h",
+    "src/core/lib/transport/metadata_batch.h",
+    "src/core/lib/transport/static_metadata.h",
+    "src/core/lib/transport/transport.h",
+    "src/core/lib/transport/transport_impl.h",
+    "src/core/ext/transport/chttp2/transport/bin_encoder.h",
+    "src/core/ext/transport/chttp2/transport/chttp2_transport.h",
+    "src/core/ext/transport/chttp2/transport/frame.h",
+    "src/core/ext/transport/chttp2/transport/frame_data.h",
+    "src/core/ext/transport/chttp2/transport/frame_goaway.h",
+    "src/core/ext/transport/chttp2/transport/frame_ping.h",
+    "src/core/ext/transport/chttp2/transport/frame_rst_stream.h",
+    "src/core/ext/transport/chttp2/transport/frame_settings.h",
+    "src/core/ext/transport/chttp2/transport/frame_window_update.h",
+    "src/core/ext/transport/chttp2/transport/hpack_encoder.h",
+    "src/core/ext/transport/chttp2/transport/hpack_parser.h",
+    "src/core/ext/transport/chttp2/transport/hpack_table.h",
+    "src/core/ext/transport/chttp2/transport/http2_errors.h",
+    "src/core/ext/transport/chttp2/transport/huffsyms.h",
+    "src/core/ext/transport/chttp2/transport/incoming_metadata.h",
+    "src/core/ext/transport/chttp2/transport/internal.h",
+    "src/core/ext/transport/chttp2/transport/status_conversion.h",
+    "src/core/ext/transport/chttp2/transport/stream_map.h",
+    "src/core/ext/transport/chttp2/transport/timeout_encoding.h",
+    "src/core/ext/transport/chttp2/transport/varint.h",
+    "src/core/ext/transport/chttp2/alpn/alpn.h",
+    "src/core/ext/client_config/client_channel.h",
+    "src/core/ext/client_config/client_channel_factory.h",
+    "src/core/ext/client_config/client_config.h",
+    "src/core/ext/client_config/connector.h",
+    "src/core/ext/client_config/initial_connect_string.h",
+    "src/core/ext/client_config/lb_policy.h",
+    "src/core/ext/client_config/lb_policy_factory.h",
+    "src/core/ext/client_config/lb_policy_registry.h",
+    "src/core/ext/client_config/parse_address.h",
+    "src/core/ext/client_config/resolver.h",
+    "src/core/ext/client_config/resolver_factory.h",
+    "src/core/ext/client_config/resolver_registry.h",
+    "src/core/ext/client_config/subchannel.h",
+    "src/core/ext/client_config/subchannel_call_holder.h",
+    "src/core/ext/client_config/subchannel_index.h",
+    "src/core/ext/client_config/uri_parser.h",
+    "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
+    "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h",
+    "src/core/ext/census/aggregation.h",
+    "src/core/ext/census/census_interface.h",
+    "src/core/ext/census/census_rpc_stats.h",
+    "src/core/ext/census/grpc_filter.h",
+    "src/core/ext/census/mlog.h",
+    "src/core/ext/census/rpc_metric_id.h",
+    "src/core/lib/surface/init.c",
+    "src/core/lib/surface/init_unsecure.c",
+    "src/core/lib/channel/channel_args.c",
+    "src/core/lib/channel/channel_stack.c",
+    "src/core/lib/channel/channel_stack_builder.c",
+    "src/core/lib/channel/compress_filter.c",
+    "src/core/lib/channel/connected_channel.c",
+    "src/core/lib/channel/http_client_filter.c",
+    "src/core/lib/channel/http_server_filter.c",
+    "src/core/lib/compression/compression_algorithm.c",
+    "src/core/lib/compression/message_compress.c",
+    "src/core/lib/debug/trace.c",
+    "src/core/lib/http/format_request.c",
+    "src/core/lib/http/httpcli.c",
+    "src/core/lib/http/parser.c",
+    "src/core/lib/iomgr/closure.c",
+    "src/core/lib/iomgr/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_posix.c",
+    "src/core/lib/iomgr/exec_ctx.c",
+    "src/core/lib/iomgr/executor.c",
+    "src/core/lib/iomgr/iocp_windows.c",
+    "src/core/lib/iomgr/iomgr.c",
+    "src/core/lib/iomgr/iomgr_posix.c",
+    "src/core/lib/iomgr/iomgr_windows.c",
+    "src/core/lib/iomgr/pollset_set_windows.c",
+    "src/core/lib/iomgr/pollset_windows.c",
+    "src/core/lib/iomgr/resolve_address_posix.c",
+    "src/core/lib/iomgr/resolve_address_windows.c",
+    "src/core/lib/iomgr/sockaddr_utils.c",
+    "src/core/lib/iomgr/socket_utils_common_posix.c",
+    "src/core/lib/iomgr/socket_utils_linux.c",
+    "src/core/lib/iomgr/socket_utils_posix.c",
+    "src/core/lib/iomgr/socket_windows.c",
+    "src/core/lib/iomgr/tcp_client_posix.c",
+    "src/core/lib/iomgr/tcp_client_windows.c",
+    "src/core/lib/iomgr/tcp_posix.c",
+    "src/core/lib/iomgr/tcp_server_posix.c",
+    "src/core/lib/iomgr/tcp_server_windows.c",
+    "src/core/lib/iomgr/tcp_windows.c",
+    "src/core/lib/iomgr/time_averaged_stats.c",
+    "src/core/lib/iomgr/timer.c",
+    "src/core/lib/iomgr/timer_heap.c",
+    "src/core/lib/iomgr/udp_server.c",
+    "src/core/lib/iomgr/unix_sockets_posix.c",
+    "src/core/lib/iomgr/unix_sockets_posix_noop.c",
+    "src/core/lib/iomgr/wakeup_fd_eventfd.c",
+    "src/core/lib/iomgr/wakeup_fd_nospecial.c",
+    "src/core/lib/iomgr/wakeup_fd_pipe.c",
+    "src/core/lib/iomgr/wakeup_fd_posix.c",
+    "src/core/lib/iomgr/workqueue_posix.c",
+    "src/core/lib/iomgr/workqueue_windows.c",
+    "src/core/lib/json/json.c",
+    "src/core/lib/json/json_reader.c",
+    "src/core/lib/json/json_string.c",
+    "src/core/lib/json/json_writer.c",
+    "src/core/lib/surface/alarm.c",
+    "src/core/lib/surface/api_trace.c",
+    "src/core/lib/surface/byte_buffer.c",
+    "src/core/lib/surface/byte_buffer_reader.c",
+    "src/core/lib/surface/call.c",
+    "src/core/lib/surface/call_details.c",
+    "src/core/lib/surface/call_log_batch.c",
+    "src/core/lib/surface/channel.c",
+    "src/core/lib/surface/channel_init.c",
+    "src/core/lib/surface/channel_ping.c",
+    "src/core/lib/surface/channel_stack_type.c",
+    "src/core/lib/surface/completion_queue.c",
+    "src/core/lib/surface/event_string.c",
+    "src/core/lib/surface/lame_client.c",
+    "src/core/lib/surface/metadata_array.c",
+    "src/core/lib/surface/server.c",
+    "src/core/lib/surface/validate_metadata.c",
+    "src/core/lib/surface/version.c",
+    "src/core/lib/transport/byte_stream.c",
+    "src/core/lib/transport/connectivity_state.c",
+    "src/core/lib/transport/metadata.c",
+    "src/core/lib/transport/metadata_batch.c",
+    "src/core/lib/transport/static_metadata.c",
+    "src/core/lib/transport/transport.c",
+    "src/core/lib/transport/transport_op_string.c",
+    "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c",
+    "src/core/ext/transport/chttp2/transport/bin_encoder.c",
+    "src/core/ext/transport/chttp2/transport/chttp2_plugin.c",
+    "src/core/ext/transport/chttp2/transport/chttp2_transport.c",
+    "src/core/ext/transport/chttp2/transport/frame_data.c",
+    "src/core/ext/transport/chttp2/transport/frame_goaway.c",
+    "src/core/ext/transport/chttp2/transport/frame_ping.c",
+    "src/core/ext/transport/chttp2/transport/frame_rst_stream.c",
+    "src/core/ext/transport/chttp2/transport/frame_settings.c",
+    "src/core/ext/transport/chttp2/transport/frame_window_update.c",
+    "src/core/ext/transport/chttp2/transport/hpack_encoder.c",
+    "src/core/ext/transport/chttp2/transport/hpack_parser.c",
+    "src/core/ext/transport/chttp2/transport/hpack_table.c",
+    "src/core/ext/transport/chttp2/transport/huffsyms.c",
+    "src/core/ext/transport/chttp2/transport/incoming_metadata.c",
+    "src/core/ext/transport/chttp2/transport/parsing.c",
+    "src/core/ext/transport/chttp2/transport/status_conversion.c",
+    "src/core/ext/transport/chttp2/transport/stream_lists.c",
+    "src/core/ext/transport/chttp2/transport/stream_map.c",
+    "src/core/ext/transport/chttp2/transport/timeout_encoding.c",
+    "src/core/ext/transport/chttp2/transport/varint.c",
+    "src/core/ext/transport/chttp2/transport/writing.c",
+    "src/core/ext/transport/chttp2/alpn/alpn.c",
+    "src/core/ext/transport/chttp2/client/insecure/channel_create.c",
+    "src/core/ext/client_config/channel_connectivity.c",
+    "src/core/ext/client_config/client_channel.c",
+    "src/core/ext/client_config/client_channel_factory.c",
+    "src/core/ext/client_config/client_config.c",
+    "src/core/ext/client_config/client_config_plugin.c",
+    "src/core/ext/client_config/connector.c",
+    "src/core/ext/client_config/default_initial_connect_string.c",
+    "src/core/ext/client_config/initial_connect_string.c",
+    "src/core/ext/client_config/lb_policy.c",
+    "src/core/ext/client_config/lb_policy_factory.c",
+    "src/core/ext/client_config/lb_policy_registry.c",
+    "src/core/ext/client_config/parse_address.c",
+    "src/core/ext/client_config/resolver.c",
+    "src/core/ext/client_config/resolver_factory.c",
+    "src/core/ext/client_config/resolver_registry.c",
+    "src/core/ext/client_config/subchannel.c",
+    "src/core/ext/client_config/subchannel_call_holder.c",
+    "src/core/ext/client_config/subchannel_index.c",
+    "src/core/ext/client_config/uri_parser.c",
+    "src/core/ext/resolver/dns/native/dns_resolver.c",
+    "src/core/ext/resolver/sockaddr/sockaddr_resolver.c",
+    "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
+    "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c",
+    "src/core/ext/lb_policy/pick_first/pick_first.c",
+    "src/core/ext/lb_policy/round_robin/round_robin.c",
+    "src/core/ext/census/context.c",
+    "src/core/ext/census/grpc_context.c",
+    "src/core/ext/census/grpc_filter.c",
+    "src/core/ext/census/grpc_plugin.c",
+    "src/core/ext/census/initialize.c",
+    "src/core/ext/census/mlog.c",
+    "src/core/ext/census/operation.c",
+    "src/core/ext/census/placeholders.c",
+    "src/core/ext/census/tracing.c",
+    "src/core/plugin_registry/grpc_unsecure_plugin_registry.c",
   ],
   hdrs = [
     "include/grpc/byte_buffer.h",
@@ -814,6 +777,20 @@
     "include/grpc/impl/codegen/grpc_types.h",
     "include/grpc/impl/codegen/propagation_bits.h",
     "include/grpc/impl/codegen/status.h",
+    "include/grpc/impl/codegen/alloc.h",
+    "include/grpc/impl/codegen/atm.h",
+    "include/grpc/impl/codegen/atm_gcc_atomic.h",
+    "include/grpc/impl/codegen/atm_gcc_sync.h",
+    "include/grpc/impl/codegen/atm_win32.h",
+    "include/grpc/impl/codegen/log.h",
+    "include/grpc/impl/codegen/port_platform.h",
+    "include/grpc/impl/codegen/slice.h",
+    "include/grpc/impl/codegen/slice_buffer.h",
+    "include/grpc/impl/codegen/sync.h",
+    "include/grpc/impl/codegen/sync_generic.h",
+    "include/grpc/impl/codegen/sync_posix.h",
+    "include/grpc/impl/codegen/sync_win32.h",
+    "include/grpc/impl/codegen/time.h",
     "include/grpc/census.h",
   ],
   includes = [
@@ -822,6 +799,7 @@
   ],
   deps = [
     ":gpr",
+    "//external:nanopb",
   ],
   copts = [
     "-std=gnu99",
@@ -829,11 +807,11 @@
 )
 
 
+
 cc_library(
   name = "grpc_zookeeper",
   srcs = [
-    "src/core/client_config/resolvers/zookeeper_resolver.h",
-    "src/core/client_config/resolvers/zookeeper_resolver.c",
+    "src/core/ext/resolver/zookeeper/zookeeper_resolver.c",
   ],
   hdrs = [
     "include/grpc/grpc_zookeeper.h",
@@ -849,6 +827,7 @@
 )
 
 
+
 cc_library(
   name = "grpc++",
   srcs = [
@@ -857,8 +836,6 @@
     "src/cpp/common/secure_auth_context.h",
     "src/cpp/server/secure_server_credentials.h",
     "src/cpp/client/create_channel_internal.h",
-    "src/cpp/common/core_codegen.h",
-    "src/cpp/common/create_auth_context.h",
     "src/cpp/server/dynamic_thread_pool.h",
     "src/cpp/server/thread_pool_interface.h",
     "src/cpp/client/secure_credentials.cc",
@@ -929,8 +906,6 @@
     "include/grpc++/support/async_unary_call.h",
     "include/grpc++/support/byte_buffer.h",
     "include/grpc++/support/channel_arguments.h",
-    "include/grpc++/support/config.h",
-    "include/grpc++/support/config_protobuf.h",
     "include/grpc++/support/slice.h",
     "include/grpc++/support/status.h",
     "include/grpc++/support/status_code_enum.h",
@@ -947,9 +922,8 @@
     "include/grpc++/impl/codegen/client_unary_call.h",
     "include/grpc++/impl/codegen/completion_queue.h",
     "include/grpc++/impl/codegen/completion_queue_tag.h",
-    "include/grpc++/impl/codegen/config.h",
-    "include/grpc++/impl/codegen/config_protobuf.h",
     "include/grpc++/impl/codegen/core_codegen_interface.h",
+    "include/grpc++/impl/codegen/create_auth_context.h",
     "include/grpc++/impl/codegen/grpc_library.h",
     "include/grpc++/impl/codegen/method_handler_impl.h",
     "include/grpc++/impl/codegen/proto_utils.h",
@@ -969,25 +943,12 @@
     "include/grpc++/impl/codegen/sync_no_cxx11.h",
     "include/grpc++/impl/codegen/sync_stream.h",
     "include/grpc++/impl/codegen/time.h",
-  ],
-  includes = [
-    "include",
-    ".",
-  ],
-  deps = [
-    "//external:libssl",
-    "//external:protobuf_clib",
-    ":grpc",
-  ],
-)
-
-
-cc_library(
-  name = "grpc++_codegen_lib",
-  srcs = [
-    "src/cpp/codegen/codegen_init.cc",
-  ],
-  hdrs = [
+    "include/grpc/impl/codegen/byte_buffer.h",
+    "include/grpc/impl/codegen/compression_types.h",
+    "include/grpc/impl/codegen/connectivity_state.h",
+    "include/grpc/impl/codegen/grpc_types.h",
+    "include/grpc/impl/codegen/propagation_bits.h",
+    "include/grpc/impl/codegen/status.h",
     "include/grpc/impl/codegen/alloc.h",
     "include/grpc/impl/codegen/atm.h",
     "include/grpc/impl/codegen/atm_gcc_atomic.h",
@@ -1002,60 +963,29 @@
     "include/grpc/impl/codegen/sync_posix.h",
     "include/grpc/impl/codegen/sync_win32.h",
     "include/grpc/impl/codegen/time.h",
-    "include/grpc/impl/codegen/byte_buffer.h",
-    "include/grpc/impl/codegen/compression_types.h",
-    "include/grpc/impl/codegen/connectivity_state.h",
-    "include/grpc/impl/codegen/grpc_types.h",
-    "include/grpc/impl/codegen/propagation_bits.h",
-    "include/grpc/impl/codegen/status.h",
-    "include/grpc++/impl/codegen/async_stream.h",
-    "include/grpc++/impl/codegen/async_unary_call.h",
-    "include/grpc++/impl/codegen/call.h",
-    "include/grpc++/impl/codegen/call_hook.h",
-    "include/grpc++/impl/codegen/channel_interface.h",
-    "include/grpc++/impl/codegen/client_context.h",
-    "include/grpc++/impl/codegen/client_unary_call.h",
-    "include/grpc++/impl/codegen/completion_queue.h",
-    "include/grpc++/impl/codegen/completion_queue_tag.h",
     "include/grpc++/impl/codegen/config.h",
     "include/grpc++/impl/codegen/config_protobuf.h",
-    "include/grpc++/impl/codegen/core_codegen_interface.h",
-    "include/grpc++/impl/codegen/grpc_library.h",
-    "include/grpc++/impl/codegen/method_handler_impl.h",
-    "include/grpc++/impl/codegen/proto_utils.h",
-    "include/grpc++/impl/codegen/rpc_method.h",
-    "include/grpc++/impl/codegen/rpc_service_method.h",
-    "include/grpc++/impl/codegen/security/auth_context.h",
-    "include/grpc++/impl/codegen/serialization_traits.h",
-    "include/grpc++/impl/codegen/server_context.h",
-    "include/grpc++/impl/codegen/server_interface.h",
-    "include/grpc++/impl/codegen/service_type.h",
-    "include/grpc++/impl/codegen/status.h",
-    "include/grpc++/impl/codegen/status_code_enum.h",
-    "include/grpc++/impl/codegen/string_ref.h",
-    "include/grpc++/impl/codegen/stub_options.h",
-    "include/grpc++/impl/codegen/sync.h",
-    "include/grpc++/impl/codegen/sync_cxx11.h",
-    "include/grpc++/impl/codegen/sync_no_cxx11.h",
-    "include/grpc++/impl/codegen/sync_stream.h",
-    "include/grpc++/impl/codegen/time.h",
+    "include/grpc++/support/config.h",
+    "include/grpc++/support/config_protobuf.h",
   ],
   includes = [
     "include",
     ".",
   ],
   deps = [
-    "//external:protobuf_compiler",
+    "//external:libssl",
+    "//external:protobuf_clib",
+    ":grpc",
   ],
 )
 
 
+
 cc_library(
   name = "grpc++_unsecure",
   srcs = [
     "src/cpp/client/create_channel_internal.h",
     "src/cpp/common/core_codegen.h",
-    "src/cpp/common/create_auth_context.h",
     "src/cpp/server/dynamic_thread_pool.h",
     "src/cpp/server/thread_pool_interface.h",
     "src/cpp/common/insecure_create_auth_context.cc",
@@ -1121,8 +1051,6 @@
     "include/grpc++/support/async_unary_call.h",
     "include/grpc++/support/byte_buffer.h",
     "include/grpc++/support/channel_arguments.h",
-    "include/grpc++/support/config.h",
-    "include/grpc++/support/config_protobuf.h",
     "include/grpc++/support/slice.h",
     "include/grpc++/support/status.h",
     "include/grpc++/support/status_code_enum.h",
@@ -1139,9 +1067,8 @@
     "include/grpc++/impl/codegen/client_unary_call.h",
     "include/grpc++/impl/codegen/completion_queue.h",
     "include/grpc++/impl/codegen/completion_queue_tag.h",
-    "include/grpc++/impl/codegen/config.h",
-    "include/grpc++/impl/codegen/config_protobuf.h",
     "include/grpc++/impl/codegen/core_codegen_interface.h",
+    "include/grpc++/impl/codegen/create_auth_context.h",
     "include/grpc++/impl/codegen/grpc_library.h",
     "include/grpc++/impl/codegen/method_handler_impl.h",
     "include/grpc++/impl/codegen/proto_utils.h",
@@ -1161,44 +1088,12 @@
     "include/grpc++/impl/codegen/sync_no_cxx11.h",
     "include/grpc++/impl/codegen/sync_stream.h",
     "include/grpc++/impl/codegen/time.h",
-  ],
-  includes = [
-    "include",
-    ".",
-  ],
-  deps = [
-    "//external:protobuf_clib",
-    ":gpr",
-    ":grpc_unsecure",
-  ],
-)
-
-
-cc_library(
-  name = "grpc_plugin_support",
-  srcs = [
-    "include/grpc++/support/config.h",
-    "include/grpc++/support/config_protobuf.h",
-    "src/compiler/config.h",
-    "src/compiler/cpp_generator.h",
-    "src/compiler/cpp_generator_helpers.h",
-    "src/compiler/csharp_generator.h",
-    "src/compiler/csharp_generator_helpers.h",
-    "src/compiler/generator_helpers.h",
-    "src/compiler/objective_c_generator.h",
-    "src/compiler/objective_c_generator_helpers.h",
-    "src/compiler/python_generator.h",
-    "src/compiler/ruby_generator.h",
-    "src/compiler/ruby_generator_helpers-inl.h",
-    "src/compiler/ruby_generator_map-inl.h",
-    "src/compiler/ruby_generator_string-inl.h",
-    "src/compiler/cpp_generator.cc",
-    "src/compiler/csharp_generator.cc",
-    "src/compiler/objective_c_generator.cc",
-    "src/compiler/python_generator.cc",
-    "src/compiler/ruby_generator.cc",
-  ],
-  hdrs = [
+    "include/grpc/impl/codegen/byte_buffer.h",
+    "include/grpc/impl/codegen/compression_types.h",
+    "include/grpc/impl/codegen/connectivity_state.h",
+    "include/grpc/impl/codegen/grpc_types.h",
+    "include/grpc/impl/codegen/propagation_bits.h",
+    "include/grpc/impl/codegen/status.h",
     "include/grpc/impl/codegen/alloc.h",
     "include/grpc/impl/codegen/atm.h",
     "include/grpc/impl/codegen/atm_gcc_atomic.h",
@@ -1213,6 +1108,55 @@
     "include/grpc/impl/codegen/sync_posix.h",
     "include/grpc/impl/codegen/sync_win32.h",
     "include/grpc/impl/codegen/time.h",
+    "include/grpc++/impl/codegen/config.h",
+    "include/grpc++/impl/codegen/config_protobuf.h",
+    "include/grpc++/support/config.h",
+    "include/grpc++/support/config_protobuf.h",
+  ],
+  includes = [
+    "include",
+    ".",
+  ],
+  deps = [
+    "//external:protobuf_clib",
+    ":gpr",
+    ":grpc_unsecure",
+    ":grpc",
+  ],
+)
+
+
+
+cc_library(
+  name = "grpc_plugin_support",
+  srcs = [
+    "src/compiler/config.h",
+    "src/compiler/cpp_generator.h",
+    "src/compiler/cpp_generator_helpers.h",
+    "src/compiler/csharp_generator.h",
+    "src/compiler/csharp_generator_helpers.h",
+    "src/compiler/generator_helpers.h",
+    "src/compiler/node_generator.h",
+    "src/compiler/node_generator_helpers.h",
+    "src/compiler/objective_c_generator.h",
+    "src/compiler/objective_c_generator_helpers.h",
+    "src/compiler/python_generator.h",
+    "src/compiler/ruby_generator.h",
+    "src/compiler/ruby_generator_helpers-inl.h",
+    "src/compiler/ruby_generator_map-inl.h",
+    "src/compiler/ruby_generator_string-inl.h",
+    "src/compiler/cpp_generator.cc",
+    "src/compiler/csharp_generator.cc",
+    "src/compiler/node_generator.cc",
+    "src/compiler/objective_c_generator.cc",
+    "src/compiler/python_generator.cc",
+    "src/compiler/ruby_generator.cc",
+  ],
+  hdrs = [
+    "include/grpc++/support/config.h",
+    "include/grpc++/support/config_protobuf.h",
+    "include/grpc++/impl/codegen/config.h",
+    "include/grpc++/impl/codegen/config_protobuf.h",
   ],
   includes = [
     "include",
@@ -1220,11 +1164,11 @@
   ],
   deps = [
     "//external:protobuf_compiler",
-    ":grpc++_codegen_lib",
   ],
 )
 
 
+
 cc_library(
   name = "grpc_csharp_ext",
   srcs = [
@@ -1244,53 +1188,54 @@
 
 
 
+
 objc_library(
   name = "gpr_objc",
   srcs = [
-    "src/core/profiling/basic_timers.c",
-    "src/core/profiling/stap_timers.c",
-    "src/core/support/alloc.c",
-    "src/core/support/avl.c",
-    "src/core/support/backoff.c",
-    "src/core/support/cmdline.c",
-    "src/core/support/cpu_iphone.c",
-    "src/core/support/cpu_linux.c",
-    "src/core/support/cpu_posix.c",
-    "src/core/support/cpu_windows.c",
-    "src/core/support/env_linux.c",
-    "src/core/support/env_posix.c",
-    "src/core/support/env_win32.c",
-    "src/core/support/histogram.c",
-    "src/core/support/host_port.c",
-    "src/core/support/load_file.c",
-    "src/core/support/log.c",
-    "src/core/support/log_android.c",
-    "src/core/support/log_linux.c",
-    "src/core/support/log_posix.c",
-    "src/core/support/log_win32.c",
-    "src/core/support/murmur_hash.c",
-    "src/core/support/slice.c",
-    "src/core/support/slice_buffer.c",
-    "src/core/support/stack_lockfree.c",
-    "src/core/support/string.c",
-    "src/core/support/string_posix.c",
-    "src/core/support/string_win32.c",
-    "src/core/support/subprocess_posix.c",
-    "src/core/support/subprocess_windows.c",
-    "src/core/support/sync.c",
-    "src/core/support/sync_posix.c",
-    "src/core/support/sync_win32.c",
-    "src/core/support/thd.c",
-    "src/core/support/thd_posix.c",
-    "src/core/support/thd_win32.c",
-    "src/core/support/time.c",
-    "src/core/support/time_posix.c",
-    "src/core/support/time_precise.c",
-    "src/core/support/time_win32.c",
-    "src/core/support/tls_pthread.c",
-    "src/core/support/tmpfile_posix.c",
-    "src/core/support/tmpfile_win32.c",
-    "src/core/support/wrap_memcpy.c",
+    "src/core/lib/profiling/basic_timers.c",
+    "src/core/lib/profiling/stap_timers.c",
+    "src/core/lib/support/alloc.c",
+    "src/core/lib/support/avl.c",
+    "src/core/lib/support/backoff.c",
+    "src/core/lib/support/cmdline.c",
+    "src/core/lib/support/cpu_iphone.c",
+    "src/core/lib/support/cpu_linux.c",
+    "src/core/lib/support/cpu_posix.c",
+    "src/core/lib/support/cpu_windows.c",
+    "src/core/lib/support/env_linux.c",
+    "src/core/lib/support/env_posix.c",
+    "src/core/lib/support/env_win32.c",
+    "src/core/lib/support/histogram.c",
+    "src/core/lib/support/host_port.c",
+    "src/core/lib/support/load_file.c",
+    "src/core/lib/support/log.c",
+    "src/core/lib/support/log_android.c",
+    "src/core/lib/support/log_linux.c",
+    "src/core/lib/support/log_posix.c",
+    "src/core/lib/support/log_win32.c",
+    "src/core/lib/support/murmur_hash.c",
+    "src/core/lib/support/slice.c",
+    "src/core/lib/support/slice_buffer.c",
+    "src/core/lib/support/stack_lockfree.c",
+    "src/core/lib/support/string.c",
+    "src/core/lib/support/string_posix.c",
+    "src/core/lib/support/string_win32.c",
+    "src/core/lib/support/subprocess_posix.c",
+    "src/core/lib/support/subprocess_windows.c",
+    "src/core/lib/support/sync.c",
+    "src/core/lib/support/sync_posix.c",
+    "src/core/lib/support/sync_win32.c",
+    "src/core/lib/support/thd.c",
+    "src/core/lib/support/thd_posix.c",
+    "src/core/lib/support/thd_win32.c",
+    "src/core/lib/support/time.c",
+    "src/core/lib/support/time_posix.c",
+    "src/core/lib/support/time_precise.c",
+    "src/core/lib/support/time_win32.c",
+    "src/core/lib/support/tls_pthread.c",
+    "src/core/lib/support/tmpfile_posix.c",
+    "src/core/lib/support/tmpfile_win32.c",
+    "src/core/lib/support/wrap_memcpy.c",
   ],
   hdrs = [
     "include/grpc/support/alloc.h",
@@ -1335,18 +1280,18 @@
     "include/grpc/impl/codegen/sync_posix.h",
     "include/grpc/impl/codegen/sync_win32.h",
     "include/grpc/impl/codegen/time.h",
-    "src/core/profiling/timers.h",
-    "src/core/support/backoff.h",
-    "src/core/support/block_annotate.h",
-    "src/core/support/env.h",
-    "src/core/support/load_file.h",
-    "src/core/support/murmur_hash.h",
-    "src/core/support/stack_lockfree.h",
-    "src/core/support/string.h",
-    "src/core/support/string_win32.h",
-    "src/core/support/thd_internal.h",
-    "src/core/support/time_precise.h",
-    "src/core/support/tmpfile.h",
+    "src/core/lib/profiling/timers.h",
+    "src/core/lib/support/backoff.h",
+    "src/core/lib/support/block_annotate.h",
+    "src/core/lib/support/env.h",
+    "src/core/lib/support/load_file.h",
+    "src/core/lib/support/murmur_hash.h",
+    "src/core/lib/support/stack_lockfree.h",
+    "src/core/lib/support/string.h",
+    "src/core/lib/support/string_win32.h",
+    "src/core/lib/support/thd_internal.h",
+    "src/core/lib/support/time_precise.h",
+    "src/core/lib/support/tmpfile.h",
   ],
   includes = [
     "include",
@@ -1357,175 +1302,174 @@
 )
 
 
+
 objc_library(
   name = "grpc_objc",
   srcs = [
-    "src/core/census/grpc_context.c",
-    "src/core/census/grpc_filter.c",
-    "src/core/census/grpc_plugin.c",
-    "src/core/channel/channel_args.c",
-    "src/core/channel/channel_stack.c",
-    "src/core/channel/channel_stack_builder.c",
-    "src/core/channel/client_channel.c",
-    "src/core/channel/client_uchannel.c",
-    "src/core/channel/compress_filter.c",
-    "src/core/channel/connected_channel.c",
-    "src/core/channel/http_client_filter.c",
-    "src/core/channel/http_server_filter.c",
-    "src/core/channel/subchannel_call_holder.c",
-    "src/core/client_config/client_config.c",
-    "src/core/client_config/connector.c",
-    "src/core/client_config/default_initial_connect_string.c",
-    "src/core/client_config/initial_connect_string.c",
-    "src/core/client_config/lb_policies/load_balancer_api.c",
-    "src/core/client_config/lb_policies/pick_first.c",
-    "src/core/client_config/lb_policies/round_robin.c",
-    "src/core/client_config/lb_policy.c",
-    "src/core/client_config/lb_policy_factory.c",
-    "src/core/client_config/lb_policy_registry.c",
-    "src/core/client_config/resolver.c",
-    "src/core/client_config/resolver_factory.c",
-    "src/core/client_config/resolver_registry.c",
-    "src/core/client_config/resolvers/dns_resolver.c",
-    "src/core/client_config/resolvers/sockaddr_resolver.c",
-    "src/core/client_config/subchannel.c",
-    "src/core/client_config/subchannel_factory.c",
-    "src/core/client_config/subchannel_index.c",
-    "src/core/client_config/uri_parser.c",
-    "src/core/compression/compression_algorithm.c",
-    "src/core/compression/message_compress.c",
-    "src/core/debug/trace.c",
-    "src/core/httpcli/format_request.c",
-    "src/core/httpcli/httpcli.c",
-    "src/core/httpcli/parser.c",
-    "src/core/iomgr/closure.c",
-    "src/core/iomgr/endpoint.c",
-    "src/core/iomgr/endpoint_pair_posix.c",
-    "src/core/iomgr/endpoint_pair_windows.c",
-    "src/core/iomgr/exec_ctx.c",
-    "src/core/iomgr/executor.c",
-    "src/core/iomgr/fd_posix.c",
-    "src/core/iomgr/iocp_windows.c",
-    "src/core/iomgr/iomgr.c",
-    "src/core/iomgr/iomgr_posix.c",
-    "src/core/iomgr/iomgr_windows.c",
-    "src/core/iomgr/pollset_multipoller_with_epoll.c",
-    "src/core/iomgr/pollset_multipoller_with_poll_posix.c",
-    "src/core/iomgr/pollset_posix.c",
-    "src/core/iomgr/pollset_set_posix.c",
-    "src/core/iomgr/pollset_set_windows.c",
-    "src/core/iomgr/pollset_windows.c",
-    "src/core/iomgr/resolve_address_posix.c",
-    "src/core/iomgr/resolve_address_windows.c",
-    "src/core/iomgr/sockaddr_utils.c",
-    "src/core/iomgr/socket_utils_common_posix.c",
-    "src/core/iomgr/socket_utils_linux.c",
-    "src/core/iomgr/socket_utils_posix.c",
-    "src/core/iomgr/socket_windows.c",
-    "src/core/iomgr/tcp_client_posix.c",
-    "src/core/iomgr/tcp_client_windows.c",
-    "src/core/iomgr/tcp_posix.c",
-    "src/core/iomgr/tcp_server_posix.c",
-    "src/core/iomgr/tcp_server_windows.c",
-    "src/core/iomgr/tcp_windows.c",
-    "src/core/iomgr/time_averaged_stats.c",
-    "src/core/iomgr/timer.c",
-    "src/core/iomgr/timer_heap.c",
-    "src/core/iomgr/udp_server.c",
-    "src/core/iomgr/wakeup_fd_eventfd.c",
-    "src/core/iomgr/wakeup_fd_nospecial.c",
-    "src/core/iomgr/wakeup_fd_pipe.c",
-    "src/core/iomgr/wakeup_fd_posix.c",
-    "src/core/iomgr/workqueue_posix.c",
-    "src/core/iomgr/workqueue_windows.c",
-    "src/core/json/json.c",
-    "src/core/json/json_reader.c",
-    "src/core/json/json_string.c",
-    "src/core/json/json_writer.c",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
-    "src/core/surface/alarm.c",
-    "src/core/surface/api_trace.c",
-    "src/core/surface/byte_buffer.c",
-    "src/core/surface/byte_buffer_reader.c",
-    "src/core/surface/call.c",
-    "src/core/surface/call_details.c",
-    "src/core/surface/call_log_batch.c",
-    "src/core/surface/channel.c",
-    "src/core/surface/channel_connectivity.c",
-    "src/core/surface/channel_create.c",
-    "src/core/surface/channel_init.c",
-    "src/core/surface/channel_ping.c",
-    "src/core/surface/channel_stack_type.c",
-    "src/core/surface/completion_queue.c",
-    "src/core/surface/event_string.c",
-    "src/core/surface/init.c",
-    "src/core/surface/lame_client.c",
-    "src/core/surface/metadata_array.c",
-    "src/core/surface/server.c",
-    "src/core/surface/server_chttp2.c",
-    "src/core/surface/validate_metadata.c",
-    "src/core/surface/version.c",
-    "src/core/transport/byte_stream.c",
-    "src/core/transport/chttp2/alpn.c",
-    "src/core/transport/chttp2/bin_encoder.c",
-    "src/core/transport/chttp2/frame_data.c",
-    "src/core/transport/chttp2/frame_goaway.c",
-    "src/core/transport/chttp2/frame_ping.c",
-    "src/core/transport/chttp2/frame_rst_stream.c",
-    "src/core/transport/chttp2/frame_settings.c",
-    "src/core/transport/chttp2/frame_window_update.c",
-    "src/core/transport/chttp2/hpack_encoder.c",
-    "src/core/transport/chttp2/hpack_parser.c",
-    "src/core/transport/chttp2/hpack_table.c",
-    "src/core/transport/chttp2/huffsyms.c",
-    "src/core/transport/chttp2/incoming_metadata.c",
-    "src/core/transport/chttp2/parsing.c",
-    "src/core/transport/chttp2/status_conversion.c",
-    "src/core/transport/chttp2/stream_lists.c",
-    "src/core/transport/chttp2/stream_map.c",
-    "src/core/transport/chttp2/timeout_encoding.c",
-    "src/core/transport/chttp2/varint.c",
-    "src/core/transport/chttp2/writing.c",
-    "src/core/transport/chttp2_transport.c",
-    "src/core/transport/connectivity_state.c",
-    "src/core/transport/metadata.c",
-    "src/core/transport/metadata_batch.c",
-    "src/core/transport/static_metadata.c",
-    "src/core/transport/transport.c",
-    "src/core/transport/transport_op_string.c",
-    "src/core/httpcli/httpcli_security_connector.c",
-    "src/core/security/b64.c",
-    "src/core/security/client_auth_filter.c",
-    "src/core/security/credentials.c",
-    "src/core/security/credentials_metadata.c",
-    "src/core/security/credentials_posix.c",
-    "src/core/security/credentials_win32.c",
-    "src/core/security/google_default_credentials.c",
-    "src/core/security/handshake.c",
-    "src/core/security/json_token.c",
-    "src/core/security/jwt_verifier.c",
-    "src/core/security/secure_endpoint.c",
-    "src/core/security/security_connector.c",
-    "src/core/security/security_context.c",
-    "src/core/security/server_auth_filter.c",
-    "src/core/security/server_secure_chttp2.c",
-    "src/core/surface/init_secure.c",
-    "src/core/surface/secure_channel_create.c",
-    "src/core/tsi/fake_transport_security.c",
-    "src/core/tsi/ssl_transport_security.c",
-    "src/core/tsi/transport_security.c",
-    "src/core/census/context.c",
-    "src/core/census/initialize.c",
-    "src/core/census/mlog.c",
-    "src/core/census/operation.c",
-    "src/core/census/placeholders.c",
-    "src/core/census/tracing.c",
-    "third_party/nanopb/pb_common.c",
-    "third_party/nanopb/pb_decode.c",
-    "third_party/nanopb/pb_encode.c",
+    "src/core/lib/surface/init.c",
+    "src/core/lib/channel/channel_args.c",
+    "src/core/lib/channel/channel_stack.c",
+    "src/core/lib/channel/channel_stack_builder.c",
+    "src/core/lib/channel/compress_filter.c",
+    "src/core/lib/channel/connected_channel.c",
+    "src/core/lib/channel/http_client_filter.c",
+    "src/core/lib/channel/http_server_filter.c",
+    "src/core/lib/compression/compression_algorithm.c",
+    "src/core/lib/compression/message_compress.c",
+    "src/core/lib/debug/trace.c",
+    "src/core/lib/http/format_request.c",
+    "src/core/lib/http/httpcli.c",
+    "src/core/lib/http/parser.c",
+    "src/core/lib/iomgr/closure.c",
+    "src/core/lib/iomgr/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_posix.c",
+    "src/core/lib/iomgr/exec_ctx.c",
+    "src/core/lib/iomgr/executor.c",
+    "src/core/lib/iomgr/iocp_windows.c",
+    "src/core/lib/iomgr/iomgr.c",
+    "src/core/lib/iomgr/iomgr_posix.c",
+    "src/core/lib/iomgr/iomgr_windows.c",
+    "src/core/lib/iomgr/pollset_set_windows.c",
+    "src/core/lib/iomgr/pollset_windows.c",
+    "src/core/lib/iomgr/resolve_address_posix.c",
+    "src/core/lib/iomgr/resolve_address_windows.c",
+    "src/core/lib/iomgr/sockaddr_utils.c",
+    "src/core/lib/iomgr/socket_utils_common_posix.c",
+    "src/core/lib/iomgr/socket_utils_linux.c",
+    "src/core/lib/iomgr/socket_utils_posix.c",
+    "src/core/lib/iomgr/socket_windows.c",
+    "src/core/lib/iomgr/tcp_client_posix.c",
+    "src/core/lib/iomgr/tcp_client_windows.c",
+    "src/core/lib/iomgr/tcp_posix.c",
+    "src/core/lib/iomgr/tcp_server_posix.c",
+    "src/core/lib/iomgr/tcp_server_windows.c",
+    "src/core/lib/iomgr/tcp_windows.c",
+    "src/core/lib/iomgr/time_averaged_stats.c",
+    "src/core/lib/iomgr/timer.c",
+    "src/core/lib/iomgr/timer_heap.c",
+    "src/core/lib/iomgr/udp_server.c",
+    "src/core/lib/iomgr/unix_sockets_posix.c",
+    "src/core/lib/iomgr/unix_sockets_posix_noop.c",
+    "src/core/lib/iomgr/wakeup_fd_eventfd.c",
+    "src/core/lib/iomgr/wakeup_fd_nospecial.c",
+    "src/core/lib/iomgr/wakeup_fd_pipe.c",
+    "src/core/lib/iomgr/wakeup_fd_posix.c",
+    "src/core/lib/iomgr/workqueue_posix.c",
+    "src/core/lib/iomgr/workqueue_windows.c",
+    "src/core/lib/json/json.c",
+    "src/core/lib/json/json_reader.c",
+    "src/core/lib/json/json_string.c",
+    "src/core/lib/json/json_writer.c",
+    "src/core/lib/surface/alarm.c",
+    "src/core/lib/surface/api_trace.c",
+    "src/core/lib/surface/byte_buffer.c",
+    "src/core/lib/surface/byte_buffer_reader.c",
+    "src/core/lib/surface/call.c",
+    "src/core/lib/surface/call_details.c",
+    "src/core/lib/surface/call_log_batch.c",
+    "src/core/lib/surface/channel.c",
+    "src/core/lib/surface/channel_init.c",
+    "src/core/lib/surface/channel_ping.c",
+    "src/core/lib/surface/channel_stack_type.c",
+    "src/core/lib/surface/completion_queue.c",
+    "src/core/lib/surface/event_string.c",
+    "src/core/lib/surface/lame_client.c",
+    "src/core/lib/surface/metadata_array.c",
+    "src/core/lib/surface/server.c",
+    "src/core/lib/surface/validate_metadata.c",
+    "src/core/lib/surface/version.c",
+    "src/core/lib/transport/byte_stream.c",
+    "src/core/lib/transport/connectivity_state.c",
+    "src/core/lib/transport/metadata.c",
+    "src/core/lib/transport/metadata_batch.c",
+    "src/core/lib/transport/static_metadata.c",
+    "src/core/lib/transport/transport.c",
+    "src/core/lib/transport/transport_op_string.c",
+    "src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c",
+    "src/core/ext/transport/chttp2/transport/bin_encoder.c",
+    "src/core/ext/transport/chttp2/transport/chttp2_plugin.c",
+    "src/core/ext/transport/chttp2/transport/chttp2_transport.c",
+    "src/core/ext/transport/chttp2/transport/frame_data.c",
+    "src/core/ext/transport/chttp2/transport/frame_goaway.c",
+    "src/core/ext/transport/chttp2/transport/frame_ping.c",
+    "src/core/ext/transport/chttp2/transport/frame_rst_stream.c",
+    "src/core/ext/transport/chttp2/transport/frame_settings.c",
+    "src/core/ext/transport/chttp2/transport/frame_window_update.c",
+    "src/core/ext/transport/chttp2/transport/hpack_encoder.c",
+    "src/core/ext/transport/chttp2/transport/hpack_parser.c",
+    "src/core/ext/transport/chttp2/transport/hpack_table.c",
+    "src/core/ext/transport/chttp2/transport/huffsyms.c",
+    "src/core/ext/transport/chttp2/transport/incoming_metadata.c",
+    "src/core/ext/transport/chttp2/transport/parsing.c",
+    "src/core/ext/transport/chttp2/transport/status_conversion.c",
+    "src/core/ext/transport/chttp2/transport/stream_lists.c",
+    "src/core/ext/transport/chttp2/transport/stream_map.c",
+    "src/core/ext/transport/chttp2/transport/timeout_encoding.c",
+    "src/core/ext/transport/chttp2/transport/varint.c",
+    "src/core/ext/transport/chttp2/transport/writing.c",
+    "src/core/ext/transport/chttp2/alpn/alpn.c",
+    "src/core/lib/http/httpcli_security_connector.c",
+    "src/core/lib/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/surface/init_secure.c",
+    "src/core/lib/tsi/fake_transport_security.c",
+    "src/core/lib/tsi/ssl_transport_security.c",
+    "src/core/lib/tsi/transport_security.c",
+    "src/core/ext/transport/chttp2/client/secure/secure_channel_create.c",
+    "src/core/ext/client_config/channel_connectivity.c",
+    "src/core/ext/client_config/client_channel.c",
+    "src/core/ext/client_config/client_channel_factory.c",
+    "src/core/ext/client_config/client_config.c",
+    "src/core/ext/client_config/client_config_plugin.c",
+    "src/core/ext/client_config/connector.c",
+    "src/core/ext/client_config/default_initial_connect_string.c",
+    "src/core/ext/client_config/initial_connect_string.c",
+    "src/core/ext/client_config/lb_policy.c",
+    "src/core/ext/client_config/lb_policy_factory.c",
+    "src/core/ext/client_config/lb_policy_registry.c",
+    "src/core/ext/client_config/parse_address.c",
+    "src/core/ext/client_config/resolver.c",
+    "src/core/ext/client_config/resolver_factory.c",
+    "src/core/ext/client_config/resolver_registry.c",
+    "src/core/ext/client_config/subchannel.c",
+    "src/core/ext/client_config/subchannel_call_holder.c",
+    "src/core/ext/client_config/subchannel_index.c",
+    "src/core/ext/client_config/uri_parser.c",
+    "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c",
+    "src/core/ext/transport/chttp2/client/insecure/channel_create.c",
+    "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
+    "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c",
+    "src/core/ext/lb_policy/pick_first/pick_first.c",
+    "src/core/ext/lb_policy/round_robin/round_robin.c",
+    "src/core/ext/resolver/dns/native/dns_resolver.c",
+    "src/core/ext/resolver/sockaddr/sockaddr_resolver.c",
+    "src/core/ext/census/context.c",
+    "src/core/ext/census/grpc_context.c",
+    "src/core/ext/census/grpc_filter.c",
+    "src/core/ext/census/grpc_plugin.c",
+    "src/core/ext/census/initialize.c",
+    "src/core/ext/census/mlog.c",
+    "src/core/ext/census/operation.c",
+    "src/core/ext/census/placeholders.c",
+    "src/core/ext/census/tracing.c",
+    "src/core/plugin_registry/grpc_plugin_registry.c",
   ],
   hdrs = [
-    "include/grpc/grpc_security.h",
     "include/grpc/byte_buffer.h",
     "include/grpc/byte_buffer_reader.h",
     "include/grpc/compression.h",
@@ -1537,148 +1481,155 @@
     "include/grpc/impl/codegen/grpc_types.h",
     "include/grpc/impl/codegen/propagation_bits.h",
     "include/grpc/impl/codegen/status.h",
+    "include/grpc/impl/codegen/alloc.h",
+    "include/grpc/impl/codegen/atm.h",
+    "include/grpc/impl/codegen/atm_gcc_atomic.h",
+    "include/grpc/impl/codegen/atm_gcc_sync.h",
+    "include/grpc/impl/codegen/atm_win32.h",
+    "include/grpc/impl/codegen/log.h",
+    "include/grpc/impl/codegen/port_platform.h",
+    "include/grpc/impl/codegen/slice.h",
+    "include/grpc/impl/codegen/slice_buffer.h",
+    "include/grpc/impl/codegen/sync.h",
+    "include/grpc/impl/codegen/sync_generic.h",
+    "include/grpc/impl/codegen/sync_posix.h",
+    "include/grpc/impl/codegen/sync_win32.h",
+    "include/grpc/impl/codegen/time.h",
+    "include/grpc/grpc_security.h",
+    "include/grpc/grpc_security_constants.h",
     "include/grpc/census.h",
-    "src/core/census/grpc_filter.h",
-    "src/core/census/grpc_plugin.h",
-    "src/core/channel/channel_args.h",
-    "src/core/channel/channel_stack.h",
-    "src/core/channel/channel_stack_builder.h",
-    "src/core/channel/client_channel.h",
-    "src/core/channel/client_uchannel.h",
-    "src/core/channel/compress_filter.h",
-    "src/core/channel/connected_channel.h",
-    "src/core/channel/context.h",
-    "src/core/channel/http_client_filter.h",
-    "src/core/channel/http_server_filter.h",
-    "src/core/channel/subchannel_call_holder.h",
-    "src/core/client_config/client_config.h",
-    "src/core/client_config/connector.h",
-    "src/core/client_config/initial_connect_string.h",
-    "src/core/client_config/lb_policies/load_balancer_api.h",
-    "src/core/client_config/lb_policies/pick_first.h",
-    "src/core/client_config/lb_policies/round_robin.h",
-    "src/core/client_config/lb_policy.h",
-    "src/core/client_config/lb_policy_factory.h",
-    "src/core/client_config/lb_policy_registry.h",
-    "src/core/client_config/resolver.h",
-    "src/core/client_config/resolver_factory.h",
-    "src/core/client_config/resolver_registry.h",
-    "src/core/client_config/resolvers/dns_resolver.h",
-    "src/core/client_config/resolvers/sockaddr_resolver.h",
-    "src/core/client_config/subchannel.h",
-    "src/core/client_config/subchannel_factory.h",
-    "src/core/client_config/subchannel_index.h",
-    "src/core/client_config/uri_parser.h",
-    "src/core/compression/algorithm_metadata.h",
-    "src/core/compression/message_compress.h",
-    "src/core/debug/trace.h",
-    "src/core/httpcli/format_request.h",
-    "src/core/httpcli/httpcli.h",
-    "src/core/httpcli/parser.h",
-    "src/core/iomgr/closure.h",
-    "src/core/iomgr/endpoint.h",
-    "src/core/iomgr/endpoint_pair.h",
-    "src/core/iomgr/exec_ctx.h",
-    "src/core/iomgr/executor.h",
-    "src/core/iomgr/fd_posix.h",
-    "src/core/iomgr/iocp_windows.h",
-    "src/core/iomgr/iomgr.h",
-    "src/core/iomgr/iomgr_internal.h",
-    "src/core/iomgr/iomgr_posix.h",
-    "src/core/iomgr/pollset.h",
-    "src/core/iomgr/pollset_posix.h",
-    "src/core/iomgr/pollset_set.h",
-    "src/core/iomgr/pollset_set_posix.h",
-    "src/core/iomgr/pollset_set_windows.h",
-    "src/core/iomgr/pollset_windows.h",
-    "src/core/iomgr/resolve_address.h",
-    "src/core/iomgr/sockaddr.h",
-    "src/core/iomgr/sockaddr_posix.h",
-    "src/core/iomgr/sockaddr_utils.h",
-    "src/core/iomgr/sockaddr_win32.h",
-    "src/core/iomgr/socket_utils_posix.h",
-    "src/core/iomgr/socket_windows.h",
-    "src/core/iomgr/tcp_client.h",
-    "src/core/iomgr/tcp_posix.h",
-    "src/core/iomgr/tcp_server.h",
-    "src/core/iomgr/tcp_windows.h",
-    "src/core/iomgr/time_averaged_stats.h",
-    "src/core/iomgr/timer.h",
-    "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/udp_server.h",
-    "src/core/iomgr/wakeup_fd_pipe.h",
-    "src/core/iomgr/wakeup_fd_posix.h",
-    "src/core/iomgr/workqueue.h",
-    "src/core/iomgr/workqueue_posix.h",
-    "src/core/iomgr/workqueue_windows.h",
-    "src/core/json/json.h",
-    "src/core/json/json_common.h",
-    "src/core/json/json_reader.h",
-    "src/core/json/json_writer.h",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
-    "src/core/statistics/census_interface.h",
-    "src/core/statistics/census_rpc_stats.h",
-    "src/core/surface/api_trace.h",
-    "src/core/surface/call.h",
-    "src/core/surface/call_test_only.h",
-    "src/core/surface/channel.h",
-    "src/core/surface/channel_init.h",
-    "src/core/surface/channel_stack_type.h",
-    "src/core/surface/completion_queue.h",
-    "src/core/surface/event_string.h",
-    "src/core/surface/init.h",
-    "src/core/surface/lame_client.h",
-    "src/core/surface/server.h",
-    "src/core/surface/surface_trace.h",
-    "src/core/transport/byte_stream.h",
-    "src/core/transport/chttp2/alpn.h",
-    "src/core/transport/chttp2/bin_encoder.h",
-    "src/core/transport/chttp2/frame.h",
-    "src/core/transport/chttp2/frame_data.h",
-    "src/core/transport/chttp2/frame_goaway.h",
-    "src/core/transport/chttp2/frame_ping.h",
-    "src/core/transport/chttp2/frame_rst_stream.h",
-    "src/core/transport/chttp2/frame_settings.h",
-    "src/core/transport/chttp2/frame_window_update.h",
-    "src/core/transport/chttp2/hpack_encoder.h",
-    "src/core/transport/chttp2/hpack_parser.h",
-    "src/core/transport/chttp2/hpack_table.h",
-    "src/core/transport/chttp2/http2_errors.h",
-    "src/core/transport/chttp2/huffsyms.h",
-    "src/core/transport/chttp2/incoming_metadata.h",
-    "src/core/transport/chttp2/internal.h",
-    "src/core/transport/chttp2/status_conversion.h",
-    "src/core/transport/chttp2/stream_map.h",
-    "src/core/transport/chttp2/timeout_encoding.h",
-    "src/core/transport/chttp2/varint.h",
-    "src/core/transport/chttp2_transport.h",
-    "src/core/transport/connectivity_state.h",
-    "src/core/transport/metadata.h",
-    "src/core/transport/metadata_batch.h",
-    "src/core/transport/static_metadata.h",
-    "src/core/transport/transport.h",
-    "src/core/transport/transport_impl.h",
-    "src/core/security/auth_filters.h",
-    "src/core/security/b64.h",
-    "src/core/security/credentials.h",
-    "src/core/security/handshake.h",
-    "src/core/security/json_token.h",
-    "src/core/security/jwt_verifier.h",
-    "src/core/security/secure_endpoint.h",
-    "src/core/security/security_connector.h",
-    "src/core/security/security_context.h",
-    "src/core/tsi/fake_transport_security.h",
-    "src/core/tsi/ssl_transport_security.h",
-    "src/core/tsi/ssl_types.h",
-    "src/core/tsi/transport_security.h",
-    "src/core/tsi/transport_security_interface.h",
-    "src/core/census/aggregation.h",
-    "src/core/census/mlog.h",
-    "src/core/census/rpc_metric_id.h",
-    "third_party/nanopb/pb.h",
-    "third_party/nanopb/pb_common.h",
-    "third_party/nanopb/pb_decode.h",
-    "third_party/nanopb/pb_encode.h",
+    "src/core/lib/channel/channel_args.h",
+    "src/core/lib/channel/channel_stack.h",
+    "src/core/lib/channel/channel_stack_builder.h",
+    "src/core/lib/channel/compress_filter.h",
+    "src/core/lib/channel/connected_channel.h",
+    "src/core/lib/channel/context.h",
+    "src/core/lib/channel/http_client_filter.h",
+    "src/core/lib/channel/http_server_filter.h",
+    "src/core/lib/compression/algorithm_metadata.h",
+    "src/core/lib/compression/message_compress.h",
+    "src/core/lib/debug/trace.h",
+    "src/core/lib/http/format_request.h",
+    "src/core/lib/http/httpcli.h",
+    "src/core/lib/http/parser.h",
+    "src/core/lib/iomgr/closure.h",
+    "src/core/lib/iomgr/endpoint.h",
+    "src/core/lib/iomgr/endpoint_pair.h",
+    "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
+    "src/core/lib/iomgr/ev_posix.h",
+    "src/core/lib/iomgr/exec_ctx.h",
+    "src/core/lib/iomgr/executor.h",
+    "src/core/lib/iomgr/iocp_windows.h",
+    "src/core/lib/iomgr/iomgr.h",
+    "src/core/lib/iomgr/iomgr_internal.h",
+    "src/core/lib/iomgr/iomgr_posix.h",
+    "src/core/lib/iomgr/pollset.h",
+    "src/core/lib/iomgr/pollset_set.h",
+    "src/core/lib/iomgr/pollset_set_windows.h",
+    "src/core/lib/iomgr/pollset_windows.h",
+    "src/core/lib/iomgr/resolve_address.h",
+    "src/core/lib/iomgr/sockaddr.h",
+    "src/core/lib/iomgr/sockaddr_posix.h",
+    "src/core/lib/iomgr/sockaddr_utils.h",
+    "src/core/lib/iomgr/sockaddr_win32.h",
+    "src/core/lib/iomgr/socket_utils_posix.h",
+    "src/core/lib/iomgr/socket_windows.h",
+    "src/core/lib/iomgr/tcp_client.h",
+    "src/core/lib/iomgr/tcp_posix.h",
+    "src/core/lib/iomgr/tcp_server.h",
+    "src/core/lib/iomgr/tcp_windows.h",
+    "src/core/lib/iomgr/time_averaged_stats.h",
+    "src/core/lib/iomgr/timer.h",
+    "src/core/lib/iomgr/timer_heap.h",
+    "src/core/lib/iomgr/udp_server.h",
+    "src/core/lib/iomgr/unix_sockets_posix.h",
+    "src/core/lib/iomgr/wakeup_fd_pipe.h",
+    "src/core/lib/iomgr/wakeup_fd_posix.h",
+    "src/core/lib/iomgr/workqueue.h",
+    "src/core/lib/iomgr/workqueue_posix.h",
+    "src/core/lib/iomgr/workqueue_windows.h",
+    "src/core/lib/json/json.h",
+    "src/core/lib/json/json_common.h",
+    "src/core/lib/json/json_reader.h",
+    "src/core/lib/json/json_writer.h",
+    "src/core/lib/surface/api_trace.h",
+    "src/core/lib/surface/call.h",
+    "src/core/lib/surface/call_test_only.h",
+    "src/core/lib/surface/channel.h",
+    "src/core/lib/surface/channel_init.h",
+    "src/core/lib/surface/channel_stack_type.h",
+    "src/core/lib/surface/completion_queue.h",
+    "src/core/lib/surface/event_string.h",
+    "src/core/lib/surface/init.h",
+    "src/core/lib/surface/lame_client.h",
+    "src/core/lib/surface/server.h",
+    "src/core/lib/surface/surface_trace.h",
+    "src/core/lib/transport/byte_stream.h",
+    "src/core/lib/transport/connectivity_state.h",
+    "src/core/lib/transport/metadata.h",
+    "src/core/lib/transport/metadata_batch.h",
+    "src/core/lib/transport/static_metadata.h",
+    "src/core/lib/transport/transport.h",
+    "src/core/lib/transport/transport_impl.h",
+    "src/core/ext/transport/chttp2/transport/bin_encoder.h",
+    "src/core/ext/transport/chttp2/transport/chttp2_transport.h",
+    "src/core/ext/transport/chttp2/transport/frame.h",
+    "src/core/ext/transport/chttp2/transport/frame_data.h",
+    "src/core/ext/transport/chttp2/transport/frame_goaway.h",
+    "src/core/ext/transport/chttp2/transport/frame_ping.h",
+    "src/core/ext/transport/chttp2/transport/frame_rst_stream.h",
+    "src/core/ext/transport/chttp2/transport/frame_settings.h",
+    "src/core/ext/transport/chttp2/transport/frame_window_update.h",
+    "src/core/ext/transport/chttp2/transport/hpack_encoder.h",
+    "src/core/ext/transport/chttp2/transport/hpack_parser.h",
+    "src/core/ext/transport/chttp2/transport/hpack_table.h",
+    "src/core/ext/transport/chttp2/transport/http2_errors.h",
+    "src/core/ext/transport/chttp2/transport/huffsyms.h",
+    "src/core/ext/transport/chttp2/transport/incoming_metadata.h",
+    "src/core/ext/transport/chttp2/transport/internal.h",
+    "src/core/ext/transport/chttp2/transport/status_conversion.h",
+    "src/core/ext/transport/chttp2/transport/stream_map.h",
+    "src/core/ext/transport/chttp2/transport/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/tsi/fake_transport_security.h",
+    "src/core/lib/tsi/ssl_transport_security.h",
+    "src/core/lib/tsi/ssl_types.h",
+    "src/core/lib/tsi/transport_security.h",
+    "src/core/lib/tsi/transport_security_interface.h",
+    "src/core/ext/client_config/client_channel.h",
+    "src/core/ext/client_config/client_channel_factory.h",
+    "src/core/ext/client_config/client_config.h",
+    "src/core/ext/client_config/connector.h",
+    "src/core/ext/client_config/initial_connect_string.h",
+    "src/core/ext/client_config/lb_policy.h",
+    "src/core/ext/client_config/lb_policy_factory.h",
+    "src/core/ext/client_config/lb_policy_registry.h",
+    "src/core/ext/client_config/parse_address.h",
+    "src/core/ext/client_config/resolver.h",
+    "src/core/ext/client_config/resolver_factory.h",
+    "src/core/ext/client_config/resolver_registry.h",
+    "src/core/ext/client_config/subchannel.h",
+    "src/core/ext/client_config/subchannel_call_holder.h",
+    "src/core/ext/client_config/subchannel_index.h",
+    "src/core/ext/client_config/uri_parser.h",
+    "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
+    "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h",
+    "src/core/ext/census/aggregation.h",
+    "src/core/ext/census/census_interface.h",
+    "src/core/ext/census/census_rpc_stats.h",
+    "src/core/ext/census/grpc_filter.h",
+    "src/core/ext/census/mlog.h",
+    "src/core/ext/census/rpc_metric_id.h",
   ],
   includes = [
     "include",
@@ -1687,6 +1638,7 @@
   deps = [
     ":gpr_objc",
     "//external:libssl_objc",
+    "//external:nanopb",
   ],
   sdk_dylibs = ["libz"],
 )
@@ -1718,6 +1670,18 @@
 
 
 cc_binary(
+  name = "grpc_node_plugin",
+  srcs = [
+    "src/compiler/node_plugin.cc",
+  ],
+  deps = [
+    "//external:protobuf_compiler",
+    ":grpc_plugin_support",
+  ],
+)
+
+
+cc_binary(
   name = "grpc_objective_c_plugin",
   srcs = [
     "src/compiler/objective_c_plugin.cc",
diff --git a/LICENSE b/LICENSE
index ac4b207..0209b57 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2015-2016, Google Inc.
+Copyright 2015, Google Inc.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/Makefile b/Makefile
index ef4e7bc..3b7dbd9 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
 # This file can be regenerated from the template by running
 # tools/buildgen/generate_projects.sh
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -95,6 +95,16 @@
 CPPFLAGS_opt = -O2
 DEFINES_opt = NDEBUG
 
+VALID_CONFIG_asan-trace-cmp = 1
+REQUIRE_CUSTOM_LIBRARIES_asan-trace-cmp = 1
+CC_asan-trace-cmp = clang
+CXX_asan-trace-cmp = clang++
+LD_asan-trace-cmp = clang
+LDXX_asan-trace-cmp = clang++
+CPPFLAGS_asan-trace-cmp = -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
+LDFLAGS_asan-trace-cmp = -fsanitize=address
+DEFINES_asan-trace-cmp += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
+
 VALID_CONFIG_dbg = 1
 CC_dbg = $(DEFAULT_CC)
 CXX_dbg = $(DEFAULT_CXX)
@@ -109,7 +119,7 @@
 CXX_easan = clang++
 LD_easan = clang
 LDXX_easan = clang++
-CPPFLAGS_easan = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
+CPPFLAGS_easan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_easan = -fsanitize=address
 DEFINES_easan = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
 DEFINES_easan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
@@ -120,7 +130,7 @@
 CXX_asan = clang++
 LD_asan = clang
 LDXX_asan = clang++
-CPPFLAGS_asan = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
+CPPFLAGS_asan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_asan = -fsanitize=address
 DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
 
@@ -130,7 +140,7 @@
 CXX_msan = clang++
 LD_msan = clang
 LDXX_msan = clang++
-CPPFLAGS_msan = -O0 -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
+CPPFLAGS_msan = -O0 -fsanitize-coverage=edge -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
 DEFINES_msan = NDEBUG
 DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=4
@@ -159,7 +169,7 @@
 CXX_asan-noleaks = clang++
 LD_asan-noleaks = clang
 LDXX_asan-noleaks = clang++
-CPPFLAGS_asan-noleaks = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
+CPPFLAGS_asan-noleaks = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_asan-noleaks = -fsanitize=address
 DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
 
@@ -177,7 +187,7 @@
 CXX_ubsan = clang++
 LD_ubsan = clang
 LDXX_ubsan = clang++
-CPPFLAGS_ubsan = -O1 -fsanitize=undefined -fno-omit-frame-pointer -Wno-unused-command-line-argument
+CPPFLAGS_ubsan = -O1 -fsanitize-coverage=edge -fsanitize=undefined -fno-omit-frame-pointer -Wno-unused-command-line-argument
 LDFLAGS_ubsan = -fsanitize=undefined
 DEFINES_ubsan = NDEBUG
 DEFINES_ubsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
@@ -769,7 +779,7 @@
 
 .SECONDARY = %.pb.h %.pb.cc
 
-PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
+PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_node_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
 ifeq ($(DEP_MISSING),)
 all: static shared plugins
 dep_error:
@@ -871,6 +881,7 @@
 algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test
 alloc_test: $(BINDIR)/$(CONFIG)/alloc_test
 alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
+api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer
 bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
 census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
 channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
@@ -878,6 +889,7 @@
 chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
 chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test
 chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test
+client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer
 compression_test: $(BINDIR)/$(CONFIG)/compression_test
 concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test
 dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test
@@ -892,6 +904,7 @@
 fling_test: $(BINDIR)/$(CONFIG)/fling_test
 gen_hpack_tables: $(BINDIR)/$(CONFIG)/gen_hpack_tables
 gen_legal_metadata_characters: $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters
+goaway_server_test: $(BINDIR)/$(CONFIG)/goaway_server_test
 gpr_avl_test: $(BINDIR)/$(CONFIG)/gpr_avl_test
 gpr_backoff_test: $(BINDIR)/$(CONFIG)/gpr_backoff_test
 gpr_cmdline_test: $(BINDIR)/$(CONFIG)/gpr_cmdline_test
@@ -925,14 +938,20 @@
 grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token
 grpc_security_connector_test: $(BINDIR)/$(CONFIG)/grpc_security_connector_test
 grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt
+hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test
 hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test
 hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test
+http_fuzzer_test: $(BINDIR)/$(CONFIG)/http_fuzzer_test
+http_parser_test: $(BINDIR)/$(CONFIG)/http_parser_test
 httpcli_format_request_test: $(BINDIR)/$(CONFIG)/httpcli_format_request_test
-httpcli_parser_test: $(BINDIR)/$(CONFIG)/httpcli_parser_test
 httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test
 httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test
 init_test: $(BINDIR)/$(CONFIG)/init_test
+internal_api_canary_iomgr_test: $(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test
+internal_api_canary_support_test: $(BINDIR)/$(CONFIG)/internal_api_canary_support_test
+internal_api_canary_transport_test: $(BINDIR)/$(CONFIG)/internal_api_canary_transport_test
 invalid_call_argument_test: $(BINDIR)/$(CONFIG)/invalid_call_argument_test
+json_fuzzer_test: $(BINDIR)/$(CONFIG)/json_fuzzer_test
 json_rewrite: $(BINDIR)/$(CONFIG)/json_rewrite
 json_rewrite_test: $(BINDIR)/$(CONFIG)/json_rewrite_test
 json_stream_error_test: $(BINDIR)/$(CONFIG)/json_stream_error_test
@@ -944,11 +963,14 @@
 mlog_test: $(BINDIR)/$(CONFIG)/mlog_test
 multiple_server_queues_test: $(BINDIR)/$(CONFIG)/multiple_server_queues_test
 murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test
+nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test
+nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test
 no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
 resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test
 secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test
 secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test
 server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
+server_fuzzer: $(BINDIR)/$(CONFIG)/server_fuzzer
 server_test: $(BINDIR)/$(CONFIG)/server_test
 set_initial_connect_string_test: $(BINDIR)/$(CONFIG)/set_initial_connect_string_test
 sockaddr_resolver_test: $(BINDIR)/$(CONFIG)/sockaddr_resolver_test
@@ -966,6 +988,7 @@
 transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test
 transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test
 udp_server_test: $(BINDIR)/$(CONFIG)/udp_server_test
+uri_fuzzer_test: $(BINDIR)/$(CONFIG)/uri_fuzzer_test
 uri_parser_test: $(BINDIR)/$(CONFIG)/uri_parser_test
 workqueue_test: $(BINDIR)/$(CONFIG)/workqueue_test
 alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test
@@ -977,7 +1000,8 @@
 cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
 client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test
 client_crash_test_server: $(BINDIR)/$(CONFIG)/client_crash_test_server
-codegen_test: $(BINDIR)/$(CONFIG)/codegen_test
+codegen_test_full: $(BINDIR)/$(CONFIG)/codegen_test_full
+codegen_test_minimal: $(BINDIR)/$(CONFIG)/codegen_test_minimal
 credentials_test: $(BINDIR)/$(CONFIG)/credentials_test
 cxx_byte_buffer_test: $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test
 cxx_slice_test: $(BINDIR)/$(CONFIG)/cxx_slice_test
@@ -989,6 +1013,7 @@
 grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli
 grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin
 grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin
+grpc_node_plugin: $(BINDIR)/$(CONFIG)/grpc_node_plugin
 grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin
 grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
 grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
@@ -997,10 +1022,11 @@
 interop_client: $(BINDIR)/$(CONFIG)/interop_client
 interop_server: $(BINDIR)/$(CONFIG)/interop_server
 interop_test: $(BINDIR)/$(CONFIG)/interop_test
+json_run_localhost: $(BINDIR)/$(CONFIG)/json_run_localhost
 metrics_client: $(BINDIR)/$(CONFIG)/metrics_client
 mock_test: $(BINDIR)/$(CONFIG)/mock_test
-qps_driver: $(BINDIR)/$(CONFIG)/qps_driver
 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
@@ -1052,12 +1078,14 @@
 boringssl_rsa_test: $(BINDIR)/$(CONFIG)/boringssl_rsa_test
 boringssl_thread_test: $(BINDIR)/$(CONFIG)/boringssl_thread_test
 boringssl_pkcs7_test: $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test
+boringssl_x509_test: $(BINDIR)/$(CONFIG)/boringssl_x509_test
 boringssl_tab_test: $(BINDIR)/$(CONFIG)/boringssl_tab_test
 boringssl_v3name_test: $(BINDIR)/$(CONFIG)/boringssl_v3name_test
 boringssl_pqueue_test: $(BINDIR)/$(CONFIG)/boringssl_pqueue_test
 boringssl_ssl_test: $(BINDIR)/$(CONFIG)/boringssl_ssl_test
 badreq_bad_client_test: $(BINDIR)/$(CONFIG)/badreq_bad_client_test
 connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test
+head_of_line_blocking_bad_client_test: $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
 headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test
 initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
 server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test
@@ -1073,8 +1101,6 @@
 h2_fakesec_test: $(BINDIR)/$(CONFIG)/h2_fakesec_test
 h2_full_test: $(BINDIR)/$(CONFIG)/h2_full_test
 h2_full+pipe_test: $(BINDIR)/$(CONFIG)/h2_full+pipe_test
-h2_full+poll_test: $(BINDIR)/$(CONFIG)/h2_full+poll_test
-h2_full+poll+pipe_test: $(BINDIR)/$(CONFIG)/h2_full+poll+pipe_test
 h2_full+trace_test: $(BINDIR)/$(CONFIG)/h2_full+trace_test
 h2_oauth2_test: $(BINDIR)/$(CONFIG)/h2_oauth2_test
 h2_proxy_test: $(BINDIR)/$(CONFIG)/h2_proxy_test
@@ -1082,25 +1108,28 @@
 h2_sockpair+trace_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test
 h2_sockpair_1byte_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test
 h2_ssl_test: $(BINDIR)/$(CONFIG)/h2_ssl_test
-h2_ssl+poll_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_test
+h2_ssl_cert_test: $(BINDIR)/$(CONFIG)/h2_ssl_cert_test
 h2_ssl_proxy_test: $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test
-h2_uchannel_test: $(BINDIR)/$(CONFIG)/h2_uchannel_test
 h2_uds_test: $(BINDIR)/$(CONFIG)/h2_uds_test
-h2_uds+poll_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_test
 h2_census_nosec_test: $(BINDIR)/$(CONFIG)/h2_census_nosec_test
 h2_compress_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_nosec_test
 h2_full_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_nosec_test
 h2_full+pipe_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+pipe_nosec_test
-h2_full+poll_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_nosec_test
-h2_full+poll+pipe_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll+pipe_nosec_test
 h2_full+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test
 h2_proxy_nosec_test: $(BINDIR)/$(CONFIG)/h2_proxy_nosec_test
 h2_sockpair_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test
 h2_sockpair+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test
 h2_sockpair_1byte_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test
-h2_uchannel_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_nosec_test
 h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test
-h2_uds+poll_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_nosec_test
+api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
+client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry
+hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry
+http_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry
+json_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry
+nanopb_fuzzer_response_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry
+nanopb_fuzzer_serverlist_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry
+server_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry
+uri_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry
 
 run_dep_checks:
 	$(OPENSSL_ALPN_CHECK_CMD) || true
@@ -1172,7 +1201,7 @@
 
 pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
 
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a
+privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a
 
 ifeq ($(HAS_ZOOKEEPER),true)
 privatelibs_zookeeper: 
@@ -1207,6 +1236,7 @@
   $(BINDIR)/$(CONFIG)/fling_server \
   $(BINDIR)/$(CONFIG)/fling_stream_test \
   $(BINDIR)/$(CONFIG)/fling_test \
+  $(BINDIR)/$(CONFIG)/goaway_server_test \
   $(BINDIR)/$(CONFIG)/gpr_avl_test \
   $(BINDIR)/$(CONFIG)/gpr_backoff_test \
   $(BINDIR)/$(CONFIG)/gpr_cmdline_test \
@@ -1238,11 +1268,14 @@
   $(BINDIR)/$(CONFIG)/grpc_security_connector_test \
   $(BINDIR)/$(CONFIG)/hpack_parser_test \
   $(BINDIR)/$(CONFIG)/hpack_table_test \
+  $(BINDIR)/$(CONFIG)/http_parser_test \
   $(BINDIR)/$(CONFIG)/httpcli_format_request_test \
-  $(BINDIR)/$(CONFIG)/httpcli_parser_test \
   $(BINDIR)/$(CONFIG)/httpcli_test \
   $(BINDIR)/$(CONFIG)/httpscli_test \
   $(BINDIR)/$(CONFIG)/init_test \
+  $(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test \
+  $(BINDIR)/$(CONFIG)/internal_api_canary_support_test \
+  $(BINDIR)/$(CONFIG)/internal_api_canary_transport_test \
   $(BINDIR)/$(CONFIG)/invalid_call_argument_test \
   $(BINDIR)/$(CONFIG)/json_rewrite \
   $(BINDIR)/$(CONFIG)/json_rewrite_test \
@@ -1281,6 +1314,7 @@
   $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \
   $(BINDIR)/$(CONFIG)/badreq_bad_client_test \
   $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \
+  $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \
   $(BINDIR)/$(CONFIG)/headers_bad_client_test \
   $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
   $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \
@@ -1296,8 +1330,6 @@
   $(BINDIR)/$(CONFIG)/h2_fakesec_test \
   $(BINDIR)/$(CONFIG)/h2_full_test \
   $(BINDIR)/$(CONFIG)/h2_full+pipe_test \
-  $(BINDIR)/$(CONFIG)/h2_full+poll_test \
-  $(BINDIR)/$(CONFIG)/h2_full+poll+pipe_test \
   $(BINDIR)/$(CONFIG)/h2_full+trace_test \
   $(BINDIR)/$(CONFIG)/h2_oauth2_test \
   $(BINDIR)/$(CONFIG)/h2_proxy_test \
@@ -1305,25 +1337,28 @@
   $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test \
   $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test \
   $(BINDIR)/$(CONFIG)/h2_ssl_test \
-  $(BINDIR)/$(CONFIG)/h2_ssl+poll_test \
+  $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \
   $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test \
-  $(BINDIR)/$(CONFIG)/h2_uchannel_test \
   $(BINDIR)/$(CONFIG)/h2_uds_test \
-  $(BINDIR)/$(CONFIG)/h2_uds+poll_test \
   $(BINDIR)/$(CONFIG)/h2_census_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_compress_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_full_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_full+pipe_nosec_test \
-  $(BINDIR)/$(CONFIG)/h2_full+poll_nosec_test \
-  $(BINDIR)/$(CONFIG)/h2_full+poll+pipe_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_proxy_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test \
-  $(BINDIR)/$(CONFIG)/h2_uchannel_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_uds_nosec_test \
-  $(BINDIR)/$(CONFIG)/h2_uds+poll_nosec_test \
+  $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry \
+  $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \
+  $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \
+  $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry \
+  $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry \
+  $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry \
+  $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry \
+  $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry \
+  $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry \
 
 
 buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
@@ -1336,7 +1371,8 @@
   $(BINDIR)/$(CONFIG)/cli_call_test \
   $(BINDIR)/$(CONFIG)/client_crash_test \
   $(BINDIR)/$(CONFIG)/client_crash_test_server \
-  $(BINDIR)/$(CONFIG)/codegen_test \
+  $(BINDIR)/$(CONFIG)/codegen_test_full \
+  $(BINDIR)/$(CONFIG)/codegen_test_minimal \
   $(BINDIR)/$(CONFIG)/credentials_test \
   $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test \
   $(BINDIR)/$(CONFIG)/cxx_slice_test \
@@ -1351,11 +1387,14 @@
   $(BINDIR)/$(CONFIG)/interop_client \
   $(BINDIR)/$(CONFIG)/interop_server \
   $(BINDIR)/$(CONFIG)/interop_test \
+  $(BINDIR)/$(CONFIG)/json_run_localhost \
   $(BINDIR)/$(CONFIG)/metrics_client \
   $(BINDIR)/$(CONFIG)/mock_test \
   $(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 \
   $(BINDIR)/$(CONFIG)/secure_auth_context_test \
@@ -1402,6 +1441,7 @@
   $(BINDIR)/$(CONFIG)/boringssl_rsa_test \
   $(BINDIR)/$(CONFIG)/boringssl_thread_test \
   $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test \
+  $(BINDIR)/$(CONFIG)/boringssl_x509_test \
   $(BINDIR)/$(CONFIG)/boringssl_tab_test \
   $(BINDIR)/$(CONFIG)/boringssl_v3name_test \
   $(BINDIR)/$(CONFIG)/boringssl_pqueue_test \
@@ -1464,6 +1504,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/fling_stream_test || ( echo test fling_stream_test failed ; exit 1 )
 	$(E) "[RUN]     Testing fling_test"
 	$(Q) $(BINDIR)/$(CONFIG)/fling_test || ( echo test fling_test failed ; exit 1 )
+	$(E) "[RUN]     Testing goaway_server_test"
+	$(Q) $(BINDIR)/$(CONFIG)/goaway_server_test || ( echo test goaway_server_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_avl_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_avl_test || ( echo test gpr_avl_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_backoff_test"
@@ -1526,10 +1568,10 @@
 	$(Q) $(BINDIR)/$(CONFIG)/hpack_parser_test || ( echo test hpack_parser_test failed ; exit 1 )
 	$(E) "[RUN]     Testing hpack_table_test"
 	$(Q) $(BINDIR)/$(CONFIG)/hpack_table_test || ( echo test hpack_table_test failed ; exit 1 )
+	$(E) "[RUN]     Testing http_parser_test"
+	$(Q) $(BINDIR)/$(CONFIG)/http_parser_test || ( echo test http_parser_test failed ; exit 1 )
 	$(E) "[RUN]     Testing httpcli_format_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/httpcli_format_request_test || ( echo test httpcli_format_request_test failed ; exit 1 )
-	$(E) "[RUN]     Testing httpcli_parser_test"
-	$(Q) $(BINDIR)/$(CONFIG)/httpcli_parser_test || ( echo test httpcli_parser_test failed ; exit 1 )
 	$(E) "[RUN]     Testing httpcli_test"
 	$(Q) $(BINDIR)/$(CONFIG)/httpcli_test || ( echo test httpcli_test failed ; exit 1 )
 	$(E) "[RUN]     Testing httpscli_test"
@@ -1606,6 +1648,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing connection_prefix_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test || ( echo test connection_prefix_bad_client_test failed ; exit 1 )
+	$(E) "[RUN]     Testing head_of_line_blocking_bad_client_test"
+	$(Q) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test || ( echo test head_of_line_blocking_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing headers_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing initial_settings_frame_bad_client_test"
@@ -1648,8 +1692,10 @@
 	$(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 )
 	$(E) "[RUN]     Testing client_crash_test"
 	$(Q) $(BINDIR)/$(CONFIG)/client_crash_test || ( echo test client_crash_test failed ; exit 1 )
-	$(E) "[RUN]     Testing codegen_test"
-	$(Q) $(BINDIR)/$(CONFIG)/codegen_test || ( echo test codegen_test failed ; exit 1 )
+	$(E) "[RUN]     Testing codegen_test_full"
+	$(Q) $(BINDIR)/$(CONFIG)/codegen_test_full || ( echo test codegen_test_full failed ; exit 1 )
+	$(E) "[RUN]     Testing codegen_test_minimal"
+	$(Q) $(BINDIR)/$(CONFIG)/codegen_test_minimal || ( echo test codegen_test_minimal failed ; exit 1 )
 	$(E) "[RUN]     Testing credentials_test"
 	$(Q) $(BINDIR)/$(CONFIG)/credentials_test || ( echo test credentials_test failed ; exit 1 )
 	$(E) "[RUN]     Testing cxx_byte_buffer_test"
@@ -1725,7 +1771,7 @@
 
 tools_cxx: privatelibs_cxx
 
-buildbenchmarks: privatelibs $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark $(BINDIR)/$(CONFIG)/qps_driver $(BINDIR)/$(CONFIG)/qps_worker
+buildbenchmarks: privatelibs $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark
 
 benchmarks: buildbenchmarks
 
@@ -2200,6 +2246,8 @@
 	$(Q) $(INSTALL) -d $(prefix)/bin
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(prefix)/bin/grpc_csharp_plugin
 	$(Q) $(INSTALL) -d $(prefix)/bin
+	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_node_plugin $(prefix)/bin/grpc_node_plugin
+	$(Q) $(INSTALL) -d $(prefix)/bin
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin
 	$(Q) $(INSTALL) -d $(prefix)/bin
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin
@@ -2256,50 +2304,50 @@
 
 
 LIBGPR_SRC = \
-    src/core/profiling/basic_timers.c \
-    src/core/profiling/stap_timers.c \
-    src/core/support/alloc.c \
-    src/core/support/avl.c \
-    src/core/support/backoff.c \
-    src/core/support/cmdline.c \
-    src/core/support/cpu_iphone.c \
-    src/core/support/cpu_linux.c \
-    src/core/support/cpu_posix.c \
-    src/core/support/cpu_windows.c \
-    src/core/support/env_linux.c \
-    src/core/support/env_posix.c \
-    src/core/support/env_win32.c \
-    src/core/support/histogram.c \
-    src/core/support/host_port.c \
-    src/core/support/load_file.c \
-    src/core/support/log.c \
-    src/core/support/log_android.c \
-    src/core/support/log_linux.c \
-    src/core/support/log_posix.c \
-    src/core/support/log_win32.c \
-    src/core/support/murmur_hash.c \
-    src/core/support/slice.c \
-    src/core/support/slice_buffer.c \
-    src/core/support/stack_lockfree.c \
-    src/core/support/string.c \
-    src/core/support/string_posix.c \
-    src/core/support/string_win32.c \
-    src/core/support/subprocess_posix.c \
-    src/core/support/subprocess_windows.c \
-    src/core/support/sync.c \
-    src/core/support/sync_posix.c \
-    src/core/support/sync_win32.c \
-    src/core/support/thd.c \
-    src/core/support/thd_posix.c \
-    src/core/support/thd_win32.c \
-    src/core/support/time.c \
-    src/core/support/time_posix.c \
-    src/core/support/time_precise.c \
-    src/core/support/time_win32.c \
-    src/core/support/tls_pthread.c \
-    src/core/support/tmpfile_posix.c \
-    src/core/support/tmpfile_win32.c \
-    src/core/support/wrap_memcpy.c \
+    src/core/lib/profiling/basic_timers.c \
+    src/core/lib/profiling/stap_timers.c \
+    src/core/lib/support/alloc.c \
+    src/core/lib/support/avl.c \
+    src/core/lib/support/backoff.c \
+    src/core/lib/support/cmdline.c \
+    src/core/lib/support/cpu_iphone.c \
+    src/core/lib/support/cpu_linux.c \
+    src/core/lib/support/cpu_posix.c \
+    src/core/lib/support/cpu_windows.c \
+    src/core/lib/support/env_linux.c \
+    src/core/lib/support/env_posix.c \
+    src/core/lib/support/env_win32.c \
+    src/core/lib/support/histogram.c \
+    src/core/lib/support/host_port.c \
+    src/core/lib/support/load_file.c \
+    src/core/lib/support/log.c \
+    src/core/lib/support/log_android.c \
+    src/core/lib/support/log_linux.c \
+    src/core/lib/support/log_posix.c \
+    src/core/lib/support/log_win32.c \
+    src/core/lib/support/murmur_hash.c \
+    src/core/lib/support/slice.c \
+    src/core/lib/support/slice_buffer.c \
+    src/core/lib/support/stack_lockfree.c \
+    src/core/lib/support/string.c \
+    src/core/lib/support/string_posix.c \
+    src/core/lib/support/string_win32.c \
+    src/core/lib/support/subprocess_posix.c \
+    src/core/lib/support/subprocess_windows.c \
+    src/core/lib/support/sync.c \
+    src/core/lib/support/sync_posix.c \
+    src/core/lib/support/sync_win32.c \
+    src/core/lib/support/thd.c \
+    src/core/lib/support/thd_posix.c \
+    src/core/lib/support/thd_win32.c \
+    src/core/lib/support/time.c \
+    src/core/lib/support/time_posix.c \
+    src/core/lib/support/time_precise.c \
+    src/core/lib/support/time_win32.c \
+    src/core/lib/support/tls_pthread.c \
+    src/core/lib/support/tmpfile_posix.c \
+    src/core/lib/support/tmpfile_win32.c \
+    src/core/lib/support/wrap_memcpy.c \
 
 PUBLIC_HEADERS_C += \
     include/grpc/support/alloc.h \
@@ -2385,6 +2433,7 @@
 LIBGPR_TEST_UTIL_SRC = \
     test/core/util/test_config.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBGPR_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGPR_TEST_UTIL_SRC))))
 
@@ -2407,172 +2456,173 @@
 
 
 LIBGRPC_SRC = \
-    src/core/census/grpc_context.c \
-    src/core/census/grpc_filter.c \
-    src/core/census/grpc_plugin.c \
-    src/core/channel/channel_args.c \
-    src/core/channel/channel_stack.c \
-    src/core/channel/channel_stack_builder.c \
-    src/core/channel/client_channel.c \
-    src/core/channel/client_uchannel.c \
-    src/core/channel/compress_filter.c \
-    src/core/channel/connected_channel.c \
-    src/core/channel/http_client_filter.c \
-    src/core/channel/http_server_filter.c \
-    src/core/channel/subchannel_call_holder.c \
-    src/core/client_config/client_config.c \
-    src/core/client_config/connector.c \
-    src/core/client_config/default_initial_connect_string.c \
-    src/core/client_config/initial_connect_string.c \
-    src/core/client_config/lb_policies/load_balancer_api.c \
-    src/core/client_config/lb_policies/pick_first.c \
-    src/core/client_config/lb_policies/round_robin.c \
-    src/core/client_config/lb_policy.c \
-    src/core/client_config/lb_policy_factory.c \
-    src/core/client_config/lb_policy_registry.c \
-    src/core/client_config/resolver.c \
-    src/core/client_config/resolver_factory.c \
-    src/core/client_config/resolver_registry.c \
-    src/core/client_config/resolvers/dns_resolver.c \
-    src/core/client_config/resolvers/sockaddr_resolver.c \
-    src/core/client_config/subchannel.c \
-    src/core/client_config/subchannel_factory.c \
-    src/core/client_config/subchannel_index.c \
-    src/core/client_config/uri_parser.c \
-    src/core/compression/compression_algorithm.c \
-    src/core/compression/message_compress.c \
-    src/core/debug/trace.c \
-    src/core/httpcli/format_request.c \
-    src/core/httpcli/httpcli.c \
-    src/core/httpcli/parser.c \
-    src/core/iomgr/closure.c \
-    src/core/iomgr/endpoint.c \
-    src/core/iomgr/endpoint_pair_posix.c \
-    src/core/iomgr/endpoint_pair_windows.c \
-    src/core/iomgr/exec_ctx.c \
-    src/core/iomgr/executor.c \
-    src/core/iomgr/fd_posix.c \
-    src/core/iomgr/iocp_windows.c \
-    src/core/iomgr/iomgr.c \
-    src/core/iomgr/iomgr_posix.c \
-    src/core/iomgr/iomgr_windows.c \
-    src/core/iomgr/pollset_multipoller_with_epoll.c \
-    src/core/iomgr/pollset_multipoller_with_poll_posix.c \
-    src/core/iomgr/pollset_posix.c \
-    src/core/iomgr/pollset_set_posix.c \
-    src/core/iomgr/pollset_set_windows.c \
-    src/core/iomgr/pollset_windows.c \
-    src/core/iomgr/resolve_address_posix.c \
-    src/core/iomgr/resolve_address_windows.c \
-    src/core/iomgr/sockaddr_utils.c \
-    src/core/iomgr/socket_utils_common_posix.c \
-    src/core/iomgr/socket_utils_linux.c \
-    src/core/iomgr/socket_utils_posix.c \
-    src/core/iomgr/socket_windows.c \
-    src/core/iomgr/tcp_client_posix.c \
-    src/core/iomgr/tcp_client_windows.c \
-    src/core/iomgr/tcp_posix.c \
-    src/core/iomgr/tcp_server_posix.c \
-    src/core/iomgr/tcp_server_windows.c \
-    src/core/iomgr/tcp_windows.c \
-    src/core/iomgr/time_averaged_stats.c \
-    src/core/iomgr/timer.c \
-    src/core/iomgr/timer_heap.c \
-    src/core/iomgr/udp_server.c \
-    src/core/iomgr/wakeup_fd_eventfd.c \
-    src/core/iomgr/wakeup_fd_nospecial.c \
-    src/core/iomgr/wakeup_fd_pipe.c \
-    src/core/iomgr/wakeup_fd_posix.c \
-    src/core/iomgr/workqueue_posix.c \
-    src/core/iomgr/workqueue_windows.c \
-    src/core/json/json.c \
-    src/core/json/json_reader.c \
-    src/core/json/json_string.c \
-    src/core/json/json_writer.c \
-    src/core/proto/grpc/lb/v0/load_balancer.pb.c \
-    src/core/surface/alarm.c \
-    src/core/surface/api_trace.c \
-    src/core/surface/byte_buffer.c \
-    src/core/surface/byte_buffer_reader.c \
-    src/core/surface/call.c \
-    src/core/surface/call_details.c \
-    src/core/surface/call_log_batch.c \
-    src/core/surface/channel.c \
-    src/core/surface/channel_connectivity.c \
-    src/core/surface/channel_create.c \
-    src/core/surface/channel_init.c \
-    src/core/surface/channel_ping.c \
-    src/core/surface/channel_stack_type.c \
-    src/core/surface/completion_queue.c \
-    src/core/surface/event_string.c \
-    src/core/surface/init.c \
-    src/core/surface/lame_client.c \
-    src/core/surface/metadata_array.c \
-    src/core/surface/server.c \
-    src/core/surface/server_chttp2.c \
-    src/core/surface/validate_metadata.c \
-    src/core/surface/version.c \
-    src/core/transport/byte_stream.c \
-    src/core/transport/chttp2/alpn.c \
-    src/core/transport/chttp2/bin_encoder.c \
-    src/core/transport/chttp2/frame_data.c \
-    src/core/transport/chttp2/frame_goaway.c \
-    src/core/transport/chttp2/frame_ping.c \
-    src/core/transport/chttp2/frame_rst_stream.c \
-    src/core/transport/chttp2/frame_settings.c \
-    src/core/transport/chttp2/frame_window_update.c \
-    src/core/transport/chttp2/hpack_encoder.c \
-    src/core/transport/chttp2/hpack_parser.c \
-    src/core/transport/chttp2/hpack_table.c \
-    src/core/transport/chttp2/huffsyms.c \
-    src/core/transport/chttp2/incoming_metadata.c \
-    src/core/transport/chttp2/parsing.c \
-    src/core/transport/chttp2/status_conversion.c \
-    src/core/transport/chttp2/stream_lists.c \
-    src/core/transport/chttp2/stream_map.c \
-    src/core/transport/chttp2/timeout_encoding.c \
-    src/core/transport/chttp2/varint.c \
-    src/core/transport/chttp2/writing.c \
-    src/core/transport/chttp2_transport.c \
-    src/core/transport/connectivity_state.c \
-    src/core/transport/metadata.c \
-    src/core/transport/metadata_batch.c \
-    src/core/transport/static_metadata.c \
-    src/core/transport/transport.c \
-    src/core/transport/transport_op_string.c \
-    src/core/httpcli/httpcli_security_connector.c \
-    src/core/security/b64.c \
-    src/core/security/client_auth_filter.c \
-    src/core/security/credentials.c \
-    src/core/security/credentials_metadata.c \
-    src/core/security/credentials_posix.c \
-    src/core/security/credentials_win32.c \
-    src/core/security/google_default_credentials.c \
-    src/core/security/handshake.c \
-    src/core/security/json_token.c \
-    src/core/security/jwt_verifier.c \
-    src/core/security/secure_endpoint.c \
-    src/core/security/security_connector.c \
-    src/core/security/security_context.c \
-    src/core/security/server_auth_filter.c \
-    src/core/security/server_secure_chttp2.c \
-    src/core/surface/init_secure.c \
-    src/core/surface/secure_channel_create.c \
-    src/core/tsi/fake_transport_security.c \
-    src/core/tsi/ssl_transport_security.c \
-    src/core/tsi/transport_security.c \
-    src/core/census/context.c \
-    src/core/census/initialize.c \
-    src/core/census/mlog.c \
-    src/core/census/operation.c \
-    src/core/census/placeholders.c \
-    src/core/census/tracing.c \
+    src/core/lib/surface/init.c \
+    src/core/lib/channel/channel_args.c \
+    src/core/lib/channel/channel_stack.c \
+    src/core/lib/channel/channel_stack_builder.c \
+    src/core/lib/channel/compress_filter.c \
+    src/core/lib/channel/connected_channel.c \
+    src/core/lib/channel/http_client_filter.c \
+    src/core/lib/channel/http_server_filter.c \
+    src/core/lib/compression/compression_algorithm.c \
+    src/core/lib/compression/message_compress.c \
+    src/core/lib/debug/trace.c \
+    src/core/lib/http/format_request.c \
+    src/core/lib/http/httpcli.c \
+    src/core/lib/http/parser.c \
+    src/core/lib/iomgr/closure.c \
+    src/core/lib/iomgr/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_posix.c \
+    src/core/lib/iomgr/exec_ctx.c \
+    src/core/lib/iomgr/executor.c \
+    src/core/lib/iomgr/iocp_windows.c \
+    src/core/lib/iomgr/iomgr.c \
+    src/core/lib/iomgr/iomgr_posix.c \
+    src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/pollset_set_windows.c \
+    src/core/lib/iomgr/pollset_windows.c \
+    src/core/lib/iomgr/resolve_address_posix.c \
+    src/core/lib/iomgr/resolve_address_windows.c \
+    src/core/lib/iomgr/sockaddr_utils.c \
+    src/core/lib/iomgr/socket_utils_common_posix.c \
+    src/core/lib/iomgr/socket_utils_linux.c \
+    src/core/lib/iomgr/socket_utils_posix.c \
+    src/core/lib/iomgr/socket_windows.c \
+    src/core/lib/iomgr/tcp_client_posix.c \
+    src/core/lib/iomgr/tcp_client_windows.c \
+    src/core/lib/iomgr/tcp_posix.c \
+    src/core/lib/iomgr/tcp_server_posix.c \
+    src/core/lib/iomgr/tcp_server_windows.c \
+    src/core/lib/iomgr/tcp_windows.c \
+    src/core/lib/iomgr/time_averaged_stats.c \
+    src/core/lib/iomgr/timer.c \
+    src/core/lib/iomgr/timer_heap.c \
+    src/core/lib/iomgr/udp_server.c \
+    src/core/lib/iomgr/unix_sockets_posix.c \
+    src/core/lib/iomgr/unix_sockets_posix_noop.c \
+    src/core/lib/iomgr/wakeup_fd_eventfd.c \
+    src/core/lib/iomgr/wakeup_fd_nospecial.c \
+    src/core/lib/iomgr/wakeup_fd_pipe.c \
+    src/core/lib/iomgr/wakeup_fd_posix.c \
+    src/core/lib/iomgr/workqueue_posix.c \
+    src/core/lib/iomgr/workqueue_windows.c \
+    src/core/lib/json/json.c \
+    src/core/lib/json/json_reader.c \
+    src/core/lib/json/json_string.c \
+    src/core/lib/json/json_writer.c \
+    src/core/lib/surface/alarm.c \
+    src/core/lib/surface/api_trace.c \
+    src/core/lib/surface/byte_buffer.c \
+    src/core/lib/surface/byte_buffer_reader.c \
+    src/core/lib/surface/call.c \
+    src/core/lib/surface/call_details.c \
+    src/core/lib/surface/call_log_batch.c \
+    src/core/lib/surface/channel.c \
+    src/core/lib/surface/channel_init.c \
+    src/core/lib/surface/channel_ping.c \
+    src/core/lib/surface/channel_stack_type.c \
+    src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/event_string.c \
+    src/core/lib/surface/lame_client.c \
+    src/core/lib/surface/metadata_array.c \
+    src/core/lib/surface/server.c \
+    src/core/lib/surface/validate_metadata.c \
+    src/core/lib/surface/version.c \
+    src/core/lib/transport/byte_stream.c \
+    src/core/lib/transport/connectivity_state.c \
+    src/core/lib/transport/metadata.c \
+    src/core/lib/transport/metadata_batch.c \
+    src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/transport.c \
+    src/core/lib/transport/transport_op_string.c \
+    src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \
+    src/core/ext/transport/chttp2/transport/bin_encoder.c \
+    src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
+    src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/frame_data.c \
+    src/core/ext/transport/chttp2/transport/frame_goaway.c \
+    src/core/ext/transport/chttp2/transport/frame_ping.c \
+    src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+    src/core/ext/transport/chttp2/transport/frame_settings.c \
+    src/core/ext/transport/chttp2/transport/frame_window_update.c \
+    src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+    src/core/ext/transport/chttp2/transport/hpack_parser.c \
+    src/core/ext/transport/chttp2/transport/hpack_table.c \
+    src/core/ext/transport/chttp2/transport/huffsyms.c \
+    src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+    src/core/ext/transport/chttp2/transport/parsing.c \
+    src/core/ext/transport/chttp2/transport/status_conversion.c \
+    src/core/ext/transport/chttp2/transport/stream_lists.c \
+    src/core/ext/transport/chttp2/transport/stream_map.c \
+    src/core/ext/transport/chttp2/transport/timeout_encoding.c \
+    src/core/ext/transport/chttp2/transport/varint.c \
+    src/core/ext/transport/chttp2/transport/writing.c \
+    src/core/ext/transport/chttp2/alpn/alpn.c \
+    src/core/lib/http/httpcli_security_connector.c \
+    src/core/lib/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/surface/init_secure.c \
+    src/core/lib/tsi/fake_transport_security.c \
+    src/core/lib/tsi/ssl_transport_security.c \
+    src/core/lib/tsi/transport_security.c \
+    src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \
+    src/core/ext/client_config/channel_connectivity.c \
+    src/core/ext/client_config/client_channel.c \
+    src/core/ext/client_config/client_channel_factory.c \
+    src/core/ext/client_config/client_config.c \
+    src/core/ext/client_config/client_config_plugin.c \
+    src/core/ext/client_config/connector.c \
+    src/core/ext/client_config/default_initial_connect_string.c \
+    src/core/ext/client_config/initial_connect_string.c \
+    src/core/ext/client_config/lb_policy.c \
+    src/core/ext/client_config/lb_policy_factory.c \
+    src/core/ext/client_config/lb_policy_registry.c \
+    src/core/ext/client_config/parse_address.c \
+    src/core/ext/client_config/resolver.c \
+    src/core/ext/client_config/resolver_factory.c \
+    src/core/ext/client_config/resolver_registry.c \
+    src/core/ext/client_config/subchannel.c \
+    src/core/ext/client_config/subchannel_call_holder.c \
+    src/core/ext/client_config/subchannel_index.c \
+    src/core/ext/client_config/uri_parser.c \
+    src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
+    src/core/ext/transport/chttp2/client/insecure/channel_create.c \
+    src/core/ext/lb_policy/grpclb/load_balancer_api.c \
+    src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
+    src/core/ext/lb_policy/pick_first/pick_first.c \
+    src/core/ext/lb_policy/round_robin/round_robin.c \
+    src/core/ext/resolver/dns/native/dns_resolver.c \
+    src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
+    src/core/ext/census/context.c \
+    src/core/ext/census/grpc_context.c \
+    src/core/ext/census/grpc_filter.c \
+    src/core/ext/census/grpc_plugin.c \
+    src/core/ext/census/initialize.c \
+    src/core/ext/census/mlog.c \
+    src/core/ext/census/operation.c \
+    src/core/ext/census/placeholders.c \
+    src/core/ext/census/tracing.c \
+    src/core/plugin_registry/grpc_plugin_registry.c \
 
 PUBLIC_HEADERS_C += \
-    include/grpc/grpc_security.h \
     include/grpc/byte_buffer.h \
     include/grpc/byte_buffer_reader.h \
     include/grpc/compression.h \
@@ -2584,6 +2634,22 @@
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/status.h \
+    include/grpc/impl/codegen/alloc.h \
+    include/grpc/impl/codegen/atm.h \
+    include/grpc/impl/codegen/atm_gcc_atomic.h \
+    include/grpc/impl/codegen/atm_gcc_sync.h \
+    include/grpc/impl/codegen/atm_win32.h \
+    include/grpc/impl/codegen/log.h \
+    include/grpc/impl/codegen/port_platform.h \
+    include/grpc/impl/codegen/slice.h \
+    include/grpc/impl/codegen/slice_buffer.h \
+    include/grpc/impl/codegen/sync.h \
+    include/grpc/impl/codegen/sync_generic.h \
+    include/grpc/impl/codegen/sync_posix.h \
+    include/grpc/impl/codegen/sync_win32.h \
+    include/grpc/impl/codegen/time.h \
+    include/grpc/grpc_security.h \
+    include/grpc/grpc_security_constants.h \
     include/grpc/census.h \
 
 LIBGRPC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_SRC))))
@@ -2638,51 +2704,8 @@
 endif
 
 
-LIBGRPC_CODEGEN_LIB_SRC = \
-
-PUBLIC_HEADERS_C += \
-    include/grpc/impl/codegen/alloc.h \
-    include/grpc/impl/codegen/atm.h \
-    include/grpc/impl/codegen/atm_gcc_atomic.h \
-    include/grpc/impl/codegen/atm_gcc_sync.h \
-    include/grpc/impl/codegen/atm_win32.h \
-    include/grpc/impl/codegen/log.h \
-    include/grpc/impl/codegen/port_platform.h \
-    include/grpc/impl/codegen/slice.h \
-    include/grpc/impl/codegen/slice_buffer.h \
-    include/grpc/impl/codegen/sync.h \
-    include/grpc/impl/codegen/sync_generic.h \
-    include/grpc/impl/codegen/sync_posix.h \
-    include/grpc/impl/codegen/sync_win32.h \
-    include/grpc/impl/codegen/time.h \
-    include/grpc/impl/codegen/byte_buffer.h \
-    include/grpc/impl/codegen/compression_types.h \
-    include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/grpc_types.h \
-    include/grpc/impl/codegen/propagation_bits.h \
-    include/grpc/impl/codegen/status.h \
-
-LIBGRPC_CODEGEN_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CODEGEN_LIB_SRC))))
-
-
-$(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a: $(ZLIB_DEP)  $(LIBGRPC_CODEGEN_LIB_OBJS) 
-	$(E) "[AR]      Creating $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a
-	$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a $(LIBGRPC_CODEGEN_LIB_OBJS) 
-ifeq ($(SYSTEM),Darwin)
-	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a
-endif
-
-
-
-
-ifneq ($(NO_DEPS),true)
--include $(LIBGRPC_CODEGEN_LIB_OBJS:.o=.dep)
-endif
-
-
 LIBGRPC_TEST_UTIL_SRC = \
+    test/core/end2end/data/client_certs.c \
     test/core/end2end/data/server1_cert.c \
     test/core/end2end/data/server1_key.c \
     test/core/end2end/data/test_root_cert.c \
@@ -2691,7 +2714,10 @@
     test/core/end2end/fixtures/proxy.c \
     test/core/iomgr/endpoint_tests.c \
     test/core/util/grpc_profiler.c \
+    test/core/util/memory_counters.c \
+    test/core/util/mock_endpoint.c \
     test/core/util/parse_hexstring.c \
+    test/core/util/passthru_endpoint.c \
     test/core/util/port_posix.c \
     test/core/util/port_server_client.c \
     test/core/util/port_windows.c \
@@ -2738,7 +2764,10 @@
     test/core/end2end/fixtures/proxy.c \
     test/core/iomgr/endpoint_tests.c \
     test/core/util/grpc_profiler.c \
+    test/core/util/memory_counters.c \
+    test/core/util/mock_endpoint.c \
     test/core/util/parse_hexstring.c \
+    test/core/util/passthru_endpoint.c \
     test/core/util/port_posix.c \
     test/core/util/port_server_client.c \
     test/core/util/port_windows.c \
@@ -2767,149 +2796,151 @@
 
 
 LIBGRPC_UNSECURE_SRC = \
-    src/core/surface/init_unsecure.c \
-    src/core/census/grpc_context.c \
-    src/core/census/grpc_filter.c \
-    src/core/census/grpc_plugin.c \
-    src/core/channel/channel_args.c \
-    src/core/channel/channel_stack.c \
-    src/core/channel/channel_stack_builder.c \
-    src/core/channel/client_channel.c \
-    src/core/channel/client_uchannel.c \
-    src/core/channel/compress_filter.c \
-    src/core/channel/connected_channel.c \
-    src/core/channel/http_client_filter.c \
-    src/core/channel/http_server_filter.c \
-    src/core/channel/subchannel_call_holder.c \
-    src/core/client_config/client_config.c \
-    src/core/client_config/connector.c \
-    src/core/client_config/default_initial_connect_string.c \
-    src/core/client_config/initial_connect_string.c \
-    src/core/client_config/lb_policies/load_balancer_api.c \
-    src/core/client_config/lb_policies/pick_first.c \
-    src/core/client_config/lb_policies/round_robin.c \
-    src/core/client_config/lb_policy.c \
-    src/core/client_config/lb_policy_factory.c \
-    src/core/client_config/lb_policy_registry.c \
-    src/core/client_config/resolver.c \
-    src/core/client_config/resolver_factory.c \
-    src/core/client_config/resolver_registry.c \
-    src/core/client_config/resolvers/dns_resolver.c \
-    src/core/client_config/resolvers/sockaddr_resolver.c \
-    src/core/client_config/subchannel.c \
-    src/core/client_config/subchannel_factory.c \
-    src/core/client_config/subchannel_index.c \
-    src/core/client_config/uri_parser.c \
-    src/core/compression/compression_algorithm.c \
-    src/core/compression/message_compress.c \
-    src/core/debug/trace.c \
-    src/core/httpcli/format_request.c \
-    src/core/httpcli/httpcli.c \
-    src/core/httpcli/parser.c \
-    src/core/iomgr/closure.c \
-    src/core/iomgr/endpoint.c \
-    src/core/iomgr/endpoint_pair_posix.c \
-    src/core/iomgr/endpoint_pair_windows.c \
-    src/core/iomgr/exec_ctx.c \
-    src/core/iomgr/executor.c \
-    src/core/iomgr/fd_posix.c \
-    src/core/iomgr/iocp_windows.c \
-    src/core/iomgr/iomgr.c \
-    src/core/iomgr/iomgr_posix.c \
-    src/core/iomgr/iomgr_windows.c \
-    src/core/iomgr/pollset_multipoller_with_epoll.c \
-    src/core/iomgr/pollset_multipoller_with_poll_posix.c \
-    src/core/iomgr/pollset_posix.c \
-    src/core/iomgr/pollset_set_posix.c \
-    src/core/iomgr/pollset_set_windows.c \
-    src/core/iomgr/pollset_windows.c \
-    src/core/iomgr/resolve_address_posix.c \
-    src/core/iomgr/resolve_address_windows.c \
-    src/core/iomgr/sockaddr_utils.c \
-    src/core/iomgr/socket_utils_common_posix.c \
-    src/core/iomgr/socket_utils_linux.c \
-    src/core/iomgr/socket_utils_posix.c \
-    src/core/iomgr/socket_windows.c \
-    src/core/iomgr/tcp_client_posix.c \
-    src/core/iomgr/tcp_client_windows.c \
-    src/core/iomgr/tcp_posix.c \
-    src/core/iomgr/tcp_server_posix.c \
-    src/core/iomgr/tcp_server_windows.c \
-    src/core/iomgr/tcp_windows.c \
-    src/core/iomgr/time_averaged_stats.c \
-    src/core/iomgr/timer.c \
-    src/core/iomgr/timer_heap.c \
-    src/core/iomgr/udp_server.c \
-    src/core/iomgr/wakeup_fd_eventfd.c \
-    src/core/iomgr/wakeup_fd_nospecial.c \
-    src/core/iomgr/wakeup_fd_pipe.c \
-    src/core/iomgr/wakeup_fd_posix.c \
-    src/core/iomgr/workqueue_posix.c \
-    src/core/iomgr/workqueue_windows.c \
-    src/core/json/json.c \
-    src/core/json/json_reader.c \
-    src/core/json/json_string.c \
-    src/core/json/json_writer.c \
-    src/core/proto/grpc/lb/v0/load_balancer.pb.c \
-    src/core/surface/alarm.c \
-    src/core/surface/api_trace.c \
-    src/core/surface/byte_buffer.c \
-    src/core/surface/byte_buffer_reader.c \
-    src/core/surface/call.c \
-    src/core/surface/call_details.c \
-    src/core/surface/call_log_batch.c \
-    src/core/surface/channel.c \
-    src/core/surface/channel_connectivity.c \
-    src/core/surface/channel_create.c \
-    src/core/surface/channel_init.c \
-    src/core/surface/channel_ping.c \
-    src/core/surface/channel_stack_type.c \
-    src/core/surface/completion_queue.c \
-    src/core/surface/event_string.c \
-    src/core/surface/init.c \
-    src/core/surface/lame_client.c \
-    src/core/surface/metadata_array.c \
-    src/core/surface/server.c \
-    src/core/surface/server_chttp2.c \
-    src/core/surface/validate_metadata.c \
-    src/core/surface/version.c \
-    src/core/transport/byte_stream.c \
-    src/core/transport/chttp2/alpn.c \
-    src/core/transport/chttp2/bin_encoder.c \
-    src/core/transport/chttp2/frame_data.c \
-    src/core/transport/chttp2/frame_goaway.c \
-    src/core/transport/chttp2/frame_ping.c \
-    src/core/transport/chttp2/frame_rst_stream.c \
-    src/core/transport/chttp2/frame_settings.c \
-    src/core/transport/chttp2/frame_window_update.c \
-    src/core/transport/chttp2/hpack_encoder.c \
-    src/core/transport/chttp2/hpack_parser.c \
-    src/core/transport/chttp2/hpack_table.c \
-    src/core/transport/chttp2/huffsyms.c \
-    src/core/transport/chttp2/incoming_metadata.c \
-    src/core/transport/chttp2/parsing.c \
-    src/core/transport/chttp2/status_conversion.c \
-    src/core/transport/chttp2/stream_lists.c \
-    src/core/transport/chttp2/stream_map.c \
-    src/core/transport/chttp2/timeout_encoding.c \
-    src/core/transport/chttp2/varint.c \
-    src/core/transport/chttp2/writing.c \
-    src/core/transport/chttp2_transport.c \
-    src/core/transport/connectivity_state.c \
-    src/core/transport/metadata.c \
-    src/core/transport/metadata_batch.c \
-    src/core/transport/static_metadata.c \
-    src/core/transport/transport.c \
-    src/core/transport/transport_op_string.c \
-    src/core/census/context.c \
-    src/core/census/initialize.c \
-    src/core/census/mlog.c \
-    src/core/census/operation.c \
-    src/core/census/placeholders.c \
-    src/core/census/tracing.c \
+    src/core/lib/surface/init.c \
+    src/core/lib/surface/init_unsecure.c \
+    src/core/lib/channel/channel_args.c \
+    src/core/lib/channel/channel_stack.c \
+    src/core/lib/channel/channel_stack_builder.c \
+    src/core/lib/channel/compress_filter.c \
+    src/core/lib/channel/connected_channel.c \
+    src/core/lib/channel/http_client_filter.c \
+    src/core/lib/channel/http_server_filter.c \
+    src/core/lib/compression/compression_algorithm.c \
+    src/core/lib/compression/message_compress.c \
+    src/core/lib/debug/trace.c \
+    src/core/lib/http/format_request.c \
+    src/core/lib/http/httpcli.c \
+    src/core/lib/http/parser.c \
+    src/core/lib/iomgr/closure.c \
+    src/core/lib/iomgr/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_posix.c \
+    src/core/lib/iomgr/exec_ctx.c \
+    src/core/lib/iomgr/executor.c \
+    src/core/lib/iomgr/iocp_windows.c \
+    src/core/lib/iomgr/iomgr.c \
+    src/core/lib/iomgr/iomgr_posix.c \
+    src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/pollset_set_windows.c \
+    src/core/lib/iomgr/pollset_windows.c \
+    src/core/lib/iomgr/resolve_address_posix.c \
+    src/core/lib/iomgr/resolve_address_windows.c \
+    src/core/lib/iomgr/sockaddr_utils.c \
+    src/core/lib/iomgr/socket_utils_common_posix.c \
+    src/core/lib/iomgr/socket_utils_linux.c \
+    src/core/lib/iomgr/socket_utils_posix.c \
+    src/core/lib/iomgr/socket_windows.c \
+    src/core/lib/iomgr/tcp_client_posix.c \
+    src/core/lib/iomgr/tcp_client_windows.c \
+    src/core/lib/iomgr/tcp_posix.c \
+    src/core/lib/iomgr/tcp_server_posix.c \
+    src/core/lib/iomgr/tcp_server_windows.c \
+    src/core/lib/iomgr/tcp_windows.c \
+    src/core/lib/iomgr/time_averaged_stats.c \
+    src/core/lib/iomgr/timer.c \
+    src/core/lib/iomgr/timer_heap.c \
+    src/core/lib/iomgr/udp_server.c \
+    src/core/lib/iomgr/unix_sockets_posix.c \
+    src/core/lib/iomgr/unix_sockets_posix_noop.c \
+    src/core/lib/iomgr/wakeup_fd_eventfd.c \
+    src/core/lib/iomgr/wakeup_fd_nospecial.c \
+    src/core/lib/iomgr/wakeup_fd_pipe.c \
+    src/core/lib/iomgr/wakeup_fd_posix.c \
+    src/core/lib/iomgr/workqueue_posix.c \
+    src/core/lib/iomgr/workqueue_windows.c \
+    src/core/lib/json/json.c \
+    src/core/lib/json/json_reader.c \
+    src/core/lib/json/json_string.c \
+    src/core/lib/json/json_writer.c \
+    src/core/lib/surface/alarm.c \
+    src/core/lib/surface/api_trace.c \
+    src/core/lib/surface/byte_buffer.c \
+    src/core/lib/surface/byte_buffer_reader.c \
+    src/core/lib/surface/call.c \
+    src/core/lib/surface/call_details.c \
+    src/core/lib/surface/call_log_batch.c \
+    src/core/lib/surface/channel.c \
+    src/core/lib/surface/channel_init.c \
+    src/core/lib/surface/channel_ping.c \
+    src/core/lib/surface/channel_stack_type.c \
+    src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/event_string.c \
+    src/core/lib/surface/lame_client.c \
+    src/core/lib/surface/metadata_array.c \
+    src/core/lib/surface/server.c \
+    src/core/lib/surface/validate_metadata.c \
+    src/core/lib/surface/version.c \
+    src/core/lib/transport/byte_stream.c \
+    src/core/lib/transport/connectivity_state.c \
+    src/core/lib/transport/metadata.c \
+    src/core/lib/transport/metadata_batch.c \
+    src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/transport.c \
+    src/core/lib/transport/transport_op_string.c \
+    src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
+    src/core/ext/transport/chttp2/transport/bin_encoder.c \
+    src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
+    src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/frame_data.c \
+    src/core/ext/transport/chttp2/transport/frame_goaway.c \
+    src/core/ext/transport/chttp2/transport/frame_ping.c \
+    src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+    src/core/ext/transport/chttp2/transport/frame_settings.c \
+    src/core/ext/transport/chttp2/transport/frame_window_update.c \
+    src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+    src/core/ext/transport/chttp2/transport/hpack_parser.c \
+    src/core/ext/transport/chttp2/transport/hpack_table.c \
+    src/core/ext/transport/chttp2/transport/huffsyms.c \
+    src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+    src/core/ext/transport/chttp2/transport/parsing.c \
+    src/core/ext/transport/chttp2/transport/status_conversion.c \
+    src/core/ext/transport/chttp2/transport/stream_lists.c \
+    src/core/ext/transport/chttp2/transport/stream_map.c \
+    src/core/ext/transport/chttp2/transport/timeout_encoding.c \
+    src/core/ext/transport/chttp2/transport/varint.c \
+    src/core/ext/transport/chttp2/transport/writing.c \
+    src/core/ext/transport/chttp2/alpn/alpn.c \
+    src/core/ext/transport/chttp2/client/insecure/channel_create.c \
+    src/core/ext/client_config/channel_connectivity.c \
+    src/core/ext/client_config/client_channel.c \
+    src/core/ext/client_config/client_channel_factory.c \
+    src/core/ext/client_config/client_config.c \
+    src/core/ext/client_config/client_config_plugin.c \
+    src/core/ext/client_config/connector.c \
+    src/core/ext/client_config/default_initial_connect_string.c \
+    src/core/ext/client_config/initial_connect_string.c \
+    src/core/ext/client_config/lb_policy.c \
+    src/core/ext/client_config/lb_policy_factory.c \
+    src/core/ext/client_config/lb_policy_registry.c \
+    src/core/ext/client_config/parse_address.c \
+    src/core/ext/client_config/resolver.c \
+    src/core/ext/client_config/resolver_factory.c \
+    src/core/ext/client_config/resolver_registry.c \
+    src/core/ext/client_config/subchannel.c \
+    src/core/ext/client_config/subchannel_call_holder.c \
+    src/core/ext/client_config/subchannel_index.c \
+    src/core/ext/client_config/uri_parser.c \
+    src/core/ext/resolver/dns/native/dns_resolver.c \
+    src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
+    src/core/ext/lb_policy/grpclb/load_balancer_api.c \
+    src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
+    src/core/ext/lb_policy/pick_first/pick_first.c \
+    src/core/ext/lb_policy/round_robin/round_robin.c \
+    src/core/ext/census/context.c \
+    src/core/ext/census/grpc_context.c \
+    src/core/ext/census/grpc_filter.c \
+    src/core/ext/census/grpc_plugin.c \
+    src/core/ext/census/initialize.c \
+    src/core/ext/census/mlog.c \
+    src/core/ext/census/operation.c \
+    src/core/ext/census/placeholders.c \
+    src/core/ext/census/tracing.c \
+    src/core/plugin_registry/grpc_unsecure_plugin_registry.c \
 
 PUBLIC_HEADERS_C += \
     include/grpc/byte_buffer.h \
@@ -2923,6 +2954,20 @@
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/status.h \
+    include/grpc/impl/codegen/alloc.h \
+    include/grpc/impl/codegen/atm.h \
+    include/grpc/impl/codegen/atm_gcc_atomic.h \
+    include/grpc/impl/codegen/atm_gcc_sync.h \
+    include/grpc/impl/codegen/atm_win32.h \
+    include/grpc/impl/codegen/log.h \
+    include/grpc/impl/codegen/port_platform.h \
+    include/grpc/impl/codegen/slice.h \
+    include/grpc/impl/codegen/slice_buffer.h \
+    include/grpc/impl/codegen/sync.h \
+    include/grpc/impl/codegen/sync_generic.h \
+    include/grpc/impl/codegen/sync_posix.h \
+    include/grpc/impl/codegen/sync_win32.h \
+    include/grpc/impl/codegen/time.h \
     include/grpc/census.h \
 
 LIBGRPC_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_UNSECURE_SRC))))
@@ -2963,7 +3008,7 @@
 
 
 LIBGRPC_ZOOKEEPER_SRC = \
-    src/core/client_config/resolvers/zookeeper_resolver.c \
+    src/core/ext/resolver/zookeeper/zookeeper_resolver.c \
 
 PUBLIC_HEADERS_C += \
     include/grpc/grpc_zookeeper.h \
@@ -3008,6 +3053,7 @@
 LIBRECONNECT_SERVER_SRC = \
     test/core/util/reconnect_server.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBRECONNECT_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBRECONNECT_SERVER_SRC))))
 
@@ -3046,6 +3092,7 @@
 LIBTEST_TCP_SERVER_SRC = \
     test/core/util/test_tcp_server.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBTEST_TCP_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBTEST_TCP_SERVER_SRC))))
 
@@ -3150,8 +3197,6 @@
     include/grpc++/support/async_unary_call.h \
     include/grpc++/support/byte_buffer.h \
     include/grpc++/support/channel_arguments.h \
-    include/grpc++/support/config.h \
-    include/grpc++/support/config_protobuf.h \
     include/grpc++/support/slice.h \
     include/grpc++/support/status.h \
     include/grpc++/support/status_code_enum.h \
@@ -3168,9 +3213,8 @@
     include/grpc++/impl/codegen/client_unary_call.h \
     include/grpc++/impl/codegen/completion_queue.h \
     include/grpc++/impl/codegen/completion_queue_tag.h \
-    include/grpc++/impl/codegen/config.h \
-    include/grpc++/impl/codegen/config_protobuf.h \
     include/grpc++/impl/codegen/core_codegen_interface.h \
+    include/grpc++/impl/codegen/create_auth_context.h \
     include/grpc++/impl/codegen/grpc_library.h \
     include/grpc++/impl/codegen/method_handler_impl.h \
     include/grpc++/impl/codegen/proto_utils.h \
@@ -3190,6 +3234,30 @@
     include/grpc++/impl/codegen/sync_no_cxx11.h \
     include/grpc++/impl/codegen/sync_stream.h \
     include/grpc++/impl/codegen/time.h \
+    include/grpc/impl/codegen/byte_buffer.h \
+    include/grpc/impl/codegen/compression_types.h \
+    include/grpc/impl/codegen/connectivity_state.h \
+    include/grpc/impl/codegen/grpc_types.h \
+    include/grpc/impl/codegen/propagation_bits.h \
+    include/grpc/impl/codegen/status.h \
+    include/grpc/impl/codegen/alloc.h \
+    include/grpc/impl/codegen/atm.h \
+    include/grpc/impl/codegen/atm_gcc_atomic.h \
+    include/grpc/impl/codegen/atm_gcc_sync.h \
+    include/grpc/impl/codegen/atm_win32.h \
+    include/grpc/impl/codegen/log.h \
+    include/grpc/impl/codegen/port_platform.h \
+    include/grpc/impl/codegen/slice.h \
+    include/grpc/impl/codegen/slice_buffer.h \
+    include/grpc/impl/codegen/sync.h \
+    include/grpc/impl/codegen/sync_generic.h \
+    include/grpc/impl/codegen/sync_posix.h \
+    include/grpc/impl/codegen/sync_win32.h \
+    include/grpc/impl/codegen/time.h \
+    include/grpc++/impl/codegen/config.h \
+    include/grpc++/impl/codegen/config_protobuf.h \
+    include/grpc++/support/config.h \
+    include/grpc++/support/config_protobuf.h \
 
 LIBGRPC++_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_SRC))))
 
@@ -3254,96 +3322,10 @@
 endif
 
 
-LIBGRPC++_CODEGEN_LIB_SRC = \
-    src/cpp/codegen/codegen_init.cc \
-
-PUBLIC_HEADERS_CXX += \
-    include/grpc/impl/codegen/alloc.h \
-    include/grpc/impl/codegen/atm.h \
-    include/grpc/impl/codegen/atm_gcc_atomic.h \
-    include/grpc/impl/codegen/atm_gcc_sync.h \
-    include/grpc/impl/codegen/atm_win32.h \
-    include/grpc/impl/codegen/log.h \
-    include/grpc/impl/codegen/port_platform.h \
-    include/grpc/impl/codegen/slice.h \
-    include/grpc/impl/codegen/slice_buffer.h \
-    include/grpc/impl/codegen/sync.h \
-    include/grpc/impl/codegen/sync_generic.h \
-    include/grpc/impl/codegen/sync_posix.h \
-    include/grpc/impl/codegen/sync_win32.h \
-    include/grpc/impl/codegen/time.h \
-    include/grpc/impl/codegen/byte_buffer.h \
-    include/grpc/impl/codegen/compression_types.h \
-    include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/grpc_types.h \
-    include/grpc/impl/codegen/propagation_bits.h \
-    include/grpc/impl/codegen/status.h \
-    include/grpc++/impl/codegen/async_stream.h \
-    include/grpc++/impl/codegen/async_unary_call.h \
-    include/grpc++/impl/codegen/call.h \
-    include/grpc++/impl/codegen/call_hook.h \
-    include/grpc++/impl/codegen/channel_interface.h \
-    include/grpc++/impl/codegen/client_context.h \
-    include/grpc++/impl/codegen/client_unary_call.h \
-    include/grpc++/impl/codegen/completion_queue.h \
-    include/grpc++/impl/codegen/completion_queue_tag.h \
-    include/grpc++/impl/codegen/config.h \
-    include/grpc++/impl/codegen/config_protobuf.h \
-    include/grpc++/impl/codegen/core_codegen_interface.h \
-    include/grpc++/impl/codegen/grpc_library.h \
-    include/grpc++/impl/codegen/method_handler_impl.h \
-    include/grpc++/impl/codegen/proto_utils.h \
-    include/grpc++/impl/codegen/rpc_method.h \
-    include/grpc++/impl/codegen/rpc_service_method.h \
-    include/grpc++/impl/codegen/security/auth_context.h \
-    include/grpc++/impl/codegen/serialization_traits.h \
-    include/grpc++/impl/codegen/server_context.h \
-    include/grpc++/impl/codegen/server_interface.h \
-    include/grpc++/impl/codegen/service_type.h \
-    include/grpc++/impl/codegen/status.h \
-    include/grpc++/impl/codegen/status_code_enum.h \
-    include/grpc++/impl/codegen/string_ref.h \
-    include/grpc++/impl/codegen/stub_options.h \
-    include/grpc++/impl/codegen/sync.h \
-    include/grpc++/impl/codegen/sync_cxx11.h \
-    include/grpc++/impl/codegen/sync_no_cxx11.h \
-    include/grpc++/impl/codegen/sync_stream.h \
-    include/grpc++/impl/codegen/time.h \
-
-LIBGRPC++_CODEGEN_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CODEGEN_LIB_SRC))))
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
-
-$(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a: protobuf_dep_error
-
-
-else
-
-$(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a: $(ZLIB_DEP)  $(PROTOBUF_DEP) $(LIBGRPC++_CODEGEN_LIB_OBJS) 
-	$(E) "[AR]      Creating $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
-	$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a $(LIBGRPC++_CODEGEN_LIB_OBJS) 
-ifeq ($(SYSTEM),Darwin)
-	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
-endif
-
-
-
-
-endif
-
-ifneq ($(NO_DEPS),true)
--include $(LIBGRPC++_CODEGEN_LIB_OBJS:.o=.dep)
-endif
-
-
 LIBGRPC++_TEST_CONFIG_SRC = \
     test/cpp/util/test_config.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBGRPC++_TEST_CONFIG_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_CONFIG_SRC))))
 
@@ -3401,6 +3383,7 @@
     test/cpp/util/subprocess.cc \
     test/cpp/util/test_credentials_provider.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBGRPC++_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_UTIL_SRC))))
 
@@ -3517,8 +3500,6 @@
     include/grpc++/support/async_unary_call.h \
     include/grpc++/support/byte_buffer.h \
     include/grpc++/support/channel_arguments.h \
-    include/grpc++/support/config.h \
-    include/grpc++/support/config_protobuf.h \
     include/grpc++/support/slice.h \
     include/grpc++/support/status.h \
     include/grpc++/support/status_code_enum.h \
@@ -3535,9 +3516,8 @@
     include/grpc++/impl/codegen/client_unary_call.h \
     include/grpc++/impl/codegen/completion_queue.h \
     include/grpc++/impl/codegen/completion_queue_tag.h \
-    include/grpc++/impl/codegen/config.h \
-    include/grpc++/impl/codegen/config_protobuf.h \
     include/grpc++/impl/codegen/core_codegen_interface.h \
+    include/grpc++/impl/codegen/create_auth_context.h \
     include/grpc++/impl/codegen/grpc_library.h \
     include/grpc++/impl/codegen/method_handler_impl.h \
     include/grpc++/impl/codegen/proto_utils.h \
@@ -3557,6 +3537,30 @@
     include/grpc++/impl/codegen/sync_no_cxx11.h \
     include/grpc++/impl/codegen/sync_stream.h \
     include/grpc++/impl/codegen/time.h \
+    include/grpc/impl/codegen/byte_buffer.h \
+    include/grpc/impl/codegen/compression_types.h \
+    include/grpc/impl/codegen/connectivity_state.h \
+    include/grpc/impl/codegen/grpc_types.h \
+    include/grpc/impl/codegen/propagation_bits.h \
+    include/grpc/impl/codegen/status.h \
+    include/grpc/impl/codegen/alloc.h \
+    include/grpc/impl/codegen/atm.h \
+    include/grpc/impl/codegen/atm_gcc_atomic.h \
+    include/grpc/impl/codegen/atm_gcc_sync.h \
+    include/grpc/impl/codegen/atm_win32.h \
+    include/grpc/impl/codegen/log.h \
+    include/grpc/impl/codegen/port_platform.h \
+    include/grpc/impl/codegen/slice.h \
+    include/grpc/impl/codegen/slice_buffer.h \
+    include/grpc/impl/codegen/sync.h \
+    include/grpc/impl/codegen/sync_generic.h \
+    include/grpc/impl/codegen/sync_posix.h \
+    include/grpc/impl/codegen/sync_win32.h \
+    include/grpc/impl/codegen/time.h \
+    include/grpc++/impl/codegen/config.h \
+    include/grpc++/impl/codegen/config_protobuf.h \
+    include/grpc++/support/config.h \
+    include/grpc++/support/config_protobuf.h \
 
 LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC))))
 
@@ -3583,18 +3587,18 @@
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/grpc_unsecure.$(SHARED_EXT)
+$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/grpc_unsecure.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_unsecure.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_unsecure.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp -lgrpc-imp
 else
-$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT)
+$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure -lgrpc
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure -lgrpc
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).so.0
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION).so
 endif
@@ -3610,25 +3614,16 @@
 LIBGRPC_PLUGIN_SUPPORT_SRC = \
     src/compiler/cpp_generator.cc \
     src/compiler/csharp_generator.cc \
+    src/compiler/node_generator.cc \
     src/compiler/objective_c_generator.cc \
     src/compiler/python_generator.cc \
     src/compiler/ruby_generator.cc \
 
 PUBLIC_HEADERS_CXX += \
-    include/grpc/impl/codegen/alloc.h \
-    include/grpc/impl/codegen/atm.h \
-    include/grpc/impl/codegen/atm_gcc_atomic.h \
-    include/grpc/impl/codegen/atm_gcc_sync.h \
-    include/grpc/impl/codegen/atm_win32.h \
-    include/grpc/impl/codegen/log.h \
-    include/grpc/impl/codegen/port_platform.h \
-    include/grpc/impl/codegen/slice.h \
-    include/grpc/impl/codegen/slice_buffer.h \
-    include/grpc/impl/codegen/sync.h \
-    include/grpc/impl/codegen/sync_generic.h \
-    include/grpc/impl/codegen/sync_posix.h \
-    include/grpc/impl/codegen/sync_win32.h \
-    include/grpc/impl/codegen/time.h \
+    include/grpc++/support/config.h \
+    include/grpc++/support/config_protobuf.h \
+    include/grpc++/impl/codegen/config.h \
+    include/grpc++/impl/codegen/config_protobuf.h \
 
 LIBGRPC_PLUGIN_SUPPORT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_PLUGIN_SUPPORT_SRC))))
 
@@ -3665,6 +3660,7 @@
     $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
     test/cpp/interop/client_helper.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBINTEROP_CLIENT_HELPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_CLIENT_HELPER_SRC))))
 
@@ -3718,6 +3714,7 @@
     test/cpp/interop/client.cc \
     test/cpp/interop/interop_client.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBINTEROP_CLIENT_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_CLIENT_MAIN_SRC))))
 
@@ -3768,6 +3765,7 @@
 LIBINTEROP_SERVER_HELPER_SRC = \
     test/cpp/interop/server_helper.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBINTEROP_SERVER_HELPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_HELPER_SRC))))
 
@@ -3819,6 +3817,7 @@
     $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \
     test/cpp/interop/server_main.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBINTEROP_SERVER_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_MAIN_SRC))))
 
@@ -3884,6 +3883,7 @@
     test/cpp/qps/usage_timer.cc \
     test/cpp/util/benchmark_config.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBQPS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBQPS_SRC))))
 
@@ -3943,6 +3943,7 @@
 LIBGRPC_CSHARP_EXT_SRC = \
     src/csharp/ext/grpc_csharp_ext.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBGRPC_CSHARP_EXT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CSHARP_EXT_SRC))))
 
@@ -4069,6 +4070,7 @@
     third_party/boringssl/crypto/bn/shift.c \
     third_party/boringssl/crypto/bn/sqrt.c \
     third_party/boringssl/crypto/buf/buf.c \
+    third_party/boringssl/crypto/bytestring/asn1_compat.c \
     third_party/boringssl/crypto/bytestring/ber.c \
     third_party/boringssl/crypto/bytestring/cbb.c \
     third_party/boringssl/crypto/bytestring/cbs.c \
@@ -4092,6 +4094,7 @@
     third_party/boringssl/crypto/cpu-intel.c \
     third_party/boringssl/crypto/crypto.c \
     third_party/boringssl/crypto/curve25519/curve25519.c \
+    third_party/boringssl/crypto/curve25519/x25519-x86_64.c \
     third_party/boringssl/crypto/des/des.c \
     third_party/boringssl/crypto/dh/check.c \
     third_party/boringssl/crypto/dh/dh.c \
@@ -4283,6 +4286,7 @@
     third_party/boringssl/ssl/ssl_buffer.c \
     third_party/boringssl/ssl/ssl_cert.c \
     third_party/boringssl/ssl/ssl_cipher.c \
+    third_party/boringssl/ssl/ssl_ecdh.c \
     third_party/boringssl/ssl/ssl_file.c \
     third_party/boringssl/ssl/ssl_lib.c \
     third_party/boringssl/ssl/ssl_rsa.c \
@@ -4292,6 +4296,7 @@
     third_party/boringssl/ssl/t1_lib.c \
     third_party/boringssl/ssl/tls_record.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_SRC))))
 
@@ -4320,6 +4325,7 @@
     third_party/boringssl/crypto/test/malloc.cc \
     third_party/boringssl/crypto/test/test_util.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_TEST_UTIL_SRC))))
 
@@ -4357,6 +4363,7 @@
 LIBBORINGSSL_AES_TEST_LIB_SRC = \
     third_party/boringssl/crypto/aes/aes_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_AES_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_AES_TEST_LIB_SRC))))
 
@@ -4394,6 +4401,7 @@
 LIBBORINGSSL_ASN1_TEST_LIB_SRC = \
     third_party/boringssl/crypto/asn1/asn1_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_ASN1_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ASN1_TEST_LIB_SRC))))
 
@@ -4431,6 +4439,7 @@
 LIBBORINGSSL_BASE64_TEST_LIB_SRC = \
     third_party/boringssl/crypto/base64/base64_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_BASE64_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BASE64_TEST_LIB_SRC))))
 
@@ -4468,6 +4477,7 @@
 LIBBORINGSSL_BIO_TEST_LIB_SRC = \
     third_party/boringssl/crypto/bio/bio_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_BIO_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BIO_TEST_LIB_SRC))))
 
@@ -4505,6 +4515,7 @@
 LIBBORINGSSL_BN_TEST_LIB_SRC = \
     third_party/boringssl/crypto/bn/bn_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_BN_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BN_TEST_LIB_SRC))))
 
@@ -4542,6 +4553,7 @@
 LIBBORINGSSL_BYTESTRING_TEST_LIB_SRC = \
     third_party/boringssl/crypto/bytestring/bytestring_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_BYTESTRING_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BYTESTRING_TEST_LIB_SRC))))
 
@@ -4579,6 +4591,7 @@
 LIBBORINGSSL_AEAD_TEST_LIB_SRC = \
     third_party/boringssl/crypto/cipher/aead_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_AEAD_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_AEAD_TEST_LIB_SRC))))
 
@@ -4616,6 +4629,7 @@
 LIBBORINGSSL_CIPHER_TEST_LIB_SRC = \
     third_party/boringssl/crypto/cipher/cipher_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_CIPHER_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_CIPHER_TEST_LIB_SRC))))
 
@@ -4653,6 +4667,7 @@
 LIBBORINGSSL_CMAC_TEST_LIB_SRC = \
     third_party/boringssl/crypto/cmac/cmac_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_CMAC_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_CMAC_TEST_LIB_SRC))))
 
@@ -4690,6 +4705,7 @@
 LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_SRC = \
     third_party/boringssl/crypto/constant_time_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_SRC))))
 
@@ -4716,6 +4732,7 @@
 LIBBORINGSSL_ED25519_TEST_LIB_SRC = \
     third_party/boringssl/crypto/curve25519/ed25519_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_ED25519_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ED25519_TEST_LIB_SRC))))
 
@@ -4753,6 +4770,7 @@
 LIBBORINGSSL_X25519_TEST_LIB_SRC = \
     third_party/boringssl/crypto/curve25519/x25519_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_X25519_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_X25519_TEST_LIB_SRC))))
 
@@ -4790,6 +4808,7 @@
 LIBBORINGSSL_DH_TEST_LIB_SRC = \
     third_party/boringssl/crypto/dh/dh_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_DH_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_DH_TEST_LIB_SRC))))
 
@@ -4827,6 +4846,7 @@
 LIBBORINGSSL_DIGEST_TEST_LIB_SRC = \
     third_party/boringssl/crypto/digest/digest_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_DIGEST_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_DIGEST_TEST_LIB_SRC))))
 
@@ -4864,6 +4884,7 @@
 LIBBORINGSSL_DSA_TEST_LIB_SRC = \
     third_party/boringssl/crypto/dsa/dsa_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_DSA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_DSA_TEST_LIB_SRC))))
 
@@ -4890,6 +4911,7 @@
 LIBBORINGSSL_EC_TEST_LIB_SRC = \
     third_party/boringssl/crypto/ec/ec_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_EC_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EC_TEST_LIB_SRC))))
 
@@ -4927,6 +4949,7 @@
 LIBBORINGSSL_EXAMPLE_MUL_LIB_SRC = \
     third_party/boringssl/crypto/ec/example_mul.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_EXAMPLE_MUL_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EXAMPLE_MUL_LIB_SRC))))
 
@@ -4953,6 +4976,7 @@
 LIBBORINGSSL_ECDSA_TEST_LIB_SRC = \
     third_party/boringssl/crypto/ecdsa/ecdsa_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_ECDSA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ECDSA_TEST_LIB_SRC))))
 
@@ -4990,6 +5014,7 @@
 LIBBORINGSSL_ERR_TEST_LIB_SRC = \
     third_party/boringssl/crypto/err/err_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_ERR_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ERR_TEST_LIB_SRC))))
 
@@ -5027,6 +5052,7 @@
 LIBBORINGSSL_EVP_EXTRA_TEST_LIB_SRC = \
     third_party/boringssl/crypto/evp/evp_extra_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_EVP_EXTRA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EVP_EXTRA_TEST_LIB_SRC))))
 
@@ -5064,6 +5090,7 @@
 LIBBORINGSSL_EVP_TEST_LIB_SRC = \
     third_party/boringssl/crypto/evp/evp_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_EVP_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EVP_TEST_LIB_SRC))))
 
@@ -5101,6 +5128,7 @@
 LIBBORINGSSL_PBKDF_TEST_LIB_SRC = \
     third_party/boringssl/crypto/evp/pbkdf_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_PBKDF_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PBKDF_TEST_LIB_SRC))))
 
@@ -5138,6 +5166,7 @@
 LIBBORINGSSL_HKDF_TEST_LIB_SRC = \
     third_party/boringssl/crypto/hkdf/hkdf_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_HKDF_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_HKDF_TEST_LIB_SRC))))
 
@@ -5164,6 +5193,7 @@
 LIBBORINGSSL_HMAC_TEST_LIB_SRC = \
     third_party/boringssl/crypto/hmac/hmac_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_HMAC_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_HMAC_TEST_LIB_SRC))))
 
@@ -5201,6 +5231,7 @@
 LIBBORINGSSL_LHASH_TEST_LIB_SRC = \
     third_party/boringssl/crypto/lhash/lhash_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_LHASH_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_LHASH_TEST_LIB_SRC))))
 
@@ -5227,6 +5258,7 @@
 LIBBORINGSSL_GCM_TEST_LIB_SRC = \
     third_party/boringssl/crypto/modes/gcm_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_GCM_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_GCM_TEST_LIB_SRC))))
 
@@ -5253,6 +5285,7 @@
 LIBBORINGSSL_PKCS12_TEST_LIB_SRC = \
     third_party/boringssl/crypto/pkcs8/pkcs12_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_PKCS12_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PKCS12_TEST_LIB_SRC))))
 
@@ -5290,6 +5323,7 @@
 LIBBORINGSSL_PKCS8_TEST_LIB_SRC = \
     third_party/boringssl/crypto/pkcs8/pkcs8_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_PKCS8_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PKCS8_TEST_LIB_SRC))))
 
@@ -5327,6 +5361,7 @@
 LIBBORINGSSL_POLY1305_TEST_LIB_SRC = \
     third_party/boringssl/crypto/poly1305/poly1305_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_POLY1305_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_POLY1305_TEST_LIB_SRC))))
 
@@ -5364,6 +5399,7 @@
 LIBBORINGSSL_REFCOUNT_TEST_LIB_SRC = \
     third_party/boringssl/crypto/refcount_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_REFCOUNT_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_REFCOUNT_TEST_LIB_SRC))))
 
@@ -5390,6 +5426,7 @@
 LIBBORINGSSL_RSA_TEST_LIB_SRC = \
     third_party/boringssl/crypto/rsa/rsa_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_RSA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_RSA_TEST_LIB_SRC))))
 
@@ -5427,6 +5464,7 @@
 LIBBORINGSSL_THREAD_TEST_LIB_SRC = \
     third_party/boringssl/crypto/thread_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_THREAD_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_THREAD_TEST_LIB_SRC))))
 
@@ -5453,6 +5491,7 @@
 LIBBORINGSSL_PKCS7_TEST_LIB_SRC = \
     third_party/boringssl/crypto/x509/pkcs7_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_PKCS7_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PKCS7_TEST_LIB_SRC))))
 
@@ -5476,9 +5515,48 @@
 endif
 
 
+LIBBORINGSSL_X509_TEST_LIB_SRC = \
+    third_party/boringssl/crypto/x509/x509_test.cc \
+
+PUBLIC_HEADERS_CXX += \
+
+LIBBORINGSSL_X509_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_X509_TEST_LIB_SRC))))
+
+$(LIBBORINGSSL_X509_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
+$(LIBBORINGSSL_X509_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
+
+$(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a: protobuf_dep_error
+
+
+else
+
+$(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a: $(ZLIB_DEP)  $(PROTOBUF_DEP) $(LIBBORINGSSL_X509_TEST_LIB_OBJS) 
+	$(E) "[AR]      Creating $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a
+	$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBBORINGSSL_X509_TEST_LIB_OBJS) 
+ifeq ($(SYSTEM),Darwin)
+	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a
+endif
+
+
+
+
+endif
+
+ifneq ($(NO_DEPS),true)
+-include $(LIBBORINGSSL_X509_TEST_LIB_OBJS:.o=.dep)
+endif
+
+
 LIBBORINGSSL_TAB_TEST_LIB_SRC = \
     third_party/boringssl/crypto/x509v3/tab_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_TAB_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_TAB_TEST_LIB_SRC))))
 
@@ -5505,6 +5583,7 @@
 LIBBORINGSSL_V3NAME_TEST_LIB_SRC = \
     third_party/boringssl/crypto/x509v3/v3name_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_V3NAME_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_V3NAME_TEST_LIB_SRC))))
 
@@ -5531,6 +5610,7 @@
 LIBBORINGSSL_PQUEUE_TEST_LIB_SRC = \
     third_party/boringssl/ssl/pqueue/pqueue_test.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBORINGSSL_PQUEUE_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PQUEUE_TEST_LIB_SRC))))
 
@@ -5557,6 +5637,7 @@
 LIBBORINGSSL_SSL_TEST_LIB_SRC = \
     third_party/boringssl/ssl/ssl_test.cc \
 
+PUBLIC_HEADERS_CXX += \
 
 LIBBORINGSSL_SSL_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_SSL_TEST_LIB_SRC))))
 
@@ -5608,6 +5689,7 @@
     third_party/zlib/uncompr.c \
     third_party/zlib/zutil.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBZ_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBZ_SRC))))
 
@@ -5633,6 +5715,7 @@
 LIBBAD_CLIENT_TEST_SRC = \
     test/core/bad_client/bad_client.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBAD_CLIENT_TEST_SRC))))
 
@@ -5671,6 +5754,7 @@
 LIBBAD_SSL_TEST_SERVER_SRC = \
     test/core/bad_ssl/server_common.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBBAD_SSL_TEST_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBAD_SSL_TEST_SERVER_SRC))))
 
@@ -5722,9 +5806,11 @@
     test/core/end2end/tests/default_host.c \
     test/core/end2end/tests/disappearing_server.c \
     test/core/end2end/tests/empty_batch.c \
+    test/core/end2end/tests/filter_causes_close.c \
     test/core/end2end/tests/graceful_server_shutdown.c \
     test/core/end2end/tests/high_initial_seqno.c \
     test/core/end2end/tests/hpack_size.c \
+    test/core/end2end/tests/idempotent_request.c \
     test/core/end2end/tests/invoke_large_request.c \
     test/core/end2end/tests/large_metadata.c \
     test/core/end2end/tests/max_concurrent_streams.c \
@@ -5745,6 +5831,7 @@
     test/core/end2end/tests/simple_request.c \
     test/core/end2end/tests/trailing_metadata.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBEND2END_TESTS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_TESTS_SRC))))
 
@@ -5795,9 +5882,11 @@
     test/core/end2end/tests/default_host.c \
     test/core/end2end/tests/disappearing_server.c \
     test/core/end2end/tests/empty_batch.c \
+    test/core/end2end/tests/filter_causes_close.c \
     test/core/end2end/tests/graceful_server_shutdown.c \
     test/core/end2end/tests/high_initial_seqno.c \
     test/core/end2end/tests/hpack_size.c \
+    test/core/end2end/tests/idempotent_request.c \
     test/core/end2end/tests/invoke_large_request.c \
     test/core/end2end/tests/large_metadata.c \
     test/core/end2end/tests/max_concurrent_streams.c \
@@ -5818,6 +5907,7 @@
     test/core/end2end/tests/simple_request.c \
     test/core/end2end/tests/trailing_metadata.c \
 
+PUBLIC_HEADERS_C += \
 
 LIBEND2END_NOSEC_TESTS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_NOSEC_TESTS_SRC))))
 
@@ -5971,6 +6061,38 @@
 endif
 
 
+API_FUZZER_SRC = \
+    test/core/end2end/fuzzers/api_fuzzer.c \
+
+API_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/api_fuzzer: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/api_fuzzer: $(API_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(API_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/api_fuzzer
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/api_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_api_fuzzer: $(API_FUZZER_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(API_FUZZER_OBJS:.o=.dep)
+endif
+endif
+
+
 BIN_ENCODER_TEST_SRC = \
     test/core/transport/chttp2/bin_encoder_test.c \
 
@@ -6195,6 +6317,38 @@
 endif
 
 
+CLIENT_FUZZER_SRC = \
+    test/core/end2end/fuzzers/client_fuzzer.c \
+
+CLIENT_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_FUZZER_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/client_fuzzer: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/client_fuzzer: $(CLIENT_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(CLIENT_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/client_fuzzer
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/client_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_client_fuzzer: $(CLIENT_FUZZER_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(CLIENT_FUZZER_OBJS:.o=.dep)
+endif
+endif
+
+
 COMPRESSION_TEST_SRC = \
     test/core/compression/compression_test.c \
 
@@ -6643,6 +6797,38 @@
 endif
 
 
+GOAWAY_SERVER_TEST_SRC = \
+    test/core/end2end/goaway_server_test.c \
+
+GOAWAY_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GOAWAY_SERVER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/goaway_server_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/goaway_server_test: $(GOAWAY_SERVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(GOAWAY_SERVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/goaway_server_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/goaway_server_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_goaway_server_test: $(GOAWAY_SERVER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GOAWAY_SERVER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 GPR_AVL_TEST_SRC = \
     test/core/support/avl_test.c \
 
@@ -7699,6 +7885,38 @@
 endif
 
 
+HPACK_PARSER_FUZZER_TEST_SRC = \
+    test/core/transport/chttp2/hpack_parser_fuzzer_test.c \
+
+HPACK_PARSER_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_FUZZER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test: $(HPACK_PARSER_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(HPACK_PARSER_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/hpack_parser_fuzzer_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_hpack_parser_fuzzer_test: $(HPACK_PARSER_FUZZER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HPACK_PARSER_FUZZER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 HPACK_PARSER_TEST_SRC = \
     test/core/transport/chttp2/hpack_parser_test.c \
 
@@ -7763,8 +7981,72 @@
 endif
 
 
+HTTP_FUZZER_TEST_SRC = \
+    test/core/http/fuzzer.c \
+
+HTTP_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_FUZZER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/http_fuzzer_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/http_fuzzer_test: $(HTTP_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(HTTP_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_fuzzer_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/http/fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_http_fuzzer_test: $(HTTP_FUZZER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HTTP_FUZZER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+HTTP_PARSER_TEST_SRC = \
+    test/core/http/parser_test.c \
+
+HTTP_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_PARSER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/http_parser_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/http_parser_test: $(HTTP_PARSER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(HTTP_PARSER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/http_parser_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/http/parser_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_http_parser_test: $(HTTP_PARSER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HTTP_PARSER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 HTTPCLI_FORMAT_REQUEST_TEST_SRC = \
-    test/core/httpcli/format_request_test.c \
+    test/core/http/format_request_test.c \
 
 HTTPCLI_FORMAT_REQUEST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_FORMAT_REQUEST_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
@@ -7784,7 +8066,7 @@
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/httpcli/format_request_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/http/format_request_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 deps_httpcli_format_request_test: $(HTTPCLI_FORMAT_REQUEST_TEST_OBJS:.o=.dep)
 
@@ -7795,40 +8077,8 @@
 endif
 
 
-HTTPCLI_PARSER_TEST_SRC = \
-    test/core/httpcli/parser_test.c \
-
-HTTPCLI_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_PARSER_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/httpcli_parser_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/httpcli_parser_test: $(HTTPCLI_PARSER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(HTTPCLI_PARSER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/httpcli_parser_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/httpcli/parser_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_httpcli_parser_test: $(HTTPCLI_PARSER_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(HTTPCLI_PARSER_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 HTTPCLI_TEST_SRC = \
-    test/core/httpcli/httpcli_test.c \
+    test/core/http/httpcli_test.c \
 
 HTTPCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
@@ -7848,7 +8098,7 @@
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/httpcli/httpcli_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/http/httpcli_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 deps_httpcli_test: $(HTTPCLI_TEST_OBJS:.o=.dep)
 
@@ -7860,7 +8110,7 @@
 
 
 HTTPSCLI_TEST_SRC = \
-    test/core/httpcli/httpscli_test.c \
+    test/core/http/httpscli_test.c \
 
 HTTPSCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPSCLI_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
@@ -7880,7 +8130,7 @@
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/httpcli/httpscli_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/http/httpscli_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 deps_httpscli_test: $(HTTPSCLI_TEST_OBJS:.o=.dep)
 
@@ -7923,6 +8173,102 @@
 endif
 
 
+INTERNAL_API_CANARY_IOMGR_TEST_SRC = \
+    test/core/internal_api_canaries/iomgr.c \
+
+INTERNAL_API_CANARY_IOMGR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTERNAL_API_CANARY_IOMGR_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test: $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/internal_api_canaries/iomgr.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_internal_api_canary_iomgr_test: $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+INTERNAL_API_CANARY_SUPPORT_TEST_SRC = \
+    test/core/internal_api_canaries/iomgr.c \
+
+INTERNAL_API_CANARY_SUPPORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTERNAL_API_CANARY_SUPPORT_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/internal_api_canary_support_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/internal_api_canary_support_test: $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/internal_api_canary_support_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/internal_api_canaries/iomgr.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_internal_api_canary_support_test: $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+INTERNAL_API_CANARY_TRANSPORT_TEST_SRC = \
+    test/core/internal_api_canaries/iomgr.c \
+
+INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTERNAL_API_CANARY_TRANSPORT_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/internal_api_canary_transport_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/internal_api_canary_transport_test: $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/internal_api_canary_transport_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/internal_api_canaries/iomgr.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_internal_api_canary_transport_test: $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 INVALID_CALL_ARGUMENT_TEST_SRC = \
     test/core/end2end/invalid_call_argument_test.c \
 
@@ -7955,6 +8301,38 @@
 endif
 
 
+JSON_FUZZER_TEST_SRC = \
+    test/core/json/fuzzer.c \
+
+JSON_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_FUZZER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/json_fuzzer_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/json_fuzzer_test: $(JSON_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(JSON_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/json_fuzzer_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/json/fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_json_fuzzer_test: $(JSON_FUZZER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(JSON_FUZZER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 JSON_REWRITE_SRC = \
     test/core/json/json_rewrite.c \
 
@@ -8307,6 +8685,70 @@
 endif
 
 
+NANOPB_FUZZER_RESPONSE_TEST_SRC = \
+    test/core/nanopb/fuzzer_response.c \
+
+NANOPB_FUZZER_RESPONSE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_RESPONSE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test: $(NANOPB_FUZZER_RESPONSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(NANOPB_FUZZER_RESPONSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_response.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_nanopb_fuzzer_response_test: $(NANOPB_FUZZER_RESPONSE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(NANOPB_FUZZER_RESPONSE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+NANOPB_FUZZER_SERVERLIST_TEST_SRC = \
+    test/core/nanopb/fuzzer_serverlist.c \
+
+NANOPB_FUZZER_SERVERLIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_SERVERLIST_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test: $(NANOPB_FUZZER_SERVERLIST_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(NANOPB_FUZZER_SERVERLIST_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_serverlist.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_nanopb_fuzzer_serverlist_test: $(NANOPB_FUZZER_SERVERLIST_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(NANOPB_FUZZER_SERVERLIST_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 NO_SERVER_TEST_SRC = \
     test/core/end2end/no_server_test.c \
 
@@ -8467,6 +8909,38 @@
 endif
 
 
+SERVER_FUZZER_SRC = \
+    test/core/end2end/fuzzers/server_fuzzer.c \
+
+SERVER_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_FUZZER_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/server_fuzzer: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/server_fuzzer: $(SERVER_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(SERVER_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/server_fuzzer
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/server_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_server_fuzzer: $(SERVER_FUZZER_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SERVER_FUZZER_OBJS:.o=.dep)
+endif
+endif
+
+
 SERVER_TEST_SRC = \
     test/core/surface/server_test.c \
 
@@ -9011,6 +9485,38 @@
 endif
 
 
+URI_FUZZER_TEST_SRC = \
+    test/core/client_config/uri_fuzzer_test.c \
+
+URI_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_FUZZER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/uri_fuzzer_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/uri_fuzzer_test: $(URI_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(URI_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/uri_fuzzer_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/client_config/uri_fuzzer_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_uri_fuzzer_test: $(URI_FUZZER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(URI_FUZZER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 URI_PARSER_TEST_SRC = \
     test/core/client_config/uri_parser_test.c \
 
@@ -9462,21 +9968,22 @@
 endif
 
 
-CODEGEN_TEST_SRC = \
+CODEGEN_TEST_FULL_SRC = \
     $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \
-    test/cpp/codegen/codegen_test.cc \
+    test/cpp/codegen/codegen_test_full.cc \
+    src/cpp/codegen/codegen_init.cc \
 
-CODEGEN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CODEGEN_TEST_SRC))))
+CODEGEN_TEST_FULL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CODEGEN_TEST_FULL_SRC))))
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
 
-$(BINDIR)/$(CONFIG)/codegen_test: openssl_dep_error
+$(BINDIR)/$(CONFIG)/codegen_test_full: openssl_dep_error
 
 else
 
@@ -9487,41 +9994,110 @@
 
 # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
 
-$(BINDIR)/$(CONFIG)/codegen_test: protobuf_dep_error
+$(BINDIR)/$(CONFIG)/codegen_test_full: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/codegen_test: $(PROTOBUF_DEP) $(CODEGEN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(BINDIR)/$(CONFIG)/codegen_test_full: $(PROTOBUF_DEP) $(CODEGEN_TEST_FULL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test
+	$(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_FULL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test_full
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/perf_db.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/perf_db.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_full.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-deps_codegen_test: $(CODEGEN_TEST_OBJS:.o=.dep)
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_codegen_test_full: $(CODEGEN_TEST_FULL_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(CODEGEN_TEST_OBJS:.o=.dep)
+-include $(CODEGEN_TEST_FULL_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_full.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+
+
+CODEGEN_TEST_MINIMAL_SRC = \
+    $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \
+    test/cpp/codegen/codegen_test_minimal.cc \
+    src/cpp/codegen/codegen_init.cc \
+
+CODEGEN_TEST_MINIMAL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CODEGEN_TEST_MINIMAL_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/codegen_test_minimal: 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)/codegen_test_minimal: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/codegen_test_minimal: $(PROTOBUF_DEP) $(CODEGEN_TEST_MINIMAL_OBJS)
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_MINIMAL_OBJS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test_minimal
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o: 
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: 
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o: 
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/perf_db.o: 
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o: 
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o: 
+
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o: 
+
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: 
+
+deps_codegen_test_minimal: $(CODEGEN_TEST_MINIMAL_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(CODEGEN_TEST_MINIMAL_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
 
 
 CREDENTIALS_TEST_SRC = \
@@ -9973,6 +10549,37 @@
 endif
 
 
+GRPC_NODE_PLUGIN_SRC = \
+    src/compiler/node_plugin.cc \
+
+GRPC_NODE_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_NODE_PLUGIN_SRC))))
+
+
+
+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)/grpc_node_plugin: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/grpc_node_plugin: $(PROTOBUF_DEP) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a
+	$(E) "[HOSTLD]  Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_node_plugin
+
+endif
+
+$(OBJDIR)/$(CONFIG)/src/compiler/node_plugin.o:  $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a
+
+deps_grpc_node_plugin: $(GRPC_NODE_PLUGIN_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(GRPC_NODE_PLUGIN_OBJS:.o=.dep)
+endif
+
+
 GRPC_OBJECTIVE_C_PLUGIN_SRC = \
     src/compiler/objective_c_plugin.cc \
 
@@ -10261,6 +10868,49 @@
 endif
 
 
+JSON_RUN_LOCALHOST_SRC = \
+    test/cpp/qps/json_run_localhost.cc \
+
+JSON_RUN_LOCALHOST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_RUN_LOCALHOST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/json_run_localhost: 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)/json_run_localhost: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/json_run_localhost: $(PROTOBUF_DEP) $(JSON_RUN_LOCALHOST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(JSON_RUN_LOCALHOST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/json_run_localhost
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/json_run_localhost.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+
+deps_json_run_localhost: $(JSON_RUN_LOCALHOST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(JSON_RUN_LOCALHOST_OBJS:.o=.dep)
+endif
+endif
+
+
 METRICS_CLIENT_SRC = \
     $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc \
     test/cpp/interop/metrics_client.cc \
@@ -10351,49 +11001,6 @@
 endif
 
 
-QPS_DRIVER_SRC = \
-    test/cpp/qps/qps_driver.cc \
-
-QPS_DRIVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_DRIVER_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/qps_driver: 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_driver: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/qps_driver: $(PROTOBUF_DEP) $(QPS_DRIVER_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_DRIVER_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_driver
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_driver.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_driver: $(QPS_DRIVER_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(QPS_DRIVER_OBJS:.o=.dep)
-endif
-endif
-
-
 QPS_INTERARRIVAL_TEST_SRC = \
     test/cpp/qps/qps_interarrival_test.cc \
 
@@ -10437,6 +11044,52 @@
 endif
 
 
+QPS_JSON_DRIVER_SRC = \
+    test/cpp/qps/parse_json.cc \
+    test/cpp/qps/qps_json_driver.cc \
+
+QPS_JSON_DRIVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_JSON_DRIVER_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/qps_json_driver: 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_json_driver: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/qps_json_driver: $(PROTOBUF_DEP) $(QPS_JSON_DRIVER_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_JSON_DRIVER_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_json_driver
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/parse_json.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
+
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_json_driver.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_json_driver: $(QPS_JSON_DRIVER_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(QPS_JSON_DRIVER_OBJS:.o=.dep)
+endif
+endif
+
+
 QPS_OPENLOOP_TEST_SRC = \
     test/cpp/qps/qps_openloop_test.cc \
 
@@ -12148,6 +12801,33 @@
 # boringssl needs an override to ensure that it does not include
 # system openssl headers regardless of other configuration
 # we do so here with a target specific variable assignment
+$(BORINGSSL_X509_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value
+$(BORINGSSL_X509_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS)
+$(BORINGSSL_X509_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE
+
+
+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)/boringssl_x509_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/boringssl_x509_test:  $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_x509_test
+
+endif
+
+
+
+
+
+# boringssl needs an override to ensure that it does not include
+# system openssl headers regardless of other configuration
+# we do so here with a target specific variable assignment
 $(BORINGSSL_TAB_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value
 $(BORINGSSL_TAB_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS)
 $(BORINGSSL_TAB_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE
@@ -12292,6 +12972,26 @@
 endif
 
 
+HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC = \
+    test/core/bad_client/tests/head_of_line_blocking.c \
+
+HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC))))
+
+
+$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
+
+$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/head_of_line_blocking.o:  $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep)
+endif
+
+
 HEADERS_BAD_CLIENT_TEST_SRC = \
     test/core/bad_client/tests/headers.c \
 
@@ -12700,70 +13400,6 @@
 endif
 
 
-H2_FULL+POLL_TEST_SRC = \
-    test/core/end2end/fixtures/h2_full+poll.c \
-
-H2_FULL+POLL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+POLL_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/h2_full+poll_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/h2_full+poll_test: $(H2_FULL+POLL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_FULL+POLL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full+poll_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+poll.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_full+poll_test: $(H2_FULL+POLL_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(H2_FULL+POLL_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
-H2_FULL+POLL+PIPE_TEST_SRC = \
-    test/core/end2end/fixtures/h2_full+poll+pipe.c \
-
-H2_FULL+POLL+PIPE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+POLL+PIPE_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/h2_full+poll+pipe_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/h2_full+poll+pipe_test: $(H2_FULL+POLL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_FULL+POLL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full+poll+pipe_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+poll+pipe.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_full+poll+pipe_test: $(H2_FULL+POLL+PIPE_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(H2_FULL+POLL+PIPE_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 H2_FULL+TRACE_TEST_SRC = \
     test/core/end2end/fixtures/h2_full+trace.c \
 
@@ -12988,34 +13624,34 @@
 endif
 
 
-H2_SSL+POLL_TEST_SRC = \
-    test/core/end2end/fixtures/h2_ssl+poll.c \
+H2_SSL_CERT_TEST_SRC = \
+    test/core/end2end/fixtures/h2_ssl_cert.c \
 
-H2_SSL+POLL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL+POLL_TEST_SRC))))
+H2_SSL_CERT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_CERT_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
 
-$(BINDIR)/$(CONFIG)/h2_ssl+poll_test: openssl_dep_error
+$(BINDIR)/$(CONFIG)/h2_ssl_cert_test: openssl_dep_error
 
 else
 
 
 
-$(BINDIR)/$(CONFIG)/h2_ssl+poll_test: $(H2_SSL+POLL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/h2_ssl_cert_test: $(H2_SSL_CERT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_SSL+POLL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl+poll_test
+	$(Q) $(LD) $(LDFLAGS) $(H2_SSL_CERT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl_cert_test
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl+poll.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl_cert.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-deps_h2_ssl+poll_test: $(H2_SSL+POLL_TEST_OBJS:.o=.dep)
+deps_h2_ssl_cert_test: $(H2_SSL_CERT_TEST_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(H2_SSL+POLL_TEST_OBJS:.o=.dep)
+-include $(H2_SSL_CERT_TEST_OBJS:.o=.dep)
 endif
 endif
 
@@ -13052,38 +13688,6 @@
 endif
 
 
-H2_UCHANNEL_TEST_SRC = \
-    test/core/end2end/fixtures/h2_uchannel.c \
-
-H2_UCHANNEL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UCHANNEL_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/h2_uchannel_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/h2_uchannel_test: $(H2_UCHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_UCHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uchannel_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uchannel.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_uchannel_test: $(H2_UCHANNEL_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(H2_UCHANNEL_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 H2_UDS_TEST_SRC = \
     test/core/end2end/fixtures/h2_uds.c \
 
@@ -13116,38 +13720,6 @@
 endif
 
 
-H2_UDS+POLL_TEST_SRC = \
-    test/core/end2end/fixtures/h2_uds+poll.c \
-
-H2_UDS+POLL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UDS+POLL_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/h2_uds+poll_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/h2_uds+poll_test: $(H2_UDS+POLL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_UDS+POLL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uds+poll_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uds+poll.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_uds+poll_test: $(H2_UDS+POLL_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(H2_UDS+POLL_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 H2_CENSUS_NOSEC_TEST_SRC = \
     test/core/end2end/fixtures/h2_census.c \
 
@@ -13228,46 +13800,6 @@
 endif
 
 
-H2_FULL+POLL_NOSEC_TEST_SRC = \
-    test/core/end2end/fixtures/h2_full+poll.c \
-
-H2_FULL+POLL_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+POLL_NOSEC_TEST_SRC))))
-
-
-$(BINDIR)/$(CONFIG)/h2_full+poll_nosec_test: $(H2_FULL+POLL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_FULL+POLL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_full+poll_nosec_test
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+poll.o:  $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_full+poll_nosec_test: $(H2_FULL+POLL_NOSEC_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_DEPS),true)
--include $(H2_FULL+POLL_NOSEC_TEST_OBJS:.o=.dep)
-endif
-
-
-H2_FULL+POLL+PIPE_NOSEC_TEST_SRC = \
-    test/core/end2end/fixtures/h2_full+poll+pipe.c \
-
-H2_FULL+POLL+PIPE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+POLL+PIPE_NOSEC_TEST_SRC))))
-
-
-$(BINDIR)/$(CONFIG)/h2_full+poll+pipe_nosec_test: $(H2_FULL+POLL+PIPE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_FULL+POLL+PIPE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_full+poll+pipe_nosec_test
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+poll+pipe.o:  $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_full+poll+pipe_nosec_test: $(H2_FULL+POLL+PIPE_NOSEC_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_DEPS),true)
--include $(H2_FULL+POLL+PIPE_NOSEC_TEST_OBJS:.o=.dep)
-endif
-
-
 H2_FULL+TRACE_NOSEC_TEST_SRC = \
     test/core/end2end/fixtures/h2_full+trace.c \
 
@@ -13368,26 +13900,6 @@
 endif
 
 
-H2_UCHANNEL_NOSEC_TEST_SRC = \
-    test/core/end2end/fixtures/h2_uchannel.c \
-
-H2_UCHANNEL_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UCHANNEL_NOSEC_TEST_SRC))))
-
-
-$(BINDIR)/$(CONFIG)/h2_uchannel_nosec_test: $(H2_UCHANNEL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_UCHANNEL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_uchannel_nosec_test
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uchannel.o:  $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_uchannel_nosec_test: $(H2_UCHANNEL_NOSEC_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_DEPS),true)
--include $(H2_UCHANNEL_NOSEC_TEST_OBJS:.o=.dep)
-endif
-
-
 H2_UDS_NOSEC_TEST_SRC = \
     test/core/end2end/fixtures/h2_uds.c \
 
@@ -13408,23 +13920,318 @@
 endif
 
 
-H2_UDS+POLL_NOSEC_TEST_SRC = \
-    test/core/end2end/fixtures/h2_uds+poll.c \
+API_FUZZER_ONE_ENTRY_SRC = \
+    test/core/end2end/fuzzers/api_fuzzer.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
 
-H2_UDS+POLL_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UDS+POLL_NOSEC_TEST_SRC))))
+API_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/api_fuzzer_one_entry: openssl_dep_error
+
+else
 
 
-$(BINDIR)/$(CONFIG)/h2_uds+poll_nosec_test: $(H2_UDS+POLL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(BINDIR)/$(CONFIG)/api_fuzzer_one_entry: $(API_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(H2_UDS+POLL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_uds+poll_nosec_test
+	$(Q) $(LD) $(LDFLAGS) $(API_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
 
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uds+poll.o:  $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+endif
 
-deps_h2_uds+poll_nosec_test: $(H2_UDS+POLL_NOSEC_TEST_OBJS:.o=.dep)
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/api_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_api_fuzzer_one_entry: $(API_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(H2_UDS+POLL_NOSEC_TEST_OBJS:.o=.dep)
+-include $(API_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+CLIENT_FUZZER_ONE_ENTRY_SRC = \
+    test/core/end2end/fuzzers/client_fuzzer.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+CLIENT_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_FUZZER_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/client_fuzzer_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/client_fuzzer_one_entry: $(CLIENT_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(CLIENT_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/client_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_client_fuzzer_one_entry: $(CLIENT_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(CLIENT_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_SRC = \
+    test/core/transport/chttp2/hpack_parser_fuzzer_test.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry: $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/hpack_parser_fuzzer_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_hpack_parser_fuzzer_test_one_entry: $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+HTTP_FUZZER_TEST_ONE_ENTRY_SRC = \
+    test/core/http/fuzzer.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+HTTP_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_FUZZER_TEST_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry: $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/http/fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_http_fuzzer_test_one_entry: $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+JSON_FUZZER_TEST_ONE_ENTRY_SRC = \
+    test/core/json/fuzzer.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+JSON_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_FUZZER_TEST_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry: $(JSON_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(JSON_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/json/fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_json_fuzzer_test_one_entry: $(JSON_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(JSON_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_SRC = \
+    test/core/nanopb/fuzzer_response.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry: $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_response.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_nanopb_fuzzer_response_test_one_entry: $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_SRC = \
+    test/core/nanopb/fuzzer_serverlist.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry: $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_serverlist.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_nanopb_fuzzer_serverlist_test_one_entry: $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+SERVER_FUZZER_ONE_ENTRY_SRC = \
+    test/core/end2end/fuzzers/server_fuzzer.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+SERVER_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_FUZZER_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/server_fuzzer_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/server_fuzzer_one_entry: $(SERVER_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(SERVER_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/server_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_server_fuzzer_one_entry: $(SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+URI_FUZZER_TEST_ONE_ENTRY_SRC = \
+    test/core/client_config/uri_fuzzer_test.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+URI_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_FUZZER_TEST_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry: $(URI_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(URI_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/client_config/uri_fuzzer_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_uri_fuzzer_test_one_entry: $(URI_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(URI_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+endif
 endif
 
 
@@ -13436,27 +14243,28 @@
 # This is to ensure the embedded OpenSSL is built beforehand, properly
 # installing headers to their final destination on the drive. We need this
 # otherwise parallel compilation will fail if a source is compiled first.
-src/core/httpcli/httpcli_security_connector.c: $(OPENSSL_DEP)
-src/core/security/b64.c: $(OPENSSL_DEP)
-src/core/security/client_auth_filter.c: $(OPENSSL_DEP)
-src/core/security/credentials.c: $(OPENSSL_DEP)
-src/core/security/credentials_metadata.c: $(OPENSSL_DEP)
-src/core/security/credentials_posix.c: $(OPENSSL_DEP)
-src/core/security/credentials_win32.c: $(OPENSSL_DEP)
-src/core/security/google_default_credentials.c: $(OPENSSL_DEP)
-src/core/security/handshake.c: $(OPENSSL_DEP)
-src/core/security/json_token.c: $(OPENSSL_DEP)
-src/core/security/jwt_verifier.c: $(OPENSSL_DEP)
-src/core/security/secure_endpoint.c: $(OPENSSL_DEP)
-src/core/security/security_connector.c: $(OPENSSL_DEP)
-src/core/security/security_context.c: $(OPENSSL_DEP)
-src/core/security/server_auth_filter.c: $(OPENSSL_DEP)
-src/core/security/server_secure_chttp2.c: $(OPENSSL_DEP)
-src/core/surface/init_secure.c: $(OPENSSL_DEP)
-src/core/surface/secure_channel_create.c: $(OPENSSL_DEP)
-src/core/tsi/fake_transport_security.c: $(OPENSSL_DEP)
-src/core/tsi/ssl_transport_security.c: $(OPENSSL_DEP)
-src/core/tsi/transport_security.c: $(OPENSSL_DEP)
+src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP)
+src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.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/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)
+src/core/lib/tsi/transport_security.c: $(OPENSSL_DEP)
+src/core/plugin_registry/grpc_plugin_registry.c: $(OPENSSL_DEP)
 src/cpp/client/secure_credentials.cc: $(OPENSSL_DEP)
 src/cpp/common/auth_property_iterator.cc: $(OPENSSL_DEP)
 src/cpp/common/secure_auth_context.cc: $(OPENSSL_DEP)
@@ -13466,6 +14274,7 @@
 src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP)
 test/core/bad_client/bad_client.c: $(OPENSSL_DEP)
 test/core/bad_ssl/server_common.c: $(OPENSSL_DEP)
+test/core/end2end/data/client_certs.c: $(OPENSSL_DEP)
 test/core/end2end/data/server1_cert.c: $(OPENSSL_DEP)
 test/core/end2end/data/server1_key.c: $(OPENSSL_DEP)
 test/core/end2end/data/test_root_cert.c: $(OPENSSL_DEP)
diff --git a/PYTHON-MANIFEST.in b/PYTHON-MANIFEST.in
index 25aba87..534f4c1 100644
--- a/PYTHON-MANIFEST.in
+++ b/PYTHON-MANIFEST.in
@@ -2,8 +2,10 @@
 recursive-exclude src/python/grpcio/grpc/_cython *.so *.pyd
 graft src/python/grpcio/tests
 graft src/core
+graft src/boringssl
 graft include/grpc
 graft third_party/boringssl
+graft third_party/nanopb
 graft third_party/zlib
 include src/python/grpcio/commands.py
 include src/python/grpcio/grpc_version.py
diff --git a/README.md b/README.md
index abb4905..3ee2b9f 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 
 [![Join the chat at https://gitter.im/grpc/grpc](https://badges.gitter.im/grpc/grpc.svg)](https://gitter.im/grpc/grpc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
-Copyright 2015-2016 Google Inc.
+Copyright 2015 Google Inc.
 
 #Documentation
 
diff --git a/binding.gyp b/binding.gyp
index 5f9dfd9..058743e 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -5,7 +5,7 @@
 # This file can be regenerated from the template by running
 # tools/buildgen/generate_projects.sh
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -223,6 +223,7 @@
             'third_party/boringssl/crypto/bn/shift.c',
             'third_party/boringssl/crypto/bn/sqrt.c',
             'third_party/boringssl/crypto/buf/buf.c',
+            'third_party/boringssl/crypto/bytestring/asn1_compat.c',
             'third_party/boringssl/crypto/bytestring/ber.c',
             'third_party/boringssl/crypto/bytestring/cbb.c',
             'third_party/boringssl/crypto/bytestring/cbs.c',
@@ -246,6 +247,7 @@
             'third_party/boringssl/crypto/cpu-intel.c',
             'third_party/boringssl/crypto/crypto.c',
             'third_party/boringssl/crypto/curve25519/curve25519.c',
+            'third_party/boringssl/crypto/curve25519/x25519-x86_64.c',
             'third_party/boringssl/crypto/des/des.c',
             'third_party/boringssl/crypto/dh/check.c',
             'third_party/boringssl/crypto/dh/dh.c',
@@ -437,6 +439,7 @@
             'third_party/boringssl/ssl/ssl_buffer.c',
             'third_party/boringssl/ssl/ssl_cert.c',
             'third_party/boringssl/ssl/ssl_cipher.c',
+            'third_party/boringssl/ssl/ssl_ecdh.c',
             'third_party/boringssl/ssl/ssl_file.c',
             'third_party/boringssl/ssl/ssl_lib.c',
             'third_party/boringssl/ssl/ssl_rsa.c',
@@ -492,50 +495,50 @@
       'dependencies': [
       ],
       'sources': [
-        'src/core/profiling/basic_timers.c',
-        'src/core/profiling/stap_timers.c',
-        'src/core/support/alloc.c',
-        'src/core/support/avl.c',
-        'src/core/support/backoff.c',
-        'src/core/support/cmdline.c',
-        'src/core/support/cpu_iphone.c',
-        'src/core/support/cpu_linux.c',
-        'src/core/support/cpu_posix.c',
-        'src/core/support/cpu_windows.c',
-        'src/core/support/env_linux.c',
-        'src/core/support/env_posix.c',
-        'src/core/support/env_win32.c',
-        'src/core/support/histogram.c',
-        'src/core/support/host_port.c',
-        'src/core/support/load_file.c',
-        'src/core/support/log.c',
-        'src/core/support/log_android.c',
-        'src/core/support/log_linux.c',
-        'src/core/support/log_posix.c',
-        'src/core/support/log_win32.c',
-        'src/core/support/murmur_hash.c',
-        'src/core/support/slice.c',
-        'src/core/support/slice_buffer.c',
-        'src/core/support/stack_lockfree.c',
-        'src/core/support/string.c',
-        'src/core/support/string_posix.c',
-        'src/core/support/string_win32.c',
-        'src/core/support/subprocess_posix.c',
-        'src/core/support/subprocess_windows.c',
-        'src/core/support/sync.c',
-        'src/core/support/sync_posix.c',
-        'src/core/support/sync_win32.c',
-        'src/core/support/thd.c',
-        'src/core/support/thd_posix.c',
-        'src/core/support/thd_win32.c',
-        'src/core/support/time.c',
-        'src/core/support/time_posix.c',
-        'src/core/support/time_precise.c',
-        'src/core/support/time_win32.c',
-        'src/core/support/tls_pthread.c',
-        'src/core/support/tmpfile_posix.c',
-        'src/core/support/tmpfile_win32.c',
-        'src/core/support/wrap_memcpy.c',
+        'src/core/lib/profiling/basic_timers.c',
+        'src/core/lib/profiling/stap_timers.c',
+        'src/core/lib/support/alloc.c',
+        'src/core/lib/support/avl.c',
+        'src/core/lib/support/backoff.c',
+        'src/core/lib/support/cmdline.c',
+        'src/core/lib/support/cpu_iphone.c',
+        'src/core/lib/support/cpu_linux.c',
+        'src/core/lib/support/cpu_posix.c',
+        'src/core/lib/support/cpu_windows.c',
+        'src/core/lib/support/env_linux.c',
+        'src/core/lib/support/env_posix.c',
+        'src/core/lib/support/env_win32.c',
+        'src/core/lib/support/histogram.c',
+        'src/core/lib/support/host_port.c',
+        'src/core/lib/support/load_file.c',
+        'src/core/lib/support/log.c',
+        'src/core/lib/support/log_android.c',
+        'src/core/lib/support/log_linux.c',
+        'src/core/lib/support/log_posix.c',
+        'src/core/lib/support/log_win32.c',
+        'src/core/lib/support/murmur_hash.c',
+        'src/core/lib/support/slice.c',
+        'src/core/lib/support/slice_buffer.c',
+        'src/core/lib/support/stack_lockfree.c',
+        'src/core/lib/support/string.c',
+        'src/core/lib/support/string_posix.c',
+        'src/core/lib/support/string_win32.c',
+        'src/core/lib/support/subprocess_posix.c',
+        'src/core/lib/support/subprocess_windows.c',
+        'src/core/lib/support/sync.c',
+        'src/core/lib/support/sync_posix.c',
+        'src/core/lib/support/sync_win32.c',
+        'src/core/lib/support/thd.c',
+        'src/core/lib/support/thd_posix.c',
+        'src/core/lib/support/thd_win32.c',
+        'src/core/lib/support/time.c',
+        'src/core/lib/support/time_posix.c',
+        'src/core/lib/support/time_precise.c',
+        'src/core/lib/support/time_win32.c',
+        'src/core/lib/support/tls_pthread.c',
+        'src/core/lib/support/tmpfile_posix.c',
+        'src/core/lib/support/tmpfile_win32.c',
+        'src/core/lib/support/wrap_memcpy.c',
       ],
       "conditions": [
         ['OS == "mac"', {
@@ -558,169 +561,171 @@
         'gpr',
       ],
       'sources': [
-        'src/core/census/grpc_context.c',
-        'src/core/census/grpc_filter.c',
-        'src/core/census/grpc_plugin.c',
-        'src/core/channel/channel_args.c',
-        'src/core/channel/channel_stack.c',
-        'src/core/channel/channel_stack_builder.c',
-        'src/core/channel/client_channel.c',
-        'src/core/channel/client_uchannel.c',
-        'src/core/channel/compress_filter.c',
-        'src/core/channel/connected_channel.c',
-        'src/core/channel/http_client_filter.c',
-        'src/core/channel/http_server_filter.c',
-        'src/core/channel/subchannel_call_holder.c',
-        'src/core/client_config/client_config.c',
-        'src/core/client_config/connector.c',
-        'src/core/client_config/default_initial_connect_string.c',
-        'src/core/client_config/initial_connect_string.c',
-        'src/core/client_config/lb_policies/load_balancer_api.c',
-        'src/core/client_config/lb_policies/pick_first.c',
-        'src/core/client_config/lb_policies/round_robin.c',
-        'src/core/client_config/lb_policy.c',
-        'src/core/client_config/lb_policy_factory.c',
-        'src/core/client_config/lb_policy_registry.c',
-        'src/core/client_config/resolver.c',
-        'src/core/client_config/resolver_factory.c',
-        'src/core/client_config/resolver_registry.c',
-        'src/core/client_config/resolvers/dns_resolver.c',
-        'src/core/client_config/resolvers/sockaddr_resolver.c',
-        'src/core/client_config/subchannel.c',
-        'src/core/client_config/subchannel_factory.c',
-        'src/core/client_config/subchannel_index.c',
-        'src/core/client_config/uri_parser.c',
-        'src/core/compression/compression_algorithm.c',
-        'src/core/compression/message_compress.c',
-        'src/core/debug/trace.c',
-        'src/core/httpcli/format_request.c',
-        'src/core/httpcli/httpcli.c',
-        'src/core/httpcli/parser.c',
-        'src/core/iomgr/closure.c',
-        'src/core/iomgr/endpoint.c',
-        'src/core/iomgr/endpoint_pair_posix.c',
-        'src/core/iomgr/endpoint_pair_windows.c',
-        'src/core/iomgr/exec_ctx.c',
-        'src/core/iomgr/executor.c',
-        'src/core/iomgr/fd_posix.c',
-        'src/core/iomgr/iocp_windows.c',
-        'src/core/iomgr/iomgr.c',
-        'src/core/iomgr/iomgr_posix.c',
-        'src/core/iomgr/iomgr_windows.c',
-        'src/core/iomgr/pollset_multipoller_with_epoll.c',
-        'src/core/iomgr/pollset_multipoller_with_poll_posix.c',
-        'src/core/iomgr/pollset_posix.c',
-        'src/core/iomgr/pollset_set_posix.c',
-        'src/core/iomgr/pollset_set_windows.c',
-        'src/core/iomgr/pollset_windows.c',
-        'src/core/iomgr/resolve_address_posix.c',
-        'src/core/iomgr/resolve_address_windows.c',
-        'src/core/iomgr/sockaddr_utils.c',
-        'src/core/iomgr/socket_utils_common_posix.c',
-        'src/core/iomgr/socket_utils_linux.c',
-        'src/core/iomgr/socket_utils_posix.c',
-        'src/core/iomgr/socket_windows.c',
-        'src/core/iomgr/tcp_client_posix.c',
-        'src/core/iomgr/tcp_client_windows.c',
-        'src/core/iomgr/tcp_posix.c',
-        'src/core/iomgr/tcp_server_posix.c',
-        'src/core/iomgr/tcp_server_windows.c',
-        'src/core/iomgr/tcp_windows.c',
-        'src/core/iomgr/time_averaged_stats.c',
-        'src/core/iomgr/timer.c',
-        'src/core/iomgr/timer_heap.c',
-        'src/core/iomgr/udp_server.c',
-        'src/core/iomgr/wakeup_fd_eventfd.c',
-        'src/core/iomgr/wakeup_fd_nospecial.c',
-        'src/core/iomgr/wakeup_fd_pipe.c',
-        'src/core/iomgr/wakeup_fd_posix.c',
-        'src/core/iomgr/workqueue_posix.c',
-        'src/core/iomgr/workqueue_windows.c',
-        'src/core/json/json.c',
-        'src/core/json/json_reader.c',
-        'src/core/json/json_string.c',
-        'src/core/json/json_writer.c',
-        'src/core/proto/grpc/lb/v0/load_balancer.pb.c',
-        'src/core/surface/alarm.c',
-        'src/core/surface/api_trace.c',
-        'src/core/surface/byte_buffer.c',
-        'src/core/surface/byte_buffer_reader.c',
-        'src/core/surface/call.c',
-        'src/core/surface/call_details.c',
-        'src/core/surface/call_log_batch.c',
-        'src/core/surface/channel.c',
-        'src/core/surface/channel_connectivity.c',
-        'src/core/surface/channel_create.c',
-        'src/core/surface/channel_init.c',
-        'src/core/surface/channel_ping.c',
-        'src/core/surface/channel_stack_type.c',
-        'src/core/surface/completion_queue.c',
-        'src/core/surface/event_string.c',
-        'src/core/surface/init.c',
-        'src/core/surface/lame_client.c',
-        'src/core/surface/metadata_array.c',
-        'src/core/surface/server.c',
-        'src/core/surface/server_chttp2.c',
-        'src/core/surface/validate_metadata.c',
-        'src/core/surface/version.c',
-        'src/core/transport/byte_stream.c',
-        'src/core/transport/chttp2/alpn.c',
-        'src/core/transport/chttp2/bin_encoder.c',
-        'src/core/transport/chttp2/frame_data.c',
-        'src/core/transport/chttp2/frame_goaway.c',
-        'src/core/transport/chttp2/frame_ping.c',
-        'src/core/transport/chttp2/frame_rst_stream.c',
-        'src/core/transport/chttp2/frame_settings.c',
-        'src/core/transport/chttp2/frame_window_update.c',
-        'src/core/transport/chttp2/hpack_encoder.c',
-        'src/core/transport/chttp2/hpack_parser.c',
-        'src/core/transport/chttp2/hpack_table.c',
-        'src/core/transport/chttp2/huffsyms.c',
-        'src/core/transport/chttp2/incoming_metadata.c',
-        'src/core/transport/chttp2/parsing.c',
-        'src/core/transport/chttp2/status_conversion.c',
-        'src/core/transport/chttp2/stream_lists.c',
-        'src/core/transport/chttp2/stream_map.c',
-        'src/core/transport/chttp2/timeout_encoding.c',
-        'src/core/transport/chttp2/varint.c',
-        'src/core/transport/chttp2/writing.c',
-        'src/core/transport/chttp2_transport.c',
-        'src/core/transport/connectivity_state.c',
-        'src/core/transport/metadata.c',
-        'src/core/transport/metadata_batch.c',
-        'src/core/transport/static_metadata.c',
-        'src/core/transport/transport.c',
-        'src/core/transport/transport_op_string.c',
-        'src/core/httpcli/httpcli_security_connector.c',
-        'src/core/security/b64.c',
-        'src/core/security/client_auth_filter.c',
-        'src/core/security/credentials.c',
-        'src/core/security/credentials_metadata.c',
-        'src/core/security/credentials_posix.c',
-        'src/core/security/credentials_win32.c',
-        'src/core/security/google_default_credentials.c',
-        'src/core/security/handshake.c',
-        'src/core/security/json_token.c',
-        'src/core/security/jwt_verifier.c',
-        'src/core/security/secure_endpoint.c',
-        'src/core/security/security_connector.c',
-        'src/core/security/security_context.c',
-        'src/core/security/server_auth_filter.c',
-        'src/core/security/server_secure_chttp2.c',
-        'src/core/surface/init_secure.c',
-        'src/core/surface/secure_channel_create.c',
-        'src/core/tsi/fake_transport_security.c',
-        'src/core/tsi/ssl_transport_security.c',
-        'src/core/tsi/transport_security.c',
-        'src/core/census/context.c',
-        'src/core/census/initialize.c',
-        'src/core/census/mlog.c',
-        'src/core/census/operation.c',
-        'src/core/census/placeholders.c',
-        'src/core/census/tracing.c',
+        'src/core/lib/surface/init.c',
+        'src/core/lib/channel/channel_args.c',
+        'src/core/lib/channel/channel_stack.c',
+        'src/core/lib/channel/channel_stack_builder.c',
+        'src/core/lib/channel/compress_filter.c',
+        'src/core/lib/channel/connected_channel.c',
+        'src/core/lib/channel/http_client_filter.c',
+        'src/core/lib/channel/http_server_filter.c',
+        'src/core/lib/compression/compression_algorithm.c',
+        'src/core/lib/compression/message_compress.c',
+        'src/core/lib/debug/trace.c',
+        'src/core/lib/http/format_request.c',
+        'src/core/lib/http/httpcli.c',
+        'src/core/lib/http/parser.c',
+        'src/core/lib/iomgr/closure.c',
+        'src/core/lib/iomgr/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_posix.c',
+        'src/core/lib/iomgr/exec_ctx.c',
+        'src/core/lib/iomgr/executor.c',
+        'src/core/lib/iomgr/iocp_windows.c',
+        'src/core/lib/iomgr/iomgr.c',
+        'src/core/lib/iomgr/iomgr_posix.c',
+        'src/core/lib/iomgr/iomgr_windows.c',
+        'src/core/lib/iomgr/pollset_set_windows.c',
+        'src/core/lib/iomgr/pollset_windows.c',
+        'src/core/lib/iomgr/resolve_address_posix.c',
+        'src/core/lib/iomgr/resolve_address_windows.c',
+        'src/core/lib/iomgr/sockaddr_utils.c',
+        'src/core/lib/iomgr/socket_utils_common_posix.c',
+        'src/core/lib/iomgr/socket_utils_linux.c',
+        'src/core/lib/iomgr/socket_utils_posix.c',
+        'src/core/lib/iomgr/socket_windows.c',
+        'src/core/lib/iomgr/tcp_client_posix.c',
+        'src/core/lib/iomgr/tcp_client_windows.c',
+        'src/core/lib/iomgr/tcp_posix.c',
+        'src/core/lib/iomgr/tcp_server_posix.c',
+        'src/core/lib/iomgr/tcp_server_windows.c',
+        'src/core/lib/iomgr/tcp_windows.c',
+        'src/core/lib/iomgr/time_averaged_stats.c',
+        'src/core/lib/iomgr/timer.c',
+        'src/core/lib/iomgr/timer_heap.c',
+        'src/core/lib/iomgr/udp_server.c',
+        'src/core/lib/iomgr/unix_sockets_posix.c',
+        'src/core/lib/iomgr/unix_sockets_posix_noop.c',
+        'src/core/lib/iomgr/wakeup_fd_eventfd.c',
+        'src/core/lib/iomgr/wakeup_fd_nospecial.c',
+        'src/core/lib/iomgr/wakeup_fd_pipe.c',
+        'src/core/lib/iomgr/wakeup_fd_posix.c',
+        'src/core/lib/iomgr/workqueue_posix.c',
+        'src/core/lib/iomgr/workqueue_windows.c',
+        'src/core/lib/json/json.c',
+        'src/core/lib/json/json_reader.c',
+        'src/core/lib/json/json_string.c',
+        'src/core/lib/json/json_writer.c',
+        'src/core/lib/surface/alarm.c',
+        'src/core/lib/surface/api_trace.c',
+        'src/core/lib/surface/byte_buffer.c',
+        'src/core/lib/surface/byte_buffer_reader.c',
+        'src/core/lib/surface/call.c',
+        'src/core/lib/surface/call_details.c',
+        'src/core/lib/surface/call_log_batch.c',
+        'src/core/lib/surface/channel.c',
+        'src/core/lib/surface/channel_init.c',
+        'src/core/lib/surface/channel_ping.c',
+        'src/core/lib/surface/channel_stack_type.c',
+        'src/core/lib/surface/completion_queue.c',
+        'src/core/lib/surface/event_string.c',
+        'src/core/lib/surface/lame_client.c',
+        'src/core/lib/surface/metadata_array.c',
+        'src/core/lib/surface/server.c',
+        'src/core/lib/surface/validate_metadata.c',
+        'src/core/lib/surface/version.c',
+        'src/core/lib/transport/byte_stream.c',
+        'src/core/lib/transport/connectivity_state.c',
+        'src/core/lib/transport/metadata.c',
+        'src/core/lib/transport/metadata_batch.c',
+        'src/core/lib/transport/static_metadata.c',
+        'src/core/lib/transport/transport.c',
+        'src/core/lib/transport/transport_op_string.c',
+        'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c',
+        'src/core/ext/transport/chttp2/transport/bin_encoder.c',
+        'src/core/ext/transport/chttp2/transport/chttp2_plugin.c',
+        'src/core/ext/transport/chttp2/transport/chttp2_transport.c',
+        'src/core/ext/transport/chttp2/transport/frame_data.c',
+        'src/core/ext/transport/chttp2/transport/frame_goaway.c',
+        'src/core/ext/transport/chttp2/transport/frame_ping.c',
+        'src/core/ext/transport/chttp2/transport/frame_rst_stream.c',
+        'src/core/ext/transport/chttp2/transport/frame_settings.c',
+        'src/core/ext/transport/chttp2/transport/frame_window_update.c',
+        'src/core/ext/transport/chttp2/transport/hpack_encoder.c',
+        'src/core/ext/transport/chttp2/transport/hpack_parser.c',
+        'src/core/ext/transport/chttp2/transport/hpack_table.c',
+        'src/core/ext/transport/chttp2/transport/huffsyms.c',
+        'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
+        'src/core/ext/transport/chttp2/transport/parsing.c',
+        'src/core/ext/transport/chttp2/transport/status_conversion.c',
+        'src/core/ext/transport/chttp2/transport/stream_lists.c',
+        'src/core/ext/transport/chttp2/transport/stream_map.c',
+        'src/core/ext/transport/chttp2/transport/timeout_encoding.c',
+        'src/core/ext/transport/chttp2/transport/varint.c',
+        'src/core/ext/transport/chttp2/transport/writing.c',
+        'src/core/ext/transport/chttp2/alpn/alpn.c',
+        'src/core/lib/http/httpcli_security_connector.c',
+        'src/core/lib/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/surface/init_secure.c',
+        'src/core/lib/tsi/fake_transport_security.c',
+        'src/core/lib/tsi/ssl_transport_security.c',
+        'src/core/lib/tsi/transport_security.c',
+        'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c',
+        'src/core/ext/client_config/channel_connectivity.c',
+        'src/core/ext/client_config/client_channel.c',
+        'src/core/ext/client_config/client_channel_factory.c',
+        'src/core/ext/client_config/client_config.c',
+        'src/core/ext/client_config/client_config_plugin.c',
+        'src/core/ext/client_config/connector.c',
+        'src/core/ext/client_config/default_initial_connect_string.c',
+        'src/core/ext/client_config/initial_connect_string.c',
+        'src/core/ext/client_config/lb_policy.c',
+        'src/core/ext/client_config/lb_policy_factory.c',
+        'src/core/ext/client_config/lb_policy_registry.c',
+        'src/core/ext/client_config/parse_address.c',
+        'src/core/ext/client_config/resolver.c',
+        'src/core/ext/client_config/resolver_factory.c',
+        'src/core/ext/client_config/resolver_registry.c',
+        'src/core/ext/client_config/subchannel.c',
+        'src/core/ext/client_config/subchannel_call_holder.c',
+        'src/core/ext/client_config/subchannel_index.c',
+        'src/core/ext/client_config/uri_parser.c',
+        'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c',
+        'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
+        'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
+        'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c',
         'third_party/nanopb/pb_common.c',
         'third_party/nanopb/pb_decode.c',
         'third_party/nanopb/pb_encode.c',
+        'src/core/ext/lb_policy/pick_first/pick_first.c',
+        'src/core/ext/lb_policy/round_robin/round_robin.c',
+        'src/core/ext/resolver/dns/native/dns_resolver.c',
+        'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
+        'src/core/ext/census/context.c',
+        'src/core/ext/census/grpc_context.c',
+        'src/core/ext/census/grpc_filter.c',
+        'src/core/ext/census/grpc_plugin.c',
+        'src/core/ext/census/initialize.c',
+        'src/core/ext/census/mlog.c',
+        'src/core/ext/census/operation.c',
+        'src/core/ext/census/placeholders.c',
+        'src/core/ext/census/tracing.c',
+        'src/core/plugin_registry/grpc_plugin_registry.c',
       ],
       "conditions": [
         ['OS == "mac"', {
diff --git a/build.yaml b/build.yaml
index 202d569..6c00b42 100644
--- a/build.yaml
+++ b/build.yaml
@@ -13,17 +13,26 @@
   public_headers:
   - include/grpc/census.h
   headers:
-  - src/core/census/aggregation.h
-  - src/core/census/mlog.h
-  - src/core/census/rpc_metric_id.h
+  - src/core/ext/census/aggregation.h
+  - src/core/ext/census/census_interface.h
+  - src/core/ext/census/census_rpc_stats.h
+  - src/core/ext/census/grpc_filter.h
+  - src/core/ext/census/mlog.h
+  - src/core/ext/census/rpc_metric_id.h
   src:
-  - src/core/census/context.c
-  - src/core/census/initialize.c
-  - src/core/census/mlog.c
-  - src/core/census/operation.c
-  - src/core/census/placeholders.c
-  - src/core/census/tracing.c
-- name: gpr
+  - src/core/ext/census/context.c
+  - src/core/ext/census/grpc_context.c
+  - src/core/ext/census/grpc_filter.c
+  - src/core/ext/census/grpc_plugin.c
+  - src/core/ext/census/initialize.c
+  - src/core/ext/census/mlog.c
+  - src/core/ext/census/operation.c
+  - src/core/ext/census/placeholders.c
+  - src/core/ext/census/tracing.c
+  plugin: census_grpc_plugin
+  uses:
+  - grpc_base
+- name: gpr_base
   public_headers:
   - include/grpc/support/alloc.h
   - include/grpc/support/atm.h
@@ -54,63 +63,65 @@
   - include/grpc/support/tls_pthread.h
   - include/grpc/support/useful.h
   headers:
-  - src/core/profiling/timers.h
-  - src/core/support/backoff.h
-  - src/core/support/block_annotate.h
-  - src/core/support/env.h
-  - src/core/support/load_file.h
-  - src/core/support/murmur_hash.h
-  - src/core/support/stack_lockfree.h
-  - src/core/support/string.h
-  - src/core/support/string_win32.h
-  - src/core/support/thd_internal.h
-  - src/core/support/time_precise.h
-  - src/core/support/tmpfile.h
+  - src/core/lib/profiling/timers.h
+  - src/core/lib/support/backoff.h
+  - src/core/lib/support/block_annotate.h
+  - src/core/lib/support/env.h
+  - src/core/lib/support/load_file.h
+  - src/core/lib/support/murmur_hash.h
+  - src/core/lib/support/stack_lockfree.h
+  - src/core/lib/support/string.h
+  - src/core/lib/support/string_win32.h
+  - src/core/lib/support/thd_internal.h
+  - src/core/lib/support/time_precise.h
+  - src/core/lib/support/tmpfile.h
   src:
-  - src/core/profiling/basic_timers.c
-  - src/core/profiling/stap_timers.c
-  - src/core/support/alloc.c
-  - src/core/support/avl.c
-  - src/core/support/backoff.c
-  - src/core/support/cmdline.c
-  - src/core/support/cpu_iphone.c
-  - src/core/support/cpu_linux.c
-  - src/core/support/cpu_posix.c
-  - src/core/support/cpu_windows.c
-  - src/core/support/env_linux.c
-  - src/core/support/env_posix.c
-  - src/core/support/env_win32.c
-  - src/core/support/histogram.c
-  - src/core/support/host_port.c
-  - src/core/support/load_file.c
-  - src/core/support/log.c
-  - src/core/support/log_android.c
-  - src/core/support/log_linux.c
-  - src/core/support/log_posix.c
-  - src/core/support/log_win32.c
-  - src/core/support/murmur_hash.c
-  - src/core/support/slice.c
-  - src/core/support/slice_buffer.c
-  - src/core/support/stack_lockfree.c
-  - src/core/support/string.c
-  - src/core/support/string_posix.c
-  - src/core/support/string_win32.c
-  - src/core/support/subprocess_posix.c
-  - src/core/support/subprocess_windows.c
-  - src/core/support/sync.c
-  - src/core/support/sync_posix.c
-  - src/core/support/sync_win32.c
-  - src/core/support/thd.c
-  - src/core/support/thd_posix.c
-  - src/core/support/thd_win32.c
-  - src/core/support/time.c
-  - src/core/support/time_posix.c
-  - src/core/support/time_precise.c
-  - src/core/support/time_win32.c
-  - src/core/support/tls_pthread.c
-  - src/core/support/tmpfile_posix.c
-  - src/core/support/tmpfile_win32.c
-  - src/core/support/wrap_memcpy.c
+  - src/core/lib/profiling/basic_timers.c
+  - src/core/lib/profiling/stap_timers.c
+  - src/core/lib/support/alloc.c
+  - src/core/lib/support/avl.c
+  - src/core/lib/support/backoff.c
+  - src/core/lib/support/cmdline.c
+  - src/core/lib/support/cpu_iphone.c
+  - src/core/lib/support/cpu_linux.c
+  - src/core/lib/support/cpu_posix.c
+  - src/core/lib/support/cpu_windows.c
+  - src/core/lib/support/env_linux.c
+  - src/core/lib/support/env_posix.c
+  - src/core/lib/support/env_win32.c
+  - src/core/lib/support/histogram.c
+  - src/core/lib/support/host_port.c
+  - src/core/lib/support/load_file.c
+  - src/core/lib/support/log.c
+  - src/core/lib/support/log_android.c
+  - src/core/lib/support/log_linux.c
+  - src/core/lib/support/log_posix.c
+  - src/core/lib/support/log_win32.c
+  - src/core/lib/support/murmur_hash.c
+  - src/core/lib/support/slice.c
+  - src/core/lib/support/slice_buffer.c
+  - src/core/lib/support/stack_lockfree.c
+  - src/core/lib/support/string.c
+  - src/core/lib/support/string_posix.c
+  - src/core/lib/support/string_win32.c
+  - src/core/lib/support/subprocess_posix.c
+  - src/core/lib/support/subprocess_windows.c
+  - src/core/lib/support/sync.c
+  - src/core/lib/support/sync_posix.c
+  - src/core/lib/support/sync_win32.c
+  - src/core/lib/support/thd.c
+  - src/core/lib/support/thd_posix.c
+  - src/core/lib/support/thd_win32.c
+  - src/core/lib/support/time.c
+  - src/core/lib/support/time_posix.c
+  - src/core/lib/support/time_precise.c
+  - src/core/lib/support/time_win32.c
+  - src/core/lib/support/tls_pthread.c
+  - src/core/lib/support/tmpfile_posix.c
+  - src/core/lib/support/tmpfile_win32.c
+  - src/core/lib/support/wrap_memcpy.c
+  uses:
+  - gpr_codegen
 - name: gpr_codegen
   public_headers:
   - include/grpc/impl/codegen/alloc.h
@@ -127,7 +138,438 @@
   - include/grpc/impl/codegen/sync_posix.h
   - include/grpc/impl/codegen/sync_win32.h
   - include/grpc/impl/codegen/time.h
+- name: grpc_base
+  public_headers:
+  - include/grpc/byte_buffer.h
+  - include/grpc/byte_buffer_reader.h
+  - include/grpc/compression.h
+  - include/grpc/grpc.h
+  - include/grpc/status.h
+  headers:
+  - src/core/lib/channel/channel_args.h
+  - src/core/lib/channel/channel_stack.h
+  - src/core/lib/channel/channel_stack_builder.h
+  - src/core/lib/channel/compress_filter.h
+  - src/core/lib/channel/connected_channel.h
+  - src/core/lib/channel/context.h
+  - src/core/lib/channel/http_client_filter.h
+  - src/core/lib/channel/http_server_filter.h
+  - src/core/lib/compression/algorithm_metadata.h
+  - src/core/lib/compression/message_compress.h
+  - src/core/lib/debug/trace.h
+  - src/core/lib/http/format_request.h
+  - src/core/lib/http/httpcli.h
+  - src/core/lib/http/parser.h
+  - src/core/lib/iomgr/closure.h
+  - src/core/lib/iomgr/endpoint.h
+  - src/core/lib/iomgr/endpoint_pair.h
+  - src/core/lib/iomgr/ev_poll_and_epoll_posix.h
+  - src/core/lib/iomgr/ev_posix.h
+  - src/core/lib/iomgr/exec_ctx.h
+  - src/core/lib/iomgr/executor.h
+  - src/core/lib/iomgr/iocp_windows.h
+  - src/core/lib/iomgr/iomgr.h
+  - src/core/lib/iomgr/iomgr_internal.h
+  - src/core/lib/iomgr/iomgr_posix.h
+  - src/core/lib/iomgr/pollset.h
+  - src/core/lib/iomgr/pollset_set.h
+  - src/core/lib/iomgr/pollset_set_windows.h
+  - src/core/lib/iomgr/pollset_windows.h
+  - src/core/lib/iomgr/resolve_address.h
+  - src/core/lib/iomgr/sockaddr.h
+  - src/core/lib/iomgr/sockaddr_posix.h
+  - src/core/lib/iomgr/sockaddr_utils.h
+  - src/core/lib/iomgr/sockaddr_win32.h
+  - src/core/lib/iomgr/socket_utils_posix.h
+  - src/core/lib/iomgr/socket_windows.h
+  - src/core/lib/iomgr/tcp_client.h
+  - src/core/lib/iomgr/tcp_posix.h
+  - src/core/lib/iomgr/tcp_server.h
+  - src/core/lib/iomgr/tcp_windows.h
+  - src/core/lib/iomgr/time_averaged_stats.h
+  - src/core/lib/iomgr/timer.h
+  - src/core/lib/iomgr/timer_heap.h
+  - src/core/lib/iomgr/udp_server.h
+  - src/core/lib/iomgr/unix_sockets_posix.h
+  - src/core/lib/iomgr/wakeup_fd_pipe.h
+  - src/core/lib/iomgr/wakeup_fd_posix.h
+  - src/core/lib/iomgr/workqueue.h
+  - src/core/lib/iomgr/workqueue_posix.h
+  - src/core/lib/iomgr/workqueue_windows.h
+  - src/core/lib/json/json.h
+  - src/core/lib/json/json_common.h
+  - src/core/lib/json/json_reader.h
+  - src/core/lib/json/json_writer.h
+  - src/core/lib/surface/api_trace.h
+  - src/core/lib/surface/call.h
+  - src/core/lib/surface/call_test_only.h
+  - src/core/lib/surface/channel.h
+  - src/core/lib/surface/channel_init.h
+  - src/core/lib/surface/channel_stack_type.h
+  - src/core/lib/surface/completion_queue.h
+  - src/core/lib/surface/event_string.h
+  - src/core/lib/surface/init.h
+  - src/core/lib/surface/lame_client.h
+  - src/core/lib/surface/server.h
+  - src/core/lib/surface/surface_trace.h
+  - src/core/lib/transport/byte_stream.h
+  - src/core/lib/transport/connectivity_state.h
+  - src/core/lib/transport/metadata.h
+  - src/core/lib/transport/metadata_batch.h
+  - src/core/lib/transport/static_metadata.h
+  - src/core/lib/transport/transport.h
+  - src/core/lib/transport/transport_impl.h
+  src:
+  - src/core/lib/channel/channel_args.c
+  - src/core/lib/channel/channel_stack.c
+  - src/core/lib/channel/channel_stack_builder.c
+  - src/core/lib/channel/compress_filter.c
+  - src/core/lib/channel/connected_channel.c
+  - src/core/lib/channel/http_client_filter.c
+  - src/core/lib/channel/http_server_filter.c
+  - src/core/lib/compression/compression_algorithm.c
+  - src/core/lib/compression/message_compress.c
+  - src/core/lib/debug/trace.c
+  - src/core/lib/http/format_request.c
+  - src/core/lib/http/httpcli.c
+  - src/core/lib/http/parser.c
+  - src/core/lib/iomgr/closure.c
+  - src/core/lib/iomgr/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_posix.c
+  - src/core/lib/iomgr/exec_ctx.c
+  - src/core/lib/iomgr/executor.c
+  - src/core/lib/iomgr/iocp_windows.c
+  - src/core/lib/iomgr/iomgr.c
+  - src/core/lib/iomgr/iomgr_posix.c
+  - src/core/lib/iomgr/iomgr_windows.c
+  - src/core/lib/iomgr/pollset_set_windows.c
+  - src/core/lib/iomgr/pollset_windows.c
+  - src/core/lib/iomgr/resolve_address_posix.c
+  - src/core/lib/iomgr/resolve_address_windows.c
+  - src/core/lib/iomgr/sockaddr_utils.c
+  - src/core/lib/iomgr/socket_utils_common_posix.c
+  - src/core/lib/iomgr/socket_utils_linux.c
+  - src/core/lib/iomgr/socket_utils_posix.c
+  - src/core/lib/iomgr/socket_windows.c
+  - src/core/lib/iomgr/tcp_client_posix.c
+  - src/core/lib/iomgr/tcp_client_windows.c
+  - src/core/lib/iomgr/tcp_posix.c
+  - src/core/lib/iomgr/tcp_server_posix.c
+  - src/core/lib/iomgr/tcp_server_windows.c
+  - src/core/lib/iomgr/tcp_windows.c
+  - src/core/lib/iomgr/time_averaged_stats.c
+  - src/core/lib/iomgr/timer.c
+  - src/core/lib/iomgr/timer_heap.c
+  - src/core/lib/iomgr/udp_server.c
+  - src/core/lib/iomgr/unix_sockets_posix.c
+  - src/core/lib/iomgr/unix_sockets_posix_noop.c
+  - src/core/lib/iomgr/wakeup_fd_eventfd.c
+  - src/core/lib/iomgr/wakeup_fd_nospecial.c
+  - src/core/lib/iomgr/wakeup_fd_pipe.c
+  - src/core/lib/iomgr/wakeup_fd_posix.c
+  - src/core/lib/iomgr/workqueue_posix.c
+  - src/core/lib/iomgr/workqueue_windows.c
+  - src/core/lib/json/json.c
+  - src/core/lib/json/json_reader.c
+  - src/core/lib/json/json_string.c
+  - src/core/lib/json/json_writer.c
+  - src/core/lib/surface/alarm.c
+  - src/core/lib/surface/api_trace.c
+  - src/core/lib/surface/byte_buffer.c
+  - src/core/lib/surface/byte_buffer_reader.c
+  - src/core/lib/surface/call.c
+  - src/core/lib/surface/call_details.c
+  - src/core/lib/surface/call_log_batch.c
+  - src/core/lib/surface/channel.c
+  - src/core/lib/surface/channel_init.c
+  - src/core/lib/surface/channel_ping.c
+  - src/core/lib/surface/channel_stack_type.c
+  - src/core/lib/surface/completion_queue.c
+  - src/core/lib/surface/event_string.c
+  - src/core/lib/surface/lame_client.c
+  - src/core/lib/surface/metadata_array.c
+  - src/core/lib/surface/server.c
+  - src/core/lib/surface/validate_metadata.c
+  - src/core/lib/surface/version.c
+  - src/core/lib/transport/byte_stream.c
+  - src/core/lib/transport/connectivity_state.c
+  - src/core/lib/transport/metadata.c
+  - src/core/lib/transport/metadata_batch.c
+  - src/core/lib/transport/static_metadata.c
+  - src/core/lib/transport/transport.c
+  - src/core/lib/transport/transport_op_string.c
+  deps:
+  - gpr
+  uses:
+  - grpc_codegen
+- name: grpc_client_config
+  headers:
+  - src/core/ext/client_config/client_channel.h
+  - src/core/ext/client_config/client_channel_factory.h
+  - src/core/ext/client_config/client_config.h
+  - src/core/ext/client_config/connector.h
+  - src/core/ext/client_config/initial_connect_string.h
+  - src/core/ext/client_config/lb_policy.h
+  - src/core/ext/client_config/lb_policy_factory.h
+  - src/core/ext/client_config/lb_policy_registry.h
+  - src/core/ext/client_config/parse_address.h
+  - src/core/ext/client_config/resolver.h
+  - src/core/ext/client_config/resolver_factory.h
+  - src/core/ext/client_config/resolver_registry.h
+  - src/core/ext/client_config/subchannel.h
+  - src/core/ext/client_config/subchannel_call_holder.h
+  - src/core/ext/client_config/subchannel_index.h
+  - src/core/ext/client_config/uri_parser.h
+  src:
+  - src/core/ext/client_config/channel_connectivity.c
+  - src/core/ext/client_config/client_channel.c
+  - src/core/ext/client_config/client_channel_factory.c
+  - src/core/ext/client_config/client_config.c
+  - src/core/ext/client_config/client_config_plugin.c
+  - src/core/ext/client_config/connector.c
+  - src/core/ext/client_config/default_initial_connect_string.c
+  - src/core/ext/client_config/initial_connect_string.c
+  - src/core/ext/client_config/lb_policy.c
+  - src/core/ext/client_config/lb_policy_factory.c
+  - src/core/ext/client_config/lb_policy_registry.c
+  - src/core/ext/client_config/parse_address.c
+  - src/core/ext/client_config/resolver.c
+  - src/core/ext/client_config/resolver_factory.c
+  - src/core/ext/client_config/resolver_registry.c
+  - src/core/ext/client_config/subchannel.c
+  - src/core/ext/client_config/subchannel_call_holder.c
+  - src/core/ext/client_config/subchannel_index.c
+  - src/core/ext/client_config/uri_parser.c
+  plugin: grpc_client_config
+  uses:
+  - grpc_base
+- name: grpc_codegen
+  public_headers:
+  - include/grpc/impl/codegen/byte_buffer.h
+  - include/grpc/impl/codegen/compression_types.h
+  - include/grpc/impl/codegen/connectivity_state.h
+  - include/grpc/impl/codegen/grpc_types.h
+  - include/grpc/impl/codegen/propagation_bits.h
+  - include/grpc/impl/codegen/status.h
+  uses:
+  - gpr_codegen
+- name: grpc_lb_policy_grpclb
+  headers:
+  - src/core/ext/lb_policy/grpclb/load_balancer_api.h
+  - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h
+  src:
+  - src/core/ext/lb_policy/grpclb/load_balancer_api.c
+  - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c
+  uses:
+  - grpc_base
+  - grpc_client_config
+  - nanopb
+- name: grpc_lb_policy_pick_first
+  src:
+  - src/core/ext/lb_policy/pick_first/pick_first.c
+  plugin: grpc_lb_policy_pick_first
+  uses:
+  - grpc_base
+  - grpc_client_config
+- name: grpc_lb_policy_round_robin
+  src:
+  - src/core/ext/lb_policy/round_robin/round_robin.c
+  plugin: grpc_lb_policy_round_robin
+  uses:
+  - grpc_base
+  - grpc_client_config
+- name: grpc_resolver_dns_native
+  src:
+  - src/core/ext/resolver/dns/native/dns_resolver.c
+  plugin: grpc_resolver_dns_native
+  uses:
+  - grpc_base
+  - grpc_client_config
+- name: grpc_resolver_sockaddr
+  src:
+  - src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+  plugin: grpc_resolver_sockaddr
+  uses:
+  - grpc_base
+  - grpc_client_config
+- name: grpc_secure
+  public_headers:
+  - 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:
+  - 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/surface/init_secure.c
+  secure: true
+  uses:
+  - grpc_base
+  - grpc_transport_chttp2_alpn
+  - tsi
+- name: grpc_test_util_base
+  build: test
+  headers:
+  - test/core/end2end/cq_verifier.h
+  - test/core/end2end/fixtures/proxy.h
+  - test/core/iomgr/endpoint_tests.h
+  - test/core/util/grpc_profiler.h
+  - test/core/util/memory_counters.h
+  - test/core/util/mock_endpoint.h
+  - test/core/util/parse_hexstring.h
+  - test/core/util/passthru_endpoint.h
+  - test/core/util/port.h
+  - test/core/util/port_server_client.h
+  - test/core/util/slice_splitter.h
+  src:
+  - test/core/end2end/cq_verifier.c
+  - test/core/end2end/fixtures/proxy.c
+  - test/core/iomgr/endpoint_tests.c
+  - test/core/util/grpc_profiler.c
+  - test/core/util/memory_counters.c
+  - test/core/util/mock_endpoint.c
+  - test/core/util/parse_hexstring.c
+  - test/core/util/passthru_endpoint.c
+  - test/core/util/port_posix.c
+  - test/core/util/port_server_client.c
+  - test/core/util/port_windows.c
+  - test/core/util/slice_splitter.c
+  deps:
+  - grpc
+  - gpr_test_util
+- name: grpc_transport_chttp2
+  headers:
+  - src/core/ext/transport/chttp2/transport/bin_encoder.h
+  - src/core/ext/transport/chttp2/transport/chttp2_transport.h
+  - src/core/ext/transport/chttp2/transport/frame.h
+  - src/core/ext/transport/chttp2/transport/frame_data.h
+  - src/core/ext/transport/chttp2/transport/frame_goaway.h
+  - src/core/ext/transport/chttp2/transport/frame_ping.h
+  - src/core/ext/transport/chttp2/transport/frame_rst_stream.h
+  - src/core/ext/transport/chttp2/transport/frame_settings.h
+  - src/core/ext/transport/chttp2/transport/frame_window_update.h
+  - src/core/ext/transport/chttp2/transport/hpack_encoder.h
+  - src/core/ext/transport/chttp2/transport/hpack_parser.h
+  - src/core/ext/transport/chttp2/transport/hpack_table.h
+  - src/core/ext/transport/chttp2/transport/http2_errors.h
+  - src/core/ext/transport/chttp2/transport/huffsyms.h
+  - src/core/ext/transport/chttp2/transport/incoming_metadata.h
+  - src/core/ext/transport/chttp2/transport/internal.h
+  - src/core/ext/transport/chttp2/transport/status_conversion.h
+  - src/core/ext/transport/chttp2/transport/stream_map.h
+  - src/core/ext/transport/chttp2/transport/timeout_encoding.h
+  - src/core/ext/transport/chttp2/transport/varint.h
+  src:
+  - src/core/ext/transport/chttp2/transport/bin_encoder.c
+  - src/core/ext/transport/chttp2/transport/chttp2_plugin.c
+  - src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  - src/core/ext/transport/chttp2/transport/frame_data.c
+  - src/core/ext/transport/chttp2/transport/frame_goaway.c
+  - src/core/ext/transport/chttp2/transport/frame_ping.c
+  - src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+  - src/core/ext/transport/chttp2/transport/frame_settings.c
+  - src/core/ext/transport/chttp2/transport/frame_window_update.c
+  - src/core/ext/transport/chttp2/transport/hpack_encoder.c
+  - src/core/ext/transport/chttp2/transport/hpack_parser.c
+  - src/core/ext/transport/chttp2/transport/hpack_table.c
+  - src/core/ext/transport/chttp2/transport/huffsyms.c
+  - src/core/ext/transport/chttp2/transport/incoming_metadata.c
+  - src/core/ext/transport/chttp2/transport/parsing.c
+  - src/core/ext/transport/chttp2/transport/status_conversion.c
+  - src/core/ext/transport/chttp2/transport/stream_lists.c
+  - src/core/ext/transport/chttp2/transport/stream_map.c
+  - src/core/ext/transport/chttp2/transport/timeout_encoding.c
+  - src/core/ext/transport/chttp2/transport/varint.c
+  - src/core/ext/transport/chttp2/transport/writing.c
+  plugin: grpc_chttp2_plugin
+  uses:
+  - grpc_base
+  - grpc_transport_chttp2_alpn
+- name: grpc_transport_chttp2_alpn
+  headers:
+  - src/core/ext/transport/chttp2/alpn/alpn.h
+  src:
+  - src/core/ext/transport/chttp2/alpn/alpn.c
+  deps:
+  - gpr
+- name: grpc_transport_chttp2_client_insecure
+  src:
+  - src/core/ext/transport/chttp2/client/insecure/channel_create.c
+  uses:
+  - grpc_transport_chttp2
+  - grpc_base
+  - grpc_client_config
+- name: grpc_transport_chttp2_client_secure
+  src:
+  - src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+  uses:
+  - grpc_transport_chttp2
+  - grpc_base
+  - grpc_client_config
+  - grpc_secure
+- name: grpc_transport_chttp2_server_insecure
+  src:
+  - src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
+  uses:
+  - grpc_transport_chttp2
+  - grpc_base
+- name: grpc_transport_chttp2_server_secure
+  src:
+  - src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
+  uses:
+  - grpc_transport_chttp2
+  - grpc_base
+  - grpc_secure
+- name: nanopb
+  headers:
+  - third_party/nanopb/pb.h
+  - third_party/nanopb/pb_common.h
+  - third_party/nanopb/pb_decode.h
+  - third_party/nanopb/pb_encode.h
+  src:
+  - third_party/nanopb/pb_common.c
+  - third_party/nanopb/pb_decode.c
+  - third_party/nanopb/pb_encode.c
+- name: tsi
+  headers:
+  - src/core/lib/tsi/fake_transport_security.h
+  - src/core/lib/tsi/ssl_transport_security.h
+  - src/core/lib/tsi/ssl_types.h
+  - src/core/lib/tsi/transport_security.h
+  - src/core/lib/tsi/transport_security_interface.h
+  src:
+  - src/core/lib/tsi/fake_transport_security.c
+  - src/core/lib/tsi/ssl_transport_security.c
+  - src/core/lib/tsi/transport_security.c
+  deps:
+  - gpr
+  secure: true
 - name: grpc++_base
+  language: c++
   public_headers:
   - include/grpc++/alarm.h
   - include/grpc++/channel.h
@@ -164,8 +606,6 @@
   - include/grpc++/support/async_unary_call.h
   - include/grpc++/support/byte_buffer.h
   - include/grpc++/support/channel_arguments.h
-  - include/grpc++/support/config.h
-  - include/grpc++/support/config_protobuf.h
   - include/grpc++/support/slice.h
   - include/grpc++/support/status.h
   - include/grpc++/support/status_code_enum.h
@@ -176,7 +616,6 @@
   headers:
   - src/cpp/client/create_channel_internal.h
   - src/cpp/common/core_codegen.h
-  - src/cpp/common/create_auth_context.h
   - src/cpp/server/dynamic_thread_pool.h
   - src/cpp/server/thread_pool_interface.h
   src:
@@ -204,7 +643,13 @@
   - src/cpp/util/status.cc
   - src/cpp/util/string_ref.cc
   - src/cpp/util/time.cc
+  deps:
+  - grpc
+  uses:
+  - grpc++_codegen
+  - grpc++_config
 - name: grpc++_codegen
+  language: c++
   public_headers:
   - include/grpc++/impl/codegen/async_stream.h
   - include/grpc++/impl/codegen/async_unary_call.h
@@ -215,9 +660,8 @@
   - include/grpc++/impl/codegen/client_unary_call.h
   - include/grpc++/impl/codegen/completion_queue.h
   - include/grpc++/impl/codegen/completion_queue_tag.h
-  - include/grpc++/impl/codegen/config.h
-  - include/grpc++/impl/codegen/config_protobuf.h
   - include/grpc++/impl/codegen/core_codegen_interface.h
+  - include/grpc++/impl/codegen/create_auth_context.h
   - include/grpc++/impl/codegen/grpc_library.h
   - include/grpc++/impl/codegen/method_handler_impl.h
   - include/grpc++/impl/codegen/proto_utils.h
@@ -239,351 +683,27 @@
   - include/grpc++/impl/codegen/time.h
   src:
   - src/cpp/codegen/codegen_init.cc
-- name: grpc_base
+  uses:
+  - grpc_codegen
+  - grpc++_config_codegen
+- name: grpc++_config
+  language: c++
   public_headers:
-  - include/grpc/byte_buffer.h
-  - include/grpc/byte_buffer_reader.h
-  - include/grpc/compression.h
-  - include/grpc/grpc.h
-  - include/grpc/status.h
-  headers:
-  - src/core/census/grpc_filter.h
-  - src/core/census/grpc_plugin.h
-  - src/core/channel/channel_args.h
-  - src/core/channel/channel_stack.h
-  - src/core/channel/channel_stack_builder.h
-  - src/core/channel/client_channel.h
-  - src/core/channel/client_uchannel.h
-  - src/core/channel/compress_filter.h
-  - src/core/channel/connected_channel.h
-  - src/core/channel/context.h
-  - src/core/channel/http_client_filter.h
-  - src/core/channel/http_server_filter.h
-  - src/core/channel/subchannel_call_holder.h
-  - src/core/client_config/client_config.h
-  - src/core/client_config/connector.h
-  - src/core/client_config/initial_connect_string.h
-  - src/core/client_config/lb_policies/load_balancer_api.h
-  - src/core/client_config/lb_policies/pick_first.h
-  - src/core/client_config/lb_policies/round_robin.h
-  - src/core/client_config/lb_policy.h
-  - src/core/client_config/lb_policy_factory.h
-  - src/core/client_config/lb_policy_registry.h
-  - src/core/client_config/resolver.h
-  - src/core/client_config/resolver_factory.h
-  - src/core/client_config/resolver_registry.h
-  - src/core/client_config/resolvers/dns_resolver.h
-  - src/core/client_config/resolvers/sockaddr_resolver.h
-  - src/core/client_config/subchannel.h
-  - src/core/client_config/subchannel_factory.h
-  - src/core/client_config/subchannel_index.h
-  - src/core/client_config/uri_parser.h
-  - src/core/compression/algorithm_metadata.h
-  - src/core/compression/message_compress.h
-  - src/core/debug/trace.h
-  - src/core/httpcli/format_request.h
-  - src/core/httpcli/httpcli.h
-  - src/core/httpcli/parser.h
-  - src/core/iomgr/closure.h
-  - src/core/iomgr/endpoint.h
-  - src/core/iomgr/endpoint_pair.h
-  - src/core/iomgr/exec_ctx.h
-  - src/core/iomgr/executor.h
-  - src/core/iomgr/fd_posix.h
-  - src/core/iomgr/iocp_windows.h
-  - src/core/iomgr/iomgr.h
-  - src/core/iomgr/iomgr_internal.h
-  - src/core/iomgr/iomgr_posix.h
-  - src/core/iomgr/pollset.h
-  - src/core/iomgr/pollset_posix.h
-  - src/core/iomgr/pollset_set.h
-  - src/core/iomgr/pollset_set_posix.h
-  - src/core/iomgr/pollset_set_windows.h
-  - src/core/iomgr/pollset_windows.h
-  - src/core/iomgr/resolve_address.h
-  - src/core/iomgr/sockaddr.h
-  - src/core/iomgr/sockaddr_posix.h
-  - src/core/iomgr/sockaddr_utils.h
-  - src/core/iomgr/sockaddr_win32.h
-  - src/core/iomgr/socket_utils_posix.h
-  - src/core/iomgr/socket_windows.h
-  - src/core/iomgr/tcp_client.h
-  - src/core/iomgr/tcp_posix.h
-  - src/core/iomgr/tcp_server.h
-  - src/core/iomgr/tcp_windows.h
-  - src/core/iomgr/time_averaged_stats.h
-  - src/core/iomgr/timer.h
-  - src/core/iomgr/timer_heap.h
-  - src/core/iomgr/udp_server.h
-  - src/core/iomgr/wakeup_fd_pipe.h
-  - src/core/iomgr/wakeup_fd_posix.h
-  - src/core/iomgr/workqueue.h
-  - src/core/iomgr/workqueue_posix.h
-  - src/core/iomgr/workqueue_windows.h
-  - src/core/json/json.h
-  - src/core/json/json_common.h
-  - src/core/json/json_reader.h
-  - src/core/json/json_writer.h
-  - src/core/proto/grpc/lb/v0/load_balancer.pb.h
-  - src/core/statistics/census_interface.h
-  - src/core/statistics/census_rpc_stats.h
-  - src/core/surface/api_trace.h
-  - src/core/surface/call.h
-  - src/core/surface/call_test_only.h
-  - src/core/surface/channel.h
-  - src/core/surface/channel_init.h
-  - src/core/surface/channel_stack_type.h
-  - src/core/surface/completion_queue.h
-  - src/core/surface/event_string.h
-  - src/core/surface/init.h
-  - src/core/surface/lame_client.h
-  - src/core/surface/server.h
-  - src/core/surface/surface_trace.h
-  - src/core/transport/byte_stream.h
-  - src/core/transport/chttp2/alpn.h
-  - src/core/transport/chttp2/bin_encoder.h
-  - src/core/transport/chttp2/frame.h
-  - src/core/transport/chttp2/frame_data.h
-  - src/core/transport/chttp2/frame_goaway.h
-  - src/core/transport/chttp2/frame_ping.h
-  - src/core/transport/chttp2/frame_rst_stream.h
-  - src/core/transport/chttp2/frame_settings.h
-  - src/core/transport/chttp2/frame_window_update.h
-  - src/core/transport/chttp2/hpack_encoder.h
-  - src/core/transport/chttp2/hpack_parser.h
-  - src/core/transport/chttp2/hpack_table.h
-  - src/core/transport/chttp2/http2_errors.h
-  - src/core/transport/chttp2/huffsyms.h
-  - src/core/transport/chttp2/incoming_metadata.h
-  - src/core/transport/chttp2/internal.h
-  - src/core/transport/chttp2/status_conversion.h
-  - src/core/transport/chttp2/stream_map.h
-  - src/core/transport/chttp2/timeout_encoding.h
-  - src/core/transport/chttp2/varint.h
-  - src/core/transport/chttp2_transport.h
-  - src/core/transport/connectivity_state.h
-  - src/core/transport/metadata.h
-  - src/core/transport/metadata_batch.h
-  - src/core/transport/static_metadata.h
-  - src/core/transport/transport.h
-  - src/core/transport/transport_impl.h
-  src:
-  - src/core/census/grpc_context.c
-  - src/core/census/grpc_filter.c
-  - src/core/census/grpc_plugin.c
-  - src/core/channel/channel_args.c
-  - src/core/channel/channel_stack.c
-  - src/core/channel/channel_stack_builder.c
-  - src/core/channel/client_channel.c
-  - src/core/channel/client_uchannel.c
-  - src/core/channel/compress_filter.c
-  - src/core/channel/connected_channel.c
-  - src/core/channel/http_client_filter.c
-  - src/core/channel/http_server_filter.c
-  - src/core/channel/subchannel_call_holder.c
-  - src/core/client_config/client_config.c
-  - src/core/client_config/connector.c
-  - src/core/client_config/default_initial_connect_string.c
-  - src/core/client_config/initial_connect_string.c
-  - src/core/client_config/lb_policies/load_balancer_api.c
-  - src/core/client_config/lb_policies/pick_first.c
-  - src/core/client_config/lb_policies/round_robin.c
-  - src/core/client_config/lb_policy.c
-  - src/core/client_config/lb_policy_factory.c
-  - src/core/client_config/lb_policy_registry.c
-  - src/core/client_config/resolver.c
-  - src/core/client_config/resolver_factory.c
-  - src/core/client_config/resolver_registry.c
-  - src/core/client_config/resolvers/dns_resolver.c
-  - src/core/client_config/resolvers/sockaddr_resolver.c
-  - src/core/client_config/subchannel.c
-  - src/core/client_config/subchannel_factory.c
-  - src/core/client_config/subchannel_index.c
-  - src/core/client_config/uri_parser.c
-  - src/core/compression/compression_algorithm.c
-  - src/core/compression/message_compress.c
-  - src/core/debug/trace.c
-  - src/core/httpcli/format_request.c
-  - src/core/httpcli/httpcli.c
-  - src/core/httpcli/parser.c
-  - src/core/iomgr/closure.c
-  - src/core/iomgr/endpoint.c
-  - src/core/iomgr/endpoint_pair_posix.c
-  - src/core/iomgr/endpoint_pair_windows.c
-  - src/core/iomgr/exec_ctx.c
-  - src/core/iomgr/executor.c
-  - src/core/iomgr/fd_posix.c
-  - src/core/iomgr/iocp_windows.c
-  - src/core/iomgr/iomgr.c
-  - src/core/iomgr/iomgr_posix.c
-  - src/core/iomgr/iomgr_windows.c
-  - src/core/iomgr/pollset_multipoller_with_epoll.c
-  - src/core/iomgr/pollset_multipoller_with_poll_posix.c
-  - src/core/iomgr/pollset_posix.c
-  - src/core/iomgr/pollset_set_posix.c
-  - src/core/iomgr/pollset_set_windows.c
-  - src/core/iomgr/pollset_windows.c
-  - src/core/iomgr/resolve_address_posix.c
-  - src/core/iomgr/resolve_address_windows.c
-  - src/core/iomgr/sockaddr_utils.c
-  - src/core/iomgr/socket_utils_common_posix.c
-  - src/core/iomgr/socket_utils_linux.c
-  - src/core/iomgr/socket_utils_posix.c
-  - src/core/iomgr/socket_windows.c
-  - src/core/iomgr/tcp_client_posix.c
-  - src/core/iomgr/tcp_client_windows.c
-  - src/core/iomgr/tcp_posix.c
-  - src/core/iomgr/tcp_server_posix.c
-  - src/core/iomgr/tcp_server_windows.c
-  - src/core/iomgr/tcp_windows.c
-  - src/core/iomgr/time_averaged_stats.c
-  - src/core/iomgr/timer.c
-  - src/core/iomgr/timer_heap.c
-  - src/core/iomgr/udp_server.c
-  - src/core/iomgr/wakeup_fd_eventfd.c
-  - src/core/iomgr/wakeup_fd_nospecial.c
-  - src/core/iomgr/wakeup_fd_pipe.c
-  - src/core/iomgr/wakeup_fd_posix.c
-  - src/core/iomgr/workqueue_posix.c
-  - src/core/iomgr/workqueue_windows.c
-  - src/core/json/json.c
-  - src/core/json/json_reader.c
-  - src/core/json/json_string.c
-  - src/core/json/json_writer.c
-  - src/core/proto/grpc/lb/v0/load_balancer.pb.c
-  - src/core/surface/alarm.c
-  - src/core/surface/api_trace.c
-  - src/core/surface/byte_buffer.c
-  - src/core/surface/byte_buffer_reader.c
-  - src/core/surface/call.c
-  - src/core/surface/call_details.c
-  - src/core/surface/call_log_batch.c
-  - src/core/surface/channel.c
-  - src/core/surface/channel_connectivity.c
-  - src/core/surface/channel_create.c
-  - src/core/surface/channel_init.c
-  - src/core/surface/channel_ping.c
-  - src/core/surface/channel_stack_type.c
-  - src/core/surface/completion_queue.c
-  - src/core/surface/event_string.c
-  - src/core/surface/init.c
-  - src/core/surface/lame_client.c
-  - src/core/surface/metadata_array.c
-  - src/core/surface/server.c
-  - src/core/surface/server_chttp2.c
-  - src/core/surface/validate_metadata.c
-  - src/core/surface/version.c
-  - src/core/transport/byte_stream.c
-  - src/core/transport/chttp2/alpn.c
-  - src/core/transport/chttp2/bin_encoder.c
-  - src/core/transport/chttp2/frame_data.c
-  - src/core/transport/chttp2/frame_goaway.c
-  - src/core/transport/chttp2/frame_ping.c
-  - src/core/transport/chttp2/frame_rst_stream.c
-  - src/core/transport/chttp2/frame_settings.c
-  - src/core/transport/chttp2/frame_window_update.c
-  - src/core/transport/chttp2/hpack_encoder.c
-  - src/core/transport/chttp2/hpack_parser.c
-  - src/core/transport/chttp2/hpack_table.c
-  - src/core/transport/chttp2/huffsyms.c
-  - src/core/transport/chttp2/incoming_metadata.c
-  - src/core/transport/chttp2/parsing.c
-  - src/core/transport/chttp2/status_conversion.c
-  - src/core/transport/chttp2/stream_lists.c
-  - src/core/transport/chttp2/stream_map.c
-  - src/core/transport/chttp2/timeout_encoding.c
-  - src/core/transport/chttp2/varint.c
-  - src/core/transport/chttp2/writing.c
-  - src/core/transport/chttp2_transport.c
-  - src/core/transport/connectivity_state.c
-  - src/core/transport/metadata.c
-  - src/core/transport/metadata_batch.c
-  - src/core/transport/static_metadata.c
-  - src/core/transport/transport.c
-  - src/core/transport/transport_op_string.c
-- name: grpc_codegen
+  - include/grpc++/support/config.h
+  - include/grpc++/support/config_protobuf.h
+  uses:
+  - grpc++_config_codegen
+- name: grpc++_config_codegen
+  language: c++
   public_headers:
-  - include/grpc/impl/codegen/byte_buffer.h
-  - include/grpc/impl/codegen/compression_types.h
-  - include/grpc/impl/codegen/connectivity_state.h
-  - include/grpc/impl/codegen/grpc_types.h
-  - include/grpc/impl/codegen/propagation_bits.h
-  - include/grpc/impl/codegen/status.h
-- name: grpc_secure
-  headers:
-  - src/core/security/auth_filters.h
-  - src/core/security/b64.h
-  - src/core/security/credentials.h
-  - src/core/security/handshake.h
-  - src/core/security/json_token.h
-  - src/core/security/jwt_verifier.h
-  - src/core/security/secure_endpoint.h
-  - src/core/security/security_connector.h
-  - src/core/security/security_context.h
-  - src/core/tsi/fake_transport_security.h
-  - src/core/tsi/ssl_transport_security.h
-  - src/core/tsi/ssl_types.h
-  - src/core/tsi/transport_security.h
-  - src/core/tsi/transport_security_interface.h
-  src:
-  - src/core/httpcli/httpcli_security_connector.c
-  - src/core/security/b64.c
-  - src/core/security/client_auth_filter.c
-  - src/core/security/credentials.c
-  - src/core/security/credentials_metadata.c
-  - src/core/security/credentials_posix.c
-  - src/core/security/credentials_win32.c
-  - src/core/security/google_default_credentials.c
-  - src/core/security/handshake.c
-  - src/core/security/json_token.c
-  - src/core/security/jwt_verifier.c
-  - src/core/security/secure_endpoint.c
-  - src/core/security/security_connector.c
-  - src/core/security/security_context.c
-  - src/core/security/server_auth_filter.c
-  - src/core/security/server_secure_chttp2.c
-  - src/core/surface/init_secure.c
-  - src/core/surface/secure_channel_create.c
-  - src/core/tsi/fake_transport_security.c
-  - src/core/tsi/ssl_transport_security.c
-  - src/core/tsi/transport_security.c
-- name: grpc_test_util_base
-  headers:
-  - test/core/end2end/cq_verifier.h
-  - test/core/end2end/fixtures/proxy.h
-  - test/core/iomgr/endpoint_tests.h
-  - test/core/util/grpc_profiler.h
-  - test/core/util/parse_hexstring.h
-  - test/core/util/port.h
-  - test/core/util/port_server_client.h
-  - test/core/util/slice_splitter.h
-  src:
-  - test/core/end2end/cq_verifier.c
-  - test/core/end2end/fixtures/proxy.c
-  - test/core/iomgr/endpoint_tests.c
-  - test/core/util/grpc_profiler.c
-  - test/core/util/parse_hexstring.c
-  - test/core/util/port_posix.c
-  - test/core/util/port_server_client.c
-  - test/core/util/port_windows.c
-  - test/core/util/slice_splitter.c
-- name: nanopb
-  headers:
-  - third_party/nanopb/pb.h
-  - third_party/nanopb/pb_common.h
-  - third_party/nanopb/pb_decode.h
-  - third_party/nanopb/pb_encode.h
-  src:
-  - third_party/nanopb/pb_common.c
-  - third_party/nanopb/pb_decode.c
-  - third_party/nanopb/pb_encode.c
+  - include/grpc++/impl/codegen/config.h
+  - include/grpc++/impl/codegen/config_protobuf.h
 libs:
 - name: gpr
   build: all
   language: c
   filegroups:
-  - gpr
-  - gpr_codegen
+  - gpr_base
   secure: false
   vs_project_guid: '{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}'
 - name: gpr_test_util
@@ -600,34 +720,30 @@
 - name: grpc
   build: all
   language: c
-  public_headers:
-  - include/grpc/grpc_security.h
-  deps:
-  - gpr
+  src:
+  - src/core/lib/surface/init.c
   baselib: true
   deps_linkage: static
   dll: true
   filegroups:
   - grpc_base
+  - grpc_transport_chttp2_server_secure
+  - grpc_transport_chttp2_client_secure
+  - grpc_transport_chttp2_server_insecure
+  - grpc_transport_chttp2_client_insecure
+  - grpc_lb_policy_grpclb
+  - grpc_lb_policy_pick_first
+  - grpc_lb_policy_round_robin
+  - grpc_resolver_dns_native
+  - grpc_resolver_sockaddr
   - grpc_secure
-  - grpc_codegen
   - census
-  - nanopb
+  generate_plugin_registry: true
   secure: true
   vs_packages:
   - grpc.dependencies.openssl
   - grpc.dependencies.zlib
   vs_project_guid: '{29D16885-7228-4C31-81ED-5F9187C7F2A9}'
-- name: grpc_codegen_lib
-  build: protoc
-  language: c
-  headers: []
-  src: []
-  filegroups:
-  - gpr_codegen
-  - grpc_codegen
-  secure: false
-  vs_project_guid: '{A828FD72-44CE-4EA5-8966-6E4624458D58}'
 - name: grpc_dll
   build: private
   language: c
@@ -656,6 +772,7 @@
   - test/core/end2end/data/ssl_test_data.h
   - test/core/security/oauth2_utils.h
   src:
+  - test/core/end2end/data/client_certs.c
   - test/core/end2end/data/server1_cert.c
   - test/core/end2end/data/server1_key.c
   - test/core/end2end/data/test_root_cert.c
@@ -682,17 +799,22 @@
   build: all
   language: c
   src:
-  - src/core/surface/init_unsecure.c
-  deps:
-  - gpr
+  - src/core/lib/surface/init.c
+  - src/core/lib/surface/init_unsecure.c
   baselib: true
   deps_linkage: static
   dll: true
   filegroups:
   - grpc_base
-  - grpc_codegen
+  - grpc_transport_chttp2_server_insecure
+  - grpc_transport_chttp2_client_insecure
+  - grpc_resolver_dns_native
+  - grpc_resolver_sockaddr
+  - grpc_lb_policy_grpclb
+  - grpc_lb_policy_pick_first
+  - grpc_lb_policy_round_robin
   - census
-  - nanopb
+  generate_plugin_registry: true
   secure: false
   vs_project_guid: '{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}'
 - name: grpc_zookeeper
@@ -700,10 +822,8 @@
   language: c
   public_headers:
   - include/grpc/grpc_zookeeper.h
-  headers:
-  - src/core/client_config/resolvers/zookeeper_resolver.h
   src:
-  - src/core/client_config/resolvers/zookeeper_resolver.c
+  - src/core/ext/resolver/zookeeper/zookeeper_resolver.c
   deps:
   - gpr
   - grpc
@@ -761,17 +881,6 @@
   - grpc++_codegen
   secure: check
   vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}'
-- name: grpc++_codegen_lib
-  build: protoc
-  language: c++
-  headers: []
-  src: []
-  filegroups:
-  - gpr_codegen
-  - grpc_codegen
-  - grpc++_codegen
-  secure: false
-  vs_project_guid: '{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}'
 - name: grpc++_test_config
   build: private
   language: c++
@@ -823,14 +932,14 @@
   build: protoc
   language: c++
   headers:
-  - include/grpc++/support/config.h
-  - include/grpc++/support/config_protobuf.h
   - src/compiler/config.h
   - src/compiler/cpp_generator.h
   - src/compiler/cpp_generator_helpers.h
   - src/compiler/csharp_generator.h
   - src/compiler/csharp_generator_helpers.h
   - src/compiler/generator_helpers.h
+  - src/compiler/node_generator.h
+  - src/compiler/node_generator_helpers.h
   - src/compiler/objective_c_generator.h
   - src/compiler/objective_c_generator_helpers.h
   - src/compiler/python_generator.h
@@ -841,13 +950,12 @@
   src:
   - src/compiler/cpp_generator.cc
   - src/compiler/csharp_generator.cc
+  - src/compiler/node_generator.cc
   - src/compiler/objective_c_generator.cc
   - src/compiler/python_generator.cc
   - src/compiler/ruby_generator.cc
-  deps:
-  - grpc++_codegen_lib
   filegroups:
-  - gpr_codegen
+  - grpc++_config
   secure: false
   vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}'
   vs_props:
@@ -1013,6 +1121,20 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: api_fuzzer
+  build: fuzzer
+  language: c
+  src:
+  - test/core/end2end/fuzzers/api_fuzzer.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/end2end/fuzzers/api_fuzzer_corpus
+  dict: test/core/end2end/fuzzers/api_fuzzer.dictionary
+  maxlen: 2048
 - name: bin_encoder_test
   build: test
   language: c
@@ -1081,6 +1203,20 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: client_fuzzer
+  build: fuzzer
+  language: c
+  src:
+  - test/core/end2end/fuzzers/client_fuzzer.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/end2end/fuzzers/client_fuzzer_corpus
+  dict: test/core/end2end/fuzzers/hpack.dictionary
+  maxlen: 2048
 - name: compression_test
   build: test
   language: c
@@ -1241,6 +1377,21 @@
   src:
   - tools/codegen/core/gen_legal_metadata_characters.c
   deps: []
+- name: goaway_server_test
+  cpu_cost: 0.1
+  build: test
+  language: c
+  src:
+  - test/core/end2end/goaway_server_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: gpr_avl_test
   build: test
   language: c
@@ -1542,6 +1693,20 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: hpack_parser_fuzzer_test
+  build: fuzzer
+  language: c
+  src:
+  - test/core/transport/chttp2/hpack_parser_fuzzer_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/transport/chttp2/hpack_parser_corpus
+  dict: test/core/end2end/fuzzers/hpack.dictionary
+  maxlen: 512
 - name: hpack_parser_test
   build: test
   language: c
@@ -1562,21 +1727,34 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: httpcli_format_request_test
-  build: test
+- name: http_fuzzer_test
+  build: fuzzer
   language: c
   src:
-  - test/core/httpcli/format_request_test.c
+  - test/core/http/fuzzer.c
   deps:
   - grpc_test_util
   - grpc
   - gpr_test_util
   - gpr
-- name: httpcli_parser_test
+  corpus_dirs:
+  - test/core/http/corpus
+  maxlen: 2048
+- name: http_parser_test
   build: test
   language: c
   src:
-  - test/core/httpcli/parser_test.c
+  - test/core/http/parser_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: httpcli_format_request_test
+  build: test
+  language: c
+  src:
+  - test/core/http/format_request_test.c
   deps:
   - grpc_test_util
   - grpc
@@ -1587,7 +1765,7 @@
   build: test
   language: c
   src:
-  - test/core/httpcli/httpcli_test.c
+  - test/core/http/httpcli_test.c
   deps:
   - grpc_test_util
   - grpc
@@ -1602,7 +1780,7 @@
   build: test
   language: c
   src:
-  - test/core/httpcli/httpscli_test.c
+  - test/core/http/httpscli_test.c
   deps:
   - grpc_test_util
   - grpc
@@ -1620,6 +1798,39 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: internal_api_canary_iomgr_test
+  build: test
+  run: false
+  language: c
+  src:
+  - test/core/internal_api_canaries/iomgr.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: internal_api_canary_support_test
+  build: test
+  run: false
+  language: c
+  src:
+  - test/core/internal_api_canaries/iomgr.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: internal_api_canary_transport_test
+  build: test
+  run: false
+  language: c
+  src:
+  - test/core/internal_api_canaries/iomgr.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: invalid_call_argument_test
   build: test
   language: c
@@ -1630,6 +1841,19 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: json_fuzzer_test
+  build: fuzzer
+  language: c
+  src:
+  - test/core/json/fuzzer.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/json/corpus
+  maxlen: 512
 - name: json_rewrite
   build: test
   run: false
@@ -1744,6 +1968,32 @@
   deps:
   - gpr_test_util
   - gpr
+- name: nanopb_fuzzer_response_test
+  build: fuzzer
+  language: c
+  src:
+  - test/core/nanopb/fuzzer_response.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/nanopb/corpus_response
+  maxlen: 128
+- name: nanopb_fuzzer_serverlist_test
+  build: fuzzer
+  language: c
+  src:
+  - test/core/nanopb/fuzzer_serverlist.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/nanopb/corpus_serverlist
+  maxlen: 128
 - name: no_server_test
   cpu_cost: 0.1
   build: test
@@ -1795,6 +2045,20 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: server_fuzzer
+  build: fuzzer
+  language: c
+  src:
+  - test/core/end2end/fuzzers/server_fuzzer.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/end2end/fuzzers/server_fuzzer_corpus
+  dict: test/core/end2end/fuzzers/hpack.dictionary
+  maxlen: 2048
 - name: server_test
   build: test
   language: c
@@ -1993,6 +2257,19 @@
   - mac
   - linux
   - posix
+- name: uri_fuzzer_test
+  build: fuzzer
+  language: c
+  src:
+  - test/core/client_config/uri_fuzzer_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/client_config/uri_corpus
+  maxlen: 128
 - name: uri_parser_test
   build: test
   language: c
@@ -2144,7 +2421,7 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: codegen_test
+- name: codegen_test_full
   gtest: true
   build: test
   language: c++
@@ -2155,9 +2432,27 @@
   - src/proto/grpc/testing/perf_db.proto
   - src/proto/grpc/testing/services.proto
   - src/proto/grpc/testing/stats.proto
-  - test/cpp/codegen/codegen_test.cc
+  - test/cpp/codegen/codegen_test_full.cc
   deps:
-  - grpc++_codegen_lib
+  - grpc++
+  - grpc
+  - gpr
+  filegroups:
+  - grpc++_codegen
+- name: codegen_test_minimal
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - src/proto/grpc/testing/control.proto
+  - src/proto/grpc/testing/messages.proto
+  - src/proto/grpc/testing/payloads.proto
+  - src/proto/grpc/testing/perf_db.proto
+  - src/proto/grpc/testing/services.proto
+  - src/proto/grpc/testing/stats.proto
+  - test/cpp/codegen/codegen_test_minimal.cc
+  filegroups:
+  - grpc++_codegen
 - name: credentials_test
   gtest: true
   build: test
@@ -2290,6 +2585,15 @@
   secure: false
   vs_config_type: Application
   vs_project_guid: '{3C813052-A49A-4662-B90A-1ADBEC7EE453}'
+- name: grpc_node_plugin
+  build: protoc
+  language: c++
+  src:
+  - src/compiler/node_plugin.cc
+  deps:
+  - grpc_plugin_support
+  secure: false
+  vs_config_type: Application
 - name: grpc_objective_c_plugin
   build: protoc
   language: c++
@@ -2398,6 +2702,20 @@
   - mac
   - linux
   - posix
+- name: json_run_localhost
+  build: test
+  run: false
+  language: c++
+  src:
+  - test/cpp/qps/json_run_localhost.cc
+  deps:
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  - grpc++_test_config
 - name: metrics_client
   build: test
   run: false
@@ -2425,20 +2743,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: qps_driver
-  build: benchmark
-  language: c++
-  src:
-  - test/cpp/qps/qps_driver.cc
-  deps:
-  - qps
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
-  - gpr_test_util
-  - gpr
-  - grpc++_test_config
 - name: qps_interarrival_test
   build: test
   run: false
@@ -2457,6 +2761,24 @@
   - mac
   - linux
   - posix
+- name: qps_json_driver
+  build: test
+  run: false
+  language: c++
+  headers:
+  - test/cpp/qps/parse_json.h
+  src:
+  - test/cpp/qps/parse_json.cc
+  - test/cpp/qps/qps_json_driver.cc
+  deps:
+  - qps
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  - grpc++_test_config
 - name: qps_openloop_test
   cpu_cost: 0.5
   build: test
@@ -2496,7 +2818,8 @@
   - linux
   - posix
 - name: qps_worker
-  build: benchmark
+  build: test
+  run: false
   language: c++
   headers:
   - test/cpp/qps/client.h
@@ -2774,8 +3097,8 @@
 configs:
   asan:
     CC: clang
-    CPPFLAGS: -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument
-      -DGPR_NO_DIRECT_SYSCALLS
+    CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer
+      -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
     CXX: clang++
     LD: clang
     LDFLAGS: -fsanitize=address
@@ -2787,8 +3110,8 @@
     timeout_multiplier: 3
   asan-noleaks:
     CC: clang
-    CPPFLAGS: -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument
-      -DGPR_NO_DIRECT_SYSCALLS
+    CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer
+      -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
     CXX: clang++
     LD: clang
     LDFLAGS: -fsanitize=address
@@ -2797,6 +3120,19 @@
     test_environ:
       ASAN_OPTIONS: detect_leaks=0:color=always
     timeout_multiplier: 3
+  asan-trace-cmp:
+    CC: clang
+    CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address
+      -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
+    CXX: clang++
+    LD: clang
+    LDFLAGS: -fsanitize=address
+    LDXX: clang++
+    compile_the_world: true
+    test_environ:
+      ASAN_OPTIONS: detect_leaks=1:color=always
+      LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
+    timeout_multiplier: 3
   basicprof:
     CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC
     DEFINES: NDEBUG
@@ -2805,8 +3141,8 @@
     DEFINES: _DEBUG DEBUG
   easan:
     CC: clang
-    CPPFLAGS: -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument
-      -DGPR_NO_DIRECT_SYSCALLS
+    CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer
+      -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
     CXX: clang++
     DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
     LD: clang
@@ -2855,9 +3191,9 @@
     valgrind: --tool=memcheck --leak-check=full
   msan:
     CC: clang
-    CPPFLAGS: -O0 -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer
-      -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument
-      -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
+    CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=memory -fsanitize-memory-track-origins
+      -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1
+      -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
     CXX: clang++
     DEFINES: NDEBUG
     LD: clang
@@ -2890,7 +3226,8 @@
     timeout_multiplier: 5
   ubsan:
     CC: clang
-    CPPFLAGS: -O1 -fsanitize=undefined -fno-omit-frame-pointer -Wno-unused-command-line-argument
+    CPPFLAGS: -O1 -fsanitize-coverage=edge -fsanitize=undefined -fno-omit-frame-pointer
+      -Wno-unused-command-line-argument
     CXX: clang++
     DEFINES: NDEBUG
     LD: clang
diff --git a/config.m4 b/config.m4
index 91b87e2..2d930a6 100644
--- a/config.m4
+++ b/config.m4
@@ -36,213 +36,215 @@
     src/php/ext/grpc/server.c \
     src/php/ext/grpc/server_credentials.c \
     src/php/ext/grpc/timeval.c \
-    src/core/profiling/basic_timers.c \
-    src/core/profiling/stap_timers.c \
-    src/core/support/alloc.c \
-    src/core/support/avl.c \
-    src/core/support/backoff.c \
-    src/core/support/cmdline.c \
-    src/core/support/cpu_iphone.c \
-    src/core/support/cpu_linux.c \
-    src/core/support/cpu_posix.c \
-    src/core/support/cpu_windows.c \
-    src/core/support/env_linux.c \
-    src/core/support/env_posix.c \
-    src/core/support/env_win32.c \
-    src/core/support/histogram.c \
-    src/core/support/host_port.c \
-    src/core/support/load_file.c \
-    src/core/support/log.c \
-    src/core/support/log_android.c \
-    src/core/support/log_linux.c \
-    src/core/support/log_posix.c \
-    src/core/support/log_win32.c \
-    src/core/support/murmur_hash.c \
-    src/core/support/slice.c \
-    src/core/support/slice_buffer.c \
-    src/core/support/stack_lockfree.c \
-    src/core/support/string.c \
-    src/core/support/string_posix.c \
-    src/core/support/string_win32.c \
-    src/core/support/subprocess_posix.c \
-    src/core/support/subprocess_windows.c \
-    src/core/support/sync.c \
-    src/core/support/sync_posix.c \
-    src/core/support/sync_win32.c \
-    src/core/support/thd.c \
-    src/core/support/thd_posix.c \
-    src/core/support/thd_win32.c \
-    src/core/support/time.c \
-    src/core/support/time_posix.c \
-    src/core/support/time_precise.c \
-    src/core/support/time_win32.c \
-    src/core/support/tls_pthread.c \
-    src/core/support/tmpfile_posix.c \
-    src/core/support/tmpfile_win32.c \
-    src/core/support/wrap_memcpy.c \
-    src/core/census/grpc_context.c \
-    src/core/census/grpc_filter.c \
-    src/core/census/grpc_plugin.c \
-    src/core/channel/channel_args.c \
-    src/core/channel/channel_stack.c \
-    src/core/channel/channel_stack_builder.c \
-    src/core/channel/client_channel.c \
-    src/core/channel/client_uchannel.c \
-    src/core/channel/compress_filter.c \
-    src/core/channel/connected_channel.c \
-    src/core/channel/http_client_filter.c \
-    src/core/channel/http_server_filter.c \
-    src/core/channel/subchannel_call_holder.c \
-    src/core/client_config/client_config.c \
-    src/core/client_config/connector.c \
-    src/core/client_config/default_initial_connect_string.c \
-    src/core/client_config/initial_connect_string.c \
-    src/core/client_config/lb_policies/load_balancer_api.c \
-    src/core/client_config/lb_policies/pick_first.c \
-    src/core/client_config/lb_policies/round_robin.c \
-    src/core/client_config/lb_policy.c \
-    src/core/client_config/lb_policy_factory.c \
-    src/core/client_config/lb_policy_registry.c \
-    src/core/client_config/resolver.c \
-    src/core/client_config/resolver_factory.c \
-    src/core/client_config/resolver_registry.c \
-    src/core/client_config/resolvers/dns_resolver.c \
-    src/core/client_config/resolvers/sockaddr_resolver.c \
-    src/core/client_config/subchannel.c \
-    src/core/client_config/subchannel_factory.c \
-    src/core/client_config/subchannel_index.c \
-    src/core/client_config/uri_parser.c \
-    src/core/compression/compression_algorithm.c \
-    src/core/compression/message_compress.c \
-    src/core/debug/trace.c \
-    src/core/httpcli/format_request.c \
-    src/core/httpcli/httpcli.c \
-    src/core/httpcli/parser.c \
-    src/core/iomgr/closure.c \
-    src/core/iomgr/endpoint.c \
-    src/core/iomgr/endpoint_pair_posix.c \
-    src/core/iomgr/endpoint_pair_windows.c \
-    src/core/iomgr/exec_ctx.c \
-    src/core/iomgr/executor.c \
-    src/core/iomgr/fd_posix.c \
-    src/core/iomgr/iocp_windows.c \
-    src/core/iomgr/iomgr.c \
-    src/core/iomgr/iomgr_posix.c \
-    src/core/iomgr/iomgr_windows.c \
-    src/core/iomgr/pollset_multipoller_with_epoll.c \
-    src/core/iomgr/pollset_multipoller_with_poll_posix.c \
-    src/core/iomgr/pollset_posix.c \
-    src/core/iomgr/pollset_set_posix.c \
-    src/core/iomgr/pollset_set_windows.c \
-    src/core/iomgr/pollset_windows.c \
-    src/core/iomgr/resolve_address_posix.c \
-    src/core/iomgr/resolve_address_windows.c \
-    src/core/iomgr/sockaddr_utils.c \
-    src/core/iomgr/socket_utils_common_posix.c \
-    src/core/iomgr/socket_utils_linux.c \
-    src/core/iomgr/socket_utils_posix.c \
-    src/core/iomgr/socket_windows.c \
-    src/core/iomgr/tcp_client_posix.c \
-    src/core/iomgr/tcp_client_windows.c \
-    src/core/iomgr/tcp_posix.c \
-    src/core/iomgr/tcp_server_posix.c \
-    src/core/iomgr/tcp_server_windows.c \
-    src/core/iomgr/tcp_windows.c \
-    src/core/iomgr/time_averaged_stats.c \
-    src/core/iomgr/timer.c \
-    src/core/iomgr/timer_heap.c \
-    src/core/iomgr/udp_server.c \
-    src/core/iomgr/wakeup_fd_eventfd.c \
-    src/core/iomgr/wakeup_fd_nospecial.c \
-    src/core/iomgr/wakeup_fd_pipe.c \
-    src/core/iomgr/wakeup_fd_posix.c \
-    src/core/iomgr/workqueue_posix.c \
-    src/core/iomgr/workqueue_windows.c \
-    src/core/json/json.c \
-    src/core/json/json_reader.c \
-    src/core/json/json_string.c \
-    src/core/json/json_writer.c \
-    src/core/proto/grpc/lb/v0/load_balancer.pb.c \
-    src/core/surface/alarm.c \
-    src/core/surface/api_trace.c \
-    src/core/surface/byte_buffer.c \
-    src/core/surface/byte_buffer_reader.c \
-    src/core/surface/call.c \
-    src/core/surface/call_details.c \
-    src/core/surface/call_log_batch.c \
-    src/core/surface/channel.c \
-    src/core/surface/channel_connectivity.c \
-    src/core/surface/channel_create.c \
-    src/core/surface/channel_init.c \
-    src/core/surface/channel_ping.c \
-    src/core/surface/channel_stack_type.c \
-    src/core/surface/completion_queue.c \
-    src/core/surface/event_string.c \
-    src/core/surface/init.c \
-    src/core/surface/lame_client.c \
-    src/core/surface/metadata_array.c \
-    src/core/surface/server.c \
-    src/core/surface/server_chttp2.c \
-    src/core/surface/validate_metadata.c \
-    src/core/surface/version.c \
-    src/core/transport/byte_stream.c \
-    src/core/transport/chttp2/alpn.c \
-    src/core/transport/chttp2/bin_encoder.c \
-    src/core/transport/chttp2/frame_data.c \
-    src/core/transport/chttp2/frame_goaway.c \
-    src/core/transport/chttp2/frame_ping.c \
-    src/core/transport/chttp2/frame_rst_stream.c \
-    src/core/transport/chttp2/frame_settings.c \
-    src/core/transport/chttp2/frame_window_update.c \
-    src/core/transport/chttp2/hpack_encoder.c \
-    src/core/transport/chttp2/hpack_parser.c \
-    src/core/transport/chttp2/hpack_table.c \
-    src/core/transport/chttp2/huffsyms.c \
-    src/core/transport/chttp2/incoming_metadata.c \
-    src/core/transport/chttp2/parsing.c \
-    src/core/transport/chttp2/status_conversion.c \
-    src/core/transport/chttp2/stream_lists.c \
-    src/core/transport/chttp2/stream_map.c \
-    src/core/transport/chttp2/timeout_encoding.c \
-    src/core/transport/chttp2/varint.c \
-    src/core/transport/chttp2/writing.c \
-    src/core/transport/chttp2_transport.c \
-    src/core/transport/connectivity_state.c \
-    src/core/transport/metadata.c \
-    src/core/transport/metadata_batch.c \
-    src/core/transport/static_metadata.c \
-    src/core/transport/transport.c \
-    src/core/transport/transport_op_string.c \
-    src/core/httpcli/httpcli_security_connector.c \
-    src/core/security/b64.c \
-    src/core/security/client_auth_filter.c \
-    src/core/security/credentials.c \
-    src/core/security/credentials_metadata.c \
-    src/core/security/credentials_posix.c \
-    src/core/security/credentials_win32.c \
-    src/core/security/google_default_credentials.c \
-    src/core/security/handshake.c \
-    src/core/security/json_token.c \
-    src/core/security/jwt_verifier.c \
-    src/core/security/secure_endpoint.c \
-    src/core/security/security_connector.c \
-    src/core/security/security_context.c \
-    src/core/security/server_auth_filter.c \
-    src/core/security/server_secure_chttp2.c \
-    src/core/surface/init_secure.c \
-    src/core/surface/secure_channel_create.c \
-    src/core/tsi/fake_transport_security.c \
-    src/core/tsi/ssl_transport_security.c \
-    src/core/tsi/transport_security.c \
-    src/core/census/context.c \
-    src/core/census/initialize.c \
-    src/core/census/mlog.c \
-    src/core/census/operation.c \
-    src/core/census/placeholders.c \
-    src/core/census/tracing.c \
+    src/core/lib/profiling/basic_timers.c \
+    src/core/lib/profiling/stap_timers.c \
+    src/core/lib/support/alloc.c \
+    src/core/lib/support/avl.c \
+    src/core/lib/support/backoff.c \
+    src/core/lib/support/cmdline.c \
+    src/core/lib/support/cpu_iphone.c \
+    src/core/lib/support/cpu_linux.c \
+    src/core/lib/support/cpu_posix.c \
+    src/core/lib/support/cpu_windows.c \
+    src/core/lib/support/env_linux.c \
+    src/core/lib/support/env_posix.c \
+    src/core/lib/support/env_win32.c \
+    src/core/lib/support/histogram.c \
+    src/core/lib/support/host_port.c \
+    src/core/lib/support/load_file.c \
+    src/core/lib/support/log.c \
+    src/core/lib/support/log_android.c \
+    src/core/lib/support/log_linux.c \
+    src/core/lib/support/log_posix.c \
+    src/core/lib/support/log_win32.c \
+    src/core/lib/support/murmur_hash.c \
+    src/core/lib/support/slice.c \
+    src/core/lib/support/slice_buffer.c \
+    src/core/lib/support/stack_lockfree.c \
+    src/core/lib/support/string.c \
+    src/core/lib/support/string_posix.c \
+    src/core/lib/support/string_win32.c \
+    src/core/lib/support/subprocess_posix.c \
+    src/core/lib/support/subprocess_windows.c \
+    src/core/lib/support/sync.c \
+    src/core/lib/support/sync_posix.c \
+    src/core/lib/support/sync_win32.c \
+    src/core/lib/support/thd.c \
+    src/core/lib/support/thd_posix.c \
+    src/core/lib/support/thd_win32.c \
+    src/core/lib/support/time.c \
+    src/core/lib/support/time_posix.c \
+    src/core/lib/support/time_precise.c \
+    src/core/lib/support/time_win32.c \
+    src/core/lib/support/tls_pthread.c \
+    src/core/lib/support/tmpfile_posix.c \
+    src/core/lib/support/tmpfile_win32.c \
+    src/core/lib/support/wrap_memcpy.c \
+    src/core/lib/surface/init.c \
+    src/core/lib/channel/channel_args.c \
+    src/core/lib/channel/channel_stack.c \
+    src/core/lib/channel/channel_stack_builder.c \
+    src/core/lib/channel/compress_filter.c \
+    src/core/lib/channel/connected_channel.c \
+    src/core/lib/channel/http_client_filter.c \
+    src/core/lib/channel/http_server_filter.c \
+    src/core/lib/compression/compression_algorithm.c \
+    src/core/lib/compression/message_compress.c \
+    src/core/lib/debug/trace.c \
+    src/core/lib/http/format_request.c \
+    src/core/lib/http/httpcli.c \
+    src/core/lib/http/parser.c \
+    src/core/lib/iomgr/closure.c \
+    src/core/lib/iomgr/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_posix.c \
+    src/core/lib/iomgr/exec_ctx.c \
+    src/core/lib/iomgr/executor.c \
+    src/core/lib/iomgr/iocp_windows.c \
+    src/core/lib/iomgr/iomgr.c \
+    src/core/lib/iomgr/iomgr_posix.c \
+    src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/pollset_set_windows.c \
+    src/core/lib/iomgr/pollset_windows.c \
+    src/core/lib/iomgr/resolve_address_posix.c \
+    src/core/lib/iomgr/resolve_address_windows.c \
+    src/core/lib/iomgr/sockaddr_utils.c \
+    src/core/lib/iomgr/socket_utils_common_posix.c \
+    src/core/lib/iomgr/socket_utils_linux.c \
+    src/core/lib/iomgr/socket_utils_posix.c \
+    src/core/lib/iomgr/socket_windows.c \
+    src/core/lib/iomgr/tcp_client_posix.c \
+    src/core/lib/iomgr/tcp_client_windows.c \
+    src/core/lib/iomgr/tcp_posix.c \
+    src/core/lib/iomgr/tcp_server_posix.c \
+    src/core/lib/iomgr/tcp_server_windows.c \
+    src/core/lib/iomgr/tcp_windows.c \
+    src/core/lib/iomgr/time_averaged_stats.c \
+    src/core/lib/iomgr/timer.c \
+    src/core/lib/iomgr/timer_heap.c \
+    src/core/lib/iomgr/udp_server.c \
+    src/core/lib/iomgr/unix_sockets_posix.c \
+    src/core/lib/iomgr/unix_sockets_posix_noop.c \
+    src/core/lib/iomgr/wakeup_fd_eventfd.c \
+    src/core/lib/iomgr/wakeup_fd_nospecial.c \
+    src/core/lib/iomgr/wakeup_fd_pipe.c \
+    src/core/lib/iomgr/wakeup_fd_posix.c \
+    src/core/lib/iomgr/workqueue_posix.c \
+    src/core/lib/iomgr/workqueue_windows.c \
+    src/core/lib/json/json.c \
+    src/core/lib/json/json_reader.c \
+    src/core/lib/json/json_string.c \
+    src/core/lib/json/json_writer.c \
+    src/core/lib/surface/alarm.c \
+    src/core/lib/surface/api_trace.c \
+    src/core/lib/surface/byte_buffer.c \
+    src/core/lib/surface/byte_buffer_reader.c \
+    src/core/lib/surface/call.c \
+    src/core/lib/surface/call_details.c \
+    src/core/lib/surface/call_log_batch.c \
+    src/core/lib/surface/channel.c \
+    src/core/lib/surface/channel_init.c \
+    src/core/lib/surface/channel_ping.c \
+    src/core/lib/surface/channel_stack_type.c \
+    src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/event_string.c \
+    src/core/lib/surface/lame_client.c \
+    src/core/lib/surface/metadata_array.c \
+    src/core/lib/surface/server.c \
+    src/core/lib/surface/validate_metadata.c \
+    src/core/lib/surface/version.c \
+    src/core/lib/transport/byte_stream.c \
+    src/core/lib/transport/connectivity_state.c \
+    src/core/lib/transport/metadata.c \
+    src/core/lib/transport/metadata_batch.c \
+    src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/transport.c \
+    src/core/lib/transport/transport_op_string.c \
+    src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \
+    src/core/ext/transport/chttp2/transport/bin_encoder.c \
+    src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
+    src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/frame_data.c \
+    src/core/ext/transport/chttp2/transport/frame_goaway.c \
+    src/core/ext/transport/chttp2/transport/frame_ping.c \
+    src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+    src/core/ext/transport/chttp2/transport/frame_settings.c \
+    src/core/ext/transport/chttp2/transport/frame_window_update.c \
+    src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+    src/core/ext/transport/chttp2/transport/hpack_parser.c \
+    src/core/ext/transport/chttp2/transport/hpack_table.c \
+    src/core/ext/transport/chttp2/transport/huffsyms.c \
+    src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+    src/core/ext/transport/chttp2/transport/parsing.c \
+    src/core/ext/transport/chttp2/transport/status_conversion.c \
+    src/core/ext/transport/chttp2/transport/stream_lists.c \
+    src/core/ext/transport/chttp2/transport/stream_map.c \
+    src/core/ext/transport/chttp2/transport/timeout_encoding.c \
+    src/core/ext/transport/chttp2/transport/varint.c \
+    src/core/ext/transport/chttp2/transport/writing.c \
+    src/core/ext/transport/chttp2/alpn/alpn.c \
+    src/core/lib/http/httpcli_security_connector.c \
+    src/core/lib/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/surface/init_secure.c \
+    src/core/lib/tsi/fake_transport_security.c \
+    src/core/lib/tsi/ssl_transport_security.c \
+    src/core/lib/tsi/transport_security.c \
+    src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \
+    src/core/ext/client_config/channel_connectivity.c \
+    src/core/ext/client_config/client_channel.c \
+    src/core/ext/client_config/client_channel_factory.c \
+    src/core/ext/client_config/client_config.c \
+    src/core/ext/client_config/client_config_plugin.c \
+    src/core/ext/client_config/connector.c \
+    src/core/ext/client_config/default_initial_connect_string.c \
+    src/core/ext/client_config/initial_connect_string.c \
+    src/core/ext/client_config/lb_policy.c \
+    src/core/ext/client_config/lb_policy_factory.c \
+    src/core/ext/client_config/lb_policy_registry.c \
+    src/core/ext/client_config/parse_address.c \
+    src/core/ext/client_config/resolver.c \
+    src/core/ext/client_config/resolver_factory.c \
+    src/core/ext/client_config/resolver_registry.c \
+    src/core/ext/client_config/subchannel.c \
+    src/core/ext/client_config/subchannel_call_holder.c \
+    src/core/ext/client_config/subchannel_index.c \
+    src/core/ext/client_config/uri_parser.c \
+    src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
+    src/core/ext/transport/chttp2/client/insecure/channel_create.c \
+    src/core/ext/lb_policy/grpclb/load_balancer_api.c \
+    src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
+    src/core/ext/lb_policy/pick_first/pick_first.c \
+    src/core/ext/lb_policy/round_robin/round_robin.c \
+    src/core/ext/resolver/dns/native/dns_resolver.c \
+    src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
+    src/core/ext/census/context.c \
+    src/core/ext/census/grpc_context.c \
+    src/core/ext/census/grpc_filter.c \
+    src/core/ext/census/grpc_plugin.c \
+    src/core/ext/census/initialize.c \
+    src/core/ext/census/mlog.c \
+    src/core/ext/census/operation.c \
+    src/core/ext/census/placeholders.c \
+    src/core/ext/census/tracing.c \
+    src/core/plugin_registry/grpc_plugin_registry.c \
     src/boringssl/err_data.c \
     third_party/boringssl/crypto/aes/aes.c \
     third_party/boringssl/crypto/aes/mode_wrappers.c \
@@ -315,6 +317,7 @@
     third_party/boringssl/crypto/bn/shift.c \
     third_party/boringssl/crypto/bn/sqrt.c \
     third_party/boringssl/crypto/buf/buf.c \
+    third_party/boringssl/crypto/bytestring/asn1_compat.c \
     third_party/boringssl/crypto/bytestring/ber.c \
     third_party/boringssl/crypto/bytestring/cbb.c \
     third_party/boringssl/crypto/bytestring/cbs.c \
@@ -338,6 +341,7 @@
     third_party/boringssl/crypto/cpu-intel.c \
     third_party/boringssl/crypto/crypto.c \
     third_party/boringssl/crypto/curve25519/curve25519.c \
+    third_party/boringssl/crypto/curve25519/x25519-x86_64.c \
     third_party/boringssl/crypto/des/des.c \
     third_party/boringssl/crypto/dh/check.c \
     third_party/boringssl/crypto/dh/dh.c \
@@ -529,6 +533,7 @@
     third_party/boringssl/ssl/ssl_buffer.c \
     third_party/boringssl/ssl/ssl_cert.c \
     third_party/boringssl/ssl/ssl_cipher.c \
+    third_party/boringssl/ssl/ssl_ecdh.c \
     third_party/boringssl/ssl/ssl_file.c \
     third_party/boringssl/ssl/ssl_lib.c \
     third_party/boringssl/ssl/ssl_rsa.c \
@@ -545,24 +550,33 @@
   PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
 
   PHP_ADD_BUILD_DIR($ext_builddir/src/boringssl)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/census)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/channel)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/client_config)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/client_config/lb_policies)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/client_config/resolvers)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/compression)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/debug)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/httpcli)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/iomgr)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/json)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/profiling)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/proto/grpc/lb/v0)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/security)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/support)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/surface)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/transport)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/transport/chttp2)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/client_config)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/pick_first)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/round_robin)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/dns/native)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/sockaddr)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/alpn)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client/insecure)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client/secure)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/http)
+  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/support)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/surface)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/transport)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/tsi)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/plugin_registry)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/aes)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/asn1)
diff --git a/doc/binary-logging.md b/doc/binary-logging.md
new file mode 100644
index 0000000..69020d9
--- /dev/null
+++ b/doc/binary-logging.md
@@ -0,0 +1,59 @@
+# Binary Logging
+
+## Format
+
+The log format is described in [this proto file](src/proto/grpc/binary_log/v1alpha/log.proto). It is intended that multiple parts of the call will be logged in separate files, and then correlated by analysis tools using the rpc\_id.
+
+## API
+
+The binary logger will be a separate library from gRPC, in each language that we support. The user will need to explicitly call into the library to generate logs. The library will provide the ability to log sending or receiving, as relevant, the following on both the client and the server:
+
+ - Initial metadata
+ - Messages
+ - Status with trailing metadata from the server
+ - Additional key/value pairs that are associated with a call but not sent over the wire
+
+The following is an example of what such an API could look like in C++:
+
+```c++
+// The context provides the method_name, deadline, peer, and metadata contents.
+// direction = CLIENT_SEND
+LogRequestHeaders(ClientContext context);
+// direction = SERVER_RECV
+LogRequestHeaders(ServerContext context);
+
+// The context provides the metadata contents
+// direction = CLIENT_RECV
+LogResponseHeaders(ClientContext context);
+// direction = SERVER_SEND
+LogResponseHeaders(ServerContext context);
+
+// The context provides the metadata contents
+// direction = CLIENT_RECV
+LogStatus(ClientContext context, grpc_status_code code, string details);
+// direction = SERVER_SEND
+LogStatus(ServerContext context, grpc_status_code code, string details);
+
+// The context provides the user data contents
+// direction = CLIENT_SEND
+LogUserData(ClientContext context);
+// direction = SERVER_SEND
+LogUserData(ServerContext context);
+
+// direction = CLIENT_SEND
+LogRequestMessage(ClientContext context, uint32_t length, T message);
+// direction = SERVER_RECV
+LogRequestMessage(ServerContext context, uint32_t length, T message);
+// direction = CLIENT_RECV
+LogResponseMessage(ClientContext context, uint32_t length, T message);
+// direction = SERVER_SEND
+LogResponseMessage(ServerContext context, uint32_t length, T message);
+```
+
+In all of those cases, the `rpc_id` is provided by the context, and each combination of method and context argument type implies a single direction, as noted in the comments.
+
+For the message log functions, the `length` argument indicates the length of the complete message, and the `message` argument may be only part of the complete message, stripped of sensitive material and/or shortened for efficiency.
+
+## Language differences
+
+In other languages, more or less data will need to be passed explicitly as separate arguments. In some languages, for example, the metadata will be separate from the context-like object and will need to be passed as a separate argument.
diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index 3beb1d1..6297b5c 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -27,7 +27,7 @@
     * Whether to use a plaintext or encrypted connection
 * --use_test_ca=BOOLEAN
     * Whether to replace platform root CAs with
-      [ca.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/ca.pem)
+      [ca.pem](https://github.com/grpc/grpc/blob/master/src/core/lib/tsi/test_creds/ca.pem)
       as the CA root
 * --default_service_account=ACCOUNT_EMAIL
     * Email of the GCE default service account. Only applicable
@@ -920,7 +920,7 @@
     * Whether to use a plaintext or encrypted connection
 
 Servers must support TLS with ALPN. They should use
-[server1.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/server1.pem)
+[server1.pem](https://github.com/grpc/grpc/blob/master/src/core/lib/tsi/test_creds/server1.pem)
 for their certificate.
 
 ### EmptyCall
diff --git a/examples/cpp/helloworld/Makefile b/examples/cpp/helloworld/Makefile
index b785612..4b1867e 100644
--- a/examples/cpp/helloworld/Makefile
+++ b/examples/cpp/helloworld/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/examples/cpp/helloworld/greeter_async_server.cc b/examples/cpp/helloworld/greeter_async_server.cc
index c9b1a67..64e065b 100644
--- a/examples/cpp/helloworld/greeter_async_server.cc
+++ b/examples/cpp/helloworld/greeter_async_server.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/examples/cpp/route_guide/Makefile b/examples/cpp/route_guide/Makefile
index 3f8a598..0fbb0a8 100644
--- a/examples/cpp/route_guide/Makefile
+++ b/examples/cpp/route_guide/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/examples/csharp/helloworld/.nuget/packages.config b/examples/csharp/helloworld/.nuget/packages.config
index fb77831..0f89a66 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.0" />
+  <package id="Grpc.Tools" version="0.13.1" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/Greeter/Greeter.csproj b/examples/csharp/helloworld/Greeter/Greeter.csproj
index a25ad5f..1e9399f 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>39f4a691</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>96275748</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.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.0\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.13.1\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">
@@ -52,15 +52,20 @@
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
+    <None Include="..\..\..\protos\helloworld.proto">
+      <Link>protos\helloworld.proto</Link>
+    </None>
+    <None Include="..\generate_protos.bat">
+      <Link>generate_protos.bat</Link>
+    </None>
     <None Include="packages.config" />
-    <None Include="protos\helloworld.proto" />
   </ItemGroup>
   <ItemGroup />
-  <Import Project="..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.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')" />
   <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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <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'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/Greeter/Helloworld.cs b/examples/csharp/helloworld/Greeter/Helloworld.cs
index 63969b7..3cacdeb 100644
--- a/examples/csharp/helloworld/Greeter/Helloworld.cs
+++ b/examples/csharp/helloworld/Greeter/Helloworld.cs
@@ -26,8 +26,9 @@
             "ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz",
             "dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo",
             "CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl",
-            "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEIYChBpby5ncnBjLmV4",
-            "YW1wbGVzogIDSExXYgZwcm90bzM="));
+            "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4",
+            "YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw",
+            "cm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
diff --git a/examples/csharp/helloworld/Greeter/packages.config b/examples/csharp/helloworld/Greeter/packages.config
index abe9ad0..7d24440 100644
--- a/examples/csharp/helloworld/Greeter/packages.config
+++ b/examples/csharp/helloworld/Greeter/packages.config
@@ -1,8 +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.0" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.0" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.0" 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="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 a71cfee..e10a605 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>dcebbc77</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>d94f6f5f</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.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.0\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.13.1\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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.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')" />
   <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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <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'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/GreeterClient/Program.cs b/examples/csharp/helloworld/GreeterClient/Program.cs
index ffc7fab..4393f2f 100644
--- a/examples/csharp/helloworld/GreeterClient/Program.cs
+++ b/examples/csharp/helloworld/GreeterClient/Program.cs
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/examples/csharp/helloworld/GreeterClient/packages.config b/examples/csharp/helloworld/GreeterClient/packages.config
index abe9ad0..7d24440 100644
--- a/examples/csharp/helloworld/GreeterClient/packages.config
+++ b/examples/csharp/helloworld/GreeterClient/packages.config
@@ -1,8 +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.0" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.0" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.0" 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="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 34eea8c..6c70f75 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>2ea5dfd0</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>6f89e9f2</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.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.0\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.13.1\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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.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')" />
   <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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <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'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/GreeterServer/packages.config b/examples/csharp/helloworld/GreeterServer/packages.config
index abe9ad0..7d24440 100644
--- a/examples/csharp/helloworld/GreeterServer/packages.config
+++ b/examples/csharp/helloworld/GreeterServer/packages.config
@@ -1,8 +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.0" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.0" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.0" 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="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 7f3654c..99f81a7 100644
--- a/examples/csharp/helloworld/generate_protos.bat
+++ b/examples/csharp/helloworld/generate_protos.bat
@@ -5,6 +5,8 @@
 @rem enter this directory
 cd /d %~dp0
 
-packages\Google.Protobuf.3.0.0-beta2\tools\protoc.exe -I../../protos --csharp_out Greeter  ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=packages\Grpc.Tools.0.13.0\tools\grpc_csharp_plugin.exe
+set TOOLS_PATH=packages\Grpc.Tools.0.13.1\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
 
 endlocal
\ No newline at end of file
diff --git a/examples/csharp/route_guide/.nuget/packages.config b/examples/csharp/route_guide/.nuget/packages.config
index fb77831..0f89a66 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.0" />
+  <package id="Grpc.Tools" version="0.13.1" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/route_guide/RouteGuide/RouteGuide.cs b/examples/csharp/route_guide/RouteGuide/RouteGuide.cs
index 3bd79df..bcd77ec 100644
--- a/examples/csharp/route_guide/RouteGuide/RouteGuide.cs
+++ b/examples/csharp/route_guide/RouteGuide/RouteGuide.cs
@@ -37,7 +37,8 @@
             "b3V0ZWd1aWRlLkZlYXR1cmUiADABEj4KC1JlY29yZFJvdXRlEhEucm91dGVn",
             "dWlkZS5Qb2ludBoYLnJvdXRlZ3VpZGUuUm91dGVTdW1tYXJ5IgAoARI/CglS",
             "b3V0ZUNoYXQSFS5yb3V0ZWd1aWRlLlJvdXRlTm90ZRoVLnJvdXRlZ3VpZGUu",
-            "Um91dGVOb3RlIgAoATABQg8KB2V4LmdycGOiAgNSVEdiBnByb3RvMw=="));
+            "Um91dGVOb3RlIgAoATABQjYKG2lvLmdycGMuZXhhbXBsZXMucm91dGVndWlk",
+            "ZUIPUm91dGVHdWlkZVByb3RvUAGiAgNSVEdiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
diff --git a/examples/csharp/route_guide/RouteGuide/RouteGuide.csproj b/examples/csharp/route_guide/RouteGuide/RouteGuide.csproj
index 1fbf1ce..eba1226 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>5b6d924a</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>e1e648e7</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.12.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.0\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.13.1\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>
@@ -45,8 +45,9 @@
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
-    <Reference Include="System.Interactive.Async">
-      <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
+    <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
     </Reference>
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
@@ -61,18 +62,24 @@
     <Compile Include="RouteGuideUtil.cs" />
   </ItemGroup>
   <ItemGroup>
+    <None Include="..\..\..\protos\route_guide.proto">
+      <Link>protos\route_guide.proto</Link>
+    </None>
+    <None Include="..\generate_protos.bat">
+      <Link>generate_protos.bat</Link>
+    </None>
     <None Include="packages.config" />
     <None Include="route_guide_db.json">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.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')" />
   <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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <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'))" />
   </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/packages.config b/examples/csharp/route_guide/RouteGuide/packages.config
index e4e2109..c79aef1 100644
--- a/examples/csharp/route_guide/RouteGuide/packages.config
+++ b/examples/csharp/route_guide/RouteGuide/packages.config
@@ -1,9 +1,9 @@
 <?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.0" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.0" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.0" targetFramework="net45" />
-  <package id="Ix-Async" version="1.2.3" 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="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 22395dd..c561a9f 100644
--- a/examples/csharp/route_guide/RouteGuideClient/Program.cs
+++ b/examples/csharp/route_guide/RouteGuideClient/Program.cs
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj b/examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj
index f55627e..3f7c4d0 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>69015b00</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>2a1dd0a1</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.12.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.0\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.13.1\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>
@@ -47,8 +47,9 @@
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
-    <Reference Include="System.Interactive.Async">
-      <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
+    <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
     </Reference>
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
@@ -70,12 +71,12 @@
     </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.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')" />
   <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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <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'))" />
   </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 e4e2109..c79aef1 100644
--- a/examples/csharp/route_guide/RouteGuideClient/packages.config
+++ b/examples/csharp/route_guide/RouteGuideClient/packages.config
@@ -1,9 +1,9 @@
 <?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.0" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.0" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.0" targetFramework="net45" />
-  <package id="Ix-Async" version="1.2.3" 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="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/RouteGuideServer.csproj b/examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj
index 873556d..599b12f 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>656158d8</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>164e03eb</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.12.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.0\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.13.1\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>
@@ -47,8 +47,9 @@
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
-    <Reference Include="System.Interactive.Async">
-      <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
+    <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
     </Reference>
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
@@ -71,12 +72,12 @@
     </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.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')" />
   <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.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.0\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <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'))" />
   </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 e4e2109..c79aef1 100644
--- a/examples/csharp/route_guide/RouteGuideServer/packages.config
+++ b/examples/csharp/route_guide/RouteGuideServer/packages.config
@@ -1,9 +1,9 @@
 <?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.0" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.0" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.0" targetFramework="net45" />
-  <package id="Ix-Async" version="1.2.3" 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="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 d9cd021..12be52c 100644
--- a/examples/csharp/route_guide/generate_protos.bat
+++ b/examples/csharp/route_guide/generate_protos.bat
@@ -5,6 +5,8 @@
 @rem enter this directory
 cd /d %~dp0
 
-packages\Google.Protobuf.3.0.0-beta2\tools\protoc.exe -I../../protos --csharp_out RouteGuide  ../../protos/route_guide.proto --grpc_out RouteGuide --plugin=protoc-gen-grpc=packages\Grpc.Tools.0.13.0\tools\grpc_csharp_plugin.exe
+set TOOLS_PATH=packages\Grpc.Tools.0.13.1\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
 
 endlocal
\ No newline at end of file
diff --git a/examples/node/README.md b/examples/node/README.md
index c1ef6b0..2887883 100644
--- a/examples/node/README.md
+++ b/examples/node/README.md
@@ -10,6 +10,11 @@
 -------
 
    ```sh
+   $ # Get the gRPC repository
+   $ export REPO_ROOT=grpc # REPO root can be any directory of your choice
+   $ git clone https://github.com/grpc/grpc.git $REPO_ROOT
+   $ cd $REPO_ROOT
+
    $ cd examples/node
    $ npm install
    ```
diff --git a/examples/node/greeter_client.js b/examples/node/greeter_client.js
index ca57815..7125c2f 100644
--- a/examples/node/greeter_client.js
+++ b/examples/node/greeter_client.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,22 +31,30 @@
  *
  */
 
-var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
-
 var grpc = require('grpc');
-var hello_proto = grpc.load(PROTO_PATH).helloworld;
+
+var hello_messages = require('./helloworld_pb');
+var hello_service = require('./helloworld_grpc_pb');
 
 function main() {
-  var client = new hello_proto.Greeter('localhost:50051',
-                                       grpc.credentials.createInsecure());
+  var client = new hello_service.GreeterClient('localhost:50051',
+                                               grpc.credentials.createInsecure());
   var user;
   if (process.argv.length >= 3) {
     user = process.argv[2];
   } else {
     user = 'world';
   }
-  client.sayHello({name: user}, function(err, response) {
-    console.log('Greeting:', response.message);
+
+  var request = new hello_messages.HelloRequest();
+  request.setName(user);
+
+  client.sayHello(request, function(err, response) {
+    if (err) {
+      debugger;
+      throw err;
+    }
+    console.log('Greeting:', response.getMessage());
   });
 }
 
diff --git a/examples/node/greeter_server.js b/examples/node/greeter_server.js
index 47d9892..a4aebf6 100644
--- a/examples/node/greeter_server.js
+++ b/examples/node/greeter_server.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,16 +31,18 @@
  *
  */
 
-var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
-
 var grpc = require('grpc');
-var hello_proto = grpc.load(PROTO_PATH).helloworld;
+
+var hello_messages = require('./helloworld_pb');
+var hello_service = require('./helloworld_grpc_pb');
 
 /**
  * Implements the SayHello RPC method.
  */
 function sayHello(call, callback) {
-  callback(null, {message: 'Hello ' + call.request.name});
+  var reply = new hello_messages.HelloReply();
+  reply.setMessage("Hello " + call.request.getName());
+  callback(null, reply);
 }
 
 /**
@@ -49,7 +51,7 @@
  */
 function main() {
   var server = new grpc.Server();
-  server.addProtoService(hello_proto.Greeter.service, {sayHello: sayHello});
+  server.addService(hello_service.GreeterService, {sayHello: sayHello});
   server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
   server.start();
 }
diff --git a/examples/node/helloworld_grpc_pb.js b/examples/node/helloworld_grpc_pb.js
new file mode 100644
index 0000000..3d070d7
--- /dev/null
+++ b/examples/node/helloworld_grpc_pb.js
@@ -0,0 +1,39 @@
+// GENERATED CODE -- DO NOT EDIT!
+
+var grpc = require('grpc');
+var helloworld_pb = require('./helloworld_pb.js');
+
+function serialize_HelloReply(arg) {
+  if (!(arg instanceof helloworld_pb.HelloReply)) {
+    throw new Error('Expected argument of type HelloReply');
+  }
+  return new Buffer(arg.serializeBinary());
+}
+function deserialize_HelloReply(buffer_arg) {
+  return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg));
+}
+function serialize_HelloRequest(arg) {
+  if (!(arg instanceof helloworld_pb.HelloRequest)) {
+    throw new Error('Expected argument of type HelloRequest');
+  }
+  return new Buffer(arg.serializeBinary());
+}
+function deserialize_HelloRequest(buffer_arg) {
+  return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+var GreeterService = exports.GreeterService = {
+  sayHello: {
+    path: '/helloworld.Greeter/SayHello',
+    requestStream: false,
+    responseStream: false,
+    requestType: helloworld_pb.HelloRequest,
+    responseType: helloworld_pb.HelloReply,
+    requestSerialize: serialize_HelloRequest,
+    requestDeserialize: deserialize_HelloRequest,
+    responseSerialize: serialize_HelloReply,
+    responseDeserialize: deserialize_HelloReply,
+  },
+};
+
+exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService);
diff --git a/examples/node/helloworld_pb.js b/examples/node/helloworld_pb.js
new file mode 100644
index 0000000..6405bd9
--- /dev/null
+++ b/examples/node/helloworld_pb.js
@@ -0,0 +1,332 @@
+/**
+ * @fileoverview
+ * @enhanceable
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+goog.exportSymbol('proto.helloworld.HelloReply', null, global);
+goog.exportSymbol('proto.helloworld.HelloRequest', null, global);
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.helloworld.HelloRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.helloworld.HelloRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  proto.helloworld.HelloRequest.displayName = 'proto.helloworld.HelloRequest';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.helloworld.HelloRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.helloworld.HelloRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ *     instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.helloworld.HelloRequest} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.helloworld.HelloRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    name: msg.getName()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.helloworld.HelloRequest}
+ */
+proto.helloworld.HelloRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.helloworld.HelloRequest;
+  return proto.helloworld.HelloRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.helloworld.HelloRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.helloworld.HelloRequest}
+ */
+proto.helloworld.HelloRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setName(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.helloworld.HelloRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.helloworld.HelloRequest.serializeBinaryToWriter = function(message, writer) {
+  message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.helloworld.HelloRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  this.serializeBinaryToWriter(writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.helloworld.HelloRequest.prototype.serializeBinaryToWriter = function (writer) {
+  var f = undefined;
+  f = this.getName();
+  if (f.length > 0) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.helloworld.HelloRequest} The clone.
+ */
+proto.helloworld.HelloRequest.prototype.cloneMessage = function() {
+  return /** @type {!proto.helloworld.HelloRequest} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional string name = 1;
+ * @return {string}
+ */
+proto.helloworld.HelloRequest.prototype.getName = function() {
+  return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
+};
+
+
+/** @param {string} value  */
+proto.helloworld.HelloRequest.prototype.setName = function(value) {
+  jspb.Message.setField(this, 1, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.helloworld.HelloReply = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.helloworld.HelloReply, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  proto.helloworld.HelloReply.displayName = 'proto.helloworld.HelloReply';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.helloworld.HelloReply.prototype.toObject = function(opt_includeInstance) {
+  return proto.helloworld.HelloReply.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ *     instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.helloworld.HelloReply} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.helloworld.HelloReply.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    message: msg.getMessage()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.helloworld.HelloReply}
+ */
+proto.helloworld.HelloReply.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.helloworld.HelloReply;
+  return proto.helloworld.HelloReply.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.helloworld.HelloReply} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.helloworld.HelloReply}
+ */
+proto.helloworld.HelloReply.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setMessage(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.helloworld.HelloReply} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.helloworld.HelloReply.serializeBinaryToWriter = function(message, writer) {
+  message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.helloworld.HelloReply.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  this.serializeBinaryToWriter(writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.helloworld.HelloReply.prototype.serializeBinaryToWriter = function (writer) {
+  var f = undefined;
+  f = this.getMessage();
+  if (f.length > 0) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.helloworld.HelloReply} The clone.
+ */
+proto.helloworld.HelloReply.prototype.cloneMessage = function() {
+  return /** @type {!proto.helloworld.HelloReply} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional string message = 1;
+ * @return {string}
+ */
+proto.helloworld.HelloReply.prototype.getMessage = function() {
+  return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
+};
+
+
+/** @param {string} value  */
+proto.helloworld.HelloReply.prototype.setMessage = function(value) {
+  jspb.Message.setField(this, 1, value);
+};
+
+
+goog.object.extend(exports, proto.helloworld);
diff --git a/examples/node/package.json b/examples/node/package.json
index d135df2..49ab74d 100644
--- a/examples/node/package.json
+++ b/examples/node/package.json
@@ -4,6 +4,7 @@
   "dependencies": {
     "async": "^1.5.2",
     "grpc": "0.13.0",
+    "google-protobuf": "*",
     "lodash": "^4.6.1",
     "minimist": "^1.2.0"
   }
diff --git a/examples/node/route_guide/route_guide_client.js b/examples/node/route_guide/route_guide_client.js
index 6ff0279..fd05a59 100644
--- a/examples/node/route_guide/route_guide_client.js
+++ b/examples/node/route_guide/route_guide_client.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/examples/node/route_guide/route_guide_server.js b/examples/node/route_guide/route_guide_server.js
index 9fa9827..6c01fac 100644
--- a/examples/node/route_guide/route_guide_server.js
+++ b/examples/node/route_guide/route_guide_server.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/examples/objective-c/auth_sample/MakeRPCViewController.m b/examples/objective-c/auth_sample/MakeRPCViewController.m
index 108eda4..6013186 100644
--- a/examples/objective-c/auth_sample/MakeRPCViewController.m
+++ b/examples/objective-c/auth_sample/MakeRPCViewController.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/examples/objective-c/helloworld/main.m b/examples/objective-c/helloworld/main.m
index bf35799..755dce3 100644
--- a/examples/objective-c/helloworld/main.m
+++ b/examples/objective-c/helloworld/main.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/examples/php/greeter_client.php b/examples/php/greeter_client.php
index 3fab14f..718ef88 100644
--- a/examples/php/greeter_client.php
+++ b/examples/php/greeter_client.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/examples/php/route_guide/route_guide_client.php b/examples/php/route_guide/route_guide_client.php
index cc8640c..2f9533b 100644
--- a/examples/php/route_guide/route_guide_client.php
+++ b/examples/php/route_guide/route_guide_client.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/examples/protos/helloworld.proto b/examples/protos/helloworld.proto
index e670503..0bee1fc 100644
--- a/examples/protos/helloworld.proto
+++ b/examples/protos/helloworld.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/examples/protos/route_guide.proto b/examples/protos/route_guide.proto
index b3553ee..12c4495 100644
--- a/examples/protos/route_guide.proto
+++ b/examples/protos/route_guide.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/examples/python/helloworld/greeter_client.py b/examples/python/helloworld/greeter_client.py
index 9c18b41..40d637f 100644
--- a/examples/python/helloworld/greeter_client.py
+++ b/examples/python/helloworld/greeter_client.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/examples/python/route_guide/route_guide_client.py b/examples/python/route_guide/route_guide_client.py
index 9d6f865..ffcbd06 100644
--- a/examples/python/route_guide/route_guide_client.py
+++ b/examples/python/route_guide/route_guide_client.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/examples/python/route_guide/route_guide_server.py b/examples/python/route_guide/route_guide_server.py
index f95b36b..24f948c 100644
--- a/examples/python/route_guide/route_guide_server.py
+++ b/examples/python/route_guide/route_guide_server.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/examples/ruby/greeter_client.rb b/examples/ruby/greeter_client.rb
index 2a24316..cb4aa19 100755
--- a/examples/ruby/greeter_client.rb
+++ b/examples/ruby/greeter_client.rb
@@ -1,6 +1,6 @@
 #!/usr/bin/env ruby
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/examples/ruby/route_guide/route_guide_client.rb b/examples/ruby/route_guide/route_guide_client.rb
index 86dd1fe..e7f802c 100755
--- a/examples/ruby/route_guide/route_guide_client.rb
+++ b/examples/ruby/route_guide/route_guide_client.rb
@@ -1,6 +1,6 @@
 #!/usr/bin/env ruby
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/gRPC.podspec b/gRPC.podspec
index 86121c9..d66e033 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -63,18 +63,18 @@
 
   # Core cross-platform gRPC library, written in C.
   s.subspec 'C-Core' do |ss|
-    ss.source_files = 'src/core/profiling/timers.h',
-                      'src/core/support/backoff.h',
-                      'src/core/support/block_annotate.h',
-                      'src/core/support/env.h',
-                      'src/core/support/load_file.h',
-                      'src/core/support/murmur_hash.h',
-                      'src/core/support/stack_lockfree.h',
-                      'src/core/support/string.h',
-                      'src/core/support/string_win32.h',
-                      'src/core/support/thd_internal.h',
-                      'src/core/support/time_precise.h',
-                      'src/core/support/tmpfile.h',
+    ss.source_files = 'src/core/lib/profiling/timers.h',
+                      'src/core/lib/support/backoff.h',
+                      'src/core/lib/support/block_annotate.h',
+                      'src/core/lib/support/env.h',
+                      'src/core/lib/support/load_file.h',
+                      'src/core/lib/support/murmur_hash.h',
+                      'src/core/lib/support/stack_lockfree.h',
+                      'src/core/lib/support/string.h',
+                      'src/core/lib/support/string_win32.h',
+                      'src/core/lib/support/thd_internal.h',
+                      'src/core/lib/support/time_precise.h',
+                      'src/core/lib/support/tmpfile.h',
                       'include/grpc/support/alloc.h',
                       'include/grpc/support/atm.h',
                       'include/grpc/support/atm_gcc_atomic.h',
@@ -117,192 +117,186 @@
                       'include/grpc/impl/codegen/sync_posix.h',
                       'include/grpc/impl/codegen/sync_win32.h',
                       'include/grpc/impl/codegen/time.h',
-                      'src/core/profiling/basic_timers.c',
-                      'src/core/profiling/stap_timers.c',
-                      'src/core/support/alloc.c',
-                      'src/core/support/avl.c',
-                      'src/core/support/backoff.c',
-                      'src/core/support/cmdline.c',
-                      'src/core/support/cpu_iphone.c',
-                      'src/core/support/cpu_linux.c',
-                      'src/core/support/cpu_posix.c',
-                      'src/core/support/cpu_windows.c',
-                      'src/core/support/env_linux.c',
-                      'src/core/support/env_posix.c',
-                      'src/core/support/env_win32.c',
-                      'src/core/support/histogram.c',
-                      'src/core/support/host_port.c',
-                      'src/core/support/load_file.c',
-                      'src/core/support/log.c',
-                      'src/core/support/log_android.c',
-                      'src/core/support/log_linux.c',
-                      'src/core/support/log_posix.c',
-                      'src/core/support/log_win32.c',
-                      'src/core/support/murmur_hash.c',
-                      'src/core/support/slice.c',
-                      'src/core/support/slice_buffer.c',
-                      'src/core/support/stack_lockfree.c',
-                      'src/core/support/string.c',
-                      'src/core/support/string_posix.c',
-                      'src/core/support/string_win32.c',
-                      'src/core/support/subprocess_posix.c',
-                      'src/core/support/subprocess_windows.c',
-                      'src/core/support/sync.c',
-                      'src/core/support/sync_posix.c',
-                      'src/core/support/sync_win32.c',
-                      'src/core/support/thd.c',
-                      'src/core/support/thd_posix.c',
-                      'src/core/support/thd_win32.c',
-                      'src/core/support/time.c',
-                      'src/core/support/time_posix.c',
-                      'src/core/support/time_precise.c',
-                      'src/core/support/time_win32.c',
-                      'src/core/support/tls_pthread.c',
-                      'src/core/support/tmpfile_posix.c',
-                      'src/core/support/tmpfile_win32.c',
-                      'src/core/support/wrap_memcpy.c',
-                      'src/core/census/grpc_filter.h',
-                      'src/core/census/grpc_plugin.h',
-                      'src/core/channel/channel_args.h',
-                      'src/core/channel/channel_stack.h',
-                      'src/core/channel/channel_stack_builder.h',
-                      'src/core/channel/client_channel.h',
-                      'src/core/channel/client_uchannel.h',
-                      'src/core/channel/compress_filter.h',
-                      'src/core/channel/connected_channel.h',
-                      'src/core/channel/context.h',
-                      'src/core/channel/http_client_filter.h',
-                      'src/core/channel/http_server_filter.h',
-                      'src/core/channel/subchannel_call_holder.h',
-                      'src/core/client_config/client_config.h',
-                      'src/core/client_config/connector.h',
-                      'src/core/client_config/initial_connect_string.h',
-                      'src/core/client_config/lb_policies/load_balancer_api.h',
-                      'src/core/client_config/lb_policies/pick_first.h',
-                      'src/core/client_config/lb_policies/round_robin.h',
-                      'src/core/client_config/lb_policy.h',
-                      'src/core/client_config/lb_policy_factory.h',
-                      'src/core/client_config/lb_policy_registry.h',
-                      'src/core/client_config/resolver.h',
-                      'src/core/client_config/resolver_factory.h',
-                      'src/core/client_config/resolver_registry.h',
-                      'src/core/client_config/resolvers/dns_resolver.h',
-                      'src/core/client_config/resolvers/sockaddr_resolver.h',
-                      'src/core/client_config/subchannel.h',
-                      'src/core/client_config/subchannel_factory.h',
-                      'src/core/client_config/subchannel_index.h',
-                      'src/core/client_config/uri_parser.h',
-                      'src/core/compression/algorithm_metadata.h',
-                      'src/core/compression/message_compress.h',
-                      'src/core/debug/trace.h',
-                      'src/core/httpcli/format_request.h',
-                      'src/core/httpcli/httpcli.h',
-                      'src/core/httpcli/parser.h',
-                      'src/core/iomgr/closure.h',
-                      'src/core/iomgr/endpoint.h',
-                      'src/core/iomgr/endpoint_pair.h',
-                      'src/core/iomgr/exec_ctx.h',
-                      'src/core/iomgr/executor.h',
-                      'src/core/iomgr/fd_posix.h',
-                      'src/core/iomgr/iocp_windows.h',
-                      'src/core/iomgr/iomgr.h',
-                      'src/core/iomgr/iomgr_internal.h',
-                      'src/core/iomgr/iomgr_posix.h',
-                      'src/core/iomgr/pollset.h',
-                      'src/core/iomgr/pollset_posix.h',
-                      'src/core/iomgr/pollset_set.h',
-                      'src/core/iomgr/pollset_set_posix.h',
-                      'src/core/iomgr/pollset_set_windows.h',
-                      'src/core/iomgr/pollset_windows.h',
-                      'src/core/iomgr/resolve_address.h',
-                      'src/core/iomgr/sockaddr.h',
-                      'src/core/iomgr/sockaddr_posix.h',
-                      'src/core/iomgr/sockaddr_utils.h',
-                      'src/core/iomgr/sockaddr_win32.h',
-                      'src/core/iomgr/socket_utils_posix.h',
-                      'src/core/iomgr/socket_windows.h',
-                      'src/core/iomgr/tcp_client.h',
-                      'src/core/iomgr/tcp_posix.h',
-                      'src/core/iomgr/tcp_server.h',
-                      'src/core/iomgr/tcp_windows.h',
-                      'src/core/iomgr/time_averaged_stats.h',
-                      'src/core/iomgr/timer.h',
-                      'src/core/iomgr/timer_heap.h',
-                      'src/core/iomgr/udp_server.h',
-                      'src/core/iomgr/wakeup_fd_pipe.h',
-                      'src/core/iomgr/wakeup_fd_posix.h',
-                      'src/core/iomgr/workqueue.h',
-                      'src/core/iomgr/workqueue_posix.h',
-                      'src/core/iomgr/workqueue_windows.h',
-                      'src/core/json/json.h',
-                      'src/core/json/json_common.h',
-                      'src/core/json/json_reader.h',
-                      'src/core/json/json_writer.h',
-                      'src/core/proto/grpc/lb/v0/load_balancer.pb.h',
-                      'src/core/statistics/census_interface.h',
-                      'src/core/statistics/census_rpc_stats.h',
-                      'src/core/surface/api_trace.h',
-                      'src/core/surface/call.h',
-                      'src/core/surface/call_test_only.h',
-                      'src/core/surface/channel.h',
-                      'src/core/surface/channel_init.h',
-                      'src/core/surface/channel_stack_type.h',
-                      'src/core/surface/completion_queue.h',
-                      'src/core/surface/event_string.h',
-                      'src/core/surface/init.h',
-                      'src/core/surface/lame_client.h',
-                      'src/core/surface/server.h',
-                      'src/core/surface/surface_trace.h',
-                      'src/core/transport/byte_stream.h',
-                      'src/core/transport/chttp2/alpn.h',
-                      'src/core/transport/chttp2/bin_encoder.h',
-                      'src/core/transport/chttp2/frame.h',
-                      'src/core/transport/chttp2/frame_data.h',
-                      'src/core/transport/chttp2/frame_goaway.h',
-                      'src/core/transport/chttp2/frame_ping.h',
-                      'src/core/transport/chttp2/frame_rst_stream.h',
-                      'src/core/transport/chttp2/frame_settings.h',
-                      'src/core/transport/chttp2/frame_window_update.h',
-                      'src/core/transport/chttp2/hpack_encoder.h',
-                      'src/core/transport/chttp2/hpack_parser.h',
-                      'src/core/transport/chttp2/hpack_table.h',
-                      'src/core/transport/chttp2/http2_errors.h',
-                      'src/core/transport/chttp2/huffsyms.h',
-                      'src/core/transport/chttp2/incoming_metadata.h',
-                      'src/core/transport/chttp2/internal.h',
-                      'src/core/transport/chttp2/status_conversion.h',
-                      'src/core/transport/chttp2/stream_map.h',
-                      'src/core/transport/chttp2/timeout_encoding.h',
-                      'src/core/transport/chttp2/varint.h',
-                      'src/core/transport/chttp2_transport.h',
-                      'src/core/transport/connectivity_state.h',
-                      'src/core/transport/metadata.h',
-                      'src/core/transport/metadata_batch.h',
-                      'src/core/transport/static_metadata.h',
-                      'src/core/transport/transport.h',
-                      'src/core/transport/transport_impl.h',
-                      'src/core/security/auth_filters.h',
-                      'src/core/security/b64.h',
-                      'src/core/security/credentials.h',
-                      'src/core/security/handshake.h',
-                      'src/core/security/json_token.h',
-                      'src/core/security/jwt_verifier.h',
-                      'src/core/security/secure_endpoint.h',
-                      'src/core/security/security_connector.h',
-                      'src/core/security/security_context.h',
-                      'src/core/tsi/fake_transport_security.h',
-                      'src/core/tsi/ssl_transport_security.h',
-                      'src/core/tsi/ssl_types.h',
-                      'src/core/tsi/transport_security.h',
-                      'src/core/tsi/transport_security_interface.h',
-                      'src/core/census/aggregation.h',
-                      'src/core/census/mlog.h',
-                      'src/core/census/rpc_metric_id.h',
+                      'src/core/lib/profiling/basic_timers.c',
+                      'src/core/lib/profiling/stap_timers.c',
+                      'src/core/lib/support/alloc.c',
+                      'src/core/lib/support/avl.c',
+                      'src/core/lib/support/backoff.c',
+                      'src/core/lib/support/cmdline.c',
+                      'src/core/lib/support/cpu_iphone.c',
+                      'src/core/lib/support/cpu_linux.c',
+                      'src/core/lib/support/cpu_posix.c',
+                      'src/core/lib/support/cpu_windows.c',
+                      'src/core/lib/support/env_linux.c',
+                      'src/core/lib/support/env_posix.c',
+                      'src/core/lib/support/env_win32.c',
+                      'src/core/lib/support/histogram.c',
+                      'src/core/lib/support/host_port.c',
+                      'src/core/lib/support/load_file.c',
+                      'src/core/lib/support/log.c',
+                      'src/core/lib/support/log_android.c',
+                      'src/core/lib/support/log_linux.c',
+                      'src/core/lib/support/log_posix.c',
+                      'src/core/lib/support/log_win32.c',
+                      'src/core/lib/support/murmur_hash.c',
+                      'src/core/lib/support/slice.c',
+                      'src/core/lib/support/slice_buffer.c',
+                      'src/core/lib/support/stack_lockfree.c',
+                      'src/core/lib/support/string.c',
+                      'src/core/lib/support/string_posix.c',
+                      'src/core/lib/support/string_win32.c',
+                      'src/core/lib/support/subprocess_posix.c',
+                      'src/core/lib/support/subprocess_windows.c',
+                      'src/core/lib/support/sync.c',
+                      'src/core/lib/support/sync_posix.c',
+                      'src/core/lib/support/sync_win32.c',
+                      'src/core/lib/support/thd.c',
+                      'src/core/lib/support/thd_posix.c',
+                      'src/core/lib/support/thd_win32.c',
+                      'src/core/lib/support/time.c',
+                      'src/core/lib/support/time_posix.c',
+                      'src/core/lib/support/time_precise.c',
+                      'src/core/lib/support/time_win32.c',
+                      'src/core/lib/support/tls_pthread.c',
+                      'src/core/lib/support/tmpfile_posix.c',
+                      'src/core/lib/support/tmpfile_win32.c',
+                      'src/core/lib/support/wrap_memcpy.c',
+                      'src/core/lib/channel/channel_args.h',
+                      'src/core/lib/channel/channel_stack.h',
+                      'src/core/lib/channel/channel_stack_builder.h',
+                      'src/core/lib/channel/compress_filter.h',
+                      'src/core/lib/channel/connected_channel.h',
+                      'src/core/lib/channel/context.h',
+                      'src/core/lib/channel/http_client_filter.h',
+                      'src/core/lib/channel/http_server_filter.h',
+                      'src/core/lib/compression/algorithm_metadata.h',
+                      'src/core/lib/compression/message_compress.h',
+                      'src/core/lib/debug/trace.h',
+                      'src/core/lib/http/format_request.h',
+                      'src/core/lib/http/httpcli.h',
+                      'src/core/lib/http/parser.h',
+                      'src/core/lib/iomgr/closure.h',
+                      'src/core/lib/iomgr/endpoint.h',
+                      'src/core/lib/iomgr/endpoint_pair.h',
+                      'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
+                      'src/core/lib/iomgr/ev_posix.h',
+                      'src/core/lib/iomgr/exec_ctx.h',
+                      'src/core/lib/iomgr/executor.h',
+                      'src/core/lib/iomgr/iocp_windows.h',
+                      'src/core/lib/iomgr/iomgr.h',
+                      'src/core/lib/iomgr/iomgr_internal.h',
+                      'src/core/lib/iomgr/iomgr_posix.h',
+                      'src/core/lib/iomgr/pollset.h',
+                      'src/core/lib/iomgr/pollset_set.h',
+                      'src/core/lib/iomgr/pollset_set_windows.h',
+                      'src/core/lib/iomgr/pollset_windows.h',
+                      'src/core/lib/iomgr/resolve_address.h',
+                      'src/core/lib/iomgr/sockaddr.h',
+                      'src/core/lib/iomgr/sockaddr_posix.h',
+                      'src/core/lib/iomgr/sockaddr_utils.h',
+                      'src/core/lib/iomgr/sockaddr_win32.h',
+                      'src/core/lib/iomgr/socket_utils_posix.h',
+                      'src/core/lib/iomgr/socket_windows.h',
+                      'src/core/lib/iomgr/tcp_client.h',
+                      'src/core/lib/iomgr/tcp_posix.h',
+                      'src/core/lib/iomgr/tcp_server.h',
+                      'src/core/lib/iomgr/tcp_windows.h',
+                      'src/core/lib/iomgr/time_averaged_stats.h',
+                      'src/core/lib/iomgr/timer.h',
+                      'src/core/lib/iomgr/timer_heap.h',
+                      'src/core/lib/iomgr/udp_server.h',
+                      'src/core/lib/iomgr/unix_sockets_posix.h',
+                      'src/core/lib/iomgr/wakeup_fd_pipe.h',
+                      'src/core/lib/iomgr/wakeup_fd_posix.h',
+                      'src/core/lib/iomgr/workqueue.h',
+                      'src/core/lib/iomgr/workqueue_posix.h',
+                      'src/core/lib/iomgr/workqueue_windows.h',
+                      'src/core/lib/json/json.h',
+                      'src/core/lib/json/json_common.h',
+                      'src/core/lib/json/json_reader.h',
+                      'src/core/lib/json/json_writer.h',
+                      'src/core/lib/surface/api_trace.h',
+                      'src/core/lib/surface/call.h',
+                      'src/core/lib/surface/call_test_only.h',
+                      'src/core/lib/surface/channel.h',
+                      'src/core/lib/surface/channel_init.h',
+                      'src/core/lib/surface/channel_stack_type.h',
+                      'src/core/lib/surface/completion_queue.h',
+                      'src/core/lib/surface/event_string.h',
+                      'src/core/lib/surface/init.h',
+                      'src/core/lib/surface/lame_client.h',
+                      'src/core/lib/surface/server.h',
+                      'src/core/lib/surface/surface_trace.h',
+                      'src/core/lib/transport/byte_stream.h',
+                      'src/core/lib/transport/connectivity_state.h',
+                      'src/core/lib/transport/metadata.h',
+                      'src/core/lib/transport/metadata_batch.h',
+                      'src/core/lib/transport/static_metadata.h',
+                      'src/core/lib/transport/transport.h',
+                      'src/core/lib/transport/transport_impl.h',
+                      'src/core/ext/transport/chttp2/transport/bin_encoder.h',
+                      'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
+                      'src/core/ext/transport/chttp2/transport/frame.h',
+                      'src/core/ext/transport/chttp2/transport/frame_data.h',
+                      'src/core/ext/transport/chttp2/transport/frame_goaway.h',
+                      'src/core/ext/transport/chttp2/transport/frame_ping.h',
+                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
+                      'src/core/ext/transport/chttp2/transport/frame_settings.h',
+                      'src/core/ext/transport/chttp2/transport/frame_window_update.h',
+                      'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
+                      'src/core/ext/transport/chttp2/transport/hpack_parser.h',
+                      'src/core/ext/transport/chttp2/transport/hpack_table.h',
+                      'src/core/ext/transport/chttp2/transport/http2_errors.h',
+                      'src/core/ext/transport/chttp2/transport/huffsyms.h',
+                      'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
+                      'src/core/ext/transport/chttp2/transport/internal.h',
+                      'src/core/ext/transport/chttp2/transport/status_conversion.h',
+                      'src/core/ext/transport/chttp2/transport/stream_map.h',
+                      'src/core/ext/transport/chttp2/transport/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/tsi/fake_transport_security.h',
+                      'src/core/lib/tsi/ssl_transport_security.h',
+                      'src/core/lib/tsi/ssl_types.h',
+                      'src/core/lib/tsi/transport_security.h',
+                      'src/core/lib/tsi/transport_security_interface.h',
+                      'src/core/ext/client_config/client_channel.h',
+                      'src/core/ext/client_config/client_channel_factory.h',
+                      'src/core/ext/client_config/client_config.h',
+                      'src/core/ext/client_config/connector.h',
+                      'src/core/ext/client_config/initial_connect_string.h',
+                      'src/core/ext/client_config/lb_policy.h',
+                      'src/core/ext/client_config/lb_policy_factory.h',
+                      'src/core/ext/client_config/lb_policy_registry.h',
+                      'src/core/ext/client_config/parse_address.h',
+                      'src/core/ext/client_config/resolver.h',
+                      'src/core/ext/client_config/resolver_factory.h',
+                      'src/core/ext/client_config/resolver_registry.h',
+                      'src/core/ext/client_config/subchannel.h',
+                      'src/core/ext/client_config/subchannel_call_holder.h',
+                      'src/core/ext/client_config/subchannel_index.h',
+                      'src/core/ext/client_config/uri_parser.h',
+                      'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
+                      'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h',
                       'third_party/nanopb/pb.h',
                       'third_party/nanopb/pb_common.h',
                       'third_party/nanopb/pb_decode.h',
                       'third_party/nanopb/pb_encode.h',
-                      'include/grpc/grpc_security.h',
+                      'src/core/ext/census/aggregation.h',
+                      'src/core/ext/census/census_interface.h',
+                      'src/core/ext/census/census_rpc_stats.h',
+                      'src/core/ext/census/grpc_filter.h',
+                      'src/core/ext/census/mlog.h',
+                      'src/core/ext/census/rpc_metric_id.h',
                       'include/grpc/byte_buffer.h',
                       'include/grpc/byte_buffer_reader.h',
                       'include/grpc/compression.h',
@@ -314,324 +308,337 @@
                       'include/grpc/impl/codegen/grpc_types.h',
                       'include/grpc/impl/codegen/propagation_bits.h',
                       'include/grpc/impl/codegen/status.h',
+                      'include/grpc/impl/codegen/alloc.h',
+                      'include/grpc/impl/codegen/atm.h',
+                      'include/grpc/impl/codegen/atm_gcc_atomic.h',
+                      'include/grpc/impl/codegen/atm_gcc_sync.h',
+                      'include/grpc/impl/codegen/atm_win32.h',
+                      'include/grpc/impl/codegen/log.h',
+                      'include/grpc/impl/codegen/port_platform.h',
+                      'include/grpc/impl/codegen/slice.h',
+                      'include/grpc/impl/codegen/slice_buffer.h',
+                      'include/grpc/impl/codegen/sync.h',
+                      'include/grpc/impl/codegen/sync_generic.h',
+                      'include/grpc/impl/codegen/sync_posix.h',
+                      'include/grpc/impl/codegen/sync_win32.h',
+                      'include/grpc/impl/codegen/time.h',
+                      'include/grpc/grpc_security.h',
+                      'include/grpc/grpc_security_constants.h',
                       'include/grpc/census.h',
-                      'src/core/census/grpc_context.c',
-                      'src/core/census/grpc_filter.c',
-                      'src/core/census/grpc_plugin.c',
-                      'src/core/channel/channel_args.c',
-                      'src/core/channel/channel_stack.c',
-                      'src/core/channel/channel_stack_builder.c',
-                      'src/core/channel/client_channel.c',
-                      'src/core/channel/client_uchannel.c',
-                      'src/core/channel/compress_filter.c',
-                      'src/core/channel/connected_channel.c',
-                      'src/core/channel/http_client_filter.c',
-                      'src/core/channel/http_server_filter.c',
-                      'src/core/channel/subchannel_call_holder.c',
-                      'src/core/client_config/client_config.c',
-                      'src/core/client_config/connector.c',
-                      'src/core/client_config/default_initial_connect_string.c',
-                      'src/core/client_config/initial_connect_string.c',
-                      'src/core/client_config/lb_policies/load_balancer_api.c',
-                      'src/core/client_config/lb_policies/pick_first.c',
-                      'src/core/client_config/lb_policies/round_robin.c',
-                      'src/core/client_config/lb_policy.c',
-                      'src/core/client_config/lb_policy_factory.c',
-                      'src/core/client_config/lb_policy_registry.c',
-                      'src/core/client_config/resolver.c',
-                      'src/core/client_config/resolver_factory.c',
-                      'src/core/client_config/resolver_registry.c',
-                      'src/core/client_config/resolvers/dns_resolver.c',
-                      'src/core/client_config/resolvers/sockaddr_resolver.c',
-                      'src/core/client_config/subchannel.c',
-                      'src/core/client_config/subchannel_factory.c',
-                      'src/core/client_config/subchannel_index.c',
-                      'src/core/client_config/uri_parser.c',
-                      'src/core/compression/compression_algorithm.c',
-                      'src/core/compression/message_compress.c',
-                      'src/core/debug/trace.c',
-                      'src/core/httpcli/format_request.c',
-                      'src/core/httpcli/httpcli.c',
-                      'src/core/httpcli/parser.c',
-                      'src/core/iomgr/closure.c',
-                      'src/core/iomgr/endpoint.c',
-                      'src/core/iomgr/endpoint_pair_posix.c',
-                      'src/core/iomgr/endpoint_pair_windows.c',
-                      'src/core/iomgr/exec_ctx.c',
-                      'src/core/iomgr/executor.c',
-                      'src/core/iomgr/fd_posix.c',
-                      'src/core/iomgr/iocp_windows.c',
-                      'src/core/iomgr/iomgr.c',
-                      'src/core/iomgr/iomgr_posix.c',
-                      'src/core/iomgr/iomgr_windows.c',
-                      'src/core/iomgr/pollset_multipoller_with_epoll.c',
-                      'src/core/iomgr/pollset_multipoller_with_poll_posix.c',
-                      'src/core/iomgr/pollset_posix.c',
-                      'src/core/iomgr/pollset_set_posix.c',
-                      'src/core/iomgr/pollset_set_windows.c',
-                      'src/core/iomgr/pollset_windows.c',
-                      'src/core/iomgr/resolve_address_posix.c',
-                      'src/core/iomgr/resolve_address_windows.c',
-                      'src/core/iomgr/sockaddr_utils.c',
-                      'src/core/iomgr/socket_utils_common_posix.c',
-                      'src/core/iomgr/socket_utils_linux.c',
-                      'src/core/iomgr/socket_utils_posix.c',
-                      'src/core/iomgr/socket_windows.c',
-                      'src/core/iomgr/tcp_client_posix.c',
-                      'src/core/iomgr/tcp_client_windows.c',
-                      'src/core/iomgr/tcp_posix.c',
-                      'src/core/iomgr/tcp_server_posix.c',
-                      'src/core/iomgr/tcp_server_windows.c',
-                      'src/core/iomgr/tcp_windows.c',
-                      'src/core/iomgr/time_averaged_stats.c',
-                      'src/core/iomgr/timer.c',
-                      'src/core/iomgr/timer_heap.c',
-                      'src/core/iomgr/udp_server.c',
-                      'src/core/iomgr/wakeup_fd_eventfd.c',
-                      'src/core/iomgr/wakeup_fd_nospecial.c',
-                      'src/core/iomgr/wakeup_fd_pipe.c',
-                      'src/core/iomgr/wakeup_fd_posix.c',
-                      'src/core/iomgr/workqueue_posix.c',
-                      'src/core/iomgr/workqueue_windows.c',
-                      'src/core/json/json.c',
-                      'src/core/json/json_reader.c',
-                      'src/core/json/json_string.c',
-                      'src/core/json/json_writer.c',
-                      'src/core/proto/grpc/lb/v0/load_balancer.pb.c',
-                      'src/core/surface/alarm.c',
-                      'src/core/surface/api_trace.c',
-                      'src/core/surface/byte_buffer.c',
-                      'src/core/surface/byte_buffer_reader.c',
-                      'src/core/surface/call.c',
-                      'src/core/surface/call_details.c',
-                      'src/core/surface/call_log_batch.c',
-                      'src/core/surface/channel.c',
-                      'src/core/surface/channel_connectivity.c',
-                      'src/core/surface/channel_create.c',
-                      'src/core/surface/channel_init.c',
-                      'src/core/surface/channel_ping.c',
-                      'src/core/surface/channel_stack_type.c',
-                      'src/core/surface/completion_queue.c',
-                      'src/core/surface/event_string.c',
-                      'src/core/surface/init.c',
-                      'src/core/surface/lame_client.c',
-                      'src/core/surface/metadata_array.c',
-                      'src/core/surface/server.c',
-                      'src/core/surface/server_chttp2.c',
-                      'src/core/surface/validate_metadata.c',
-                      'src/core/surface/version.c',
-                      'src/core/transport/byte_stream.c',
-                      'src/core/transport/chttp2/alpn.c',
-                      'src/core/transport/chttp2/bin_encoder.c',
-                      'src/core/transport/chttp2/frame_data.c',
-                      'src/core/transport/chttp2/frame_goaway.c',
-                      'src/core/transport/chttp2/frame_ping.c',
-                      'src/core/transport/chttp2/frame_rst_stream.c',
-                      'src/core/transport/chttp2/frame_settings.c',
-                      'src/core/transport/chttp2/frame_window_update.c',
-                      'src/core/transport/chttp2/hpack_encoder.c',
-                      'src/core/transport/chttp2/hpack_parser.c',
-                      'src/core/transport/chttp2/hpack_table.c',
-                      'src/core/transport/chttp2/huffsyms.c',
-                      'src/core/transport/chttp2/incoming_metadata.c',
-                      'src/core/transport/chttp2/parsing.c',
-                      'src/core/transport/chttp2/status_conversion.c',
-                      'src/core/transport/chttp2/stream_lists.c',
-                      'src/core/transport/chttp2/stream_map.c',
-                      'src/core/transport/chttp2/timeout_encoding.c',
-                      'src/core/transport/chttp2/varint.c',
-                      'src/core/transport/chttp2/writing.c',
-                      'src/core/transport/chttp2_transport.c',
-                      'src/core/transport/connectivity_state.c',
-                      'src/core/transport/metadata.c',
-                      'src/core/transport/metadata_batch.c',
-                      'src/core/transport/static_metadata.c',
-                      'src/core/transport/transport.c',
-                      'src/core/transport/transport_op_string.c',
-                      'src/core/httpcli/httpcli_security_connector.c',
-                      'src/core/security/b64.c',
-                      'src/core/security/client_auth_filter.c',
-                      'src/core/security/credentials.c',
-                      'src/core/security/credentials_metadata.c',
-                      'src/core/security/credentials_posix.c',
-                      'src/core/security/credentials_win32.c',
-                      'src/core/security/google_default_credentials.c',
-                      'src/core/security/handshake.c',
-                      'src/core/security/json_token.c',
-                      'src/core/security/jwt_verifier.c',
-                      'src/core/security/secure_endpoint.c',
-                      'src/core/security/security_connector.c',
-                      'src/core/security/security_context.c',
-                      'src/core/security/server_auth_filter.c',
-                      'src/core/security/server_secure_chttp2.c',
-                      'src/core/surface/init_secure.c',
-                      'src/core/surface/secure_channel_create.c',
-                      'src/core/tsi/fake_transport_security.c',
-                      'src/core/tsi/ssl_transport_security.c',
-                      'src/core/tsi/transport_security.c',
-                      'src/core/census/context.c',
-                      'src/core/census/initialize.c',
-                      'src/core/census/mlog.c',
-                      'src/core/census/operation.c',
-                      'src/core/census/placeholders.c',
-                      'src/core/census/tracing.c',
+                      'src/core/lib/surface/init.c',
+                      'src/core/lib/channel/channel_args.c',
+                      'src/core/lib/channel/channel_stack.c',
+                      'src/core/lib/channel/channel_stack_builder.c',
+                      'src/core/lib/channel/compress_filter.c',
+                      'src/core/lib/channel/connected_channel.c',
+                      'src/core/lib/channel/http_client_filter.c',
+                      'src/core/lib/channel/http_server_filter.c',
+                      'src/core/lib/compression/compression_algorithm.c',
+                      'src/core/lib/compression/message_compress.c',
+                      'src/core/lib/debug/trace.c',
+                      'src/core/lib/http/format_request.c',
+                      'src/core/lib/http/httpcli.c',
+                      'src/core/lib/http/parser.c',
+                      'src/core/lib/iomgr/closure.c',
+                      'src/core/lib/iomgr/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_posix.c',
+                      'src/core/lib/iomgr/exec_ctx.c',
+                      'src/core/lib/iomgr/executor.c',
+                      'src/core/lib/iomgr/iocp_windows.c',
+                      'src/core/lib/iomgr/iomgr.c',
+                      'src/core/lib/iomgr/iomgr_posix.c',
+                      'src/core/lib/iomgr/iomgr_windows.c',
+                      'src/core/lib/iomgr/pollset_set_windows.c',
+                      'src/core/lib/iomgr/pollset_windows.c',
+                      'src/core/lib/iomgr/resolve_address_posix.c',
+                      'src/core/lib/iomgr/resolve_address_windows.c',
+                      'src/core/lib/iomgr/sockaddr_utils.c',
+                      'src/core/lib/iomgr/socket_utils_common_posix.c',
+                      'src/core/lib/iomgr/socket_utils_linux.c',
+                      'src/core/lib/iomgr/socket_utils_posix.c',
+                      'src/core/lib/iomgr/socket_windows.c',
+                      'src/core/lib/iomgr/tcp_client_posix.c',
+                      'src/core/lib/iomgr/tcp_client_windows.c',
+                      'src/core/lib/iomgr/tcp_posix.c',
+                      'src/core/lib/iomgr/tcp_server_posix.c',
+                      'src/core/lib/iomgr/tcp_server_windows.c',
+                      'src/core/lib/iomgr/tcp_windows.c',
+                      'src/core/lib/iomgr/time_averaged_stats.c',
+                      'src/core/lib/iomgr/timer.c',
+                      'src/core/lib/iomgr/timer_heap.c',
+                      'src/core/lib/iomgr/udp_server.c',
+                      'src/core/lib/iomgr/unix_sockets_posix.c',
+                      'src/core/lib/iomgr/unix_sockets_posix_noop.c',
+                      'src/core/lib/iomgr/wakeup_fd_eventfd.c',
+                      'src/core/lib/iomgr/wakeup_fd_nospecial.c',
+                      'src/core/lib/iomgr/wakeup_fd_pipe.c',
+                      'src/core/lib/iomgr/wakeup_fd_posix.c',
+                      'src/core/lib/iomgr/workqueue_posix.c',
+                      'src/core/lib/iomgr/workqueue_windows.c',
+                      'src/core/lib/json/json.c',
+                      'src/core/lib/json/json_reader.c',
+                      'src/core/lib/json/json_string.c',
+                      'src/core/lib/json/json_writer.c',
+                      'src/core/lib/surface/alarm.c',
+                      'src/core/lib/surface/api_trace.c',
+                      'src/core/lib/surface/byte_buffer.c',
+                      'src/core/lib/surface/byte_buffer_reader.c',
+                      'src/core/lib/surface/call.c',
+                      'src/core/lib/surface/call_details.c',
+                      'src/core/lib/surface/call_log_batch.c',
+                      'src/core/lib/surface/channel.c',
+                      'src/core/lib/surface/channel_init.c',
+                      'src/core/lib/surface/channel_ping.c',
+                      'src/core/lib/surface/channel_stack_type.c',
+                      'src/core/lib/surface/completion_queue.c',
+                      'src/core/lib/surface/event_string.c',
+                      'src/core/lib/surface/lame_client.c',
+                      'src/core/lib/surface/metadata_array.c',
+                      'src/core/lib/surface/server.c',
+                      'src/core/lib/surface/validate_metadata.c',
+                      'src/core/lib/surface/version.c',
+                      'src/core/lib/transport/byte_stream.c',
+                      'src/core/lib/transport/connectivity_state.c',
+                      'src/core/lib/transport/metadata.c',
+                      'src/core/lib/transport/metadata_batch.c',
+                      'src/core/lib/transport/static_metadata.c',
+                      'src/core/lib/transport/transport.c',
+                      'src/core/lib/transport/transport_op_string.c',
+                      'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c',
+                      'src/core/ext/transport/chttp2/transport/bin_encoder.c',
+                      'src/core/ext/transport/chttp2/transport/chttp2_plugin.c',
+                      'src/core/ext/transport/chttp2/transport/chttp2_transport.c',
+                      'src/core/ext/transport/chttp2/transport/frame_data.c',
+                      'src/core/ext/transport/chttp2/transport/frame_goaway.c',
+                      'src/core/ext/transport/chttp2/transport/frame_ping.c',
+                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.c',
+                      'src/core/ext/transport/chttp2/transport/frame_settings.c',
+                      'src/core/ext/transport/chttp2/transport/frame_window_update.c',
+                      'src/core/ext/transport/chttp2/transport/hpack_encoder.c',
+                      'src/core/ext/transport/chttp2/transport/hpack_parser.c',
+                      'src/core/ext/transport/chttp2/transport/hpack_table.c',
+                      'src/core/ext/transport/chttp2/transport/huffsyms.c',
+                      'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
+                      'src/core/ext/transport/chttp2/transport/parsing.c',
+                      'src/core/ext/transport/chttp2/transport/status_conversion.c',
+                      'src/core/ext/transport/chttp2/transport/stream_lists.c',
+                      'src/core/ext/transport/chttp2/transport/stream_map.c',
+                      'src/core/ext/transport/chttp2/transport/timeout_encoding.c',
+                      'src/core/ext/transport/chttp2/transport/varint.c',
+                      'src/core/ext/transport/chttp2/transport/writing.c',
+                      'src/core/ext/transport/chttp2/alpn/alpn.c',
+                      'src/core/lib/http/httpcli_security_connector.c',
+                      'src/core/lib/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/surface/init_secure.c',
+                      'src/core/lib/tsi/fake_transport_security.c',
+                      'src/core/lib/tsi/ssl_transport_security.c',
+                      'src/core/lib/tsi/transport_security.c',
+                      'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c',
+                      'src/core/ext/client_config/channel_connectivity.c',
+                      'src/core/ext/client_config/client_channel.c',
+                      'src/core/ext/client_config/client_channel_factory.c',
+                      'src/core/ext/client_config/client_config.c',
+                      'src/core/ext/client_config/client_config_plugin.c',
+                      'src/core/ext/client_config/connector.c',
+                      'src/core/ext/client_config/default_initial_connect_string.c',
+                      'src/core/ext/client_config/initial_connect_string.c',
+                      'src/core/ext/client_config/lb_policy.c',
+                      'src/core/ext/client_config/lb_policy_factory.c',
+                      'src/core/ext/client_config/lb_policy_registry.c',
+                      'src/core/ext/client_config/parse_address.c',
+                      'src/core/ext/client_config/resolver.c',
+                      'src/core/ext/client_config/resolver_factory.c',
+                      'src/core/ext/client_config/resolver_registry.c',
+                      'src/core/ext/client_config/subchannel.c',
+                      'src/core/ext/client_config/subchannel_call_holder.c',
+                      'src/core/ext/client_config/subchannel_index.c',
+                      'src/core/ext/client_config/uri_parser.c',
+                      'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c',
+                      'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
+                      'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
+                      'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c',
                       'third_party/nanopb/pb_common.c',
                       'third_party/nanopb/pb_decode.c',
-                      'third_party/nanopb/pb_encode.c'
+                      'third_party/nanopb/pb_encode.c',
+                      'src/core/ext/lb_policy/pick_first/pick_first.c',
+                      'src/core/ext/lb_policy/round_robin/round_robin.c',
+                      'src/core/ext/resolver/dns/native/dns_resolver.c',
+                      'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
+                      'src/core/ext/census/context.c',
+                      'src/core/ext/census/grpc_context.c',
+                      'src/core/ext/census/grpc_filter.c',
+                      'src/core/ext/census/grpc_plugin.c',
+                      'src/core/ext/census/initialize.c',
+                      'src/core/ext/census/mlog.c',
+                      'src/core/ext/census/operation.c',
+                      'src/core/ext/census/placeholders.c',
+                      'src/core/ext/census/tracing.c',
+                      'src/core/plugin_registry/grpc_plugin_registry.c'
 
-    ss.private_header_files = 'src/core/profiling/timers.h',
-                              'src/core/support/backoff.h',
-                              'src/core/support/block_annotate.h',
-                              'src/core/support/env.h',
-                              'src/core/support/load_file.h',
-                              'src/core/support/murmur_hash.h',
-                              'src/core/support/stack_lockfree.h',
-                              'src/core/support/string.h',
-                              'src/core/support/string_win32.h',
-                              'src/core/support/thd_internal.h',
-                              'src/core/support/time_precise.h',
-                              'src/core/support/tmpfile.h',
-                              'src/core/census/grpc_filter.h',
-                              'src/core/census/grpc_plugin.h',
-                              'src/core/channel/channel_args.h',
-                              'src/core/channel/channel_stack.h',
-                              'src/core/channel/channel_stack_builder.h',
-                              'src/core/channel/client_channel.h',
-                              'src/core/channel/client_uchannel.h',
-                              'src/core/channel/compress_filter.h',
-                              'src/core/channel/connected_channel.h',
-                              'src/core/channel/context.h',
-                              'src/core/channel/http_client_filter.h',
-                              'src/core/channel/http_server_filter.h',
-                              'src/core/channel/subchannel_call_holder.h',
-                              'src/core/client_config/client_config.h',
-                              'src/core/client_config/connector.h',
-                              'src/core/client_config/initial_connect_string.h',
-                              'src/core/client_config/lb_policies/load_balancer_api.h',
-                              'src/core/client_config/lb_policies/pick_first.h',
-                              'src/core/client_config/lb_policies/round_robin.h',
-                              'src/core/client_config/lb_policy.h',
-                              'src/core/client_config/lb_policy_factory.h',
-                              'src/core/client_config/lb_policy_registry.h',
-                              'src/core/client_config/resolver.h',
-                              'src/core/client_config/resolver_factory.h',
-                              'src/core/client_config/resolver_registry.h',
-                              'src/core/client_config/resolvers/dns_resolver.h',
-                              'src/core/client_config/resolvers/sockaddr_resolver.h',
-                              'src/core/client_config/subchannel.h',
-                              'src/core/client_config/subchannel_factory.h',
-                              'src/core/client_config/subchannel_index.h',
-                              'src/core/client_config/uri_parser.h',
-                              'src/core/compression/algorithm_metadata.h',
-                              'src/core/compression/message_compress.h',
-                              'src/core/debug/trace.h',
-                              'src/core/httpcli/format_request.h',
-                              'src/core/httpcli/httpcli.h',
-                              'src/core/httpcli/parser.h',
-                              'src/core/iomgr/closure.h',
-                              'src/core/iomgr/endpoint.h',
-                              'src/core/iomgr/endpoint_pair.h',
-                              'src/core/iomgr/exec_ctx.h',
-                              'src/core/iomgr/executor.h',
-                              'src/core/iomgr/fd_posix.h',
-                              'src/core/iomgr/iocp_windows.h',
-                              'src/core/iomgr/iomgr.h',
-                              'src/core/iomgr/iomgr_internal.h',
-                              'src/core/iomgr/iomgr_posix.h',
-                              'src/core/iomgr/pollset.h',
-                              'src/core/iomgr/pollset_posix.h',
-                              'src/core/iomgr/pollset_set.h',
-                              'src/core/iomgr/pollset_set_posix.h',
-                              'src/core/iomgr/pollset_set_windows.h',
-                              'src/core/iomgr/pollset_windows.h',
-                              'src/core/iomgr/resolve_address.h',
-                              'src/core/iomgr/sockaddr.h',
-                              'src/core/iomgr/sockaddr_posix.h',
-                              'src/core/iomgr/sockaddr_utils.h',
-                              'src/core/iomgr/sockaddr_win32.h',
-                              'src/core/iomgr/socket_utils_posix.h',
-                              'src/core/iomgr/socket_windows.h',
-                              'src/core/iomgr/tcp_client.h',
-                              'src/core/iomgr/tcp_posix.h',
-                              'src/core/iomgr/tcp_server.h',
-                              'src/core/iomgr/tcp_windows.h',
-                              'src/core/iomgr/time_averaged_stats.h',
-                              'src/core/iomgr/timer.h',
-                              'src/core/iomgr/timer_heap.h',
-                              'src/core/iomgr/udp_server.h',
-                              'src/core/iomgr/wakeup_fd_pipe.h',
-                              'src/core/iomgr/wakeup_fd_posix.h',
-                              'src/core/iomgr/workqueue.h',
-                              'src/core/iomgr/workqueue_posix.h',
-                              'src/core/iomgr/workqueue_windows.h',
-                              'src/core/json/json.h',
-                              'src/core/json/json_common.h',
-                              'src/core/json/json_reader.h',
-                              'src/core/json/json_writer.h',
-                              'src/core/proto/grpc/lb/v0/load_balancer.pb.h',
-                              'src/core/statistics/census_interface.h',
-                              'src/core/statistics/census_rpc_stats.h',
-                              'src/core/surface/api_trace.h',
-                              'src/core/surface/call.h',
-                              'src/core/surface/call_test_only.h',
-                              'src/core/surface/channel.h',
-                              'src/core/surface/channel_init.h',
-                              'src/core/surface/channel_stack_type.h',
-                              'src/core/surface/completion_queue.h',
-                              'src/core/surface/event_string.h',
-                              'src/core/surface/init.h',
-                              'src/core/surface/lame_client.h',
-                              'src/core/surface/server.h',
-                              'src/core/surface/surface_trace.h',
-                              'src/core/transport/byte_stream.h',
-                              'src/core/transport/chttp2/alpn.h',
-                              'src/core/transport/chttp2/bin_encoder.h',
-                              'src/core/transport/chttp2/frame.h',
-                              'src/core/transport/chttp2/frame_data.h',
-                              'src/core/transport/chttp2/frame_goaway.h',
-                              'src/core/transport/chttp2/frame_ping.h',
-                              'src/core/transport/chttp2/frame_rst_stream.h',
-                              'src/core/transport/chttp2/frame_settings.h',
-                              'src/core/transport/chttp2/frame_window_update.h',
-                              'src/core/transport/chttp2/hpack_encoder.h',
-                              'src/core/transport/chttp2/hpack_parser.h',
-                              'src/core/transport/chttp2/hpack_table.h',
-                              'src/core/transport/chttp2/http2_errors.h',
-                              'src/core/transport/chttp2/huffsyms.h',
-                              'src/core/transport/chttp2/incoming_metadata.h',
-                              'src/core/transport/chttp2/internal.h',
-                              'src/core/transport/chttp2/status_conversion.h',
-                              'src/core/transport/chttp2/stream_map.h',
-                              'src/core/transport/chttp2/timeout_encoding.h',
-                              'src/core/transport/chttp2/varint.h',
-                              'src/core/transport/chttp2_transport.h',
-                              'src/core/transport/connectivity_state.h',
-                              'src/core/transport/metadata.h',
-                              'src/core/transport/metadata_batch.h',
-                              'src/core/transport/static_metadata.h',
-                              'src/core/transport/transport.h',
-                              'src/core/transport/transport_impl.h',
-                              'src/core/security/auth_filters.h',
-                              'src/core/security/b64.h',
-                              'src/core/security/credentials.h',
-                              'src/core/security/handshake.h',
-                              'src/core/security/json_token.h',
-                              'src/core/security/jwt_verifier.h',
-                              'src/core/security/secure_endpoint.h',
-                              'src/core/security/security_connector.h',
-                              'src/core/security/security_context.h',
-                              'src/core/tsi/fake_transport_security.h',
-                              'src/core/tsi/ssl_transport_security.h',
-                              'src/core/tsi/ssl_types.h',
-                              'src/core/tsi/transport_security.h',
-                              'src/core/tsi/transport_security_interface.h',
-                              'src/core/census/aggregation.h',
-                              'src/core/census/mlog.h',
-                              'src/core/census/rpc_metric_id.h',
+    ss.private_header_files = 'src/core/lib/profiling/timers.h',
+                              'src/core/lib/support/backoff.h',
+                              'src/core/lib/support/block_annotate.h',
+                              'src/core/lib/support/env.h',
+                              'src/core/lib/support/load_file.h',
+                              'src/core/lib/support/murmur_hash.h',
+                              'src/core/lib/support/stack_lockfree.h',
+                              'src/core/lib/support/string.h',
+                              'src/core/lib/support/string_win32.h',
+                              'src/core/lib/support/thd_internal.h',
+                              'src/core/lib/support/time_precise.h',
+                              'src/core/lib/support/tmpfile.h',
+                              'src/core/lib/channel/channel_args.h',
+                              'src/core/lib/channel/channel_stack.h',
+                              'src/core/lib/channel/channel_stack_builder.h',
+                              'src/core/lib/channel/compress_filter.h',
+                              'src/core/lib/channel/connected_channel.h',
+                              'src/core/lib/channel/context.h',
+                              'src/core/lib/channel/http_client_filter.h',
+                              'src/core/lib/channel/http_server_filter.h',
+                              'src/core/lib/compression/algorithm_metadata.h',
+                              'src/core/lib/compression/message_compress.h',
+                              'src/core/lib/debug/trace.h',
+                              'src/core/lib/http/format_request.h',
+                              'src/core/lib/http/httpcli.h',
+                              'src/core/lib/http/parser.h',
+                              'src/core/lib/iomgr/closure.h',
+                              'src/core/lib/iomgr/endpoint.h',
+                              'src/core/lib/iomgr/endpoint_pair.h',
+                              'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
+                              'src/core/lib/iomgr/ev_posix.h',
+                              'src/core/lib/iomgr/exec_ctx.h',
+                              'src/core/lib/iomgr/executor.h',
+                              'src/core/lib/iomgr/iocp_windows.h',
+                              'src/core/lib/iomgr/iomgr.h',
+                              'src/core/lib/iomgr/iomgr_internal.h',
+                              'src/core/lib/iomgr/iomgr_posix.h',
+                              'src/core/lib/iomgr/pollset.h',
+                              'src/core/lib/iomgr/pollset_set.h',
+                              'src/core/lib/iomgr/pollset_set_windows.h',
+                              'src/core/lib/iomgr/pollset_windows.h',
+                              'src/core/lib/iomgr/resolve_address.h',
+                              'src/core/lib/iomgr/sockaddr.h',
+                              'src/core/lib/iomgr/sockaddr_posix.h',
+                              'src/core/lib/iomgr/sockaddr_utils.h',
+                              'src/core/lib/iomgr/sockaddr_win32.h',
+                              'src/core/lib/iomgr/socket_utils_posix.h',
+                              'src/core/lib/iomgr/socket_windows.h',
+                              'src/core/lib/iomgr/tcp_client.h',
+                              'src/core/lib/iomgr/tcp_posix.h',
+                              'src/core/lib/iomgr/tcp_server.h',
+                              'src/core/lib/iomgr/tcp_windows.h',
+                              'src/core/lib/iomgr/time_averaged_stats.h',
+                              'src/core/lib/iomgr/timer.h',
+                              'src/core/lib/iomgr/timer_heap.h',
+                              'src/core/lib/iomgr/udp_server.h',
+                              'src/core/lib/iomgr/unix_sockets_posix.h',
+                              'src/core/lib/iomgr/wakeup_fd_pipe.h',
+                              'src/core/lib/iomgr/wakeup_fd_posix.h',
+                              'src/core/lib/iomgr/workqueue.h',
+                              'src/core/lib/iomgr/workqueue_posix.h',
+                              'src/core/lib/iomgr/workqueue_windows.h',
+                              'src/core/lib/json/json.h',
+                              'src/core/lib/json/json_common.h',
+                              'src/core/lib/json/json_reader.h',
+                              'src/core/lib/json/json_writer.h',
+                              'src/core/lib/surface/api_trace.h',
+                              'src/core/lib/surface/call.h',
+                              'src/core/lib/surface/call_test_only.h',
+                              'src/core/lib/surface/channel.h',
+                              'src/core/lib/surface/channel_init.h',
+                              'src/core/lib/surface/channel_stack_type.h',
+                              'src/core/lib/surface/completion_queue.h',
+                              'src/core/lib/surface/event_string.h',
+                              'src/core/lib/surface/init.h',
+                              'src/core/lib/surface/lame_client.h',
+                              'src/core/lib/surface/server.h',
+                              'src/core/lib/surface/surface_trace.h',
+                              'src/core/lib/transport/byte_stream.h',
+                              'src/core/lib/transport/connectivity_state.h',
+                              'src/core/lib/transport/metadata.h',
+                              'src/core/lib/transport/metadata_batch.h',
+                              'src/core/lib/transport/static_metadata.h',
+                              'src/core/lib/transport/transport.h',
+                              'src/core/lib/transport/transport_impl.h',
+                              'src/core/ext/transport/chttp2/transport/bin_encoder.h',
+                              'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
+                              'src/core/ext/transport/chttp2/transport/frame.h',
+                              'src/core/ext/transport/chttp2/transport/frame_data.h',
+                              'src/core/ext/transport/chttp2/transport/frame_goaway.h',
+                              'src/core/ext/transport/chttp2/transport/frame_ping.h',
+                              'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
+                              'src/core/ext/transport/chttp2/transport/frame_settings.h',
+                              'src/core/ext/transport/chttp2/transport/frame_window_update.h',
+                              'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
+                              'src/core/ext/transport/chttp2/transport/hpack_parser.h',
+                              'src/core/ext/transport/chttp2/transport/hpack_table.h',
+                              'src/core/ext/transport/chttp2/transport/http2_errors.h',
+                              'src/core/ext/transport/chttp2/transport/huffsyms.h',
+                              'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
+                              'src/core/ext/transport/chttp2/transport/internal.h',
+                              'src/core/ext/transport/chttp2/transport/status_conversion.h',
+                              'src/core/ext/transport/chttp2/transport/stream_map.h',
+                              'src/core/ext/transport/chttp2/transport/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/tsi/fake_transport_security.h',
+                              'src/core/lib/tsi/ssl_transport_security.h',
+                              'src/core/lib/tsi/ssl_types.h',
+                              'src/core/lib/tsi/transport_security.h',
+                              'src/core/lib/tsi/transport_security_interface.h',
+                              'src/core/ext/client_config/client_channel.h',
+                              'src/core/ext/client_config/client_channel_factory.h',
+                              'src/core/ext/client_config/client_config.h',
+                              'src/core/ext/client_config/connector.h',
+                              'src/core/ext/client_config/initial_connect_string.h',
+                              'src/core/ext/client_config/lb_policy.h',
+                              'src/core/ext/client_config/lb_policy_factory.h',
+                              'src/core/ext/client_config/lb_policy_registry.h',
+                              'src/core/ext/client_config/parse_address.h',
+                              'src/core/ext/client_config/resolver.h',
+                              'src/core/ext/client_config/resolver_factory.h',
+                              'src/core/ext/client_config/resolver_registry.h',
+                              'src/core/ext/client_config/subchannel.h',
+                              'src/core/ext/client_config/subchannel_call_holder.h',
+                              'src/core/ext/client_config/subchannel_index.h',
+                              'src/core/ext/client_config/uri_parser.h',
+                              'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
+                              'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h',
                               'third_party/nanopb/pb.h',
                               'third_party/nanopb/pb_common.h',
                               'third_party/nanopb/pb_decode.h',
-                              'third_party/nanopb/pb_encode.h'
+                              'third_party/nanopb/pb_encode.h',
+                              'src/core/ext/census/aggregation.h',
+                              'src/core/ext/census/census_interface.h',
+                              'src/core/ext/census/census_rpc_stats.h',
+                              'src/core/ext/census/grpc_filter.h',
+                              'src/core/ext/census/mlog.h',
+                              'src/core/ext/census/rpc_metric_id.h'
 
     ss.header_mappings_dir = '.'
     # This isn't officially supported in Cocoapods. We've asked for an alternative:
diff --git a/grpc.def b/grpc.def
index f81aa1b..6542c06 100644
--- a/grpc.def
+++ b/grpc.def
@@ -114,6 +114,7 @@
     grpc_secure_channel_create
     grpc_server_credentials_release
     grpc_ssl_server_credentials_create
+    grpc_ssl_server_credentials_create_ex
     grpc_server_add_secure_http2_port
     grpc_call_set_credentials
     grpc_server_credentials_set_auth_metadata_processor
@@ -136,6 +137,8 @@
     grpc_raw_byte_buffer_from_reader
     gpr_log
     gpr_log_message
+    gpr_set_log_verbosity
+    gpr_log_verbosity_init
     gpr_set_log_function
     gpr_slice_ref
     gpr_slice_unref
diff --git a/grpc.gemspec b/grpc.gemspec
index c062622..a9f0f68 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -24,10 +24,6 @@
   s.files += Dir.glob('include/grpc/**/*')
   s.test_files = Dir.glob('src/ruby/spec/**/*')
   s.bindir = 'src/ruby/bin'
-  %w(math noproto).each do |b|
-    s.executables += ["#{b}_client.rb", "#{b}_server.rb"]
-  end
-  s.executables += %w(grpc_ruby_interop_client grpc_ruby_interop_server)
   s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
   s.platform      = Gem::Platform::RUBY
 
@@ -35,6 +31,7 @@
   s.add_dependency 'googleauth',      '~> 0.5.1'
 
   s.add_development_dependency 'bundler',            '~> 1.9'
+  s.add_development_dependency 'facter',             '~> 2.4'
   s.add_development_dependency 'logging',            '~> 2.0'
   s.add_development_dependency 'simplecov',          '~> 0.9'
   s.add_development_dependency 'rake',               '~> 10.4'
@@ -88,63 +85,62 @@
   s.files += %w( include/grpc/impl/codegen/sync_posix.h )
   s.files += %w( include/grpc/impl/codegen/sync_win32.h )
   s.files += %w( include/grpc/impl/codegen/time.h )
-  s.files += %w( src/core/profiling/timers.h )
-  s.files += %w( src/core/support/backoff.h )
-  s.files += %w( src/core/support/block_annotate.h )
-  s.files += %w( src/core/support/env.h )
-  s.files += %w( src/core/support/load_file.h )
-  s.files += %w( src/core/support/murmur_hash.h )
-  s.files += %w( src/core/support/stack_lockfree.h )
-  s.files += %w( src/core/support/string.h )
-  s.files += %w( src/core/support/string_win32.h )
-  s.files += %w( src/core/support/thd_internal.h )
-  s.files += %w( src/core/support/time_precise.h )
-  s.files += %w( src/core/support/tmpfile.h )
-  s.files += %w( src/core/profiling/basic_timers.c )
-  s.files += %w( src/core/profiling/stap_timers.c )
-  s.files += %w( src/core/support/alloc.c )
-  s.files += %w( src/core/support/avl.c )
-  s.files += %w( src/core/support/backoff.c )
-  s.files += %w( src/core/support/cmdline.c )
-  s.files += %w( src/core/support/cpu_iphone.c )
-  s.files += %w( src/core/support/cpu_linux.c )
-  s.files += %w( src/core/support/cpu_posix.c )
-  s.files += %w( src/core/support/cpu_windows.c )
-  s.files += %w( src/core/support/env_linux.c )
-  s.files += %w( src/core/support/env_posix.c )
-  s.files += %w( src/core/support/env_win32.c )
-  s.files += %w( src/core/support/histogram.c )
-  s.files += %w( src/core/support/host_port.c )
-  s.files += %w( src/core/support/load_file.c )
-  s.files += %w( src/core/support/log.c )
-  s.files += %w( src/core/support/log_android.c )
-  s.files += %w( src/core/support/log_linux.c )
-  s.files += %w( src/core/support/log_posix.c )
-  s.files += %w( src/core/support/log_win32.c )
-  s.files += %w( src/core/support/murmur_hash.c )
-  s.files += %w( src/core/support/slice.c )
-  s.files += %w( src/core/support/slice_buffer.c )
-  s.files += %w( src/core/support/stack_lockfree.c )
-  s.files += %w( src/core/support/string.c )
-  s.files += %w( src/core/support/string_posix.c )
-  s.files += %w( src/core/support/string_win32.c )
-  s.files += %w( src/core/support/subprocess_posix.c )
-  s.files += %w( src/core/support/subprocess_windows.c )
-  s.files += %w( src/core/support/sync.c )
-  s.files += %w( src/core/support/sync_posix.c )
-  s.files += %w( src/core/support/sync_win32.c )
-  s.files += %w( src/core/support/thd.c )
-  s.files += %w( src/core/support/thd_posix.c )
-  s.files += %w( src/core/support/thd_win32.c )
-  s.files += %w( src/core/support/time.c )
-  s.files += %w( src/core/support/time_posix.c )
-  s.files += %w( src/core/support/time_precise.c )
-  s.files += %w( src/core/support/time_win32.c )
-  s.files += %w( src/core/support/tls_pthread.c )
-  s.files += %w( src/core/support/tmpfile_posix.c )
-  s.files += %w( src/core/support/tmpfile_win32.c )
-  s.files += %w( src/core/support/wrap_memcpy.c )
-  s.files += %w( include/grpc/grpc_security.h )
+  s.files += %w( src/core/lib/profiling/timers.h )
+  s.files += %w( src/core/lib/support/backoff.h )
+  s.files += %w( src/core/lib/support/block_annotate.h )
+  s.files += %w( src/core/lib/support/env.h )
+  s.files += %w( src/core/lib/support/load_file.h )
+  s.files += %w( src/core/lib/support/murmur_hash.h )
+  s.files += %w( src/core/lib/support/stack_lockfree.h )
+  s.files += %w( src/core/lib/support/string.h )
+  s.files += %w( src/core/lib/support/string_win32.h )
+  s.files += %w( src/core/lib/support/thd_internal.h )
+  s.files += %w( src/core/lib/support/time_precise.h )
+  s.files += %w( src/core/lib/support/tmpfile.h )
+  s.files += %w( src/core/lib/profiling/basic_timers.c )
+  s.files += %w( src/core/lib/profiling/stap_timers.c )
+  s.files += %w( src/core/lib/support/alloc.c )
+  s.files += %w( src/core/lib/support/avl.c )
+  s.files += %w( src/core/lib/support/backoff.c )
+  s.files += %w( src/core/lib/support/cmdline.c )
+  s.files += %w( src/core/lib/support/cpu_iphone.c )
+  s.files += %w( src/core/lib/support/cpu_linux.c )
+  s.files += %w( src/core/lib/support/cpu_posix.c )
+  s.files += %w( src/core/lib/support/cpu_windows.c )
+  s.files += %w( src/core/lib/support/env_linux.c )
+  s.files += %w( src/core/lib/support/env_posix.c )
+  s.files += %w( src/core/lib/support/env_win32.c )
+  s.files += %w( src/core/lib/support/histogram.c )
+  s.files += %w( src/core/lib/support/host_port.c )
+  s.files += %w( src/core/lib/support/load_file.c )
+  s.files += %w( src/core/lib/support/log.c )
+  s.files += %w( src/core/lib/support/log_android.c )
+  s.files += %w( src/core/lib/support/log_linux.c )
+  s.files += %w( src/core/lib/support/log_posix.c )
+  s.files += %w( src/core/lib/support/log_win32.c )
+  s.files += %w( src/core/lib/support/murmur_hash.c )
+  s.files += %w( src/core/lib/support/slice.c )
+  s.files += %w( src/core/lib/support/slice_buffer.c )
+  s.files += %w( src/core/lib/support/stack_lockfree.c )
+  s.files += %w( src/core/lib/support/string.c )
+  s.files += %w( src/core/lib/support/string_posix.c )
+  s.files += %w( src/core/lib/support/string_win32.c )
+  s.files += %w( src/core/lib/support/subprocess_posix.c )
+  s.files += %w( src/core/lib/support/subprocess_windows.c )
+  s.files += %w( src/core/lib/support/sync.c )
+  s.files += %w( src/core/lib/support/sync_posix.c )
+  s.files += %w( src/core/lib/support/sync_win32.c )
+  s.files += %w( src/core/lib/support/thd.c )
+  s.files += %w( src/core/lib/support/thd_posix.c )
+  s.files += %w( src/core/lib/support/thd_win32.c )
+  s.files += %w( src/core/lib/support/time.c )
+  s.files += %w( src/core/lib/support/time_posix.c )
+  s.files += %w( src/core/lib/support/time_precise.c )
+  s.files += %w( src/core/lib/support/time_win32.c )
+  s.files += %w( src/core/lib/support/tls_pthread.c )
+  s.files += %w( src/core/lib/support/tmpfile_posix.c )
+  s.files += %w( src/core/lib/support/tmpfile_win32.c )
+  s.files += %w( src/core/lib/support/wrap_memcpy.c )
   s.files += %w( include/grpc/byte_buffer.h )
   s.files += %w( include/grpc/byte_buffer_reader.h )
   s.files += %w( include/grpc/compression.h )
@@ -156,311 +152,324 @@
   s.files += %w( include/grpc/impl/codegen/grpc_types.h )
   s.files += %w( include/grpc/impl/codegen/propagation_bits.h )
   s.files += %w( include/grpc/impl/codegen/status.h )
+  s.files += %w( include/grpc/impl/codegen/alloc.h )
+  s.files += %w( include/grpc/impl/codegen/atm.h )
+  s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h )
+  s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h )
+  s.files += %w( include/grpc/impl/codegen/atm_win32.h )
+  s.files += %w( include/grpc/impl/codegen/log.h )
+  s.files += %w( include/grpc/impl/codegen/port_platform.h )
+  s.files += %w( include/grpc/impl/codegen/slice.h )
+  s.files += %w( include/grpc/impl/codegen/slice_buffer.h )
+  s.files += %w( include/grpc/impl/codegen/sync.h )
+  s.files += %w( include/grpc/impl/codegen/sync_generic.h )
+  s.files += %w( include/grpc/impl/codegen/sync_posix.h )
+  s.files += %w( include/grpc/impl/codegen/sync_win32.h )
+  s.files += %w( include/grpc/impl/codegen/time.h )
+  s.files += %w( include/grpc/grpc_security.h )
+  s.files += %w( include/grpc/grpc_security_constants.h )
   s.files += %w( include/grpc/census.h )
-  s.files += %w( src/core/census/grpc_filter.h )
-  s.files += %w( src/core/census/grpc_plugin.h )
-  s.files += %w( src/core/channel/channel_args.h )
-  s.files += %w( src/core/channel/channel_stack.h )
-  s.files += %w( src/core/channel/channel_stack_builder.h )
-  s.files += %w( src/core/channel/client_channel.h )
-  s.files += %w( src/core/channel/client_uchannel.h )
-  s.files += %w( src/core/channel/compress_filter.h )
-  s.files += %w( src/core/channel/connected_channel.h )
-  s.files += %w( src/core/channel/context.h )
-  s.files += %w( src/core/channel/http_client_filter.h )
-  s.files += %w( src/core/channel/http_server_filter.h )
-  s.files += %w( src/core/channel/subchannel_call_holder.h )
-  s.files += %w( src/core/client_config/client_config.h )
-  s.files += %w( src/core/client_config/connector.h )
-  s.files += %w( src/core/client_config/initial_connect_string.h )
-  s.files += %w( src/core/client_config/lb_policies/load_balancer_api.h )
-  s.files += %w( src/core/client_config/lb_policies/pick_first.h )
-  s.files += %w( src/core/client_config/lb_policies/round_robin.h )
-  s.files += %w( src/core/client_config/lb_policy.h )
-  s.files += %w( src/core/client_config/lb_policy_factory.h )
-  s.files += %w( src/core/client_config/lb_policy_registry.h )
-  s.files += %w( src/core/client_config/resolver.h )
-  s.files += %w( src/core/client_config/resolver_factory.h )
-  s.files += %w( src/core/client_config/resolver_registry.h )
-  s.files += %w( src/core/client_config/resolvers/dns_resolver.h )
-  s.files += %w( src/core/client_config/resolvers/sockaddr_resolver.h )
-  s.files += %w( src/core/client_config/subchannel.h )
-  s.files += %w( src/core/client_config/subchannel_factory.h )
-  s.files += %w( src/core/client_config/subchannel_index.h )
-  s.files += %w( src/core/client_config/uri_parser.h )
-  s.files += %w( src/core/compression/algorithm_metadata.h )
-  s.files += %w( src/core/compression/message_compress.h )
-  s.files += %w( src/core/debug/trace.h )
-  s.files += %w( src/core/httpcli/format_request.h )
-  s.files += %w( src/core/httpcli/httpcli.h )
-  s.files += %w( src/core/httpcli/parser.h )
-  s.files += %w( src/core/iomgr/closure.h )
-  s.files += %w( src/core/iomgr/endpoint.h )
-  s.files += %w( src/core/iomgr/endpoint_pair.h )
-  s.files += %w( src/core/iomgr/exec_ctx.h )
-  s.files += %w( src/core/iomgr/executor.h )
-  s.files += %w( src/core/iomgr/fd_posix.h )
-  s.files += %w( src/core/iomgr/iocp_windows.h )
-  s.files += %w( src/core/iomgr/iomgr.h )
-  s.files += %w( src/core/iomgr/iomgr_internal.h )
-  s.files += %w( src/core/iomgr/iomgr_posix.h )
-  s.files += %w( src/core/iomgr/pollset.h )
-  s.files += %w( src/core/iomgr/pollset_posix.h )
-  s.files += %w( src/core/iomgr/pollset_set.h )
-  s.files += %w( src/core/iomgr/pollset_set_posix.h )
-  s.files += %w( src/core/iomgr/pollset_set_windows.h )
-  s.files += %w( src/core/iomgr/pollset_windows.h )
-  s.files += %w( src/core/iomgr/resolve_address.h )
-  s.files += %w( src/core/iomgr/sockaddr.h )
-  s.files += %w( src/core/iomgr/sockaddr_posix.h )
-  s.files += %w( src/core/iomgr/sockaddr_utils.h )
-  s.files += %w( src/core/iomgr/sockaddr_win32.h )
-  s.files += %w( src/core/iomgr/socket_utils_posix.h )
-  s.files += %w( src/core/iomgr/socket_windows.h )
-  s.files += %w( src/core/iomgr/tcp_client.h )
-  s.files += %w( src/core/iomgr/tcp_posix.h )
-  s.files += %w( src/core/iomgr/tcp_server.h )
-  s.files += %w( src/core/iomgr/tcp_windows.h )
-  s.files += %w( src/core/iomgr/time_averaged_stats.h )
-  s.files += %w( src/core/iomgr/timer.h )
-  s.files += %w( src/core/iomgr/timer_heap.h )
-  s.files += %w( src/core/iomgr/udp_server.h )
-  s.files += %w( src/core/iomgr/wakeup_fd_pipe.h )
-  s.files += %w( src/core/iomgr/wakeup_fd_posix.h )
-  s.files += %w( src/core/iomgr/workqueue.h )
-  s.files += %w( src/core/iomgr/workqueue_posix.h )
-  s.files += %w( src/core/iomgr/workqueue_windows.h )
-  s.files += %w( src/core/json/json.h )
-  s.files += %w( src/core/json/json_common.h )
-  s.files += %w( src/core/json/json_reader.h )
-  s.files += %w( src/core/json/json_writer.h )
-  s.files += %w( src/core/proto/grpc/lb/v0/load_balancer.pb.h )
-  s.files += %w( src/core/statistics/census_interface.h )
-  s.files += %w( src/core/statistics/census_rpc_stats.h )
-  s.files += %w( src/core/surface/api_trace.h )
-  s.files += %w( src/core/surface/call.h )
-  s.files += %w( src/core/surface/call_test_only.h )
-  s.files += %w( src/core/surface/channel.h )
-  s.files += %w( src/core/surface/channel_init.h )
-  s.files += %w( src/core/surface/channel_stack_type.h )
-  s.files += %w( src/core/surface/completion_queue.h )
-  s.files += %w( src/core/surface/event_string.h )
-  s.files += %w( src/core/surface/init.h )
-  s.files += %w( src/core/surface/lame_client.h )
-  s.files += %w( src/core/surface/server.h )
-  s.files += %w( src/core/surface/surface_trace.h )
-  s.files += %w( src/core/transport/byte_stream.h )
-  s.files += %w( src/core/transport/chttp2/alpn.h )
-  s.files += %w( src/core/transport/chttp2/bin_encoder.h )
-  s.files += %w( src/core/transport/chttp2/frame.h )
-  s.files += %w( src/core/transport/chttp2/frame_data.h )
-  s.files += %w( src/core/transport/chttp2/frame_goaway.h )
-  s.files += %w( src/core/transport/chttp2/frame_ping.h )
-  s.files += %w( src/core/transport/chttp2/frame_rst_stream.h )
-  s.files += %w( src/core/transport/chttp2/frame_settings.h )
-  s.files += %w( src/core/transport/chttp2/frame_window_update.h )
-  s.files += %w( src/core/transport/chttp2/hpack_encoder.h )
-  s.files += %w( src/core/transport/chttp2/hpack_parser.h )
-  s.files += %w( src/core/transport/chttp2/hpack_table.h )
-  s.files += %w( src/core/transport/chttp2/http2_errors.h )
-  s.files += %w( src/core/transport/chttp2/huffsyms.h )
-  s.files += %w( src/core/transport/chttp2/incoming_metadata.h )
-  s.files += %w( src/core/transport/chttp2/internal.h )
-  s.files += %w( src/core/transport/chttp2/status_conversion.h )
-  s.files += %w( src/core/transport/chttp2/stream_map.h )
-  s.files += %w( src/core/transport/chttp2/timeout_encoding.h )
-  s.files += %w( src/core/transport/chttp2/varint.h )
-  s.files += %w( src/core/transport/chttp2_transport.h )
-  s.files += %w( src/core/transport/connectivity_state.h )
-  s.files += %w( src/core/transport/metadata.h )
-  s.files += %w( src/core/transport/metadata_batch.h )
-  s.files += %w( src/core/transport/static_metadata.h )
-  s.files += %w( src/core/transport/transport.h )
-  s.files += %w( src/core/transport/transport_impl.h )
-  s.files += %w( src/core/security/auth_filters.h )
-  s.files += %w( src/core/security/b64.h )
-  s.files += %w( src/core/security/credentials.h )
-  s.files += %w( src/core/security/handshake.h )
-  s.files += %w( src/core/security/json_token.h )
-  s.files += %w( src/core/security/jwt_verifier.h )
-  s.files += %w( src/core/security/secure_endpoint.h )
-  s.files += %w( src/core/security/security_connector.h )
-  s.files += %w( src/core/security/security_context.h )
-  s.files += %w( src/core/tsi/fake_transport_security.h )
-  s.files += %w( src/core/tsi/ssl_transport_security.h )
-  s.files += %w( src/core/tsi/ssl_types.h )
-  s.files += %w( src/core/tsi/transport_security.h )
-  s.files += %w( src/core/tsi/transport_security_interface.h )
-  s.files += %w( src/core/census/aggregation.h )
-  s.files += %w( src/core/census/mlog.h )
-  s.files += %w( src/core/census/rpc_metric_id.h )
+  s.files += %w( src/core/lib/channel/channel_args.h )
+  s.files += %w( src/core/lib/channel/channel_stack.h )
+  s.files += %w( src/core/lib/channel/channel_stack_builder.h )
+  s.files += %w( src/core/lib/channel/compress_filter.h )
+  s.files += %w( src/core/lib/channel/connected_channel.h )
+  s.files += %w( src/core/lib/channel/context.h )
+  s.files += %w( src/core/lib/channel/http_client_filter.h )
+  s.files += %w( src/core/lib/channel/http_server_filter.h )
+  s.files += %w( src/core/lib/compression/algorithm_metadata.h )
+  s.files += %w( src/core/lib/compression/message_compress.h )
+  s.files += %w( src/core/lib/debug/trace.h )
+  s.files += %w( src/core/lib/http/format_request.h )
+  s.files += %w( src/core/lib/http/httpcli.h )
+  s.files += %w( src/core/lib/http/parser.h )
+  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_posix.h )
+  s.files += %w( src/core/lib/iomgr/exec_ctx.h )
+  s.files += %w( src/core/lib/iomgr/executor.h )
+  s.files += %w( src/core/lib/iomgr/iocp_windows.h )
+  s.files += %w( src/core/lib/iomgr/iomgr.h )
+  s.files += %w( src/core/lib/iomgr/iomgr_internal.h )
+  s.files += %w( src/core/lib/iomgr/iomgr_posix.h )
+  s.files += %w( src/core/lib/iomgr/pollset.h )
+  s.files += %w( src/core/lib/iomgr/pollset_set.h )
+  s.files += %w( src/core/lib/iomgr/pollset_set_windows.h )
+  s.files += %w( src/core/lib/iomgr/pollset_windows.h )
+  s.files += %w( src/core/lib/iomgr/resolve_address.h )
+  s.files += %w( src/core/lib/iomgr/sockaddr.h )
+  s.files += %w( src/core/lib/iomgr/sockaddr_posix.h )
+  s.files += %w( src/core/lib/iomgr/sockaddr_utils.h )
+  s.files += %w( src/core/lib/iomgr/sockaddr_win32.h )
+  s.files += %w( src/core/lib/iomgr/socket_utils_posix.h )
+  s.files += %w( src/core/lib/iomgr/socket_windows.h )
+  s.files += %w( src/core/lib/iomgr/tcp_client.h )
+  s.files += %w( src/core/lib/iomgr/tcp_posix.h )
+  s.files += %w( src/core/lib/iomgr/tcp_server.h )
+  s.files += %w( src/core/lib/iomgr/tcp_windows.h )
+  s.files += %w( src/core/lib/iomgr/time_averaged_stats.h )
+  s.files += %w( src/core/lib/iomgr/timer.h )
+  s.files += %w( src/core/lib/iomgr/timer_heap.h )
+  s.files += %w( src/core/lib/iomgr/udp_server.h )
+  s.files += %w( src/core/lib/iomgr/unix_sockets_posix.h )
+  s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.h )
+  s.files += %w( src/core/lib/iomgr/wakeup_fd_posix.h )
+  s.files += %w( src/core/lib/iomgr/workqueue.h )
+  s.files += %w( src/core/lib/iomgr/workqueue_posix.h )
+  s.files += %w( src/core/lib/iomgr/workqueue_windows.h )
+  s.files += %w( src/core/lib/json/json.h )
+  s.files += %w( src/core/lib/json/json_common.h )
+  s.files += %w( src/core/lib/json/json_reader.h )
+  s.files += %w( src/core/lib/json/json_writer.h )
+  s.files += %w( src/core/lib/surface/api_trace.h )
+  s.files += %w( src/core/lib/surface/call.h )
+  s.files += %w( src/core/lib/surface/call_test_only.h )
+  s.files += %w( src/core/lib/surface/channel.h )
+  s.files += %w( src/core/lib/surface/channel_init.h )
+  s.files += %w( src/core/lib/surface/channel_stack_type.h )
+  s.files += %w( src/core/lib/surface/completion_queue.h )
+  s.files += %w( src/core/lib/surface/event_string.h )
+  s.files += %w( src/core/lib/surface/init.h )
+  s.files += %w( src/core/lib/surface/lame_client.h )
+  s.files += %w( src/core/lib/surface/server.h )
+  s.files += %w( src/core/lib/surface/surface_trace.h )
+  s.files += %w( src/core/lib/transport/byte_stream.h )
+  s.files += %w( src/core/lib/transport/connectivity_state.h )
+  s.files += %w( src/core/lib/transport/metadata.h )
+  s.files += %w( src/core/lib/transport/metadata_batch.h )
+  s.files += %w( src/core/lib/transport/static_metadata.h )
+  s.files += %w( src/core/lib/transport/transport.h )
+  s.files += %w( src/core/lib/transport/transport_impl.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_ping.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_rst_stream.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_settings.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_window_update.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/http2_errors.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/status_conversion.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.h )
+  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/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 )
+  s.files += %w( src/core/lib/tsi/transport_security.h )
+  s.files += %w( src/core/lib/tsi/transport_security_interface.h )
+  s.files += %w( src/core/ext/client_config/client_channel.h )
+  s.files += %w( src/core/ext/client_config/client_channel_factory.h )
+  s.files += %w( src/core/ext/client_config/client_config.h )
+  s.files += %w( src/core/ext/client_config/connector.h )
+  s.files += %w( src/core/ext/client_config/initial_connect_string.h )
+  s.files += %w( src/core/ext/client_config/lb_policy.h )
+  s.files += %w( src/core/ext/client_config/lb_policy_factory.h )
+  s.files += %w( src/core/ext/client_config/lb_policy_registry.h )
+  s.files += %w( src/core/ext/client_config/parse_address.h )
+  s.files += %w( src/core/ext/client_config/resolver.h )
+  s.files += %w( src/core/ext/client_config/resolver_factory.h )
+  s.files += %w( src/core/ext/client_config/resolver_registry.h )
+  s.files += %w( src/core/ext/client_config/subchannel.h )
+  s.files += %w( src/core/ext/client_config/subchannel_call_holder.h )
+  s.files += %w( src/core/ext/client_config/subchannel_index.h )
+  s.files += %w( src/core/ext/client_config/uri_parser.h )
+  s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h )
+  s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h )
   s.files += %w( third_party/nanopb/pb.h )
   s.files += %w( third_party/nanopb/pb_common.h )
   s.files += %w( third_party/nanopb/pb_decode.h )
   s.files += %w( third_party/nanopb/pb_encode.h )
-  s.files += %w( src/core/census/grpc_context.c )
-  s.files += %w( src/core/census/grpc_filter.c )
-  s.files += %w( src/core/census/grpc_plugin.c )
-  s.files += %w( src/core/channel/channel_args.c )
-  s.files += %w( src/core/channel/channel_stack.c )
-  s.files += %w( src/core/channel/channel_stack_builder.c )
-  s.files += %w( src/core/channel/client_channel.c )
-  s.files += %w( src/core/channel/client_uchannel.c )
-  s.files += %w( src/core/channel/compress_filter.c )
-  s.files += %w( src/core/channel/connected_channel.c )
-  s.files += %w( src/core/channel/http_client_filter.c )
-  s.files += %w( src/core/channel/http_server_filter.c )
-  s.files += %w( src/core/channel/subchannel_call_holder.c )
-  s.files += %w( src/core/client_config/client_config.c )
-  s.files += %w( src/core/client_config/connector.c )
-  s.files += %w( src/core/client_config/default_initial_connect_string.c )
-  s.files += %w( src/core/client_config/initial_connect_string.c )
-  s.files += %w( src/core/client_config/lb_policies/load_balancer_api.c )
-  s.files += %w( src/core/client_config/lb_policies/pick_first.c )
-  s.files += %w( src/core/client_config/lb_policies/round_robin.c )
-  s.files += %w( src/core/client_config/lb_policy.c )
-  s.files += %w( src/core/client_config/lb_policy_factory.c )
-  s.files += %w( src/core/client_config/lb_policy_registry.c )
-  s.files += %w( src/core/client_config/resolver.c )
-  s.files += %w( src/core/client_config/resolver_factory.c )
-  s.files += %w( src/core/client_config/resolver_registry.c )
-  s.files += %w( src/core/client_config/resolvers/dns_resolver.c )
-  s.files += %w( src/core/client_config/resolvers/sockaddr_resolver.c )
-  s.files += %w( src/core/client_config/subchannel.c )
-  s.files += %w( src/core/client_config/subchannel_factory.c )
-  s.files += %w( src/core/client_config/subchannel_index.c )
-  s.files += %w( src/core/client_config/uri_parser.c )
-  s.files += %w( src/core/compression/compression_algorithm.c )
-  s.files += %w( src/core/compression/message_compress.c )
-  s.files += %w( src/core/debug/trace.c )
-  s.files += %w( src/core/httpcli/format_request.c )
-  s.files += %w( src/core/httpcli/httpcli.c )
-  s.files += %w( src/core/httpcli/parser.c )
-  s.files += %w( src/core/iomgr/closure.c )
-  s.files += %w( src/core/iomgr/endpoint.c )
-  s.files += %w( src/core/iomgr/endpoint_pair_posix.c )
-  s.files += %w( src/core/iomgr/endpoint_pair_windows.c )
-  s.files += %w( src/core/iomgr/exec_ctx.c )
-  s.files += %w( src/core/iomgr/executor.c )
-  s.files += %w( src/core/iomgr/fd_posix.c )
-  s.files += %w( src/core/iomgr/iocp_windows.c )
-  s.files += %w( src/core/iomgr/iomgr.c )
-  s.files += %w( src/core/iomgr/iomgr_posix.c )
-  s.files += %w( src/core/iomgr/iomgr_windows.c )
-  s.files += %w( src/core/iomgr/pollset_multipoller_with_epoll.c )
-  s.files += %w( src/core/iomgr/pollset_multipoller_with_poll_posix.c )
-  s.files += %w( src/core/iomgr/pollset_posix.c )
-  s.files += %w( src/core/iomgr/pollset_set_posix.c )
-  s.files += %w( src/core/iomgr/pollset_set_windows.c )
-  s.files += %w( src/core/iomgr/pollset_windows.c )
-  s.files += %w( src/core/iomgr/resolve_address_posix.c )
-  s.files += %w( src/core/iomgr/resolve_address_windows.c )
-  s.files += %w( src/core/iomgr/sockaddr_utils.c )
-  s.files += %w( src/core/iomgr/socket_utils_common_posix.c )
-  s.files += %w( src/core/iomgr/socket_utils_linux.c )
-  s.files += %w( src/core/iomgr/socket_utils_posix.c )
-  s.files += %w( src/core/iomgr/socket_windows.c )
-  s.files += %w( src/core/iomgr/tcp_client_posix.c )
-  s.files += %w( src/core/iomgr/tcp_client_windows.c )
-  s.files += %w( src/core/iomgr/tcp_posix.c )
-  s.files += %w( src/core/iomgr/tcp_server_posix.c )
-  s.files += %w( src/core/iomgr/tcp_server_windows.c )
-  s.files += %w( src/core/iomgr/tcp_windows.c )
-  s.files += %w( src/core/iomgr/time_averaged_stats.c )
-  s.files += %w( src/core/iomgr/timer.c )
-  s.files += %w( src/core/iomgr/timer_heap.c )
-  s.files += %w( src/core/iomgr/udp_server.c )
-  s.files += %w( src/core/iomgr/wakeup_fd_eventfd.c )
-  s.files += %w( src/core/iomgr/wakeup_fd_nospecial.c )
-  s.files += %w( src/core/iomgr/wakeup_fd_pipe.c )
-  s.files += %w( src/core/iomgr/wakeup_fd_posix.c )
-  s.files += %w( src/core/iomgr/workqueue_posix.c )
-  s.files += %w( src/core/iomgr/workqueue_windows.c )
-  s.files += %w( src/core/json/json.c )
-  s.files += %w( src/core/json/json_reader.c )
-  s.files += %w( src/core/json/json_string.c )
-  s.files += %w( src/core/json/json_writer.c )
-  s.files += %w( src/core/proto/grpc/lb/v0/load_balancer.pb.c )
-  s.files += %w( src/core/surface/alarm.c )
-  s.files += %w( src/core/surface/api_trace.c )
-  s.files += %w( src/core/surface/byte_buffer.c )
-  s.files += %w( src/core/surface/byte_buffer_reader.c )
-  s.files += %w( src/core/surface/call.c )
-  s.files += %w( src/core/surface/call_details.c )
-  s.files += %w( src/core/surface/call_log_batch.c )
-  s.files += %w( src/core/surface/channel.c )
-  s.files += %w( src/core/surface/channel_connectivity.c )
-  s.files += %w( src/core/surface/channel_create.c )
-  s.files += %w( src/core/surface/channel_init.c )
-  s.files += %w( src/core/surface/channel_ping.c )
-  s.files += %w( src/core/surface/channel_stack_type.c )
-  s.files += %w( src/core/surface/completion_queue.c )
-  s.files += %w( src/core/surface/event_string.c )
-  s.files += %w( src/core/surface/init.c )
-  s.files += %w( src/core/surface/lame_client.c )
-  s.files += %w( src/core/surface/metadata_array.c )
-  s.files += %w( src/core/surface/server.c )
-  s.files += %w( src/core/surface/server_chttp2.c )
-  s.files += %w( src/core/surface/validate_metadata.c )
-  s.files += %w( src/core/surface/version.c )
-  s.files += %w( src/core/transport/byte_stream.c )
-  s.files += %w( src/core/transport/chttp2/alpn.c )
-  s.files += %w( src/core/transport/chttp2/bin_encoder.c )
-  s.files += %w( src/core/transport/chttp2/frame_data.c )
-  s.files += %w( src/core/transport/chttp2/frame_goaway.c )
-  s.files += %w( src/core/transport/chttp2/frame_ping.c )
-  s.files += %w( src/core/transport/chttp2/frame_rst_stream.c )
-  s.files += %w( src/core/transport/chttp2/frame_settings.c )
-  s.files += %w( src/core/transport/chttp2/frame_window_update.c )
-  s.files += %w( src/core/transport/chttp2/hpack_encoder.c )
-  s.files += %w( src/core/transport/chttp2/hpack_parser.c )
-  s.files += %w( src/core/transport/chttp2/hpack_table.c )
-  s.files += %w( src/core/transport/chttp2/huffsyms.c )
-  s.files += %w( src/core/transport/chttp2/incoming_metadata.c )
-  s.files += %w( src/core/transport/chttp2/parsing.c )
-  s.files += %w( src/core/transport/chttp2/status_conversion.c )
-  s.files += %w( src/core/transport/chttp2/stream_lists.c )
-  s.files += %w( src/core/transport/chttp2/stream_map.c )
-  s.files += %w( src/core/transport/chttp2/timeout_encoding.c )
-  s.files += %w( src/core/transport/chttp2/varint.c )
-  s.files += %w( src/core/transport/chttp2/writing.c )
-  s.files += %w( src/core/transport/chttp2_transport.c )
-  s.files += %w( src/core/transport/connectivity_state.c )
-  s.files += %w( src/core/transport/metadata.c )
-  s.files += %w( src/core/transport/metadata_batch.c )
-  s.files += %w( src/core/transport/static_metadata.c )
-  s.files += %w( src/core/transport/transport.c )
-  s.files += %w( src/core/transport/transport_op_string.c )
-  s.files += %w( src/core/httpcli/httpcli_security_connector.c )
-  s.files += %w( src/core/security/b64.c )
-  s.files += %w( src/core/security/client_auth_filter.c )
-  s.files += %w( src/core/security/credentials.c )
-  s.files += %w( src/core/security/credentials_metadata.c )
-  s.files += %w( src/core/security/credentials_posix.c )
-  s.files += %w( src/core/security/credentials_win32.c )
-  s.files += %w( src/core/security/google_default_credentials.c )
-  s.files += %w( src/core/security/handshake.c )
-  s.files += %w( src/core/security/json_token.c )
-  s.files += %w( src/core/security/jwt_verifier.c )
-  s.files += %w( src/core/security/secure_endpoint.c )
-  s.files += %w( src/core/security/security_connector.c )
-  s.files += %w( src/core/security/security_context.c )
-  s.files += %w( src/core/security/server_auth_filter.c )
-  s.files += %w( src/core/security/server_secure_chttp2.c )
-  s.files += %w( src/core/surface/init_secure.c )
-  s.files += %w( src/core/surface/secure_channel_create.c )
-  s.files += %w( src/core/tsi/fake_transport_security.c )
-  s.files += %w( src/core/tsi/ssl_transport_security.c )
-  s.files += %w( src/core/tsi/transport_security.c )
-  s.files += %w( src/core/census/context.c )
-  s.files += %w( src/core/census/initialize.c )
-  s.files += %w( src/core/census/mlog.c )
-  s.files += %w( src/core/census/operation.c )
-  s.files += %w( src/core/census/placeholders.c )
-  s.files += %w( src/core/census/tracing.c )
+  s.files += %w( src/core/ext/census/aggregation.h )
+  s.files += %w( src/core/ext/census/census_interface.h )
+  s.files += %w( src/core/ext/census/census_rpc_stats.h )
+  s.files += %w( src/core/ext/census/grpc_filter.h )
+  s.files += %w( src/core/ext/census/mlog.h )
+  s.files += %w( src/core/ext/census/rpc_metric_id.h )
+  s.files += %w( src/core/lib/surface/init.c )
+  s.files += %w( src/core/lib/channel/channel_args.c )
+  s.files += %w( src/core/lib/channel/channel_stack.c )
+  s.files += %w( src/core/lib/channel/channel_stack_builder.c )
+  s.files += %w( src/core/lib/channel/compress_filter.c )
+  s.files += %w( src/core/lib/channel/connected_channel.c )
+  s.files += %w( src/core/lib/channel/http_client_filter.c )
+  s.files += %w( src/core/lib/channel/http_server_filter.c )
+  s.files += %w( src/core/lib/compression/compression_algorithm.c )
+  s.files += %w( src/core/lib/compression/message_compress.c )
+  s.files += %w( src/core/lib/debug/trace.c )
+  s.files += %w( src/core/lib/http/format_request.c )
+  s.files += %w( src/core/lib/http/httpcli.c )
+  s.files += %w( src/core/lib/http/parser.c )
+  s.files += %w( src/core/lib/iomgr/closure.c )
+  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_posix.c )
+  s.files += %w( src/core/lib/iomgr/exec_ctx.c )
+  s.files += %w( src/core/lib/iomgr/executor.c )
+  s.files += %w( src/core/lib/iomgr/iocp_windows.c )
+  s.files += %w( src/core/lib/iomgr/iomgr.c )
+  s.files += %w( src/core/lib/iomgr/iomgr_posix.c )
+  s.files += %w( src/core/lib/iomgr/iomgr_windows.c )
+  s.files += %w( src/core/lib/iomgr/pollset_set_windows.c )
+  s.files += %w( src/core/lib/iomgr/pollset_windows.c )
+  s.files += %w( src/core/lib/iomgr/resolve_address_posix.c )
+  s.files += %w( src/core/lib/iomgr/resolve_address_windows.c )
+  s.files += %w( src/core/lib/iomgr/sockaddr_utils.c )
+  s.files += %w( src/core/lib/iomgr/socket_utils_common_posix.c )
+  s.files += %w( src/core/lib/iomgr/socket_utils_linux.c )
+  s.files += %w( src/core/lib/iomgr/socket_utils_posix.c )
+  s.files += %w( src/core/lib/iomgr/socket_windows.c )
+  s.files += %w( src/core/lib/iomgr/tcp_client_posix.c )
+  s.files += %w( src/core/lib/iomgr/tcp_client_windows.c )
+  s.files += %w( src/core/lib/iomgr/tcp_posix.c )
+  s.files += %w( src/core/lib/iomgr/tcp_server_posix.c )
+  s.files += %w( src/core/lib/iomgr/tcp_server_windows.c )
+  s.files += %w( src/core/lib/iomgr/tcp_windows.c )
+  s.files += %w( src/core/lib/iomgr/time_averaged_stats.c )
+  s.files += %w( src/core/lib/iomgr/timer.c )
+  s.files += %w( src/core/lib/iomgr/timer_heap.c )
+  s.files += %w( src/core/lib/iomgr/udp_server.c )
+  s.files += %w( src/core/lib/iomgr/unix_sockets_posix.c )
+  s.files += %w( src/core/lib/iomgr/unix_sockets_posix_noop.c )
+  s.files += %w( src/core/lib/iomgr/wakeup_fd_eventfd.c )
+  s.files += %w( src/core/lib/iomgr/wakeup_fd_nospecial.c )
+  s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.c )
+  s.files += %w( src/core/lib/iomgr/wakeup_fd_posix.c )
+  s.files += %w( src/core/lib/iomgr/workqueue_posix.c )
+  s.files += %w( src/core/lib/iomgr/workqueue_windows.c )
+  s.files += %w( src/core/lib/json/json.c )
+  s.files += %w( src/core/lib/json/json_reader.c )
+  s.files += %w( src/core/lib/json/json_string.c )
+  s.files += %w( src/core/lib/json/json_writer.c )
+  s.files += %w( src/core/lib/surface/alarm.c )
+  s.files += %w( src/core/lib/surface/api_trace.c )
+  s.files += %w( src/core/lib/surface/byte_buffer.c )
+  s.files += %w( src/core/lib/surface/byte_buffer_reader.c )
+  s.files += %w( src/core/lib/surface/call.c )
+  s.files += %w( src/core/lib/surface/call_details.c )
+  s.files += %w( src/core/lib/surface/call_log_batch.c )
+  s.files += %w( src/core/lib/surface/channel.c )
+  s.files += %w( src/core/lib/surface/channel_init.c )
+  s.files += %w( src/core/lib/surface/channel_ping.c )
+  s.files += %w( src/core/lib/surface/channel_stack_type.c )
+  s.files += %w( src/core/lib/surface/completion_queue.c )
+  s.files += %w( src/core/lib/surface/event_string.c )
+  s.files += %w( src/core/lib/surface/lame_client.c )
+  s.files += %w( src/core/lib/surface/metadata_array.c )
+  s.files += %w( src/core/lib/surface/server.c )
+  s.files += %w( src/core/lib/surface/validate_metadata.c )
+  s.files += %w( src/core/lib/surface/version.c )
+  s.files += %w( src/core/lib/transport/byte_stream.c )
+  s.files += %w( src/core/lib/transport/connectivity_state.c )
+  s.files += %w( src/core/lib/transport/metadata.c )
+  s.files += %w( src/core/lib/transport/metadata_batch.c )
+  s.files += %w( src/core/lib/transport/static_metadata.c )
+  s.files += %w( src/core/lib/transport/transport.c )
+  s.files += %w( src/core/lib/transport/transport_op_string.c )
+  s.files += %w( src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_plugin.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_ping.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_rst_stream.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_settings.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_window_update.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/parsing.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/status_conversion.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/stream_lists.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/timeout_encoding.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/varint.c )
+  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/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 )
+  s.files += %w( src/core/lib/tsi/transport_security.c )
+  s.files += %w( src/core/ext/transport/chttp2/client/secure/secure_channel_create.c )
+  s.files += %w( src/core/ext/client_config/channel_connectivity.c )
+  s.files += %w( src/core/ext/client_config/client_channel.c )
+  s.files += %w( src/core/ext/client_config/client_channel_factory.c )
+  s.files += %w( src/core/ext/client_config/client_config.c )
+  s.files += %w( src/core/ext/client_config/client_config_plugin.c )
+  s.files += %w( src/core/ext/client_config/connector.c )
+  s.files += %w( src/core/ext/client_config/default_initial_connect_string.c )
+  s.files += %w( src/core/ext/client_config/initial_connect_string.c )
+  s.files += %w( src/core/ext/client_config/lb_policy.c )
+  s.files += %w( src/core/ext/client_config/lb_policy_factory.c )
+  s.files += %w( src/core/ext/client_config/lb_policy_registry.c )
+  s.files += %w( src/core/ext/client_config/parse_address.c )
+  s.files += %w( src/core/ext/client_config/resolver.c )
+  s.files += %w( src/core/ext/client_config/resolver_factory.c )
+  s.files += %w( src/core/ext/client_config/resolver_registry.c )
+  s.files += %w( src/core/ext/client_config/subchannel.c )
+  s.files += %w( src/core/ext/client_config/subchannel_call_holder.c )
+  s.files += %w( src/core/ext/client_config/subchannel_index.c )
+  s.files += %w( src/core/ext/client_config/uri_parser.c )
+  s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c )
+  s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c )
+  s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c )
+  s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c )
   s.files += %w( third_party/nanopb/pb_common.c )
   s.files += %w( third_party/nanopb/pb_decode.c )
   s.files += %w( third_party/nanopb/pb_encode.c )
+  s.files += %w( src/core/ext/lb_policy/pick_first/pick_first.c )
+  s.files += %w( src/core/ext/lb_policy/round_robin/round_robin.c )
+  s.files += %w( src/core/ext/resolver/dns/native/dns_resolver.c )
+  s.files += %w( src/core/ext/resolver/sockaddr/sockaddr_resolver.c )
+  s.files += %w( src/core/ext/census/context.c )
+  s.files += %w( src/core/ext/census/grpc_context.c )
+  s.files += %w( src/core/ext/census/grpc_filter.c )
+  s.files += %w( src/core/ext/census/grpc_plugin.c )
+  s.files += %w( src/core/ext/census/initialize.c )
+  s.files += %w( src/core/ext/census/mlog.c )
+  s.files += %w( src/core/ext/census/operation.c )
+  s.files += %w( src/core/ext/census/placeholders.c )
+  s.files += %w( src/core/ext/census/tracing.c )
+  s.files += %w( src/core/plugin_registry/grpc_plugin_registry.c )
   s.files += %w( third_party/boringssl/crypto/aes/internal.h )
   s.files += %w( third_party/boringssl/crypto/asn1/asn1_locl.h )
   s.files += %w( third_party/boringssl/crypto/bio/internal.h )
@@ -470,12 +479,12 @@
   s.files += %w( third_party/boringssl/crypto/cipher/internal.h )
   s.files += %w( third_party/boringssl/crypto/conf/conf_def.h )
   s.files += %w( third_party/boringssl/crypto/conf/internal.h )
+  s.files += %w( third_party/boringssl/crypto/curve25519/internal.h )
   s.files += %w( third_party/boringssl/crypto/des/internal.h )
   s.files += %w( third_party/boringssl/crypto/dh/internal.h )
   s.files += %w( third_party/boringssl/crypto/digest/internal.h )
   s.files += %w( third_party/boringssl/crypto/digest/md32_common.h )
   s.files += %w( third_party/boringssl/crypto/directory.h )
-  s.files += %w( third_party/boringssl/crypto/dsa/internal.h )
   s.files += %w( third_party/boringssl/crypto/ec/internal.h )
   s.files += %w( third_party/boringssl/crypto/ec/p256-x86_64-table.h )
   s.files += %w( third_party/boringssl/crypto/evp/internal.h )
@@ -640,6 +649,7 @@
   s.files += %w( third_party/boringssl/crypto/bn/shift.c )
   s.files += %w( third_party/boringssl/crypto/bn/sqrt.c )
   s.files += %w( third_party/boringssl/crypto/buf/buf.c )
+  s.files += %w( third_party/boringssl/crypto/bytestring/asn1_compat.c )
   s.files += %w( third_party/boringssl/crypto/bytestring/ber.c )
   s.files += %w( third_party/boringssl/crypto/bytestring/cbb.c )
   s.files += %w( third_party/boringssl/crypto/bytestring/cbs.c )
@@ -663,6 +673,7 @@
   s.files += %w( third_party/boringssl/crypto/cpu-intel.c )
   s.files += %w( third_party/boringssl/crypto/crypto.c )
   s.files += %w( third_party/boringssl/crypto/curve25519/curve25519.c )
+  s.files += %w( third_party/boringssl/crypto/curve25519/x25519-x86_64.c )
   s.files += %w( third_party/boringssl/crypto/des/des.c )
   s.files += %w( third_party/boringssl/crypto/dh/check.c )
   s.files += %w( third_party/boringssl/crypto/dh/dh.c )
@@ -854,6 +865,7 @@
   s.files += %w( third_party/boringssl/ssl/ssl_buffer.c )
   s.files += %w( third_party/boringssl/ssl/ssl_cert.c )
   s.files += %w( third_party/boringssl/ssl/ssl_cipher.c )
+  s.files += %w( third_party/boringssl/ssl/ssl_ecdh.c )
   s.files += %w( third_party/boringssl/ssl/ssl_file.c )
   s.files += %w( third_party/boringssl/ssl/ssl_lib.c )
   s.files += %w( third_party/boringssl/ssl/ssl_rsa.c )
diff --git a/include/grpc++/alarm.h b/include/grpc++/alarm.h
index 764837a..1470fe8 100644
--- a/include/grpc++/alarm.h
+++ b/include/grpc++/alarm.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/channel.h b/include/grpc++/channel.h
index 679d473..c535d57 100644
--- a/include/grpc++/channel.h
+++ b/include/grpc++/channel.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h
index 3fbe6d1..38bee83 100644
--- a/include/grpc++/client_context.h
+++ b/include/grpc++/client_context.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/completion_queue.h b/include/grpc++/completion_queue.h
index f53f5ee..2a5a18b 100644
--- a/include/grpc++/completion_queue.h
+++ b/include/grpc++/completion_queue.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h
index 80eed06..e9ccb51 100644
--- a/include/grpc++/create_channel.h
+++ b/include/grpc++/create_channel.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/generic/async_generic_service.h b/include/grpc++/generic/async_generic_service.h
index 9ae8391..24bae52 100644
--- a/include/grpc++/generic/async_generic_service.h
+++ b/include/grpc++/generic/async_generic_service.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,8 @@
 #ifndef GRPCXX_GENERIC_ASYNC_GENERIC_SERVICE_H
 #define GRPCXX_GENERIC_ASYNC_GENERIC_SERVICE_H
 
-#include <grpc++/support/byte_buffer.h>
 #include <grpc++/support/async_stream.h>
+#include <grpc++/support/byte_buffer.h>
 
 struct grpc_server;
 
diff --git a/include/grpc++/generic/generic_stub.h b/include/grpc++/generic/generic_stub.h
index 5ac0371..d27deae 100644
--- a/include/grpc++/generic/generic_stub.h
+++ b/include/grpc++/generic/generic_stub.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/call.h b/include/grpc++/impl/call.h
index 64b6563..882710b 100644
--- a/include/grpc++/impl/call.h
+++ b/include/grpc++/impl/call.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/client_unary_call.h b/include/grpc++/impl/client_unary_call.h
index abe321e..ea42674 100644
--- a/include/grpc++/impl/client_unary_call.h
+++ b/include/grpc++/impl/client_unary_call.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/async_stream.h b/include/grpc++/impl/codegen/async_stream.h
index 8f9afe8..a607a47 100644
--- a/include/grpc++/impl/codegen/async_stream.h
+++ b/include/grpc++/impl/codegen/async_stream.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -108,7 +108,8 @@
                     const W& request, void* tag)
       : context_(context), call_(channel->CreateCall(method, context, cq)) {
     init_ops_.set_output_tag(tag);
-    init_ops_.SendInitialMetadata(context->send_initial_metadata_);
+    init_ops_.SendInitialMetadata(context->send_initial_metadata_,
+                                  context->initial_metadata_flags());
     // TODO(ctiller): don't assert
     GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
     init_ops_.ClientSendClose();
@@ -173,7 +174,8 @@
     finish_ops_.RecvMessage(response);
 
     init_ops_.set_output_tag(tag);
-    init_ops_.SendInitialMetadata(context->send_initial_metadata_);
+    init_ops_.SendInitialMetadata(context->send_initial_metadata_,
+                                  context->initial_metadata_flags());
     call_.PerformOps(&init_ops_);
   }
 
@@ -215,7 +217,8 @@
   CallOpSet<CallOpSendMessage> write_ops_;
   CallOpSet<CallOpClientSendClose> writes_done_ops_;
   CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
-            CallOpClientRecvStatus> finish_ops_;
+            CallOpClientRecvStatus>
+      finish_ops_;
 };
 
 /// Client-side interface for asynchronous bi-directional streaming.
@@ -239,7 +242,8 @@
                           void* tag)
       : context_(context), call_(channel->CreateCall(method, context, cq)) {
     init_ops_.set_output_tag(tag);
-    init_ops_.SendInitialMetadata(context->send_initial_metadata_);
+    init_ops_.SendInitialMetadata(context->send_initial_metadata_,
+                                  context->initial_metadata_flags());
     call_.PerformOps(&init_ops_);
   }
 
@@ -304,7 +308,8 @@
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
     meta_ops_.set_output_tag(tag);
-    meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+    meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
     ctx_->sent_initial_metadata_ = true;
     call_.PerformOps(&meta_ops_);
   }
@@ -318,7 +323,8 @@
   void Finish(const W& msg, const Status& status, void* tag) {
     finish_ops_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     // The response is dropped if the status is not OK.
@@ -335,7 +341,8 @@
     GPR_CODEGEN_ASSERT(!status.ok());
     finish_ops_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
@@ -350,7 +357,8 @@
   CallOpSet<CallOpSendInitialMetadata> meta_ops_;
   CallOpSet<CallOpRecvMessage<R>> read_ops_;
   CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-            CallOpServerSendStatus> finish_ops_;
+            CallOpServerSendStatus>
+      finish_ops_;
 };
 
 template <class W>
@@ -364,7 +372,8 @@
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
     meta_ops_.set_output_tag(tag);
-    meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+    meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
     ctx_->sent_initial_metadata_ = true;
     call_.PerformOps(&meta_ops_);
   }
@@ -372,7 +381,8 @@
   void Write(const W& msg, void* tag) GRPC_OVERRIDE {
     write_ops_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+      write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                     ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     // TODO(ctiller): don't assert
@@ -383,7 +393,8 @@
   void Finish(const Status& status, void* tag) {
     finish_ops_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
@@ -413,7 +424,8 @@
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
     meta_ops_.set_output_tag(tag);
-    meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+    meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
     ctx_->sent_initial_metadata_ = true;
     call_.PerformOps(&meta_ops_);
   }
@@ -427,7 +439,8 @@
   void Write(const W& msg, void* tag) GRPC_OVERRIDE {
     write_ops_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+      write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                     ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     // TODO(ctiller): don't assert
@@ -438,7 +451,8 @@
   void Finish(const Status& status, void* tag) {
     finish_ops_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
+      finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h
index 9c6dbd5..55c9788 100644
--- a/include/grpc++/impl/codegen/async_unary_call.h
+++ b/include/grpc++/impl/codegen/async_unary_call.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -67,7 +67,8 @@
         call_(channel->CreateCall(method, context, cq)),
         collection_(new CallOpSetCollection) {
     collection_->init_buf_.SetCollection(collection_);
-    collection_->init_buf_.SendInitialMetadata(context->send_initial_metadata_);
+    collection_->init_buf_.SendInitialMetadata(
+        context->send_initial_metadata_, context->initial_metadata_flags());
     // TODO(ctiller): don't assert
     GPR_CODEGEN_ASSERT(collection_->init_buf_.SendMessage(request).ok());
     collection_->init_buf_.ClientSendClose();
@@ -101,10 +102,12 @@
   class CallOpSetCollection : public CallOpSetCollectionInterface {
    public:
     SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-                    CallOpClientSendClose> init_buf_;
+                    CallOpClientSendClose>
+        init_buf_;
     CallOpSet<CallOpRecvInitialMetadata> meta_buf_;
     CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
-              CallOpClientRecvStatus> finish_buf_;
+              CallOpClientRecvStatus>
+        finish_buf_;
   };
   std::shared_ptr<CallOpSetCollection> collection_;
 };
@@ -120,7 +123,8 @@
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
     meta_buf_.set_output_tag(tag);
-    meta_buf_.SendInitialMetadata(ctx_->initial_metadata_);
+    meta_buf_.SendInitialMetadata(ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
     ctx_->sent_initial_metadata_ = true;
     call_.PerformOps(&meta_buf_);
   }
@@ -128,7 +132,8 @@
   void Finish(const W& msg, const Status& status, void* tag) {
     finish_buf_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      finish_buf_.SendInitialMetadata(ctx_->initial_metadata_);
+      finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     // The response is dropped if the status is not OK.
@@ -145,7 +150,8 @@
     GPR_CODEGEN_ASSERT(!status.ok());
     finish_buf_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
-      finish_buf_.SendInitialMetadata(ctx_->initial_metadata_);
+      finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status);
@@ -159,7 +165,8 @@
   ServerContext* ctx_;
   CallOpSet<CallOpSendInitialMetadata> meta_buf_;
   CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-            CallOpServerSendStatus> finish_buf_;
+            CallOpServerSendStatus>
+      finish_buf_;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 03affc2..aea1a6a 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -181,8 +181,10 @@
   CallOpSendInitialMetadata() : send_(false) {}
 
   void SendInitialMetadata(
-      const std::multimap<grpc::string, grpc::string>& metadata) {
+      const std::multimap<grpc::string, grpc::string>& metadata,
+      uint32_t flags) {
     send_ = true;
+    flags_ = flags;
     initial_metadata_count_ = metadata.size();
     initial_metadata_ = FillMetadataArray(metadata);
   }
@@ -192,7 +194,7 @@
     if (!send_) return;
     grpc_op* op = &ops[(*nops)++];
     op->op = GRPC_OP_SEND_INITIAL_METADATA;
-    op->flags = 0;
+    op->flags = flags_;
     op->reserved = NULL;
     op->data.send_initial_metadata.count = initial_metadata_count_;
     op->data.send_initial_metadata.metadata = initial_metadata_;
@@ -204,6 +206,7 @@
   }
 
   bool send_;
+  uint32_t flags_;
   size_t initial_metadata_count_;
   grpc_metadata* initial_metadata_;
 };
@@ -280,7 +283,8 @@
       if (*status) {
         got_message = true;
         *status = SerializationTraits<R>::Deserialize(recv_buf_, message_,
-                                                      max_message_size).ok();
+                                                      max_message_size)
+                      .ok();
       } else {
         got_message = false;
         g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
diff --git a/include/grpc++/impl/codegen/call_hook.h b/include/grpc++/impl/codegen/call_hook.h
index 0b60272..6a82582 100644
--- a/include/grpc++/impl/codegen/call_hook.h
+++ b/include/grpc++/impl/codegen/call_hook.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h
index 271d464..e23fd4e 100644
--- a/include/grpc++/impl/codegen/client_context.h
+++ b/include/grpc++/impl/codegen/client_context.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,7 @@
 
 #include <grpc++/impl/codegen/config.h>
 #include <grpc++/impl/codegen/core_codegen_interface.h>
+#include <grpc++/impl/codegen/create_auth_context.h>
 #include <grpc++/impl/codegen/security/auth_context.h>
 #include <grpc++/impl/codegen/status.h>
 #include <grpc++/impl/codegen/string_ref.h>
@@ -221,6 +222,12 @@
     deadline_ = deadline_tp.raw_time();
   }
 
+  /// EXPERIMENTAL: Set this request to be idempotent
+  void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
+
+  /// EXPERIMENTAL: Trigger fail-fast or not on this request
+  void set_fail_fast(bool fail_fast) { fail_fast_ = fail_fast; }
+
 #ifndef GRPC_CXX0X_NO_CHRONO
   /// Return the deadline for the client call.
   std::chrono::system_clock::time_point deadline() {
@@ -238,7 +245,12 @@
   /// Return the authentication context for this client call.
   ///
   /// \see grpc::AuthContext.
-  std::shared_ptr<const AuthContext> auth_context() const;
+  std::shared_ptr<const AuthContext> auth_context() const {
+    if (auth_context_.get() == nullptr) {
+      auth_context_ = CreateAuthContext(call_);
+    }
+    return auth_context_;
+  }
 
   /// Set credentials for the client call.
   ///
@@ -328,9 +340,16 @@
   grpc_call* call() { return call_; }
   void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel);
 
+  uint32_t initial_metadata_flags() const {
+    return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) |
+           (fail_fast_ ? 0 : GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY);
+  }
+
   grpc::string authority() { return authority_; }
 
   bool initial_metadata_received_;
+  bool fail_fast_;
+  bool idempotent_;
   std::shared_ptr<Channel> channel_;
   grpc::mutex mu_;
   grpc_call* call_;
diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h
index a2b7d92..70d6554 100644
--- a/include/grpc++/impl/codegen/client_unary_call.h
+++ b/include/grpc++/impl/codegen/client_unary_call.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -56,12 +56,14 @@
   Call call(channel->CreateCall(method, context, &cq));
   CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
             CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
-            CallOpClientSendClose, CallOpClientRecvStatus> ops;
+            CallOpClientSendClose, CallOpClientRecvStatus>
+      ops;
   Status status = ops.SendMessage(request);
   if (!status.ok()) {
     return status;
   }
-  ops.SendInitialMetadata(context->send_initial_metadata_);
+  ops.SendInitialMetadata(context->send_initial_metadata_,
+                          context->initial_metadata_flags());
   ops.RecvInitialMetadata(context);
   ops.RecvMessage(result);
   ops.ClientSendClose();
diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h
index 42ec287..56864d6 100644
--- a/include/grpc++/impl/codegen/completion_queue.h
+++ b/include/grpc++/impl/codegen/completion_queue.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/completion_queue_tag.h b/include/grpc++/impl/codegen/completion_queue_tag.h
index e904f73..19a0850 100644
--- a/include/grpc++/impl/codegen/completion_queue_tag.h
+++ b/include/grpc++/impl/codegen/completion_queue_tag.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/config_protobuf.h b/include/grpc++/impl/codegen/config_protobuf.h
index 3b9f05c..f1b6bea 100644
--- a/include/grpc++/impl/codegen/config_protobuf.h
+++ b/include/grpc++/impl/codegen/config_protobuf.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h
index a23031f..16424ba 100644
--- a/include/grpc++/impl/codegen/core_codegen_interface.h
+++ b/include/grpc++/impl/codegen/core_codegen_interface.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/create_auth_context.h b/include/grpc++/impl/codegen/create_auth_context.h
new file mode 100644
index 0000000..a386a36
--- /dev/null
+++ b/include/grpc++/impl/codegen/create_auth_context.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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 GRPCXX_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
+#define GRPCXX_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
+
+#include <memory>
+
+#include <grpc++/impl/codegen/security/auth_context.h>
+#include <grpc/impl/codegen/grpc_types.h>
+
+namespace grpc {
+
+std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
+
+}  // namespace grpc
+
+#endif  // GRPCXX_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
diff --git a/include/grpc++/impl/codegen/impl/async_stream.h b/include/grpc++/impl/codegen/impl/async_stream.h
index 413eab7..8f99e7e 100644
--- a/include/grpc++/impl/codegen/impl/async_stream.h
+++ b/include/grpc++/impl/codegen/impl/async_stream.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -215,7 +215,8 @@
   CallOpSet<CallOpSendMessage> write_ops_;
   CallOpSet<CallOpClientSendClose> writes_done_ops_;
   CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
-            CallOpClientRecvStatus> finish_ops_;
+            CallOpClientRecvStatus>
+      finish_ops_;
 };
 
 /// Client-side interface for asynchronous bi-directional streaming.
@@ -350,7 +351,8 @@
   CallOpSet<CallOpSendInitialMetadata> meta_ops_;
   CallOpSet<CallOpRecvMessage<R>> read_ops_;
   CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-            CallOpServerSendStatus> finish_ops_;
+            CallOpServerSendStatus>
+      finish_ops_;
 };
 
 template <class W>
diff --git a/include/grpc++/impl/codegen/impl/sync.h b/include/grpc++/impl/codegen/impl/sync.h
index 68fd0c4..88951de 100644
--- a/include/grpc++/impl/codegen/impl/sync.h
+++ b/include/grpc++/impl/codegen/impl/sync.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index 3ecca0a..ad74efa 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,8 +61,10 @@
 
     GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
     CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-              CallOpServerSendStatus> ops;
-    ops.SendInitialMetadata(param.server_context->initial_metadata_);
+              CallOpServerSendStatus>
+        ops;
+    ops.SendInitialMetadata(param.server_context->initial_metadata_,
+                            param.server_context->initial_metadata_flags());
     if (status.ok()) {
       status = ops.SendMessage(rsp);
     }
@@ -74,7 +76,8 @@
  private:
   // Application provided rpc handler function.
   std::function<Status(ServiceType*, ServerContext*, const RequestType*,
-                       ResponseType*)> func_;
+                       ResponseType*)>
+      func_;
   // The class the above handler function lives in.
   ServiceType* service_;
 };
@@ -96,8 +99,10 @@
 
     GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
     CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-              CallOpServerSendStatus> ops;
-    ops.SendInitialMetadata(param.server_context->initial_metadata_);
+              CallOpServerSendStatus>
+        ops;
+    ops.SendInitialMetadata(param.server_context->initial_metadata_,
+                            param.server_context->initial_metadata_flags());
     if (status.ok()) {
       status = ops.SendMessage(rsp);
     }
@@ -108,7 +113,8 @@
 
  private:
   std::function<Status(ServiceType*, ServerContext*, ServerReader<RequestType>*,
-                       ResponseType*)> func_;
+                       ResponseType*)>
+      func_;
   ServiceType* service_;
 };
 
@@ -134,7 +140,8 @@
 
     CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
     if (!param.server_context->sent_initial_metadata_) {
-      ops.SendInitialMetadata(param.server_context->initial_metadata_);
+      ops.SendInitialMetadata(param.server_context->initial_metadata_,
+                              param.server_context->initial_metadata_flags());
     }
     ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
     param.call->PerformOps(&ops);
@@ -143,7 +150,8 @@
 
  private:
   std::function<Status(ServiceType*, ServerContext*, const RequestType*,
-                       ServerWriter<ResponseType>*)> func_;
+                       ServerWriter<ResponseType>*)>
+      func_;
   ServiceType* service_;
 };
 
@@ -165,7 +173,8 @@
 
     CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
     if (!param.server_context->sent_initial_metadata_) {
-      ops.SendInitialMetadata(param.server_context->initial_metadata_);
+      ops.SendInitialMetadata(param.server_context->initial_metadata_,
+                              param.server_context->initial_metadata_flags());
     }
     ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
     param.call->PerformOps(&ops);
@@ -174,7 +183,8 @@
 
  private:
   std::function<Status(ServiceType*, ServerContext*,
-                       ServerReaderWriter<ResponseType, RequestType>*)> func_;
+                       ServerReaderWriter<ResponseType, RequestType>*)>
+      func_;
   ServiceType* service_;
 };
 
@@ -185,7 +195,8 @@
   static void FillOps(ServerContext* context, T* ops) {
     Status status(StatusCode::UNIMPLEMENTED, "");
     if (!context->sent_initial_metadata_) {
-      ops->SendInitialMetadata(context->initial_metadata_);
+      ops->SendInitialMetadata(context->initial_metadata_,
+                               context->initial_metadata_flags());
       context->sent_initial_metadata_ = true;
     }
     ops->ServerSendStatus(context->trailing_metadata_, status);
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h
index f77f8ee..2aaa3c3 100644
--- a/include/grpc++/impl/codegen/proto_utils.h
+++ b/include/grpc++/impl/codegen/proto_utils.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/rpc_method.h b/include/grpc++/impl/codegen/rpc_method.h
index 85d5c1c..39cb4f7 100644
--- a/include/grpc++/impl/codegen/rpc_method.h
+++ b/include/grpc++/impl/codegen/rpc_method.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index 6256301..8b1f026 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -40,10 +40,10 @@
 #include <memory>
 #include <vector>
 
-#include <grpc/impl/codegen/byte_buffer.h>
 #include <grpc++/impl/codegen/config.h>
 #include <grpc++/impl/codegen/rpc_method.h>
 #include <grpc++/impl/codegen/status.h>
+#include <grpc/impl/codegen/byte_buffer.h>
 
 namespace grpc {
 class ServerContext;
diff --git a/include/grpc++/impl/codegen/security/auth_context.h b/include/grpc++/impl/codegen/security/auth_context.h
index 7544430..75f2482 100644
--- a/include/grpc++/impl/codegen/security/auth_context.h
+++ b/include/grpc++/impl/codegen/security/auth_context.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/serialization_traits.h b/include/grpc++/impl/codegen/serialization_traits.h
index 83c3b64..fa99dbf 100644
--- a/include/grpc++/impl/codegen/serialization_traits.h
+++ b/include/grpc++/impl/codegen/serialization_traits.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h
index 91ebe57..a1e1ed1 100644
--- a/include/grpc++/impl/codegen/server_context.h
+++ b/include/grpc++/impl/codegen/server_context.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,12 +37,13 @@
 #include <map>
 #include <memory>
 
-#include <grpc/impl/codegen/compression_types.h>
-#include <grpc/impl/codegen/time.h>
-#include <grpc++/impl/codegen/security/auth_context.h>
 #include <grpc++/impl/codegen/config.h>
+#include <grpc++/impl/codegen/create_auth_context.h>
+#include <grpc++/impl/codegen/security/auth_context.h>
 #include <grpc++/impl/codegen/string_ref.h>
 #include <grpc++/impl/codegen/time.h>
+#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/impl/codegen/time.h>
 
 struct gpr_timespec;
 struct grpc_metadata;
@@ -135,7 +136,12 @@
   }
   void set_compression_algorithm(grpc_compression_algorithm algorithm);
 
-  std::shared_ptr<const AuthContext> auth_context() const;
+  std::shared_ptr<const AuthContext> auth_context() const {
+    if (auth_context_.get() == nullptr) {
+      auth_context_ = CreateAuthContext(call_);
+    }
+    return auth_context_;
+  }
 
   // Return the peer uri in a string.
   // WARNING: this value is never authenticated or subject to any security
@@ -193,7 +199,9 @@
   ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
                 size_t metadata_count);
 
-  void set_call(grpc_call* call);
+  void set_call(grpc_call* call) { call_ = call; }
+
+  uint32_t initial_metadata_flags() const { return 0; }
 
   CompletionOp* completion_op_;
   bool has_notify_when_done_tag_;
diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h
index 7d4ed27..7b7d5aa 100644
--- a/include/grpc++/impl/codegen/server_interface.h
+++ b/include/grpc++/impl/codegen/server_interface.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -192,10 +192,11 @@
     bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
       bool serialization_status =
           *status && payload_ &&
-          SerializationTraits<Message>::Deserialize(
-              payload_, request_, server_->max_message_size()).ok();
+          SerializationTraits<Message>::Deserialize(payload_, request_,
+                                                    server_->max_message_size())
+              .ok();
       bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
-      *status = serialization_status&&* status;
+      *status = serialization_status && *status;
       return ret;
     }
 
diff --git a/include/grpc++/impl/codegen/service_type.h b/include/grpc++/impl/codegen/service_type.h
index faf1893..c19dfc7 100644
--- a/include/grpc++/impl/codegen/service_type.h
+++ b/include/grpc++/impl/codegen/service_type.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/string_ref.h b/include/grpc++/impl/codegen/string_ref.h
index 4af2000..0037938 100644
--- a/include/grpc++/impl/codegen/string_ref.h
+++ b/include/grpc++/impl/codegen/string_ref.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/stub_options.h b/include/grpc++/impl/codegen/stub_options.h
index 3912ae2..8e966a8 100644
--- a/include/grpc++/impl/codegen/stub_options.h
+++ b/include/grpc++/impl/codegen/stub_options.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/sync.h b/include/grpc++/impl/codegen/sync.h
index 375af15..62194c7 100644
--- a/include/grpc++/impl/codegen/sync.h
+++ b/include/grpc++/impl/codegen/sync.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/sync_cxx11.h b/include/grpc++/impl/codegen/sync_cxx11.h
index 4910547..6626ca1 100644
--- a/include/grpc++/impl/codegen/sync_cxx11.h
+++ b/include/grpc++/impl/codegen/sync_cxx11.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/sync_no_cxx11.h b/include/grpc++/impl/codegen/sync_no_cxx11.h
index 8dea847..55c059e 100644
--- a/include/grpc++/impl/codegen/sync_no_cxx11.h
+++ b/include/grpc++/impl/codegen/sync_no_cxx11.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index 5f87846..9100ce0 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -123,8 +123,10 @@
                ClientContext* context, const W& request)
       : context_(context), call_(channel->CreateCall(method, context, &cq_)) {
     CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-              CallOpClientSendClose> ops;
-    ops.SendInitialMetadata(context->send_initial_metadata_);
+              CallOpClientSendClose>
+        ops;
+    ops.SendInitialMetadata(context->send_initial_metadata_,
+                            context->initial_metadata_flags());
     // TODO(ctiller): don't assert
     GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
     ops.ClientSendClose();
@@ -189,7 +191,8 @@
     finish_ops_.RecvMessage(response);
 
     CallOpSet<CallOpSendInitialMetadata> ops;
-    ops.SendInitialMetadata(context->send_initial_metadata_);
+    ops.SendInitialMetadata(context->send_initial_metadata_,
+                            context->initial_metadata_flags());
     call_.PerformOps(&ops);
     cq_.Pluck(&ops);
   }
@@ -235,7 +238,8 @@
  private:
   ClientContext* context_;
   CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
-            CallOpClientRecvStatus> finish_ops_;
+            CallOpClientRecvStatus>
+      finish_ops_;
   CompletionQueue cq_;
   Call call_;
 };
@@ -266,7 +270,8 @@
                      ClientContext* context)
       : context_(context), call_(channel->CreateCall(method, context, &cq_)) {
     CallOpSet<CallOpSendInitialMetadata> ops;
-    ops.SendInitialMetadata(context->send_initial_metadata_);
+    ops.SendInitialMetadata(context->send_initial_metadata_,
+                            context->initial_metadata_flags());
     call_.PerformOps(&ops);
     cq_.Pluck(&ops);
   }
@@ -332,7 +337,8 @@
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
     CallOpSet<CallOpSendInitialMetadata> ops;
-    ops.SendInitialMetadata(ctx_->initial_metadata_);
+    ops.SendInitialMetadata(ctx_->initial_metadata_,
+                            ctx_->initial_metadata_flags());
     ctx_->sent_initial_metadata_ = true;
     call_->PerformOps(&ops);
     call_->cq()->Pluck(&ops);
@@ -359,7 +365,8 @@
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
     CallOpSet<CallOpSendInitialMetadata> ops;
-    ops.SendInitialMetadata(ctx_->initial_metadata_);
+    ops.SendInitialMetadata(ctx_->initial_metadata_,
+                            ctx_->initial_metadata_flags());
     ctx_->sent_initial_metadata_ = true;
     call_->PerformOps(&ops);
     call_->cq()->Pluck(&ops);
@@ -372,7 +379,8 @@
       return false;
     }
     if (!ctx_->sent_initial_metadata_) {
-      ops.SendInitialMetadata(ctx_->initial_metadata_);
+      ops.SendInitialMetadata(ctx_->initial_metadata_,
+                              ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     call_->PerformOps(&ops);
@@ -395,7 +403,8 @@
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
     CallOpSet<CallOpSendInitialMetadata> ops;
-    ops.SendInitialMetadata(ctx_->initial_metadata_);
+    ops.SendInitialMetadata(ctx_->initial_metadata_,
+                            ctx_->initial_metadata_flags());
     ctx_->sent_initial_metadata_ = true;
     call_->PerformOps(&ops);
     call_->cq()->Pluck(&ops);
@@ -415,7 +424,8 @@
       return false;
     }
     if (!ctx_->sent_initial_metadata_) {
-      ops.SendInitialMetadata(ctx_->initial_metadata_);
+      ops.SendInitialMetadata(ctx_->initial_metadata_,
+                              ctx_->initial_metadata_flags());
       ctx_->sent_initial_metadata_ = true;
     }
     call_->PerformOps(&ops);
diff --git a/include/grpc++/impl/codegen/time.h b/include/grpc++/impl/codegen/time.h
index bed7423..d9b19bc 100644
--- a/include/grpc++/impl/codegen/time.h
+++ b/include/grpc++/impl/codegen/time.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/grpc_library.h b/include/grpc++/impl/grpc_library.h
index ecb5a4d..175cf99 100644
--- a/include/grpc++/impl/grpc_library.h
+++ b/include/grpc++/impl/grpc_library.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/method_handler_impl.h b/include/grpc++/impl/method_handler_impl.h
index 305fd28..443978b 100644
--- a/include/grpc++/impl/method_handler_impl.h
+++ b/include/grpc++/impl/method_handler_impl.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/proto_utils.h b/include/grpc++/impl/proto_utils.h
index 36acabb..a34cf9b 100644
--- a/include/grpc++/impl/proto_utils.h
+++ b/include/grpc++/impl/proto_utils.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/rpc_method.h b/include/grpc++/impl/rpc_method.h
index 8b5d1a3..27293e6 100644
--- a/include/grpc++/impl/rpc_method.h
+++ b/include/grpc++/impl/rpc_method.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/serialization_traits.h b/include/grpc++/impl/serialization_traits.h
index fad4398..5353829 100644
--- a/include/grpc++/impl/serialization_traits.h
+++ b/include/grpc++/impl/serialization_traits.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/service_type.h b/include/grpc++/impl/service_type.h
index b33fbec..ffad7a3 100644
--- a/include/grpc++/impl/service_type.h
+++ b/include/grpc++/impl/service_type.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/sync.h b/include/grpc++/impl/sync.h
index 8241390..3339cdd 100644
--- a/include/grpc++/impl/sync.h
+++ b/include/grpc++/impl/sync.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/sync_cxx11.h b/include/grpc++/impl/sync_cxx11.h
index 22997a1..78acec1 100644
--- a/include/grpc++/impl/sync_cxx11.h
+++ b/include/grpc++/impl/sync_cxx11.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/impl/sync_no_cxx11.h b/include/grpc++/impl/sync_no_cxx11.h
index def800d..e40269d 100644
--- a/include/grpc++/impl/sync_no_cxx11.h
+++ b/include/grpc++/impl/sync_no_cxx11.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/security/auth_context.h b/include/grpc++/security/auth_context.h
index 548f9a2..4244183 100644
--- a/include/grpc++/security/auth_context.h
+++ b/include/grpc++/security/auth_context.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/security/auth_metadata_processor.h b/include/grpc++/security/auth_metadata_processor.h
index b39451f..1ae32d0 100644
--- a/include/grpc++/security/auth_metadata_processor.h
+++ b/include/grpc++/security/auth_metadata_processor.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h
index bedfc9c..5439244 100644
--- a/include/grpc++/security/credentials.h
+++ b/include/grpc++/security/credentials.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/security/server_credentials.h b/include/grpc++/security/server_credentials.h
index addb11c..229bab8 100644
--- a/include/grpc++/security/server_credentials.h
+++ b/include/grpc++/security/server_credentials.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
 
 #include <grpc++/security/auth_metadata_processor.h>
 #include <grpc++/support/config.h>
+#include <grpc/grpc_security_constants.h>
 
 struct grpc_server;
 
@@ -69,7 +70,13 @@
 
 /// Options to create ServerCredentials with SSL
 struct SslServerCredentialsOptions {
-  SslServerCredentialsOptions() : force_client_auth(false) {}
+  // Deprecated
+  SslServerCredentialsOptions()
+      : force_client_auth(false),
+        client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {}
+  SslServerCredentialsOptions(
+      grpc_ssl_client_certificate_request_type request_type)
+      : force_client_auth(false), client_certificate_request(request_type) {}
 
   struct PemKeyCertPair {
     grpc::string private_key;
@@ -77,7 +84,13 @@
   };
   grpc::string pem_root_certs;
   std::vector<PemKeyCertPair> pem_key_cert_pairs;
+  // Deprecated
   bool force_client_auth;
+
+  // If both force_client_auth and client_certificate_request fields are set,
+  // force_client_auth takes effect i.e
+  // REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY will be enforced.
+  grpc_ssl_client_certificate_request_type client_certificate_request;
 };
 
 /// Builds SSL ServerCredentials given SSL specific options
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index 9eb8c28..729a514 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index 73bcfb6..86c7fec 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h
index 214188a..0d68c78 100644
--- a/include/grpc++/server_context.h
+++ b/include/grpc++/server_context.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/async_stream.h b/include/grpc++/support/async_stream.h
index 88147ea..106fd6c 100644
--- a/include/grpc++/support/async_stream.h
+++ b/include/grpc++/support/async_stream.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/async_unary_call.h b/include/grpc++/support/async_unary_call.h
index 6d74328..e1bd6db 100644
--- a/include/grpc++/support/async_unary_call.h
+++ b/include/grpc++/support/async_unary_call.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h
index 82591a8..f6eb096 100644
--- a/include/grpc++/support/byte_buffer.h
+++ b/include/grpc++/support/byte_buffer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,13 @@
 #ifndef GRPCXX_SUPPORT_BYTE_BUFFER_H
 #define GRPCXX_SUPPORT_BYTE_BUFFER_H
 
-#include <grpc/grpc.h>
-#include <grpc/byte_buffer.h>
-#include <grpc/support/log.h>
 #include <grpc++/impl/serialization_traits.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/slice.h>
 #include <grpc++/support/status.h>
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
 
 #include <vector>
 
@@ -99,8 +99,8 @@
   }
   static Status Serialize(const ByteBuffer& source, grpc_byte_buffer** buffer,
                           bool* own_buffer) {
-    *buffer = source.buffer();
-    *own_buffer = false;
+    *buffer = grpc_byte_buffer_copy(source.buffer());
+    *own_buffer = true;
     return Status::OK;
   }
 };
diff --git a/include/grpc++/support/channel_arguments.h b/include/grpc++/support/channel_arguments.h
index a9ede35..ae24393 100644
--- a/include/grpc++/support/channel_arguments.h
+++ b/include/grpc++/support/channel_arguments.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,12 +34,12 @@
 #ifndef GRPCXX_SUPPORT_CHANNEL_ARGUMENTS_H
 #define GRPCXX_SUPPORT_CHANNEL_ARGUMENTS_H
 
-#include <vector>
 #include <list>
+#include <vector>
 
+#include <grpc++/support/config.h>
 #include <grpc/compression.h>
 #include <grpc/grpc.h>
-#include <grpc++/support/config.h>
 
 namespace grpc {
 namespace testing {
diff --git a/include/grpc++/support/config.h b/include/grpc++/support/config.h
index be8c89c..10c65d9 100644
--- a/include/grpc++/support/config.h
+++ b/include/grpc++/support/config.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/config_protobuf.h b/include/grpc++/support/config_protobuf.h
index 0b466e8..3e7f169 100644
--- a/include/grpc++/support/config_protobuf.h
+++ b/include/grpc++/support/config_protobuf.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/slice.h b/include/grpc++/support/slice.h
index 724691a..cec9062 100644
--- a/include/grpc++/support/slice.h
+++ b/include/grpc++/support/slice.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,8 @@
 #ifndef GRPCXX_SUPPORT_SLICE_H
 #define GRPCXX_SUPPORT_SLICE_H
 
-#include <grpc/support/slice.h>
 #include <grpc++/support/config.h>
+#include <grpc/support/slice.h>
 
 namespace grpc {
 
diff --git a/include/grpc++/support/status.h b/include/grpc++/support/status.h
index a33fbed..bdb25b0 100644
--- a/include/grpc++/support/status.h
+++ b/include/grpc++/support/status.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/status_code_enum.h b/include/grpc++/support/status_code_enum.h
index 21b9c40..690a509 100644
--- a/include/grpc++/support/status_code_enum.h
+++ b/include/grpc++/support/status_code_enum.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/string_ref.h b/include/grpc++/support/string_ref.h
index 195e5c8..1f95e47 100644
--- a/include/grpc++/support/string_ref.h
+++ b/include/grpc++/support/string_ref.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/stub_options.h b/include/grpc++/support/stub_options.h
index f8f4c87..17a13c3 100644
--- a/include/grpc++/support/stub_options.h
+++ b/include/grpc++/support/stub_options.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/sync_stream.h b/include/grpc++/support/sync_stream.h
index 2ea2ac5..be742ef 100644
--- a/include/grpc++/support/sync_stream.h
+++ b/include/grpc++/support/sync_stream.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc++/support/time.h b/include/grpc++/support/time.h
index f0b758f..1b6fb46 100644
--- a/include/grpc++/support/time.h
+++ b/include/grpc++/support/time.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/byte_buffer.h b/include/grpc/byte_buffer.h
index fa1fd24..c3a3943 100644
--- a/include/grpc/byte_buffer.h
+++ b/include/grpc/byte_buffer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/byte_buffer_reader.h b/include/grpc/byte_buffer_reader.h
index b0e63a6..9a1c617 100644
--- a/include/grpc/byte_buffer_reader.h
+++ b/include/grpc/byte_buffer_reader.h
@@ -34,8 +34,8 @@
 #ifndef GRPC_BYTE_BUFFER_READER_H
 #define GRPC_BYTE_BUFFER_READER_H
 
-#include <grpc/grpc.h>
 #include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/grpc/census.h b/include/grpc/census.h
index 4ccf4af..39d87ba 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/compression.h b/include/grpc/compression.h
index 70ba393..8de4b13 100644
--- a/include/grpc/compression.h
+++ b/include/grpc/compression.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,8 +36,8 @@
 
 #include <stdlib.h>
 
-#include <grpc/impl/codegen/port_platform.h>
 #include <grpc/impl/codegen/compression_types.h>
+#include <grpc/impl/codegen/port_platform.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -59,9 +59,8 @@
  * compression algorithms encoded in the \a accepted_encodings bitset.
  *
  * It abort()s for unknown levels . */
-GRPCAPI grpc_compression_algorithm
-grpc_compression_algorithm_for_level(grpc_compression_level level,
-                                     uint32_t accepted_encodings);
+GRPCAPI grpc_compression_algorithm grpc_compression_algorithm_for_level(
+    grpc_compression_level level, uint32_t accepted_encodings);
 
 GRPCAPI void grpc_compression_options_init(grpc_compression_options *opts);
 
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 5113645..5c868ae 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,13 +36,13 @@
 
 #include <grpc/status.h>
 
-#include <stddef.h>
 #include <grpc/byte_buffer.h>
+#include <grpc/impl/codegen/connectivity_state.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/propagation_bits.h>
 #include <grpc/support/slice.h>
 #include <grpc/support/time.h>
-#include <grpc/impl/codegen/connectivity_state.h>
-#include <grpc/impl/codegen/propagation_bits.h>
-#include <grpc/impl/codegen/grpc_types.h>
+#include <stddef.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -154,9 +154,8 @@
 GRPCAPI void grpc_alarm_destroy(grpc_alarm *alarm);
 
 /** Check the connectivity state of a channel. */
-GRPCAPI grpc_connectivity_state
-grpc_channel_check_connectivity_state(grpc_channel *channel,
-                                      int try_to_connect);
+GRPCAPI grpc_connectivity_state grpc_channel_check_connectivity_state(
+    grpc_channel *channel, int try_to_connect);
 
 /** Watch for a change in connectivity state.
     Once the channel connectivity state is different from last_observed_state,
@@ -267,9 +266,10 @@
     and description passed in.
     Importantly, this function does not send status nor description to the
     remote endpoint. */
-GRPCAPI grpc_call_error
-grpc_call_cancel_with_status(grpc_call *call, grpc_status_code status,
-                             const char *description, void *reserved);
+GRPCAPI grpc_call_error grpc_call_cancel_with_status(grpc_call *call,
+                                                     grpc_status_code status,
+                                                     const char *description,
+                                                     void *reserved);
 
 /** Destroy a call.
     THREAD SAFETY: grpc_call_destroy is thread-compatible */
@@ -283,13 +283,19 @@
     to \a cq_bound_to_call.
     Note that \a cq_for_notification must have been registered to the server via
     \a grpc_server_register_completion_queue. */
-GRPCAPI grpc_call_error
-grpc_server_request_call(grpc_server *server, grpc_call **call,
-                         grpc_call_details *details,
-                         grpc_metadata_array *request_metadata,
-                         grpc_completion_queue *cq_bound_to_call,
-                         grpc_completion_queue *cq_for_notification,
-                         void *tag_new);
+GRPCAPI grpc_call_error grpc_server_request_call(
+    grpc_server *server, grpc_call **call, grpc_call_details *details,
+    grpc_metadata_array *request_metadata,
+    grpc_completion_queue *cq_bound_to_call,
+    grpc_completion_queue *cq_for_notification, void *tag_new);
+
+/** How to handle payloads for a registered method */
+typedef enum {
+  /** Don't try to read the payload */
+  GRPC_SRM_PAYLOAD_NONE,
+  /** Read the initial payload as a byte buffer */
+  GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER
+} grpc_server_register_method_payload_handling;
 
 /** Registers a method in the server.
     Methods to this (host, method) pair will not be reported by
@@ -298,8 +304,10 @@
     registered_method (as returned by this function).
     Must be called before grpc_server_start.
     Returns NULL on failure. */
-GRPCAPI void *grpc_server_register_method(grpc_server *server,
-                                          const char *method, const char *host);
+GRPCAPI void *grpc_server_register_method(
+    grpc_server *server, const char *method, const char *host,
+    grpc_server_register_method_payload_handling payload_handling,
+    uint32_t flags);
 
 /** Request notification of a new pre-registered call. 'cq_for_notification'
     must have been registered to the server via
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 368d5dd..79199cc 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
 #define GRPC_GRPC_SECURITY_H
 
 #include <grpc/grpc.h>
+#include <grpc/grpc_security_constants.h>
 #include <grpc/status.h>
 
 #ifdef __cplusplus
@@ -43,13 +44,6 @@
 
 /* --- Authentication Context. --- */
 
-#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
-#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
-
-#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
-#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
-#define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert"
-
 typedef struct grpc_auth_context grpc_auth_context;
 
 typedef struct grpc_auth_property_iterator {
@@ -80,9 +74,8 @@
 
 /* Finds a property in the context. May return an empty iterator (first _next
    will return NULL) if no property with this name was found in the context. */
-GRPCAPI grpc_auth_property_iterator
-grpc_auth_context_find_properties_by_name(const grpc_auth_context *ctx,
-                                          const char *name);
+GRPCAPI grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
+    const grpc_auth_context *ctx, const char *name);
 
 /* Gets the name of the property that indicates the peer identity. Will return
    NULL if the peer is not authenticated. */
@@ -131,29 +124,11 @@
    The creator of the credentials object is responsible for its release. */
 GRPCAPI void grpc_channel_credentials_release(grpc_channel_credentials *creds);
 
-/* Environment variable that points to the google default application
-   credentials json key or refresh token. Used in the
-   grpc_google_default_credentials_create function. */
-#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
-
 /* Creates default credentials to connect to a google gRPC service.
    WARNING: Do NOT use this credentials to connect to a non-google service as
    this could result in an oauth2 token leak. */
 GRPCAPI grpc_channel_credentials *grpc_google_default_credentials_create(void);
 
-/* Environment variable that points to the default SSL roots file. This file
-   must be a PEM encoded file with all the roots such as the one that can be
-   downloaded from https://pki.google.com/roots.pem.  */
-#define GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR \
-  "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"
-
-/* Results for the SSL roots override callback. */
-typedef enum {
-  GRPC_SSL_ROOTS_OVERRIDE_OK,
-  GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY, /* Do not try fallback options. */
-  GRPC_SSL_ROOTS_OVERRIDE_FAIL
-} grpc_ssl_roots_override_result;
-
 /* Callback for getting the SSL roots override from the application.
    In case of success, *pem_roots_certs must be set to a NULL terminated string
    containing the list of PEM encoded root certificates. The ownership is passed
@@ -335,7 +310,8 @@
    */
 GRPCAPI void grpc_server_credentials_release(grpc_server_credentials *creds);
 
-/* Creates an SSL server_credentials object.
+/* Deprecated in favor of grpc_ssl_server_credentials_create_ex.
+   Creates an SSL server_credentials object.
    - pem_roots_cert is the NULL-terminated string containing the PEM encoding of
      the client root certificates. This parameter may be NULL if the server does
      not want the client to be authenticated with SSL.
@@ -350,6 +326,15 @@
     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);
 
+/* Same as grpc_ssl_server_credentials_create method except uses
+   grpc_ssl_client_certificate_request_type enum to support more ways to
+   authenticate client cerificates.*/
+GRPCAPI 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);
+
 /* --- Server-side secure ports. --- */
 
 /* Add a HTTP2 over an encrypted link over tcp listener.
@@ -363,8 +348,8 @@
 
 /* Sets a credentials to a call. Can only be called on the client side before
    grpc_call_start_batch. */
-GRPCAPI grpc_call_error
-grpc_call_set_credentials(grpc_call *call, grpc_call_credentials *creds);
+GRPCAPI grpc_call_error grpc_call_set_credentials(grpc_call *call,
+                                                  grpc_call_credentials *creds);
 
 /* --- Auth Metadata Processing --- */
 
diff --git a/include/grpc/grpc_security_constants.h b/include/grpc/grpc_security_constants.h
new file mode 100644
index 0000000..da05c5a
--- /dev/null
+++ b/include/grpc/grpc_security_constants.h
@@ -0,0 +1,114 @@
+/*
+ *
+ * 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_GRPC_SECURITY_CONSTANTS_H
+#define GRPC_GRPC_SECURITY_CONSTANTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
+#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
+
+#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
+#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
+#define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert"
+
+/* Environment variable that points to the default SSL roots file. This file
+   must be a PEM encoded file with all the roots such as the one that can be
+   downloaded from https://pki.google.com/roots.pem.  */
+#define GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR \
+  "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"
+
+/* Environment variable that points to the google default application
+   credentials json key or refresh token. Used in the
+   grpc_google_default_credentials_create function. */
+#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
+
+/* Results for the SSL roots override callback. */
+typedef enum {
+  GRPC_SSL_ROOTS_OVERRIDE_OK,
+  GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY, /* Do not try fallback options. */
+  GRPC_SSL_ROOTS_OVERRIDE_FAIL
+} grpc_ssl_roots_override_result;
+
+typedef enum {
+  /* Server does not request client certificate. A client can present a self
+     signed or signed certificates if it wishes to do so and they would be
+     accepted. */
+  GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
+  /* Server requests client certificate but does not enforce that the client
+     presents a certificate.
+
+     If the client presents a certificate, the client authentication is left to
+     the application based on the metadata like certificate etc.
+
+     The key cert pair should still be valid for the SSL connection to be
+     established. */
+  GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+  /* Server requests client certificate but does not enforce that the client
+     presents a certificate.
+
+     If the client presents a certificate, the client authentication is done by
+     grpc framework (The client needs to either present a signed cert or skip no
+     certificate for a successful connection).
+
+     The key cert pair should still be valid for the SSL connection to be
+     established. */
+  GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY,
+  /* Server requests client certificate but enforces that the client presents a
+     certificate.
+
+     If the client presents a certificate, the client authentication is left to
+     the application based on the metadata like certificate etc.
+
+     The key cert pair should still be valid for the SSL connection to be
+     established. */
+  GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+  /* Server requests client certificate but enforces that the client presents a
+     certificate.
+
+     The cerificate presented by the client is verified by grpc framework (The
+     client needs to present signed certs for a successful connection).
+
+     The key cert pair should still be valid for the SSL connection to be
+     established. */
+  GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+} grpc_ssl_client_certificate_request_type;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_GRPC_SECURITY_CONSTANTS_H */
diff --git a/include/grpc/grpc_zookeeper.h b/include/grpc/grpc_zookeeper.h
index b23bd88..2b195c1 100644
--- a/include/grpc/grpc_zookeeper.h
+++ b/include/grpc/grpc_zookeeper.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/alloc.h b/include/grpc/impl/codegen/alloc.h
index 2351354..683c755 100644
--- a/include/grpc/impl/codegen/alloc.h
+++ b/include/grpc/impl/codegen/alloc.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/atm.h b/include/grpc/impl/codegen/atm.h
index 35b9750..5376026 100644
--- a/include/grpc/impl/codegen/atm.h
+++ b/include/grpc/impl/codegen/atm.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/atm_gcc_atomic.h b/include/grpc/impl/codegen/atm_gcc_atomic.h
index 196d2ae..8caf7ed 100644
--- a/include/grpc/impl/codegen/atm_gcc_atomic.h
+++ b/include/grpc/impl/codegen/atm_gcc_atomic.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/atm_gcc_sync.h b/include/grpc/impl/codegen/atm_gcc_sync.h
index 56f7559..915b09f 100644
--- a/include/grpc/impl/codegen/atm_gcc_sync.h
+++ b/include/grpc/impl/codegen/atm_gcc_sync.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/atm_win32.h b/include/grpc/impl/codegen/atm_win32.h
index 9d26462..7c1ccaf 100644
--- a/include/grpc/impl/codegen/atm_win32.h
+++ b/include/grpc/impl/codegen/atm_win32.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/byte_buffer.h b/include/grpc/impl/codegen/byte_buffer.h
index 9e96d4b..3ae8ac5 100644
--- a/include/grpc/impl/codegen/byte_buffer.h
+++ b/include/grpc/impl/codegen/byte_buffer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index b11f6ff..4c73730 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -142,6 +142,8 @@
 /** Secondary user agent: goes at the end of the user-agent metadata
     sent on each request */
 #define GRPC_ARG_SECONDARY_USER_AGENT_STRING "grpc.secondary_user_agent"
+/** The maximum time between subsequent connection attempts, in ms */
+#define GRPC_ARG_MAX_RECONNECT_BACKOFF_MS "grpc.max_reconnect_backoff_ms"
 /* The caller of the secure_channel_create functions may override the target
    name used for SSL host name checking using this channel argument which is of
    type GRPC_ARG_STRING. This *should* be used for testing only.
@@ -185,7 +187,9 @@
       server */
   GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE,
   /** this batch of operations leads to more operations than allowed */
-  GRPC_CALL_ERROR_BATCH_TOO_BIG
+  GRPC_CALL_ERROR_BATCH_TOO_BIG,
+  /** payload type requested is not the type registered */
+  GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH
 } grpc_call_error;
 
 /* Write Flags: */
@@ -199,6 +203,16 @@
 /** Mask of all valid flags. */
 #define GRPC_WRITE_USED_MASK (GRPC_WRITE_BUFFER_HINT | GRPC_WRITE_NO_COMPRESS)
 
+/* Initial metadata flags */
+/** Signal that the call is idempotent */
+#define GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST (0x00000010u)
+/** Signal that the call should not return UNAVAILABLE before it has started */
+#define GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY (0x00000020u)
+/** Mask of all valid flags */
+#define GRPC_INITIAL_METADATA_USED_MASK       \
+  (GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST | \
+   GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY)
+
 /** A single metadata element */
 typedef struct grpc_metadata {
   const char *key;
@@ -250,6 +264,7 @@
   char *host;
   size_t host_capacity;
   gpr_timespec deadline;
+  uint32_t flags;
   void *reserved;
 } grpc_call_details;
 
diff --git a/include/grpc/impl/codegen/log.h b/include/grpc/impl/codegen/log.h
index d6e18e9..aa86fc4 100644
--- a/include/grpc/impl/codegen/log.h
+++ b/include/grpc/impl/codegen/log.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,8 @@
 #ifndef GRPC_IMPL_CODEGEN_LOG_H
 #define GRPC_IMPL_CODEGEN_LOG_H
 
-#include <stdlib.h> /* for abort() */
 #include <stdarg.h>
+#include <stdlib.h> /* for abort() */
 
 #include <grpc/impl/codegen/port_platform.h>
 
@@ -61,6 +61,8 @@
   GPR_LOG_SEVERITY_ERROR
 } gpr_log_severity;
 
+#define GPR_LOG_VERBOSITY_UNSET -1
+
 /* Returns a string representation of the log severity */
 const char *gpr_log_severity_string(gpr_log_severity severity);
 
@@ -77,6 +79,11 @@
 GPRAPI void gpr_log_message(const char *file, int line,
                             gpr_log_severity severity, const char *message);
 
+/* Set global log verbosity */
+GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print);
+
+GPRAPI void gpr_log_verbosity_init();
+
 /* Log overrides: applications can use this API to intercept logging calls
    and use their own implementations */
 
diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h
index fd55cb4..3242f07 100644
--- a/include/grpc/impl/codegen/port_platform.h
+++ b/include/grpc/impl/codegen/port_platform.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -133,6 +133,9 @@
 #define GPR_POSIX_TIME 1
 #define GPR_GETPID_IN_UNISTD_H 1
 #define GPR_HAVE_MSG_NOSIGNAL 1
+#define GPR_HAVE_UNIX_SOCKET 1
+#define GPR_HAVE_IP_PKTINFO 1
+#define GPR_HAVE_IPV6_RECVPKTINFO 1
 #elif defined(__linux__)
 #define GPR_POSIX_CRASH_HANDLER 1
 #define GPR_PLATFORM_STRING "linux"
@@ -154,6 +157,9 @@
 #define GPR_POSIX_WAKEUP_FD 1
 #define GPR_POSIX_SOCKET 1
 #define GPR_POSIX_SOCKETADDR 1
+#define GPR_HAVE_UNIX_SOCKET 1
+#define GPR_HAVE_IP_PKTINFO 1
+#define GPR_HAVE_IPV6_RECVPKTINFO 1
 #ifdef __GLIBC_PREREQ
 #if __GLIBC_PREREQ(2, 9)
 #define GPR_LINUX_EVENTFD 1
@@ -214,6 +220,8 @@
 #define GPR_POSIX_TIME 1
 #define GPR_GETPID_IN_UNISTD_H 1
 #define GPR_HAVE_SO_NOSIGPIPE 1
+#define GPR_HAVE_UNIX_SOCKET 1
+#define GPR_HAVE_IP_PKTINFO 1
 #ifdef _LP64
 #define GPR_ARCH_64 1
 #else /* _LP64 */
@@ -242,6 +250,9 @@
 #define GPR_POSIX_TIME 1
 #define GPR_GETPID_IN_UNISTD_H 1
 #define GPR_HAVE_SO_NOSIGPIPE 1
+#define GPR_HAVE_UNIX_SOCKET 1
+#define GPR_HAVE_IP_PKTINFO 1
+#define GPR_HAVE_IPV6_RECVPKTINFO 1
 #ifdef _LP64
 #define GPR_ARCH_64 1
 #else /* _LP64 */
diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h
index a62fdd0..c684b75 100644
--- a/include/grpc/impl/codegen/slice.h
+++ b/include/grpc/impl/codegen/slice.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -122,8 +122,8 @@
 
 /* Equivalent to gpr_slice_new, but with a two argument destroy function that
    also takes the slice length. */
-GPRAPI gpr_slice
-gpr_slice_new_with_len(void *p, size_t len, void (*destroy)(void *, size_t));
+GPRAPI gpr_slice gpr_slice_new_with_len(void *p, size_t len,
+                                        void (*destroy)(void *, size_t));
 
 /* Equivalent to gpr_slice_new(malloc(len), len, free), but saves one malloc()
    call.
diff --git a/include/grpc/impl/codegen/slice_buffer.h b/include/grpc/impl/codegen/slice_buffer.h
index 4fe909e..8ca51ba 100644
--- a/include/grpc/impl/codegen/slice_buffer.h
+++ b/include/grpc/impl/codegen/slice_buffer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -73,8 +73,8 @@
    slice at the returned index in sb->slices)
    The implementation MAY decide to concatenate data at the end of a small
    slice added in this fashion. */
-GPRAPI size_t
-gpr_slice_buffer_add_indexed(gpr_slice_buffer *sb, gpr_slice slice);
+GPRAPI size_t gpr_slice_buffer_add_indexed(gpr_slice_buffer *sb,
+                                           gpr_slice slice);
 GPRAPI void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *slices,
                                   size_t n);
 /* add a very small (less than 8 bytes) amount of data to the end of a slice
diff --git a/include/grpc/impl/codegen/status.h b/include/grpc/impl/codegen/status.h
index 814bb4c..29e4570 100644
--- a/include/grpc/impl/codegen/status.h
+++ b/include/grpc/impl/codegen/status.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/sync_generic.h b/include/grpc/impl/codegen/sync_generic.h
index 71443b5..75e85ae 100644
--- a/include/grpc/impl/codegen/sync_generic.h
+++ b/include/grpc/impl/codegen/sync_generic.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/sync_posix.h b/include/grpc/impl/codegen/sync_posix.h
index f6e0a91..3d08cc3 100644
--- a/include/grpc/impl/codegen/sync_posix.h
+++ b/include/grpc/impl/codegen/sync_posix.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/sync_win32.h b/include/grpc/impl/codegen/sync_win32.h
index 1a6596c..bdc43dd 100644
--- a/include/grpc/impl/codegen/sync_win32.h
+++ b/include/grpc/impl/codegen/sync_win32.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/impl/codegen/time.h b/include/grpc/impl/codegen/time.h
index c22bedf..381e267 100644
--- a/include/grpc/impl/codegen/time.h
+++ b/include/grpc/impl/codegen/time.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -88,8 +88,8 @@
 GPRAPI gpr_timespec gpr_now(gpr_clock_type clock);
 
 /* Convert a timespec from one clock to another */
-GPRAPI gpr_timespec
-gpr_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock);
+GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t,
+                                           gpr_clock_type target_clock);
 
 /* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b
    respectively.  */
diff --git a/include/grpc/status.h b/include/grpc/status.h
index 3889a16..67719b5 100644
--- a/include/grpc/status.h
+++ b/include/grpc/status.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/alloc.h b/include/grpc/support/alloc.h
index 649cb2b..8d03af8 100644
--- a/include/grpc/support/alloc.h
+++ b/include/grpc/support/alloc.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/atm.h b/include/grpc/support/atm.h
index 37975db..a52e2fb 100644
--- a/include/grpc/support/atm.h
+++ b/include/grpc/support/atm.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/atm_gcc_atomic.h b/include/grpc/support/atm_gcc_atomic.h
index 2fc8f60..ceda791 100644
--- a/include/grpc/support/atm_gcc_atomic.h
+++ b/include/grpc/support/atm_gcc_atomic.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/atm_gcc_sync.h b/include/grpc/support/atm_gcc_sync.h
index 4a61dbd..b996d4a 100644
--- a/include/grpc/support/atm_gcc_sync.h
+++ b/include/grpc/support/atm_gcc_sync.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/atm_win32.h b/include/grpc/support/atm_win32.h
index ebb6a67..13526d9 100644
--- a/include/grpc/support/atm_win32.h
+++ b/include/grpc/support/atm_win32.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/avl.h b/include/grpc/support/avl.h
index 2fe2d0b..d71592d 100644
--- a/include/grpc/support/avl.h
+++ b/include/grpc/support/avl.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/cmdline.h b/include/grpc/support/cmdline.h
index 55e2ffd..5b7bc82 100644
--- a/include/grpc/support/cmdline.h
+++ b/include/grpc/support/cmdline.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/cpu.h b/include/grpc/support/cpu.h
index 3ca83b5..6734feb 100644
--- a/include/grpc/support/cpu.h
+++ b/include/grpc/support/cpu.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/histogram.h b/include/grpc/support/histogram.h
index c34c8c8..c545038 100644
--- a/include/grpc/support/histogram.h
+++ b/include/grpc/support/histogram.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/host_port.h b/include/grpc/support/host_port.h
index 53cc917..1581954 100644
--- a/include/grpc/support/host_port.h
+++ b/include/grpc/support/host_port.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/log.h b/include/grpc/support/log.h
index e6f6dd9..3fdba04 100644
--- a/include/grpc/support/log.h
+++ b/include/grpc/support/log.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/log_win32.h b/include/grpc/support/log_win32.h
index 49c9ab0..e5c25e0 100644
--- a/include/grpc/support/log_win32.h
+++ b/include/grpc/support/log_win32.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h
index 6b14f8b..7465a0e 100644
--- a/include/grpc/support/port_platform.h
+++ b/include/grpc/support/port_platform.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/slice.h b/include/grpc/support/slice.h
index b3a73b2..b45db03 100644
--- a/include/grpc/support/slice.h
+++ b/include/grpc/support/slice.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/slice_buffer.h b/include/grpc/support/slice_buffer.h
index 7bee4dd..cf7a89f 100644
--- a/include/grpc/support/slice_buffer.h
+++ b/include/grpc/support/slice_buffer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/string_util.h b/include/grpc/support/string_util.h
index 6fc38cb..f981bc0 100644
--- a/include/grpc/support/string_util.h
+++ b/include/grpc/support/string_util.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,8 @@
 #ifndef GRPC_SUPPORT_STRING_UTIL_H
 #define GRPC_SUPPORT_STRING_UTIL_H
 
+#include <grpc/support/port_platform.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/grpc/support/subprocess.h b/include/grpc/support/subprocess.h
index e013b70..2baa43e 100644
--- a/include/grpc/support/subprocess.h
+++ b/include/grpc/support/subprocess.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/sync.h b/include/grpc/support/sync.h
index 89cc76f..a014580 100644
--- a/include/grpc/support/sync.h
+++ b/include/grpc/support/sync.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/sync_generic.h b/include/grpc/support/sync_generic.h
index 28e3ab6..d74b5d8 100644
--- a/include/grpc/support/sync_generic.h
+++ b/include/grpc/support/sync_generic.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/sync_posix.h b/include/grpc/support/sync_posix.h
index fa0324f..19aca03 100644
--- a/include/grpc/support/sync_posix.h
+++ b/include/grpc/support/sync_posix.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/sync_win32.h b/include/grpc/support/sync_win32.h
index bfbc99e..5631c52 100644
--- a/include/grpc/support/sync_win32.h
+++ b/include/grpc/support/sync_win32.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/thd.h b/include/grpc/support/thd.h
index abe57eb..0514288 100644
--- a/include/grpc/support/thd.h
+++ b/include/grpc/support/thd.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h
index 2c7f853..b3f2f8c 100644
--- a/include/grpc/support/time.h
+++ b/include/grpc/support/time.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/tls.h b/include/grpc/support/tls.h
index 0ff19bb..a45e1f0 100644
--- a/include/grpc/support/tls.h
+++ b/include/grpc/support/tls.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/tls_gcc.h b/include/grpc/support/tls_gcc.h
index 21269e4..a47275f 100644
--- a/include/grpc/support/tls_gcc.h
+++ b/include/grpc/support/tls_gcc.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/tls_msvc.h b/include/grpc/support/tls_msvc.h
index 751ec35..efc653b 100644
--- a/include/grpc/support/tls_msvc.h
+++ b/include/grpc/support/tls_msvc.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/tls_pthread.h b/include/grpc/support/tls_pthread.h
index 93ba782..e681da2 100644
--- a/include/grpc/support/tls_pthread.h
+++ b/include/grpc/support/tls_pthread.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/grpc/support/useful.h b/include/grpc/support/useful.h
index a0e76da..003e096 100644
--- a/include/grpc/support/useful.h
+++ b/include/grpc/support/useful.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/package.json b/package.json
index 371dfdc..5ed7f36 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
     "lib": "src/node/src"
   },
   "scripts": {
-    "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js",
+    "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js --exclude-path=src/node/.jshintignore",
     "test": "./node_modules/.bin/mocha src/node/test && npm run-script lint",
     "gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json",
     "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test",
@@ -27,6 +27,7 @@
   },
   "bundledDependencies": ["node-pre-gyp"],
   "dependencies": {
+    "arguejs": "^0.2.3",
     "lodash": "^3.9.3",
     "nan": "^2.0.0",
     "protobufjs": "^4.0.0"
@@ -34,6 +35,7 @@
   "devDependencies": {
     "async": "^1.5.0",
     "google-auth-library": "^0.9.2",
+    "google-protobuf": "^3.0.0-alpha.5",
     "istanbul": "^0.3.21",
     "jsdoc": "^3.3.2",
     "jshint": "^2.5.0",
@@ -60,876 +62,36 @@
     "src/node/health_check",
     "src/proto",
     "etc",
-    "src/node/ext/byte_buffer.h",
-    "src/node/ext/call.h",
-    "src/node/ext/call_credentials.h",
-    "src/node/ext/channel.h",
-    "src/node/ext/channel_credentials.h",
-    "src/node/ext/completion_queue_async_worker.h",
-    "src/node/ext/server.h",
-    "src/node/ext/server_credentials.h",
-    "src/node/ext/timeval.h",
-    "src/node/ext/byte_buffer.cc",
-    "src/node/ext/call.cc",
-    "src/node/ext/call_credentials.cc",
-    "src/node/ext/channel.cc",
-    "src/node/ext/channel_credentials.cc",
-    "src/node/ext/completion_queue_async_worker.cc",
-    "src/node/ext/node_grpc.cc",
-    "src/node/ext/server.cc",
-    "src/node/ext/server_credentials.cc",
-    "src/node/ext/timeval.cc",
     "src/node/index.js",
-    "src/node/src/client.js",
-    "src/node/src/common.js",
-    "src/node/src/credentials.js",
-    "src/node/src/grpc_extension.js",
-    "src/node/src/metadata.js",
-    "src/node/src/server.js",
-    "include/grpc/grpc_security.h",
-    "include/grpc/byte_buffer.h",
-    "include/grpc/byte_buffer_reader.h",
-    "include/grpc/compression.h",
-    "include/grpc/grpc.h",
-    "include/grpc/status.h",
-    "include/grpc/impl/codegen/byte_buffer.h",
-    "include/grpc/impl/codegen/compression_types.h",
-    "include/grpc/impl/codegen/connectivity_state.h",
-    "include/grpc/impl/codegen/grpc_types.h",
-    "include/grpc/impl/codegen/propagation_bits.h",
-    "include/grpc/impl/codegen/status.h",
-    "include/grpc/census.h",
-    "src/core/census/grpc_filter.h",
-    "src/core/census/grpc_plugin.h",
-    "src/core/channel/channel_args.h",
-    "src/core/channel/channel_stack.h",
-    "src/core/channel/channel_stack_builder.h",
-    "src/core/channel/client_channel.h",
-    "src/core/channel/client_uchannel.h",
-    "src/core/channel/compress_filter.h",
-    "src/core/channel/connected_channel.h",
-    "src/core/channel/context.h",
-    "src/core/channel/http_client_filter.h",
-    "src/core/channel/http_server_filter.h",
-    "src/core/channel/subchannel_call_holder.h",
-    "src/core/client_config/client_config.h",
-    "src/core/client_config/connector.h",
-    "src/core/client_config/initial_connect_string.h",
-    "src/core/client_config/lb_policies/load_balancer_api.h",
-    "src/core/client_config/lb_policies/pick_first.h",
-    "src/core/client_config/lb_policies/round_robin.h",
-    "src/core/client_config/lb_policy.h",
-    "src/core/client_config/lb_policy_factory.h",
-    "src/core/client_config/lb_policy_registry.h",
-    "src/core/client_config/resolver.h",
-    "src/core/client_config/resolver_factory.h",
-    "src/core/client_config/resolver_registry.h",
-    "src/core/client_config/resolvers/dns_resolver.h",
-    "src/core/client_config/resolvers/sockaddr_resolver.h",
-    "src/core/client_config/subchannel.h",
-    "src/core/client_config/subchannel_factory.h",
-    "src/core/client_config/subchannel_index.h",
-    "src/core/client_config/uri_parser.h",
-    "src/core/compression/algorithm_metadata.h",
-    "src/core/compression/message_compress.h",
-    "src/core/debug/trace.h",
-    "src/core/httpcli/format_request.h",
-    "src/core/httpcli/httpcli.h",
-    "src/core/httpcli/parser.h",
-    "src/core/iomgr/closure.h",
-    "src/core/iomgr/endpoint.h",
-    "src/core/iomgr/endpoint_pair.h",
-    "src/core/iomgr/exec_ctx.h",
-    "src/core/iomgr/executor.h",
-    "src/core/iomgr/fd_posix.h",
-    "src/core/iomgr/iocp_windows.h",
-    "src/core/iomgr/iomgr.h",
-    "src/core/iomgr/iomgr_internal.h",
-    "src/core/iomgr/iomgr_posix.h",
-    "src/core/iomgr/pollset.h",
-    "src/core/iomgr/pollset_posix.h",
-    "src/core/iomgr/pollset_set.h",
-    "src/core/iomgr/pollset_set_posix.h",
-    "src/core/iomgr/pollset_set_windows.h",
-    "src/core/iomgr/pollset_windows.h",
-    "src/core/iomgr/resolve_address.h",
-    "src/core/iomgr/sockaddr.h",
-    "src/core/iomgr/sockaddr_posix.h",
-    "src/core/iomgr/sockaddr_utils.h",
-    "src/core/iomgr/sockaddr_win32.h",
-    "src/core/iomgr/socket_utils_posix.h",
-    "src/core/iomgr/socket_windows.h",
-    "src/core/iomgr/tcp_client.h",
-    "src/core/iomgr/tcp_posix.h",
-    "src/core/iomgr/tcp_server.h",
-    "src/core/iomgr/tcp_windows.h",
-    "src/core/iomgr/time_averaged_stats.h",
-    "src/core/iomgr/timer.h",
-    "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/udp_server.h",
-    "src/core/iomgr/wakeup_fd_pipe.h",
-    "src/core/iomgr/wakeup_fd_posix.h",
-    "src/core/iomgr/workqueue.h",
-    "src/core/iomgr/workqueue_posix.h",
-    "src/core/iomgr/workqueue_windows.h",
-    "src/core/json/json.h",
-    "src/core/json/json_common.h",
-    "src/core/json/json_reader.h",
-    "src/core/json/json_writer.h",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
-    "src/core/statistics/census_interface.h",
-    "src/core/statistics/census_rpc_stats.h",
-    "src/core/surface/api_trace.h",
-    "src/core/surface/call.h",
-    "src/core/surface/call_test_only.h",
-    "src/core/surface/channel.h",
-    "src/core/surface/channel_init.h",
-    "src/core/surface/channel_stack_type.h",
-    "src/core/surface/completion_queue.h",
-    "src/core/surface/event_string.h",
-    "src/core/surface/init.h",
-    "src/core/surface/lame_client.h",
-    "src/core/surface/server.h",
-    "src/core/surface/surface_trace.h",
-    "src/core/transport/byte_stream.h",
-    "src/core/transport/chttp2/alpn.h",
-    "src/core/transport/chttp2/bin_encoder.h",
-    "src/core/transport/chttp2/frame.h",
-    "src/core/transport/chttp2/frame_data.h",
-    "src/core/transport/chttp2/frame_goaway.h",
-    "src/core/transport/chttp2/frame_ping.h",
-    "src/core/transport/chttp2/frame_rst_stream.h",
-    "src/core/transport/chttp2/frame_settings.h",
-    "src/core/transport/chttp2/frame_window_update.h",
-    "src/core/transport/chttp2/hpack_encoder.h",
-    "src/core/transport/chttp2/hpack_parser.h",
-    "src/core/transport/chttp2/hpack_table.h",
-    "src/core/transport/chttp2/http2_errors.h",
-    "src/core/transport/chttp2/huffsyms.h",
-    "src/core/transport/chttp2/incoming_metadata.h",
-    "src/core/transport/chttp2/internal.h",
-    "src/core/transport/chttp2/status_conversion.h",
-    "src/core/transport/chttp2/stream_map.h",
-    "src/core/transport/chttp2/timeout_encoding.h",
-    "src/core/transport/chttp2/varint.h",
-    "src/core/transport/chttp2_transport.h",
-    "src/core/transport/connectivity_state.h",
-    "src/core/transport/metadata.h",
-    "src/core/transport/metadata_batch.h",
-    "src/core/transport/static_metadata.h",
-    "src/core/transport/transport.h",
-    "src/core/transport/transport_impl.h",
-    "src/core/security/auth_filters.h",
-    "src/core/security/b64.h",
-    "src/core/security/credentials.h",
-    "src/core/security/handshake.h",
-    "src/core/security/json_token.h",
-    "src/core/security/jwt_verifier.h",
-    "src/core/security/secure_endpoint.h",
-    "src/core/security/security_connector.h",
-    "src/core/security/security_context.h",
-    "src/core/tsi/fake_transport_security.h",
-    "src/core/tsi/ssl_transport_security.h",
-    "src/core/tsi/ssl_types.h",
-    "src/core/tsi/transport_security.h",
-    "src/core/tsi/transport_security_interface.h",
-    "src/core/census/aggregation.h",
-    "src/core/census/mlog.h",
-    "src/core/census/rpc_metric_id.h",
-    "third_party/nanopb/pb.h",
-    "third_party/nanopb/pb_common.h",
-    "third_party/nanopb/pb_decode.h",
-    "third_party/nanopb/pb_encode.h",
-    "src/core/census/grpc_context.c",
-    "src/core/census/grpc_filter.c",
-    "src/core/census/grpc_plugin.c",
-    "src/core/channel/channel_args.c",
-    "src/core/channel/channel_stack.c",
-    "src/core/channel/channel_stack_builder.c",
-    "src/core/channel/client_channel.c",
-    "src/core/channel/client_uchannel.c",
-    "src/core/channel/compress_filter.c",
-    "src/core/channel/connected_channel.c",
-    "src/core/channel/http_client_filter.c",
-    "src/core/channel/http_server_filter.c",
-    "src/core/channel/subchannel_call_holder.c",
-    "src/core/client_config/client_config.c",
-    "src/core/client_config/connector.c",
-    "src/core/client_config/default_initial_connect_string.c",
-    "src/core/client_config/initial_connect_string.c",
-    "src/core/client_config/lb_policies/load_balancer_api.c",
-    "src/core/client_config/lb_policies/pick_first.c",
-    "src/core/client_config/lb_policies/round_robin.c",
-    "src/core/client_config/lb_policy.c",
-    "src/core/client_config/lb_policy_factory.c",
-    "src/core/client_config/lb_policy_registry.c",
-    "src/core/client_config/resolver.c",
-    "src/core/client_config/resolver_factory.c",
-    "src/core/client_config/resolver_registry.c",
-    "src/core/client_config/resolvers/dns_resolver.c",
-    "src/core/client_config/resolvers/sockaddr_resolver.c",
-    "src/core/client_config/subchannel.c",
-    "src/core/client_config/subchannel_factory.c",
-    "src/core/client_config/subchannel_index.c",
-    "src/core/client_config/uri_parser.c",
-    "src/core/compression/compression_algorithm.c",
-    "src/core/compression/message_compress.c",
-    "src/core/debug/trace.c",
-    "src/core/httpcli/format_request.c",
-    "src/core/httpcli/httpcli.c",
-    "src/core/httpcli/parser.c",
-    "src/core/iomgr/closure.c",
-    "src/core/iomgr/endpoint.c",
-    "src/core/iomgr/endpoint_pair_posix.c",
-    "src/core/iomgr/endpoint_pair_windows.c",
-    "src/core/iomgr/exec_ctx.c",
-    "src/core/iomgr/executor.c",
-    "src/core/iomgr/fd_posix.c",
-    "src/core/iomgr/iocp_windows.c",
-    "src/core/iomgr/iomgr.c",
-    "src/core/iomgr/iomgr_posix.c",
-    "src/core/iomgr/iomgr_windows.c",
-    "src/core/iomgr/pollset_multipoller_with_epoll.c",
-    "src/core/iomgr/pollset_multipoller_with_poll_posix.c",
-    "src/core/iomgr/pollset_posix.c",
-    "src/core/iomgr/pollset_set_posix.c",
-    "src/core/iomgr/pollset_set_windows.c",
-    "src/core/iomgr/pollset_windows.c",
-    "src/core/iomgr/resolve_address_posix.c",
-    "src/core/iomgr/resolve_address_windows.c",
-    "src/core/iomgr/sockaddr_utils.c",
-    "src/core/iomgr/socket_utils_common_posix.c",
-    "src/core/iomgr/socket_utils_linux.c",
-    "src/core/iomgr/socket_utils_posix.c",
-    "src/core/iomgr/socket_windows.c",
-    "src/core/iomgr/tcp_client_posix.c",
-    "src/core/iomgr/tcp_client_windows.c",
-    "src/core/iomgr/tcp_posix.c",
-    "src/core/iomgr/tcp_server_posix.c",
-    "src/core/iomgr/tcp_server_windows.c",
-    "src/core/iomgr/tcp_windows.c",
-    "src/core/iomgr/time_averaged_stats.c",
-    "src/core/iomgr/timer.c",
-    "src/core/iomgr/timer_heap.c",
-    "src/core/iomgr/udp_server.c",
-    "src/core/iomgr/wakeup_fd_eventfd.c",
-    "src/core/iomgr/wakeup_fd_nospecial.c",
-    "src/core/iomgr/wakeup_fd_pipe.c",
-    "src/core/iomgr/wakeup_fd_posix.c",
-    "src/core/iomgr/workqueue_posix.c",
-    "src/core/iomgr/workqueue_windows.c",
-    "src/core/json/json.c",
-    "src/core/json/json_reader.c",
-    "src/core/json/json_string.c",
-    "src/core/json/json_writer.c",
-    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
-    "src/core/surface/alarm.c",
-    "src/core/surface/api_trace.c",
-    "src/core/surface/byte_buffer.c",
-    "src/core/surface/byte_buffer_reader.c",
-    "src/core/surface/call.c",
-    "src/core/surface/call_details.c",
-    "src/core/surface/call_log_batch.c",
-    "src/core/surface/channel.c",
-    "src/core/surface/channel_connectivity.c",
-    "src/core/surface/channel_create.c",
-    "src/core/surface/channel_init.c",
-    "src/core/surface/channel_ping.c",
-    "src/core/surface/channel_stack_type.c",
-    "src/core/surface/completion_queue.c",
-    "src/core/surface/event_string.c",
-    "src/core/surface/init.c",
-    "src/core/surface/lame_client.c",
-    "src/core/surface/metadata_array.c",
-    "src/core/surface/server.c",
-    "src/core/surface/server_chttp2.c",
-    "src/core/surface/validate_metadata.c",
-    "src/core/surface/version.c",
-    "src/core/transport/byte_stream.c",
-    "src/core/transport/chttp2/alpn.c",
-    "src/core/transport/chttp2/bin_encoder.c",
-    "src/core/transport/chttp2/frame_data.c",
-    "src/core/transport/chttp2/frame_goaway.c",
-    "src/core/transport/chttp2/frame_ping.c",
-    "src/core/transport/chttp2/frame_rst_stream.c",
-    "src/core/transport/chttp2/frame_settings.c",
-    "src/core/transport/chttp2/frame_window_update.c",
-    "src/core/transport/chttp2/hpack_encoder.c",
-    "src/core/transport/chttp2/hpack_parser.c",
-    "src/core/transport/chttp2/hpack_table.c",
-    "src/core/transport/chttp2/huffsyms.c",
-    "src/core/transport/chttp2/incoming_metadata.c",
-    "src/core/transport/chttp2/parsing.c",
-    "src/core/transport/chttp2/status_conversion.c",
-    "src/core/transport/chttp2/stream_lists.c",
-    "src/core/transport/chttp2/stream_map.c",
-    "src/core/transport/chttp2/timeout_encoding.c",
-    "src/core/transport/chttp2/varint.c",
-    "src/core/transport/chttp2/writing.c",
-    "src/core/transport/chttp2_transport.c",
-    "src/core/transport/connectivity_state.c",
-    "src/core/transport/metadata.c",
-    "src/core/transport/metadata_batch.c",
-    "src/core/transport/static_metadata.c",
-    "src/core/transport/transport.c",
-    "src/core/transport/transport_op_string.c",
-    "src/core/httpcli/httpcli_security_connector.c",
-    "src/core/security/b64.c",
-    "src/core/security/client_auth_filter.c",
-    "src/core/security/credentials.c",
-    "src/core/security/credentials_metadata.c",
-    "src/core/security/credentials_posix.c",
-    "src/core/security/credentials_win32.c",
-    "src/core/security/google_default_credentials.c",
-    "src/core/security/handshake.c",
-    "src/core/security/json_token.c",
-    "src/core/security/jwt_verifier.c",
-    "src/core/security/secure_endpoint.c",
-    "src/core/security/security_connector.c",
-    "src/core/security/security_context.c",
-    "src/core/security/server_auth_filter.c",
-    "src/core/security/server_secure_chttp2.c",
-    "src/core/surface/init_secure.c",
-    "src/core/surface/secure_channel_create.c",
-    "src/core/tsi/fake_transport_security.c",
-    "src/core/tsi/ssl_transport_security.c",
-    "src/core/tsi/transport_security.c",
-    "src/core/census/context.c",
-    "src/core/census/initialize.c",
-    "src/core/census/mlog.c",
-    "src/core/census/operation.c",
-    "src/core/census/placeholders.c",
-    "src/core/census/tracing.c",
-    "third_party/nanopb/pb_common.c",
-    "third_party/nanopb/pb_decode.c",
-    "third_party/nanopb/pb_encode.c",
-    "third_party/zlib/crc32.h",
-    "third_party/zlib/deflate.h",
-    "third_party/zlib/gzguts.h",
-    "third_party/zlib/inffast.h",
-    "third_party/zlib/inffixed.h",
-    "third_party/zlib/inflate.h",
-    "third_party/zlib/inftrees.h",
-    "third_party/zlib/trees.h",
-    "third_party/zlib/zconf.h",
-    "third_party/zlib/zlib.h",
-    "third_party/zlib/zutil.h",
-    "third_party/zlib/adler32.c",
-    "third_party/zlib/compress.c",
-    "third_party/zlib/crc32.c",
-    "third_party/zlib/deflate.c",
-    "third_party/zlib/gzclose.c",
-    "third_party/zlib/gzlib.c",
-    "third_party/zlib/gzread.c",
-    "third_party/zlib/gzwrite.c",
-    "third_party/zlib/infback.c",
-    "third_party/zlib/inffast.c",
-    "third_party/zlib/inflate.c",
-    "third_party/zlib/inftrees.c",
-    "third_party/zlib/trees.c",
-    "third_party/zlib/uncompr.c",
-    "third_party/zlib/zutil.c",
-    "third_party/boringssl/crypto/aes/internal.h",
-    "third_party/boringssl/crypto/asn1/asn1_locl.h",
-    "third_party/boringssl/crypto/bio/internal.h",
-    "third_party/boringssl/crypto/bn/internal.h",
-    "third_party/boringssl/crypto/bn/rsaz_exp.h",
-    "third_party/boringssl/crypto/bytestring/internal.h",
-    "third_party/boringssl/crypto/cipher/internal.h",
-    "third_party/boringssl/crypto/conf/conf_def.h",
-    "third_party/boringssl/crypto/conf/internal.h",
-    "third_party/boringssl/crypto/des/internal.h",
-    "third_party/boringssl/crypto/dh/internal.h",
-    "third_party/boringssl/crypto/digest/internal.h",
-    "third_party/boringssl/crypto/digest/md32_common.h",
-    "third_party/boringssl/crypto/directory.h",
-    "third_party/boringssl/crypto/dsa/internal.h",
-    "third_party/boringssl/crypto/ec/internal.h",
-    "third_party/boringssl/crypto/ec/p256-x86_64-table.h",
-    "third_party/boringssl/crypto/evp/internal.h",
-    "third_party/boringssl/crypto/internal.h",
-    "third_party/boringssl/crypto/modes/internal.h",
-    "third_party/boringssl/crypto/obj/obj_dat.h",
-    "third_party/boringssl/crypto/obj/obj_xref.h",
-    "third_party/boringssl/crypto/pkcs8/internal.h",
-    "third_party/boringssl/crypto/rand/internal.h",
-    "third_party/boringssl/crypto/rsa/internal.h",
-    "third_party/boringssl/crypto/test/scoped_types.h",
-    "third_party/boringssl/crypto/test/test_util.h",
-    "third_party/boringssl/crypto/x509/charmap.h",
-    "third_party/boringssl/crypto/x509/vpm_int.h",
-    "third_party/boringssl/crypto/x509v3/ext_dat.h",
-    "third_party/boringssl/crypto/x509v3/pcy_int.h",
-    "third_party/boringssl/include/openssl/aead.h",
-    "third_party/boringssl/include/openssl/aes.h",
-    "third_party/boringssl/include/openssl/arm_arch.h",
-    "third_party/boringssl/include/openssl/asn1.h",
-    "third_party/boringssl/include/openssl/asn1_mac.h",
-    "third_party/boringssl/include/openssl/asn1t.h",
-    "third_party/boringssl/include/openssl/base.h",
-    "third_party/boringssl/include/openssl/base64.h",
-    "third_party/boringssl/include/openssl/bio.h",
-    "third_party/boringssl/include/openssl/blowfish.h",
-    "third_party/boringssl/include/openssl/bn.h",
-    "third_party/boringssl/include/openssl/buf.h",
-    "third_party/boringssl/include/openssl/buffer.h",
-    "third_party/boringssl/include/openssl/bytestring.h",
-    "third_party/boringssl/include/openssl/cast.h",
-    "third_party/boringssl/include/openssl/chacha.h",
-    "third_party/boringssl/include/openssl/cipher.h",
-    "third_party/boringssl/include/openssl/cmac.h",
-    "third_party/boringssl/include/openssl/conf.h",
-    "third_party/boringssl/include/openssl/cpu.h",
-    "third_party/boringssl/include/openssl/crypto.h",
-    "third_party/boringssl/include/openssl/curve25519.h",
-    "third_party/boringssl/include/openssl/des.h",
-    "third_party/boringssl/include/openssl/dh.h",
-    "third_party/boringssl/include/openssl/digest.h",
-    "third_party/boringssl/include/openssl/dsa.h",
-    "third_party/boringssl/include/openssl/dtls1.h",
-    "third_party/boringssl/include/openssl/ec.h",
-    "third_party/boringssl/include/openssl/ec_key.h",
-    "third_party/boringssl/include/openssl/ecdh.h",
-    "third_party/boringssl/include/openssl/ecdsa.h",
-    "third_party/boringssl/include/openssl/engine.h",
-    "third_party/boringssl/include/openssl/err.h",
-    "third_party/boringssl/include/openssl/evp.h",
-    "third_party/boringssl/include/openssl/ex_data.h",
-    "third_party/boringssl/include/openssl/hkdf.h",
-    "third_party/boringssl/include/openssl/hmac.h",
-    "third_party/boringssl/include/openssl/lhash.h",
-    "third_party/boringssl/include/openssl/lhash_macros.h",
-    "third_party/boringssl/include/openssl/md4.h",
-    "third_party/boringssl/include/openssl/md5.h",
-    "third_party/boringssl/include/openssl/mem.h",
-    "third_party/boringssl/include/openssl/obj.h",
-    "third_party/boringssl/include/openssl/obj_mac.h",
-    "third_party/boringssl/include/openssl/objects.h",
-    "third_party/boringssl/include/openssl/opensslfeatures.h",
-    "third_party/boringssl/include/openssl/opensslv.h",
-    "third_party/boringssl/include/openssl/ossl_typ.h",
-    "third_party/boringssl/include/openssl/pem.h",
-    "third_party/boringssl/include/openssl/pkcs12.h",
-    "third_party/boringssl/include/openssl/pkcs7.h",
-    "third_party/boringssl/include/openssl/pkcs8.h",
-    "third_party/boringssl/include/openssl/poly1305.h",
-    "third_party/boringssl/include/openssl/pqueue.h",
-    "third_party/boringssl/include/openssl/rand.h",
-    "third_party/boringssl/include/openssl/rc4.h",
-    "third_party/boringssl/include/openssl/rsa.h",
-    "third_party/boringssl/include/openssl/safestack.h",
-    "third_party/boringssl/include/openssl/sha.h",
-    "third_party/boringssl/include/openssl/srtp.h",
-    "third_party/boringssl/include/openssl/ssl.h",
-    "third_party/boringssl/include/openssl/ssl3.h",
-    "third_party/boringssl/include/openssl/stack.h",
-    "third_party/boringssl/include/openssl/stack_macros.h",
-    "third_party/boringssl/include/openssl/thread.h",
-    "third_party/boringssl/include/openssl/time_support.h",
-    "third_party/boringssl/include/openssl/tls1.h",
-    "third_party/boringssl/include/openssl/type_check.h",
-    "third_party/boringssl/include/openssl/x509.h",
-    "third_party/boringssl/include/openssl/x509_vfy.h",
-    "third_party/boringssl/include/openssl/x509v3.h",
-    "third_party/boringssl/ssl/internal.h",
-    "third_party/boringssl/ssl/test/async_bio.h",
-    "third_party/boringssl/ssl/test/packeted_bio.h",
-    "third_party/boringssl/ssl/test/scoped_types.h",
-    "third_party/boringssl/ssl/test/test_config.h",
-    "src/boringssl/err_data.c",
-    "third_party/boringssl/crypto/aes/aes.c",
-    "third_party/boringssl/crypto/aes/mode_wrappers.c",
-    "third_party/boringssl/crypto/asn1/a_bitstr.c",
-    "third_party/boringssl/crypto/asn1/a_bool.c",
-    "third_party/boringssl/crypto/asn1/a_bytes.c",
-    "third_party/boringssl/crypto/asn1/a_d2i_fp.c",
-    "third_party/boringssl/crypto/asn1/a_dup.c",
-    "third_party/boringssl/crypto/asn1/a_enum.c",
-    "third_party/boringssl/crypto/asn1/a_gentm.c",
-    "third_party/boringssl/crypto/asn1/a_i2d_fp.c",
-    "third_party/boringssl/crypto/asn1/a_int.c",
-    "third_party/boringssl/crypto/asn1/a_mbstr.c",
-    "third_party/boringssl/crypto/asn1/a_object.c",
-    "third_party/boringssl/crypto/asn1/a_octet.c",
-    "third_party/boringssl/crypto/asn1/a_print.c",
-    "third_party/boringssl/crypto/asn1/a_strnid.c",
-    "third_party/boringssl/crypto/asn1/a_time.c",
-    "third_party/boringssl/crypto/asn1/a_type.c",
-    "third_party/boringssl/crypto/asn1/a_utctm.c",
-    "third_party/boringssl/crypto/asn1/a_utf8.c",
-    "third_party/boringssl/crypto/asn1/asn1_lib.c",
-    "third_party/boringssl/crypto/asn1/asn1_par.c",
-    "third_party/boringssl/crypto/asn1/asn_pack.c",
-    "third_party/boringssl/crypto/asn1/bio_asn1.c",
-    "third_party/boringssl/crypto/asn1/bio_ndef.c",
-    "third_party/boringssl/crypto/asn1/f_enum.c",
-    "third_party/boringssl/crypto/asn1/f_int.c",
-    "third_party/boringssl/crypto/asn1/f_string.c",
-    "third_party/boringssl/crypto/asn1/t_bitst.c",
-    "third_party/boringssl/crypto/asn1/t_pkey.c",
-    "third_party/boringssl/crypto/asn1/tasn_dec.c",
-    "third_party/boringssl/crypto/asn1/tasn_enc.c",
-    "third_party/boringssl/crypto/asn1/tasn_fre.c",
-    "third_party/boringssl/crypto/asn1/tasn_new.c",
-    "third_party/boringssl/crypto/asn1/tasn_prn.c",
-    "third_party/boringssl/crypto/asn1/tasn_typ.c",
-    "third_party/boringssl/crypto/asn1/tasn_utl.c",
-    "third_party/boringssl/crypto/asn1/x_bignum.c",
-    "third_party/boringssl/crypto/asn1/x_long.c",
-    "third_party/boringssl/crypto/base64/base64.c",
-    "third_party/boringssl/crypto/bio/bio.c",
-    "third_party/boringssl/crypto/bio/bio_mem.c",
-    "third_party/boringssl/crypto/bio/buffer.c",
-    "third_party/boringssl/crypto/bio/connect.c",
-    "third_party/boringssl/crypto/bio/fd.c",
-    "third_party/boringssl/crypto/bio/file.c",
-    "third_party/boringssl/crypto/bio/hexdump.c",
-    "third_party/boringssl/crypto/bio/pair.c",
-    "third_party/boringssl/crypto/bio/printf.c",
-    "third_party/boringssl/crypto/bio/socket.c",
-    "third_party/boringssl/crypto/bio/socket_helper.c",
-    "third_party/boringssl/crypto/bn/add.c",
-    "third_party/boringssl/crypto/bn/asm/x86_64-gcc.c",
-    "third_party/boringssl/crypto/bn/bn.c",
-    "third_party/boringssl/crypto/bn/bn_asn1.c",
-    "third_party/boringssl/crypto/bn/cmp.c",
-    "third_party/boringssl/crypto/bn/convert.c",
-    "third_party/boringssl/crypto/bn/ctx.c",
-    "third_party/boringssl/crypto/bn/div.c",
-    "third_party/boringssl/crypto/bn/exponentiation.c",
-    "third_party/boringssl/crypto/bn/gcd.c",
-    "third_party/boringssl/crypto/bn/generic.c",
-    "third_party/boringssl/crypto/bn/kronecker.c",
-    "third_party/boringssl/crypto/bn/montgomery.c",
-    "third_party/boringssl/crypto/bn/mul.c",
-    "third_party/boringssl/crypto/bn/prime.c",
-    "third_party/boringssl/crypto/bn/random.c",
-    "third_party/boringssl/crypto/bn/rsaz_exp.c",
-    "third_party/boringssl/crypto/bn/shift.c",
-    "third_party/boringssl/crypto/bn/sqrt.c",
-    "third_party/boringssl/crypto/buf/buf.c",
-    "third_party/boringssl/crypto/bytestring/ber.c",
-    "third_party/boringssl/crypto/bytestring/cbb.c",
-    "third_party/boringssl/crypto/bytestring/cbs.c",
-    "third_party/boringssl/crypto/chacha/chacha_generic.c",
-    "third_party/boringssl/crypto/chacha/chacha_vec.c",
-    "third_party/boringssl/crypto/cipher/aead.c",
-    "third_party/boringssl/crypto/cipher/cipher.c",
-    "third_party/boringssl/crypto/cipher/derive_key.c",
-    "third_party/boringssl/crypto/cipher/e_aes.c",
-    "third_party/boringssl/crypto/cipher/e_chacha20poly1305.c",
-    "third_party/boringssl/crypto/cipher/e_des.c",
-    "third_party/boringssl/crypto/cipher/e_null.c",
-    "third_party/boringssl/crypto/cipher/e_rc2.c",
-    "third_party/boringssl/crypto/cipher/e_rc4.c",
-    "third_party/boringssl/crypto/cipher/e_ssl3.c",
-    "third_party/boringssl/crypto/cipher/e_tls.c",
-    "third_party/boringssl/crypto/cipher/tls_cbc.c",
-    "third_party/boringssl/crypto/cmac/cmac.c",
-    "third_party/boringssl/crypto/conf/conf.c",
-    "third_party/boringssl/crypto/cpu-arm.c",
-    "third_party/boringssl/crypto/cpu-intel.c",
-    "third_party/boringssl/crypto/crypto.c",
-    "third_party/boringssl/crypto/curve25519/curve25519.c",
-    "third_party/boringssl/crypto/des/des.c",
-    "third_party/boringssl/crypto/dh/check.c",
-    "third_party/boringssl/crypto/dh/dh.c",
-    "third_party/boringssl/crypto/dh/dh_asn1.c",
-    "third_party/boringssl/crypto/dh/params.c",
-    "third_party/boringssl/crypto/digest/digest.c",
-    "third_party/boringssl/crypto/digest/digests.c",
-    "third_party/boringssl/crypto/directory_posix.c",
-    "third_party/boringssl/crypto/directory_win.c",
-    "third_party/boringssl/crypto/dsa/dsa.c",
-    "third_party/boringssl/crypto/dsa/dsa_asn1.c",
-    "third_party/boringssl/crypto/ec/ec.c",
-    "third_party/boringssl/crypto/ec/ec_asn1.c",
-    "third_party/boringssl/crypto/ec/ec_key.c",
-    "third_party/boringssl/crypto/ec/ec_montgomery.c",
-    "third_party/boringssl/crypto/ec/oct.c",
-    "third_party/boringssl/crypto/ec/p224-64.c",
-    "third_party/boringssl/crypto/ec/p256-64.c",
-    "third_party/boringssl/crypto/ec/p256-x86_64.c",
-    "third_party/boringssl/crypto/ec/simple.c",
-    "third_party/boringssl/crypto/ec/util-64.c",
-    "third_party/boringssl/crypto/ec/wnaf.c",
-    "third_party/boringssl/crypto/ecdh/ecdh.c",
-    "third_party/boringssl/crypto/ecdsa/ecdsa.c",
-    "third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c",
-    "third_party/boringssl/crypto/engine/engine.c",
-    "third_party/boringssl/crypto/err/err.c",
-    "third_party/boringssl/crypto/evp/algorithm.c",
-    "third_party/boringssl/crypto/evp/digestsign.c",
-    "third_party/boringssl/crypto/evp/evp.c",
-    "third_party/boringssl/crypto/evp/evp_asn1.c",
-    "third_party/boringssl/crypto/evp/evp_ctx.c",
-    "third_party/boringssl/crypto/evp/p_dsa_asn1.c",
-    "third_party/boringssl/crypto/evp/p_ec.c",
-    "third_party/boringssl/crypto/evp/p_ec_asn1.c",
-    "third_party/boringssl/crypto/evp/p_rsa.c",
-    "third_party/boringssl/crypto/evp/p_rsa_asn1.c",
-    "third_party/boringssl/crypto/evp/pbkdf.c",
-    "third_party/boringssl/crypto/evp/sign.c",
-    "third_party/boringssl/crypto/ex_data.c",
-    "third_party/boringssl/crypto/hkdf/hkdf.c",
-    "third_party/boringssl/crypto/hmac/hmac.c",
-    "third_party/boringssl/crypto/lhash/lhash.c",
-    "third_party/boringssl/crypto/md4/md4.c",
-    "third_party/boringssl/crypto/md5/md5.c",
-    "third_party/boringssl/crypto/mem.c",
-    "third_party/boringssl/crypto/modes/cbc.c",
-    "third_party/boringssl/crypto/modes/cfb.c",
-    "third_party/boringssl/crypto/modes/ctr.c",
-    "third_party/boringssl/crypto/modes/gcm.c",
-    "third_party/boringssl/crypto/modes/ofb.c",
-    "third_party/boringssl/crypto/obj/obj.c",
-    "third_party/boringssl/crypto/obj/obj_xref.c",
-    "third_party/boringssl/crypto/pem/pem_all.c",
-    "third_party/boringssl/crypto/pem/pem_info.c",
-    "third_party/boringssl/crypto/pem/pem_lib.c",
-    "third_party/boringssl/crypto/pem/pem_oth.c",
-    "third_party/boringssl/crypto/pem/pem_pk8.c",
-    "third_party/boringssl/crypto/pem/pem_pkey.c",
-    "third_party/boringssl/crypto/pem/pem_x509.c",
-    "third_party/boringssl/crypto/pem/pem_xaux.c",
-    "third_party/boringssl/crypto/pkcs8/p5_pbe.c",
-    "third_party/boringssl/crypto/pkcs8/p5_pbev2.c",
-    "third_party/boringssl/crypto/pkcs8/p8_pkey.c",
-    "third_party/boringssl/crypto/pkcs8/pkcs8.c",
-    "third_party/boringssl/crypto/poly1305/poly1305.c",
-    "third_party/boringssl/crypto/poly1305/poly1305_arm.c",
-    "third_party/boringssl/crypto/poly1305/poly1305_vec.c",
-    "third_party/boringssl/crypto/rand/rand.c",
-    "third_party/boringssl/crypto/rand/urandom.c",
-    "third_party/boringssl/crypto/rand/windows.c",
-    "third_party/boringssl/crypto/rc4/rc4.c",
-    "third_party/boringssl/crypto/refcount_c11.c",
-    "third_party/boringssl/crypto/refcount_lock.c",
-    "third_party/boringssl/crypto/rsa/blinding.c",
-    "third_party/boringssl/crypto/rsa/padding.c",
-    "third_party/boringssl/crypto/rsa/rsa.c",
-    "third_party/boringssl/crypto/rsa/rsa_asn1.c",
-    "third_party/boringssl/crypto/rsa/rsa_impl.c",
-    "third_party/boringssl/crypto/sha/sha1.c",
-    "third_party/boringssl/crypto/sha/sha256.c",
-    "third_party/boringssl/crypto/sha/sha512.c",
-    "third_party/boringssl/crypto/stack/stack.c",
-    "third_party/boringssl/crypto/thread.c",
-    "third_party/boringssl/crypto/thread_none.c",
-    "third_party/boringssl/crypto/thread_pthread.c",
-    "third_party/boringssl/crypto/thread_win.c",
-    "third_party/boringssl/crypto/time_support.c",
-    "third_party/boringssl/crypto/x509/a_digest.c",
-    "third_party/boringssl/crypto/x509/a_sign.c",
-    "third_party/boringssl/crypto/x509/a_strex.c",
-    "third_party/boringssl/crypto/x509/a_verify.c",
-    "third_party/boringssl/crypto/x509/asn1_gen.c",
-    "third_party/boringssl/crypto/x509/by_dir.c",
-    "third_party/boringssl/crypto/x509/by_file.c",
-    "third_party/boringssl/crypto/x509/i2d_pr.c",
-    "third_party/boringssl/crypto/x509/pkcs7.c",
-    "third_party/boringssl/crypto/x509/t_crl.c",
-    "third_party/boringssl/crypto/x509/t_req.c",
-    "third_party/boringssl/crypto/x509/t_x509.c",
-    "third_party/boringssl/crypto/x509/t_x509a.c",
-    "third_party/boringssl/crypto/x509/x509.c",
-    "third_party/boringssl/crypto/x509/x509_att.c",
-    "third_party/boringssl/crypto/x509/x509_cmp.c",
-    "third_party/boringssl/crypto/x509/x509_d2.c",
-    "third_party/boringssl/crypto/x509/x509_def.c",
-    "third_party/boringssl/crypto/x509/x509_ext.c",
-    "third_party/boringssl/crypto/x509/x509_lu.c",
-    "third_party/boringssl/crypto/x509/x509_obj.c",
-    "third_party/boringssl/crypto/x509/x509_r2x.c",
-    "third_party/boringssl/crypto/x509/x509_req.c",
-    "third_party/boringssl/crypto/x509/x509_set.c",
-    "third_party/boringssl/crypto/x509/x509_trs.c",
-    "third_party/boringssl/crypto/x509/x509_txt.c",
-    "third_party/boringssl/crypto/x509/x509_v3.c",
-    "third_party/boringssl/crypto/x509/x509_vfy.c",
-    "third_party/boringssl/crypto/x509/x509_vpm.c",
-    "third_party/boringssl/crypto/x509/x509cset.c",
-    "third_party/boringssl/crypto/x509/x509name.c",
-    "third_party/boringssl/crypto/x509/x509rset.c",
-    "third_party/boringssl/crypto/x509/x509spki.c",
-    "third_party/boringssl/crypto/x509/x509type.c",
-    "third_party/boringssl/crypto/x509/x_algor.c",
-    "third_party/boringssl/crypto/x509/x_all.c",
-    "third_party/boringssl/crypto/x509/x_attrib.c",
-    "third_party/boringssl/crypto/x509/x_crl.c",
-    "third_party/boringssl/crypto/x509/x_exten.c",
-    "third_party/boringssl/crypto/x509/x_info.c",
-    "third_party/boringssl/crypto/x509/x_name.c",
-    "third_party/boringssl/crypto/x509/x_pkey.c",
-    "third_party/boringssl/crypto/x509/x_pubkey.c",
-    "third_party/boringssl/crypto/x509/x_req.c",
-    "third_party/boringssl/crypto/x509/x_sig.c",
-    "third_party/boringssl/crypto/x509/x_spki.c",
-    "third_party/boringssl/crypto/x509/x_val.c",
-    "third_party/boringssl/crypto/x509/x_x509.c",
-    "third_party/boringssl/crypto/x509/x_x509a.c",
-    "third_party/boringssl/crypto/x509v3/pcy_cache.c",
-    "third_party/boringssl/crypto/x509v3/pcy_data.c",
-    "third_party/boringssl/crypto/x509v3/pcy_lib.c",
-    "third_party/boringssl/crypto/x509v3/pcy_map.c",
-    "third_party/boringssl/crypto/x509v3/pcy_node.c",
-    "third_party/boringssl/crypto/x509v3/pcy_tree.c",
-    "third_party/boringssl/crypto/x509v3/v3_akey.c",
-    "third_party/boringssl/crypto/x509v3/v3_akeya.c",
-    "third_party/boringssl/crypto/x509v3/v3_alt.c",
-    "third_party/boringssl/crypto/x509v3/v3_bcons.c",
-    "third_party/boringssl/crypto/x509v3/v3_bitst.c",
-    "third_party/boringssl/crypto/x509v3/v3_conf.c",
-    "third_party/boringssl/crypto/x509v3/v3_cpols.c",
-    "third_party/boringssl/crypto/x509v3/v3_crld.c",
-    "third_party/boringssl/crypto/x509v3/v3_enum.c",
-    "third_party/boringssl/crypto/x509v3/v3_extku.c",
-    "third_party/boringssl/crypto/x509v3/v3_genn.c",
-    "third_party/boringssl/crypto/x509v3/v3_ia5.c",
-    "third_party/boringssl/crypto/x509v3/v3_info.c",
-    "third_party/boringssl/crypto/x509v3/v3_int.c",
-    "third_party/boringssl/crypto/x509v3/v3_lib.c",
-    "third_party/boringssl/crypto/x509v3/v3_ncons.c",
-    "third_party/boringssl/crypto/x509v3/v3_pci.c",
-    "third_party/boringssl/crypto/x509v3/v3_pcia.c",
-    "third_party/boringssl/crypto/x509v3/v3_pcons.c",
-    "third_party/boringssl/crypto/x509v3/v3_pku.c",
-    "third_party/boringssl/crypto/x509v3/v3_pmaps.c",
-    "third_party/boringssl/crypto/x509v3/v3_prn.c",
-    "third_party/boringssl/crypto/x509v3/v3_purp.c",
-    "third_party/boringssl/crypto/x509v3/v3_skey.c",
-    "third_party/boringssl/crypto/x509v3/v3_sxnet.c",
-    "third_party/boringssl/crypto/x509v3/v3_utl.c",
-    "third_party/boringssl/ssl/custom_extensions.c",
-    "third_party/boringssl/ssl/d1_both.c",
-    "third_party/boringssl/ssl/d1_clnt.c",
-    "third_party/boringssl/ssl/d1_lib.c",
-    "third_party/boringssl/ssl/d1_meth.c",
-    "third_party/boringssl/ssl/d1_pkt.c",
-    "third_party/boringssl/ssl/d1_srtp.c",
-    "third_party/boringssl/ssl/d1_srvr.c",
-    "third_party/boringssl/ssl/dtls_record.c",
-    "third_party/boringssl/ssl/pqueue/pqueue.c",
-    "third_party/boringssl/ssl/s3_both.c",
-    "third_party/boringssl/ssl/s3_clnt.c",
-    "third_party/boringssl/ssl/s3_enc.c",
-    "third_party/boringssl/ssl/s3_lib.c",
-    "third_party/boringssl/ssl/s3_meth.c",
-    "third_party/boringssl/ssl/s3_pkt.c",
-    "third_party/boringssl/ssl/s3_srvr.c",
-    "third_party/boringssl/ssl/ssl_aead_ctx.c",
-    "third_party/boringssl/ssl/ssl_asn1.c",
-    "third_party/boringssl/ssl/ssl_buffer.c",
-    "third_party/boringssl/ssl/ssl_cert.c",
-    "third_party/boringssl/ssl/ssl_cipher.c",
-    "third_party/boringssl/ssl/ssl_file.c",
-    "third_party/boringssl/ssl/ssl_lib.c",
-    "third_party/boringssl/ssl/ssl_rsa.c",
-    "third_party/boringssl/ssl/ssl_session.c",
-    "third_party/boringssl/ssl/ssl_stat.c",
-    "third_party/boringssl/ssl/t1_enc.c",
-    "third_party/boringssl/ssl/t1_lib.c",
-    "third_party/boringssl/ssl/tls_record.c",
-    "include/grpc/support/alloc.h",
-    "include/grpc/support/atm.h",
-    "include/grpc/support/atm_gcc_atomic.h",
-    "include/grpc/support/atm_gcc_sync.h",
-    "include/grpc/support/atm_win32.h",
-    "include/grpc/support/avl.h",
-    "include/grpc/support/cmdline.h",
-    "include/grpc/support/cpu.h",
-    "include/grpc/support/histogram.h",
-    "include/grpc/support/host_port.h",
-    "include/grpc/support/log.h",
-    "include/grpc/support/log_win32.h",
-    "include/grpc/support/port_platform.h",
-    "include/grpc/support/slice.h",
-    "include/grpc/support/slice_buffer.h",
-    "include/grpc/support/string_util.h",
-    "include/grpc/support/subprocess.h",
-    "include/grpc/support/sync.h",
-    "include/grpc/support/sync_generic.h",
-    "include/grpc/support/sync_posix.h",
-    "include/grpc/support/sync_win32.h",
-    "include/grpc/support/thd.h",
-    "include/grpc/support/time.h",
-    "include/grpc/support/tls.h",
-    "include/grpc/support/tls_gcc.h",
-    "include/grpc/support/tls_msvc.h",
-    "include/grpc/support/tls_pthread.h",
-    "include/grpc/support/useful.h",
-    "include/grpc/impl/codegen/alloc.h",
-    "include/grpc/impl/codegen/atm.h",
-    "include/grpc/impl/codegen/atm_gcc_atomic.h",
-    "include/grpc/impl/codegen/atm_gcc_sync.h",
-    "include/grpc/impl/codegen/atm_win32.h",
-    "include/grpc/impl/codegen/log.h",
-    "include/grpc/impl/codegen/port_platform.h",
-    "include/grpc/impl/codegen/slice.h",
-    "include/grpc/impl/codegen/slice_buffer.h",
-    "include/grpc/impl/codegen/sync.h",
-    "include/grpc/impl/codegen/sync_generic.h",
-    "include/grpc/impl/codegen/sync_posix.h",
-    "include/grpc/impl/codegen/sync_win32.h",
-    "include/grpc/impl/codegen/time.h",
-    "src/core/profiling/timers.h",
-    "src/core/support/backoff.h",
-    "src/core/support/block_annotate.h",
-    "src/core/support/env.h",
-    "src/core/support/load_file.h",
-    "src/core/support/murmur_hash.h",
-    "src/core/support/stack_lockfree.h",
-    "src/core/support/string.h",
-    "src/core/support/string_win32.h",
-    "src/core/support/thd_internal.h",
-    "src/core/support/time_precise.h",
-    "src/core/support/tmpfile.h",
-    "src/core/profiling/basic_timers.c",
-    "src/core/profiling/stap_timers.c",
-    "src/core/support/alloc.c",
-    "src/core/support/avl.c",
-    "src/core/support/backoff.c",
-    "src/core/support/cmdline.c",
-    "src/core/support/cpu_iphone.c",
-    "src/core/support/cpu_linux.c",
-    "src/core/support/cpu_posix.c",
-    "src/core/support/cpu_windows.c",
-    "src/core/support/env_linux.c",
-    "src/core/support/env_posix.c",
-    "src/core/support/env_win32.c",
-    "src/core/support/histogram.c",
-    "src/core/support/host_port.c",
-    "src/core/support/load_file.c",
-    "src/core/support/log.c",
-    "src/core/support/log_android.c",
-    "src/core/support/log_linux.c",
-    "src/core/support/log_posix.c",
-    "src/core/support/log_win32.c",
-    "src/core/support/murmur_hash.c",
-    "src/core/support/slice.c",
-    "src/core/support/slice_buffer.c",
-    "src/core/support/stack_lockfree.c",
-    "src/core/support/string.c",
-    "src/core/support/string_posix.c",
-    "src/core/support/string_win32.c",
-    "src/core/support/subprocess_posix.c",
-    "src/core/support/subprocess_windows.c",
-    "src/core/support/sync.c",
-    "src/core/support/sync_posix.c",
-    "src/core/support/sync_win32.c",
-    "src/core/support/thd.c",
-    "src/core/support/thd_posix.c",
-    "src/core/support/thd_win32.c",
-    "src/core/support/time.c",
-    "src/core/support/time_posix.c",
-    "src/core/support/time_precise.c",
-    "src/core/support/time_win32.c",
-    "src/core/support/tls_pthread.c",
-    "src/core/support/tmpfile_posix.c",
-    "src/core/support/tmpfile_win32.c",
-    "src/core/support/wrap_memcpy.c",
+    "src/node/src",
+    "src/node/ext",
+    "include/grpc",
+    "src/core",
+    "third_party/nanopb",
+    "third_party/zlib",
+    "third_party/boringssl",
     "binding.gyp"
   ],
   "main": "src/node/index.js",
-  "license": "BSD-3-Clause"
+  "license": "BSD-3-Clause",
+  "jshintConfig" : {
+    "bitwise": true,
+    "curly": true,
+    "eqeqeq": true,
+    "esnext": true,
+    "freeze": true,
+    "immed": true,
+    "indent": 2,
+    "latedef": "nofunc",
+    "maxlen": 80,
+    "mocha": true,
+    "newcap": true,
+    "node": true,
+    "noarg": true,
+    "quotmark": "single",
+    "strict": true,
+    "trailing": true,
+    "undef": true,
+    "unused": "vars"
+  }
 }
diff --git a/package.xml b/package.xml
index a0d8bfd..d192ebd 100644
--- a/package.xml
+++ b/package.xml
@@ -92,63 +92,62 @@
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_win32.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/time.h" role="src" />
-    <file baseinstalldir="/" name="src/core/profiling/timers.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/backoff.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/block_annotate.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/env.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/load_file.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/murmur_hash.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/stack_lockfree.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/string.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/string_win32.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/thd_internal.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/time_precise.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/tmpfile.h" role="src" />
-    <file baseinstalldir="/" name="src/core/profiling/basic_timers.c" role="src" />
-    <file baseinstalldir="/" name="src/core/profiling/stap_timers.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/alloc.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/avl.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/backoff.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/cmdline.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/cpu_iphone.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/cpu_linux.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/cpu_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/cpu_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/env_linux.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/env_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/env_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/histogram.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/host_port.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/load_file.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/log.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/log_android.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/log_linux.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/log_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/log_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/murmur_hash.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/slice.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/slice_buffer.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/stack_lockfree.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/string.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/string_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/string_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/subprocess_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/subprocess_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/sync.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/sync_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/sync_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/thd.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/thd_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/thd_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/time.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/time_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/time_precise.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/time_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/tls_pthread.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/tmpfile_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/tmpfile_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/wrap_memcpy.c" role="src" />
-    <file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/profiling/timers.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/backoff.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/block_annotate.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/env.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/load_file.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/murmur_hash.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/string_win32.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/thd_internal.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/time_precise.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/tmpfile.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/profiling/basic_timers.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/profiling/stap_timers.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/alloc.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/avl.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/backoff.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/cmdline.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/cpu_iphone.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/cpu_linux.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/cpu_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/cpu_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/env_linux.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/env_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/env_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/histogram.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/host_port.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/load_file.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/log.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/log_android.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/log_linux.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/log_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/log_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/murmur_hash.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/slice.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/slice_buffer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/string.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/string_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/string_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/subprocess_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/subprocess_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/sync.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/sync_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/sync_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/thd.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/thd_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/thd_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/time.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/time_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/time_precise.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/time_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/tls_pthread.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/tmpfile_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/tmpfile_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/wrap_memcpy.c" role="src" />
     <file baseinstalldir="/" name="include/grpc/byte_buffer.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/byte_buffer_reader.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
@@ -160,311 +159,324 @@
     <file baseinstalldir="/" name="include/grpc/impl/codegen/grpc_types.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/propagation_bits.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/status.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/alloc.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/atm.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_gcc_atomic.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_gcc_sync.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_win32.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/log.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/port_platform.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/slice.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/slice_buffer.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/sync.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_generic.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_win32.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/impl/codegen/time.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/census.h" role="src" />
-    <file baseinstalldir="/" name="src/core/census/grpc_filter.h" role="src" />
-    <file baseinstalldir="/" name="src/core/census/grpc_plugin.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/channel_args.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/channel_stack.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/channel_stack_builder.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/client_channel.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/client_uchannel.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/compress_filter.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/connected_channel.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/context.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/http_client_filter.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/http_server_filter.h" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/subchannel_call_holder.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/client_config.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/connector.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/initial_connect_string.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policies/load_balancer_api.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policies/pick_first.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policies/round_robin.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policy.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policy_factory.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policy_registry.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolver.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolver_factory.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolver_registry.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolvers/dns_resolver.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolvers/sockaddr_resolver.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/subchannel.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/subchannel_factory.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/subchannel_index.h" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/uri_parser.h" role="src" />
-    <file baseinstalldir="/" name="src/core/compression/algorithm_metadata.h" role="src" />
-    <file baseinstalldir="/" name="src/core/compression/message_compress.h" role="src" />
-    <file baseinstalldir="/" name="src/core/debug/trace.h" role="src" />
-    <file baseinstalldir="/" name="src/core/httpcli/format_request.h" role="src" />
-    <file baseinstalldir="/" name="src/core/httpcli/httpcli.h" role="src" />
-    <file baseinstalldir="/" name="src/core/httpcli/parser.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/closure.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/endpoint.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/endpoint_pair.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/exec_ctx.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/executor.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/fd_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iocp_windows.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iomgr.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iomgr_internal.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iomgr_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_set.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_set_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_set_windows.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_windows.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/resolve_address.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/sockaddr.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/sockaddr_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/sockaddr_utils.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/sockaddr_win32.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/socket_utils_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/socket_windows.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_client.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_server.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_windows.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/time_averaged_stats.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/timer.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/timer_heap.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/udp_server.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_pipe.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/workqueue.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/workqueue_posix.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/workqueue_windows.h" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json.h" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json_common.h" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json_reader.h" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json_writer.h" role="src" />
-    <file baseinstalldir="/" name="src/core/proto/grpc/lb/v0/load_balancer.pb.h" role="src" />
-    <file baseinstalldir="/" name="src/core/statistics/census_interface.h" role="src" />
-    <file baseinstalldir="/" name="src/core/statistics/census_rpc_stats.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/api_trace.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/call.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/call_test_only.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel_init.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel_stack_type.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/completion_queue.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/event_string.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/init.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/lame_client.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/server.h" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/surface_trace.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/byte_stream.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/alpn.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/bin_encoder.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_data.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_goaway.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_ping.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_rst_stream.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_settings.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_window_update.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/hpack_encoder.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/hpack_parser.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/hpack_table.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/http2_errors.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/huffsyms.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/incoming_metadata.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/internal.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/status_conversion.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/stream_map.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/timeout_encoding.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/varint.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2_transport.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/connectivity_state.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/metadata.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/metadata_batch.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/static_metadata.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/transport.h" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/transport_impl.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/auth_filters.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/b64.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/handshake.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/json_token.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/jwt_verifier.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/secure_endpoint.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/security_connector.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/security_context.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/ssl_types.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/transport_security.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/transport_security_interface.h" role="src" />
-    <file baseinstalldir="/" name="src/core/census/aggregation.h" role="src" />
-    <file baseinstalldir="/" name="src/core/census/mlog.h" role="src" />
-    <file baseinstalldir="/" name="src/core/census/rpc_metric_id.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/channel_args.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/channel_stack.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/compress_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/connected_channel.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/context.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/debug/trace.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/http/format_request.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/http/httpcli.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/http/parser.h" role="src" />
+    <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_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/executor.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_internal.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/pollset.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_set.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_set_windows.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_windows.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/resolve_address.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_utils.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_win32.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/socket_windows.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_client.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_server.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_windows.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/time_averaged_stats.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/timer.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/timer_heap.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/udp_server.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/wakeup_fd_pipe.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/wakeup_fd_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/workqueue.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/workqueue_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/workqueue_windows.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json_common.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json_reader.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json_writer.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/call.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/call_test_only.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/channel.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/channel_init.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/channel_stack_type.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/completion_queue.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/event_string.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/init.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/lame_client.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/server.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/surface_trace.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/transport_impl.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_goaway.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_ping.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_rst_stream.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_settings.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_window_update.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_encoder.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_table.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_errors.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/status_conversion.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/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/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" />
+    <file baseinstalldir="/" name="src/core/lib/tsi/transport_security.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/tsi/transport_security_interface.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/client_channel.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/client_channel_factory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/client_config.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/connector.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/initial_connect_string.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/lb_policy.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/lb_policy_factory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/lb_policy_registry.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/parse_address.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/resolver.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/resolver_factory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/resolver_registry.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/subchannel.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/subchannel_call_holder.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/subchannel_index.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/uri_parser.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_common.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_encode.h" role="src" />
-    <file baseinstalldir="/" name="src/core/census/grpc_context.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/grpc_filter.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/grpc_plugin.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/channel_args.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/channel_stack.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/channel_stack_builder.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/client_channel.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/client_uchannel.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/compress_filter.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/connected_channel.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/http_client_filter.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/http_server_filter.c" role="src" />
-    <file baseinstalldir="/" name="src/core/channel/subchannel_call_holder.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/client_config.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/connector.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/default_initial_connect_string.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/initial_connect_string.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policies/load_balancer_api.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policies/pick_first.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policies/round_robin.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policy.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policy_factory.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/lb_policy_registry.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolver.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolver_factory.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolver_registry.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolvers/dns_resolver.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/resolvers/sockaddr_resolver.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/subchannel.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/subchannel_factory.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/subchannel_index.c" role="src" />
-    <file baseinstalldir="/" name="src/core/client_config/uri_parser.c" role="src" />
-    <file baseinstalldir="/" name="src/core/compression/compression_algorithm.c" role="src" />
-    <file baseinstalldir="/" name="src/core/compression/message_compress.c" role="src" />
-    <file baseinstalldir="/" name="src/core/debug/trace.c" role="src" />
-    <file baseinstalldir="/" name="src/core/httpcli/format_request.c" role="src" />
-    <file baseinstalldir="/" name="src/core/httpcli/httpcli.c" role="src" />
-    <file baseinstalldir="/" name="src/core/httpcli/parser.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/closure.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/endpoint.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/endpoint_pair_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/endpoint_pair_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/exec_ctx.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/executor.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/fd_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iocp_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iomgr.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iomgr_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/iomgr_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_multipoller_with_epoll.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_multipoller_with_poll_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_set_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_set_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/pollset_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/resolve_address_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/resolve_address_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/sockaddr_utils.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/socket_utils_common_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/socket_utils_linux.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/socket_utils_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/socket_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_client_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_client_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_server_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_server_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/tcp_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/time_averaged_stats.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/timer.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/timer_heap.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/udp_server.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_eventfd.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_nospecial.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_pipe.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/workqueue_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/workqueue_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json.c" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json_reader.c" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json_string.c" role="src" />
-    <file baseinstalldir="/" name="src/core/json/json_writer.c" role="src" />
-    <file baseinstalldir="/" name="src/core/proto/grpc/lb/v0/load_balancer.pb.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/alarm.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/api_trace.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/byte_buffer.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/byte_buffer_reader.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/call.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/call_details.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/call_log_batch.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel_connectivity.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel_create.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel_init.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel_ping.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/channel_stack_type.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/completion_queue.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/event_string.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/init.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/lame_client.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/metadata_array.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/server.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/server_chttp2.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/validate_metadata.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/version.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/byte_stream.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/alpn.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/bin_encoder.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_data.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_goaway.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_ping.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_rst_stream.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_settings.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/frame_window_update.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/hpack_encoder.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/hpack_parser.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/hpack_table.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/huffsyms.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/incoming_metadata.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/parsing.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/status_conversion.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/stream_lists.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/stream_map.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/timeout_encoding.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/varint.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2/writing.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/chttp2_transport.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/connectivity_state.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/metadata.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/metadata_batch.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/static_metadata.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/transport.c" role="src" />
-    <file baseinstalldir="/" name="src/core/transport/transport_op_string.c" role="src" />
-    <file baseinstalldir="/" name="src/core/httpcli/httpcli_security_connector.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/b64.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/client_auth_filter.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/credentials.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/credentials_metadata.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/credentials_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/credentials_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/google_default_credentials.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/handshake.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/json_token.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/jwt_verifier.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/secure_endpoint.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/security_connector.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/security_context.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/server_auth_filter.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/server_secure_chttp2.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/init_secure.c" role="src" />
-    <file baseinstalldir="/" name="src/core/surface/secure_channel_create.c" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/fake_transport_security.c" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.c" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/transport_security.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/context.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/initialize.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/mlog.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/operation.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/placeholders.c" role="src" />
-    <file baseinstalldir="/" name="src/core/census/tracing.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/aggregation.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/census_interface.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/census_rpc_stats.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/grpc_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/init.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/channel_args.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/channel_stack.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/compress_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/connected_channel.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/compression/compression_algorithm.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/debug/trace.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/http/format_request.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/http/httpcli.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/http/parser.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/closure.c" role="src" />
+    <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_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/executor.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_set_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/resolve_address_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/resolve_address_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_utils.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_common_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_linux.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/socket_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_client_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_client_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_server_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_server_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/time_averaged_stats.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/timer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/timer_heap.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/udp_server.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix_noop.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/wakeup_fd_eventfd.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/wakeup_fd_nospecial.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/wakeup_fd_pipe.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/wakeup_fd_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/workqueue_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/workqueue_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json_reader.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json_string.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/json/json_writer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/alarm.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/api_trace.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/byte_buffer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/byte_buffer_reader.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/call.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/call_details.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/call_log_batch.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/channel.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/channel_init.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/channel_ping.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/channel_stack_type.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/completion_queue.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/event_string.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/lame_client.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/metadata_array.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/server.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/version.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/transport_op_string.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_plugin.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_goaway.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_ping.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_rst_stream.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_settings.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_window_update.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_encoder.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_table.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/parsing.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/status_conversion.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_lists.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/timeout_encoding.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.c" role="src" />
+    <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/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" />
+    <file baseinstalldir="/" name="src/core/lib/tsi/transport_security.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/secure/secure_channel_create.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/channel_connectivity.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/client_channel.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/client_channel_factory.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/client_config.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/client_config_plugin.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/connector.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/default_initial_connect_string.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/initial_connect_string.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/lb_policy.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/lb_policy_factory.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/lb_policy_registry.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/parse_address.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/resolver.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/resolver_factory.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/resolver_registry.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/subchannel.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/subchannel_call_holder.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/subchannel_index.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_config/uri_parser.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_decode.c" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_encode.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/pick_first/pick_first.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/round_robin/round_robin.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/resolver/dns/native/dns_resolver.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/resolver/sockaddr/sockaddr_resolver.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/context.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/grpc_context.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/grpc_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/grpc_plugin.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/initialize.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/mlog.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/tracing.c" role="src" />
+    <file baseinstalldir="/" name="src/core/plugin_registry/grpc_plugin_registry.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/aes/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/asn1_locl.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/bio/internal.h" role="src" />
@@ -474,12 +486,12 @@
     <file baseinstalldir="/" name="third_party/boringssl/crypto/cipher/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/conf/conf_def.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/conf/internal.h" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl/crypto/curve25519/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/des/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/dh/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/digest/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/digest/md32_common.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/directory.h" role="src" />
-    <file baseinstalldir="/" name="third_party/boringssl/crypto/dsa/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/ec/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/ec/p256-x86_64-table.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/evp/internal.h" role="src" />
@@ -644,6 +656,7 @@
     <file baseinstalldir="/" name="third_party/boringssl/crypto/bn/shift.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/bn/sqrt.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/buf/buf.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl/crypto/bytestring/asn1_compat.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/bytestring/ber.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/bytestring/cbb.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/bytestring/cbs.c" role="src" />
@@ -667,6 +680,7 @@
     <file baseinstalldir="/" name="third_party/boringssl/crypto/cpu-intel.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/crypto.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/curve25519/curve25519.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl/crypto/curve25519/x25519-x86_64.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/des/des.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/dh/check.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/dh/dh.c" role="src" />
@@ -858,6 +872,7 @@
     <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_buffer.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_cert.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_cipher.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_ecdh.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_file.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_lib.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_rsa.c" role="src" />
diff --git a/setup.py b/setup.py
index afa9872..cd0d3a1 100644
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -111,7 +111,7 @@
   DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
 
 
-def cython_extensions(package_names, module_names, extra_sources, include_dirs,
+def cython_extensions(module_names, extra_sources, include_dirs,
                       libraries, define_macros, build_with_cython=False):
   # Set compiler directives linetrace argument only if we care about tracing;
   # this is due to Cython having different behavior between linetrace being
@@ -144,7 +144,7 @@
     return extensions
 
 CYTHON_EXTENSION_MODULES = cython_extensions(
-    list(CYTHON_EXTENSION_PACKAGE_NAMES), list(CYTHON_EXTENSION_MODULE_NAMES),
+    list(CYTHON_EXTENSION_MODULE_NAMES),
     list(CYTHON_HELPER_C_FILES) + list(CORE_C_FILES),
     list(EXTENSION_INCLUDE_DIRECTORIES), list(EXTENSION_LIBRARIES),
     list(DEFINE_MACROS), bool(BUILD_WITH_CYTHON))
diff --git a/src/boringssl/err_data.c b/src/boringssl/err_data.c
index 1a1d950..d4cc08b 100644
--- a/src/boringssl/err_data.c
+++ b/src/boringssl/err_data.c
@@ -54,30 +54,30 @@
 OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num);
 
 const uint32_t kOpenSSLReasonValues[] = {
-    0xc3207ba,
-    0xc3287d4,
-    0xc3307e3,
-    0xc3387f3,
-    0xc340802,
-    0xc34881b,
-    0xc350827,
-    0xc358844,
-    0xc360856,
-    0xc368864,
-    0xc370874,
-    0xc378881,
-    0xc380891,
-    0xc38889c,
-    0xc3908b2,
-    0xc3988c1,
-    0xc3a08d5,
-    0xc3a87c7,
+    0xc3207ab,
+    0xc3287c5,
+    0xc3307d4,
+    0xc3387e4,
+    0xc3407f3,
+    0xc34880c,
+    0xc350818,
+    0xc358835,
+    0xc360847,
+    0xc368855,
+    0xc370865,
+    0xc378872,
+    0xc380882,
+    0xc38888d,
+    0xc3908a3,
+    0xc3988b2,
+    0xc3a08c6,
+    0xc3a87b8,
     0xc3b00b0,
-    0x10321478,
-    0x10329484,
-    0x1033149d,
-    0x103394b0,
-    0x10340de1,
+    0x10321484,
+    0x10329490,
+    0x103314a9,
+    0x103394bc,
+    0x10340ded,
     0x103494cf,
     0x103514e4,
     0x10359516,
@@ -97,7 +97,7 @@
     0x103c9658,
     0x103d166f,
     0x103d9682,
-    0x103e0b6c,
+    0x103e0b5d,
     0x103e96b3,
     0x103f16c6,
     0x103f96e0,
@@ -108,87 +108,91 @@
     0x10421747,
     0x1042975b,
     0x1043176d,
-    0x104385d0,
-    0x104408c1,
+    0x104385c1,
+    0x104408b2,
     0x10449782,
     0x10451799,
     0x104597ae,
     0x104617bc,
     0x10469695,
     0x104714f7,
-    0x104787c7,
+    0x104787b8,
     0x104800b0,
-    0x104894c3,
-    0x14320b4f,
-    0x14328b5d,
-    0x14330b6c,
-    0x14338b7e,
+    0x10488b8c,
+    0x14320b40,
+    0x14328b4e,
+    0x14330b5d,
+    0x14338b6f,
     0x18320083,
-    0x18328e47,
-    0x18340e75,
-    0x18348e89,
-    0x18358ec0,
-    0x18368eed,
-    0x18370f00,
-    0x18378f14,
-    0x18380f38,
-    0x18388f46,
-    0x18390f5c,
-    0x18398f70,
-    0x183a0f80,
-    0x183b0f90,
-    0x183b8fa5,
-    0x183c8fd0,
-    0x183d0fe4,
-    0x183d8ff4,
-    0x183e0b9b,
-    0x183e9001,
-    0x183f1013,
-    0x183f901e,
-    0x1840102e,
-    0x1840903f,
-    0x18411050,
-    0x18419062,
-    0x1842108b,
-    0x184290bd,
-    0x184310cc,
-    0x18451135,
-    0x1845914b,
-    0x18461166,
-    0x18468ed8,
-    0x184709d9,
+    0x18328e53,
+    0x18340e81,
+    0x18348e95,
+    0x18358ecc,
+    0x18368ef9,
+    0x18370f0c,
+    0x18378f20,
+    0x18380f44,
+    0x18388f52,
+    0x18390f68,
+    0x18398f7c,
+    0x183a0f8c,
+    0x183b0f9c,
+    0x183b8fb1,
+    0x183c8fdc,
+    0x183d0ff0,
+    0x183d9000,
+    0x183e0b98,
+    0x183e900d,
+    0x183f101f,
+    0x183f902a,
+    0x1840103a,
+    0x1840904b,
+    0x1841105c,
+    0x1841906e,
+    0x18421097,
+    0x184290c9,
+    0x184310d8,
+    0x18451141,
+    0x18459157,
+    0x18461172,
+    0x18468ee4,
+    0x184709ca,
     0x18478094,
-    0x18480fbc,
-    0x18489101,
-    0x18490e5d,
-    0x18498e9e,
-    0x184a119c,
-    0x184a9119,
-    0x184b10e0,
-    0x184b8e37,
-    0x184c10a4,
-    0x184c866b,
-    0x184d1181,
-    0x203211c3,
-    0x243211cf,
-    0x24328907,
-    0x243311e1,
-    0x243391ee,
-    0x243411fb,
-    0x2434920d,
-    0x2435121c,
-    0x24359239,
-    0x24361246,
-    0x24369254,
-    0x24371262,
-    0x24379270,
-    0x24381279,
-    0x24389286,
-    0x24391299,
-    0x28320b8f,
-    0x28328b9b,
-    0x28330b6c,
-    0x28338bae,
+    0x18480fc8,
+    0x1848910d,
+    0x18490e69,
+    0x18498eaa,
+    0x184a11a8,
+    0x184a9125,
+    0x184b10ec,
+    0x184b8e43,
+    0x184c10b0,
+    0x184c865c,
+    0x184d118d,
+    0x184d80b0,
+    0x203211cf,
+    0x243211db,
+    0x243288f8,
+    0x243311ed,
+    0x243391fa,
+    0x24341207,
+    0x24349219,
+    0x24351228,
+    0x24359245,
+    0x24361252,
+    0x24369260,
+    0x2437126e,
+    0x2437927c,
+    0x24381285,
+    0x24389292,
+    0x243912a5,
+    0x28320b80,
+    0x28328b98,
+    0x28330b5d,
+    0x28338bab,
+    0x28340b8c,
+    0x28348094,
+    0x283500b0,
     0x2c32281d,
     0x2c32a82b,
     0x2c33283d,
@@ -207,7 +211,7 @@
     0x2c39a917,
     0x2c3a292b,
     0x2c3aa93c,
-    0x2c3b1359,
+    0x2c3b1365,
     0x2c3ba94d,
     0x2c3c2961,
     0x2c3ca977,
@@ -219,12 +223,12 @@
     0x2c3faa09,
     0x2c402a2c,
     0x2c40aa4b,
-    0x2c4111c3,
+    0x2c4111cf,
     0x2c41aa5c,
     0x2c422a6f,
-    0x2c429135,
+    0x2c429141,
     0x2c432a80,
-    0x2c4386a2,
+    0x2c438693,
     0x2c4429ad,
     0x30320000,
     0x30328015,
@@ -277,77 +281,79 @@
     0x304a03b4,
     0x304a83c7,
     0x304b03d2,
-    0x304b83e1,
-    0x304c03f2,
-    0x304c83fe,
-    0x304d0414,
-    0x304d8422,
-    0x304e0438,
-    0x304e844a,
-    0x304f045c,
-    0x304f846f,
-    0x30500482,
-    0x30508493,
-    0x305104a3,
-    0x305184bb,
-    0x305204d0,
-    0x305284e8,
-    0x305304fc,
-    0x30538514,
-    0x3054052d,
-    0x30548546,
-    0x30550563,
-    0x3055856e,
-    0x30560586,
-    0x30568596,
-    0x305705a7,
-    0x305785ba,
-    0x305805d0,
-    0x305885d9,
-    0x305905ee,
+    0x304b83e3,
+    0x304c03ef,
+    0x304c8405,
+    0x304d0413,
+    0x304d8429,
+    0x304e043b,
+    0x304e844d,
+    0x304f0460,
+    0x304f8473,
+    0x30500484,
+    0x30508494,
+    0x305104ac,
+    0x305184c1,
+    0x305204d9,
+    0x305284ed,
+    0x30530505,
+    0x3053851e,
+    0x30540537,
+    0x30548554,
+    0x3055055f,
+    0x30558577,
+    0x30560587,
+    0x30568598,
+    0x305705ab,
+    0x305785c1,
+    0x305805ca,
+    0x305885df,
+    0x305905f2,
     0x30598601,
-    0x305a0610,
+    0x305a0621,
     0x305a8630,
-    0x305b063f,
-    0x305b864b,
-    0x305c066b,
-    0x305c8687,
-    0x305d0698,
-    0x305d86a2,
-    0x34320ac9,
-    0x34328add,
-    0x34330afa,
-    0x34338b0d,
-    0x34340b1c,
-    0x34348b39,
+    0x305b063c,
+    0x305b865c,
+    0x305c0678,
+    0x305c8689,
+    0x305d0693,
+    0x34320aba,
+    0x34328ace,
+    0x34330aeb,
+    0x34338afe,
+    0x34340b0d,
+    0x34348b2a,
     0x3c320083,
-    0x3c328bd8,
-    0x3c330bf1,
-    0x3c338c0c,
-    0x3c340c29,
-    0x3c348c44,
-    0x3c350c5f,
-    0x3c358c74,
-    0x3c360c8d,
-    0x3c368ca5,
-    0x3c370cb6,
-    0x3c378cc4,
-    0x3c380cd1,
-    0x3c388ce5,
-    0x3c390b9b,
-    0x3c398cf9,
-    0x3c3a0d0d,
-    0x3c3a8881,
-    0x3c3b0d1d,
-    0x3c3b8d38,
-    0x3c3c0d4a,
-    0x3c3c8d60,
-    0x3c3d0d6a,
-    0x3c3d8d7e,
-    0x3c3e0d8c,
-    0x3c3e8db1,
-    0x3c3f0bc4,
-    0x3c3f8d9a,
+    0x3c328bd5,
+    0x3c330bee,
+    0x3c338c09,
+    0x3c340c26,
+    0x3c348c50,
+    0x3c350c6b,
+    0x3c358c80,
+    0x3c360c99,
+    0x3c368cb1,
+    0x3c370cc2,
+    0x3c378cd0,
+    0x3c380cdd,
+    0x3c388cf1,
+    0x3c390b98,
+    0x3c398d05,
+    0x3c3a0d19,
+    0x3c3a8872,
+    0x3c3b0d29,
+    0x3c3b8d44,
+    0x3c3c0d56,
+    0x3c3c8d6c,
+    0x3c3d0d76,
+    0x3c3d8d8a,
+    0x3c3e0d98,
+    0x3c3e8dbd,
+    0x3c3f0bc1,
+    0x3c3f8da6,
+    0x3c400094,
+    0x3c4080b0,
+    0x3c410c41,
     0x403217d3,
     0x403297e9,
     0x40331817,
@@ -362,7 +368,7 @@
     0x403798b8,
     0x403818c3,
     0x403898d5,
-    0x40390de1,
+    0x40390ded,
     0x403998e5,
     0x403a18f8,
     0x403a9919,
@@ -437,7 +443,7 @@
     0x405d1e9e,
     0x405d9eb5,
     0x405e1ed5,
-    0x405e8a17,
+    0x405e8a08,
     0x405f1ef6,
     0x405f9f03,
     0x40601f11,
@@ -474,18 +480,18 @@
     0x406fa60d,
     0x40702620,
     0x4070a63d,
-    0x40710782,
+    0x40710773,
     0x4071a64f,
     0x40722662,
     0x4072a67b,
     0x40732693,
-    0x407390bd,
+    0x407390c9,
     0x407426a7,
     0x4074a6c1,
     0x407526d2,
     0x4075a6e6,
     0x407626f4,
-    0x40769286,
+    0x40769292,
     0x40772719,
     0x4077a73b,
     0x40782756,
@@ -528,48 +534,48 @@
     0x422c251d,
     0x422ca4d8,
     0x422d24b7,
-    0x443206ad,
-    0x443286bc,
-    0x443306c8,
-    0x443386d6,
-    0x443406e9,
-    0x443486fa,
-    0x44350701,
-    0x4435870b,
-    0x4436071e,
-    0x44368734,
-    0x44370746,
-    0x44378753,
-    0x44380762,
-    0x4438876a,
-    0x44390782,
-    0x44398790,
-    0x443a07a3,
-    0x4c3212b0,
-    0x4c3292c0,
-    0x4c3312d3,
-    0x4c3392f3,
+    0x4432069e,
+    0x443286ad,
+    0x443306b9,
+    0x443386c7,
+    0x443406da,
+    0x443486eb,
+    0x443506f2,
+    0x443586fc,
+    0x4436070f,
+    0x44368725,
+    0x44370737,
+    0x44378744,
+    0x44380753,
+    0x4438875b,
+    0x44390773,
+    0x44398781,
+    0x443a0794,
+    0x4c3212bc,
+    0x4c3292cc,
+    0x4c3312df,
+    0x4c3392ff,
     0x4c340094,
     0x4c3480b0,
-    0x4c3512ff,
-    0x4c35930d,
-    0x4c361329,
-    0x4c36933c,
-    0x4c37134b,
-    0x4c379359,
-    0x4c38136e,
-    0x4c38937a,
-    0x4c39139a,
-    0x4c3993c4,
-    0x4c3a13dd,
-    0x4c3a93f6,
-    0x4c3b05d0,
-    0x4c3b940f,
-    0x4c3c1421,
-    0x4c3c9430,
-    0x4c3d10bd,
-    0x4c3d9449,
-    0x4c3e1456,
+    0x4c35130b,
+    0x4c359319,
+    0x4c361335,
+    0x4c369348,
+    0x4c371357,
+    0x4c379365,
+    0x4c38137a,
+    0x4c389386,
+    0x4c3913a6,
+    0x4c3993d0,
+    0x4c3a13e9,
+    0x4c3a9402,
+    0x4c3b05c1,
+    0x4c3b941b,
+    0x4c3c142d,
+    0x4c3c943c,
+    0x4c3d10c9,
+    0x4c3d9455,
+    0x4c3e1462,
     0x50322a92,
     0x5032aaa1,
     0x50332aac,
@@ -607,7 +613,7 @@
     0x50432d43,
     0x5043ad53,
     0x50442d62,
-    0x50448414,
+    0x50448405,
     0x50452d76,
     0x5045ad94,
     0x50462da7,
@@ -631,45 +637,45 @@
     0x504f2f62,
     0x504faf79,
     0x50502f88,
-    0x50508687,
+    0x50508678,
     0x50512f9b,
-    0x58320e1f,
-    0x68320de1,
-    0x68328b9b,
-    0x68330bae,
-    0x68338def,
-    0x68340dff,
+    0x58320e2b,
+    0x68320ded,
+    0x68328b98,
+    0x68330bab,
+    0x68338dfb,
+    0x68340e0b,
     0x683480b0,
-    0x6c320dbd,
-    0x6c328b7e,
-    0x6c330dc8,
-    0x7432098d,
-    0x783208f2,
-    0x78328907,
-    0x78330913,
+    0x6c320dc9,
+    0x6c328b6f,
+    0x6c330dd4,
+    0x7432097e,
+    0x783208e3,
+    0x783288f8,
+    0x78330904,
     0x78338083,
-    0x78340922,
-    0x78348937,
-    0x78350956,
-    0x78358978,
-    0x7836098d,
-    0x783689a3,
-    0x783709b3,
-    0x783789c6,
-    0x783809d9,
-    0x783889eb,
-    0x783909f8,
-    0x78398a17,
-    0x783a0a2c,
-    0x783a8a3a,
-    0x783b0a44,
-    0x783b8a58,
-    0x783c0a6f,
-    0x783c8a84,
-    0x783d0a9b,
-    0x783d8ab0,
-    0x783e0a06,
-    0x7c3211b2,
+    0x78340913,
+    0x78348928,
+    0x78350947,
+    0x78358969,
+    0x7836097e,
+    0x78368994,
+    0x783709a4,
+    0x783789b7,
+    0x783809ca,
+    0x783889dc,
+    0x783909e9,
+    0x78398a08,
+    0x783a0a1d,
+    0x783a8a2b,
+    0x783b0a35,
+    0x783b8a49,
+    0x783c0a60,
+    0x783c8a75,
+    0x783d0a8c,
+    0x783d8aa1,
+    0x783e09f7,
+    0x7c3211be,
 };
 
 const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]);
@@ -725,7 +731,6 @@
     "INVALID_UNIVERSALSTRING_LENGTH\0"
     "INVALID_UTF8STRING\0"
     "LIST_ERROR\0"
-    "MALLOC_FAILURE\0"
     "MISSING_ASN1_EOS\0"
     "MISSING_EOC\0"
     "MISSING_SECOND_NUMBER\0"
@@ -833,6 +838,7 @@
     "MODULUS_TOO_LARGE\0"
     "NO_PRIVATE_VALUE\0"
     "BAD_Q_VALUE\0"
+    "BAD_VERSION\0"
     "MISSING_PARAMETERS\0"
     "NEED_NEW_SETUP_VALUES\0"
     "BIGNUM_OUT_OF_RANGE\0"
@@ -840,6 +846,7 @@
     "D2I_ECPKPARAMETERS_FAILURE\0"
     "EC_GROUP_NEW_BY_NAME_FAILURE\0"
     "GROUP2PKPARAMETERS_FAILURE\0"
+    "GROUP_MISMATCH\0"
     "I2D_ECPKPARAMETERS_FAILURE\0"
     "INCOMPATIBLE_OBJECTS\0"
     "INVALID_COMPRESSED_POINT\0"
@@ -948,7 +955,6 @@
     "BAD_FIXED_HEADER_DECRYPT\0"
     "BAD_PAD_BYTE_COUNT\0"
     "BAD_RSA_PARAMETERS\0"
-    "BAD_VERSION\0"
     "BLOCK_TYPE_IS_NOT_01\0"
     "BN_NOT_INITIALIZED\0"
     "CANNOT_RECOVER_MULTI_PRIME_KEY\0"
diff --git a/src/boringssl/gen_build_yaml.py b/src/boringssl/gen_build_yaml.py
index 3a7116b..20f6413 100755
--- a/src/boringssl/gen_build_yaml.py
+++ b/src/boringssl/gen_build_yaml.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc
index 206a6e1..9319c41 100644
--- a/src/compiler/cpp_generator.cc
+++ b/src/compiler/cpp_generator.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,9 +34,6 @@
 #include <map>
 
 #include "src/compiler/cpp_generator.h"
-#include "src/compiler/cpp_generator_helpers.h"
-
-#include "src/compiler/config.h"
 
 #include <sstream>
 
@@ -50,22 +47,6 @@
   return out.str();
 }
 
-bool NoStreaming(const grpc::protobuf::MethodDescriptor *method) {
-  return !method->client_streaming() && !method->server_streaming();
-}
-
-bool ClientOnlyStreaming(const grpc::protobuf::MethodDescriptor *method) {
-  return method->client_streaming() && !method->server_streaming();
-}
-
-bool ServerOnlyStreaming(const grpc::protobuf::MethodDescriptor *method) {
-  return !method->client_streaming() && method->server_streaming();
-}
-
-bool BidiStreaming(const grpc::protobuf::MethodDescriptor *method) {
-  return method->client_streaming() && method->server_streaming();
-}
-
 grpc::string FilenameIdentifier(const grpc::string &filename) {
   grpc::string result;
   for (unsigned i = 0; i < filename.size(); i++) {
@@ -86,7 +67,7 @@
 template<class T, size_t N>
 T *array_end(T (&array)[N]) { return array + N; }
 
-void PrintIncludes(grpc::protobuf::io::Printer *printer, const std::vector<grpc::string>& headers, const Parameters &params) {
+void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, const Parameters &params) {
   std::map<grpc::string, grpc::string> vars;
 
   vars["l"] = params.use_system_headers ? '<' : '"';
@@ -105,39 +86,37 @@
   }
 }
 
-grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params) {
+grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
-    grpc::protobuf::io::StringOutputStream output_stream(&output);
-    grpc::protobuf::io::Printer printer(&output_stream, '$');
+    auto printer = file->CreatePrinter(&output);
     std::map<grpc::string, grpc::string> vars;
 
-    vars["filename"] = file->name();
-    vars["filename_identifier"] = FilenameIdentifier(file->name());
-    vars["filename_base"] = grpc_generator::StripProto(file->name());
+    vars["filename"] = file->filename();
+    vars["filename_identifier"] = FilenameIdentifier(file->filename());
+    vars["filename_base"] = file->filename_without_ext();
+    vars["message_header_ext"] = file->message_header_ext();
 
-    printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n");
-    printer.Print(vars,
+    printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
+    printer->Print(vars,
                   "// If you make any local change, they will be lost.\n");
-    printer.Print(vars, "// source: $filename$\n");
-    printer.Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
-    printer.Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
-    printer.Print(vars, "\n");
-    printer.Print(vars, "#include \"$filename_base$.pb.h\"\n");
-    printer.Print(vars, "\n");
+    printer->Print(vars, "// source: $filename$\n");
+    printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
+    printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
+    printer->Print(vars, "\n");
+    printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+    printer->Print(vars, "\n");
   }
   return output;
 }
 
-grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file,
+grpc::string GetHeaderIncludes(File *file,
                                const Parameters &params) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
-    grpc::protobuf::io::StringOutputStream output_stream(&output);
-    grpc::protobuf::io::Printer printer(&output_stream, '$');
+    auto printer = file->CreatePrinter(&output);
     std::map<grpc::string, grpc::string> vars;
 
     static const char *headers_strs[] = {
@@ -151,42 +130,38 @@
       "grpc++/impl/codegen/sync_stream.h"
     };
     std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
-    PrintIncludes(&printer, headers, params);
-    printer.Print(vars, "\n");
-    printer.Print(vars, "namespace grpc {\n");
-    printer.Print(vars, "class CompletionQueue;\n");
-    printer.Print(vars, "class Channel;\n");
-    printer.Print(vars, "class RpcService;\n");
-    printer.Print(vars, "class ServerCompletionQueue;\n");
-    printer.Print(vars, "class ServerContext;\n");
-    printer.Print(vars, "}  // namespace grpc\n\n");
+    PrintIncludes(printer.get(), headers, params);
+    printer->Print(vars, "\n");
+    printer->Print(vars, "namespace grpc {\n");
+    printer->Print(vars, "class CompletionQueue;\n");
+    printer->Print(vars, "class Channel;\n");
+    printer->Print(vars, "class RpcService;\n");
+    printer->Print(vars, "class ServerCompletionQueue;\n");
+    printer->Print(vars, "class ServerContext;\n");
+    printer->Print(vars, "}  // namespace grpc\n\n");
 
     if (!file->package().empty()) {
-      std::vector<grpc::string> parts =
-          grpc_generator::tokenize(file->package(), ".");
+      std::vector<grpc::string> parts = file->package_parts();
 
       for (auto part = parts.begin(); part != parts.end(); part++) {
         vars["part"] = *part;
-        printer.Print(vars, "namespace $part$ {\n");
+        printer->Print(vars, "namespace $part$ {\n");
       }
-      printer.Print(vars, "\n");
+      printer->Print(vars, "\n");
     }
   }
   return output;
 }
 
 void PrintHeaderClientMethodInterfaces(
-    grpc::protobuf::io::Printer *printer,
-    const grpc::protobuf::MethodDescriptor *method,
+    Printer *printer, const Method *method,
     std::map<grpc::string, grpc::string> *vars, bool is_public) {
   (*vars)["Method"] = method->name();
-  (*vars)["Request"] =
-      grpc_cpp_generator::ClassName(method->input_type(), true);
-  (*vars)["Response"] =
-      grpc_cpp_generator::ClassName(method->output_type(), true);
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
 
   if (is_public) {
-    if (NoStreaming(method)) {
+    if (method->NoStreaming()) {
       printer->Print(
           *vars,
           "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
@@ -204,7 +179,7 @@
                      "Async$Method$Raw(context, request, cq));\n");
       printer->Outdent();
       printer->Print("}\n");
-    } else if (ClientOnlyStreaming(method)) {
+    } else if (method->ClientOnlyStreaming()) {
       printer->Print(
           *vars,
           "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
@@ -230,7 +205,7 @@
                      "Async$Method$Raw(context, response, cq, tag));\n");
       printer->Outdent();
       printer->Print("}\n");
-    } else if (ServerOnlyStreaming(method)) {
+    } else if (method->ServerOnlyStreaming()) {
       printer->Print(
           *vars,
           "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
@@ -256,7 +231,7 @@
                      "Async$Method$Raw(context, request, cq, tag));\n");
       printer->Outdent();
       printer->Print("}\n");
-    } else if (BidiStreaming(method)) {
+    } else if (method->BidiStreaming()) {
       printer->Print(*vars,
                      "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
                      "$Request$, $Response$>> "
@@ -285,14 +260,14 @@
       printer->Print("}\n");
     }
   } else {
-    if (NoStreaming(method)) {
+    if (method->NoStreaming()) {
       printer->Print(
           *vars,
           "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
           "Async$Method$Raw(::grpc::ClientContext* context, "
           "const $Request$& request, "
           "::grpc::CompletionQueue* cq) = 0;\n");
-    } else if (ClientOnlyStreaming(method)) {
+    } else if (method->ClientOnlyStreaming()) {
       printer->Print(
           *vars,
           "virtual ::grpc::ClientWriterInterface< $Request$>*"
@@ -303,7 +278,7 @@
                      " Async$Method$Raw(::grpc::ClientContext* context, "
                      "$Response$* response, "
                      "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
-    } else if (ServerOnlyStreaming(method)) {
+    } else if (method->ServerOnlyStreaming()) {
       printer->Print(
           *vars,
           "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw("
@@ -314,7 +289,7 @@
           "Async$Method$Raw("
           "::grpc::ClientContext* context, const $Request$& request, "
           "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
-    } else if (BidiStreaming(method)) {
+    } else if (method->BidiStreaming()) {
       printer->Print(*vars,
                      "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
                      "$Response$>* "
@@ -328,17 +303,15 @@
   }
 }
 
-void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer,
-                             const grpc::protobuf::MethodDescriptor *method,
+void PrintHeaderClientMethod(Printer *printer,
+                             const Method *method,
                              std::map<grpc::string, grpc::string> *vars,
                              bool is_public) {
   (*vars)["Method"] = method->name();
-  (*vars)["Request"] =
-      grpc_cpp_generator::ClassName(method->input_type(), true);
-  (*vars)["Response"] =
-      grpc_cpp_generator::ClassName(method->output_type(), true);
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
   if (is_public) {
-    if (NoStreaming(method)) {
+    if (method->NoStreaming()) {
       printer->Print(
           *vars,
           "::grpc::Status $Method$(::grpc::ClientContext* context, "
@@ -356,7 +329,7 @@
                      "Async$Method$Raw(context, request, cq));\n");
       printer->Outdent();
       printer->Print("}\n");
-    } else if (ClientOnlyStreaming(method)) {
+    } else if (method->ClientOnlyStreaming()) {
       printer->Print(
           *vars,
           "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
@@ -380,7 +353,7 @@
           "Async$Method$Raw(context, response, cq, tag));\n");
       printer->Outdent();
       printer->Print("}\n");
-    } else if (ServerOnlyStreaming(method)) {
+    } else if (method->ServerOnlyStreaming()) {
       printer->Print(
           *vars,
           "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
@@ -406,7 +379,7 @@
           "Async$Method$Raw(context, request, cq, tag));\n");
       printer->Outdent();
       printer->Print("}\n");
-    } else if (BidiStreaming(method)) {
+    } else if (method->BidiStreaming()) {
       printer->Print(
           *vars,
           "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
@@ -432,13 +405,13 @@
       printer->Print("}\n");
     }
   } else {
-    if (NoStreaming(method)) {
+    if (method->NoStreaming()) {
       printer->Print(*vars,
                      "::grpc::ClientAsyncResponseReader< $Response$>* "
                      "Async$Method$Raw(::grpc::ClientContext* context, "
                      "const $Request$& request, "
                      "::grpc::CompletionQueue* cq) GRPC_OVERRIDE;\n");
-    } else if (ClientOnlyStreaming(method)) {
+    } else if (method->ClientOnlyStreaming()) {
       printer->Print(*vars,
                      "::grpc::ClientWriter< $Request$>* $Method$Raw("
                      "::grpc::ClientContext* context, $Response$* response) "
@@ -448,7 +421,7 @@
           "::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw("
           "::grpc::ClientContext* context, $Response$* response, "
           "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
-    } else if (ServerOnlyStreaming(method)) {
+    } else if (method->ServerOnlyStreaming()) {
       printer->Print(*vars,
                      "::grpc::ClientReader< $Response$>* $Method$Raw("
                      "::grpc::ClientContext* context, const $Request$& request)"
@@ -458,7 +431,7 @@
           "::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw("
           "::grpc::ClientContext* context, const $Request$& request, "
           "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
-    } else if (BidiStreaming(method)) {
+    } else if (method->BidiStreaming()) {
       printer->Print(
           *vars,
           "::grpc::ClientReaderWriter< $Request$, $Response$>* "
@@ -472,38 +445,34 @@
   }
 }
 
-void PrintHeaderClientMethodData(grpc::protobuf::io::Printer *printer,
-                                 const grpc::protobuf::MethodDescriptor *method,
+void PrintHeaderClientMethodData(Printer *printer, const Method *method,
                                  std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
 }
 
-void PrintHeaderServerMethodSync(grpc::protobuf::io::Printer *printer,
-                                 const grpc::protobuf::MethodDescriptor *method,
+void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
                                  std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
-  (*vars)["Request"] =
-      grpc_cpp_generator::ClassName(method->input_type(), true);
-  (*vars)["Response"] =
-      grpc_cpp_generator::ClassName(method->output_type(), true);
-  if (NoStreaming(method)) {
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  if (method->NoStreaming()) {
     printer->Print(*vars,
                    "virtual ::grpc::Status $Method$("
                    "::grpc::ServerContext* context, const $Request$* request, "
                    "$Response$* response);\n");
-  } else if (ClientOnlyStreaming(method)) {
+  } else if (method->ClientOnlyStreaming()) {
     printer->Print(*vars,
                    "virtual ::grpc::Status $Method$("
                    "::grpc::ServerContext* context, "
                    "::grpc::ServerReader< $Request$>* reader, "
                    "$Response$* response);\n");
-  } else if (ServerOnlyStreaming(method)) {
+  } else if (method->ServerOnlyStreaming()) {
     printer->Print(*vars,
                    "virtual ::grpc::Status $Method$("
                    "::grpc::ServerContext* context, const $Request$* request, "
                    "::grpc::ServerWriter< $Response$>* writer);\n");
-  } else if (BidiStreaming(method)) {
+  } else if (method->BidiStreaming()) {
     printer->Print(
         *vars,
         "virtual ::grpc::Status $Method$("
@@ -514,20 +483,18 @@
 }
 
 void PrintHeaderServerMethodAsync(
-    grpc::protobuf::io::Printer *printer,
-    const grpc::protobuf::MethodDescriptor *method,
+    Printer *printer,
+    const Method *method,
     std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
-  (*vars)["Request"] =
-      grpc_cpp_generator::ClassName(method->input_type(), true);
-  (*vars)["Response"] =
-      grpc_cpp_generator::ClassName(method->output_type(), true);
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
   printer->Print(*vars, "template <class BaseClass>\n");
   printer->Print(*vars,
                  "class WithAsyncMethod_$Method$ : public BaseClass {\n");
   printer->Print(
       " private:\n"
-      "  void BaseClassMustBeDerivedFromService(Service *service) {}\n");
+      "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
   printer->Print(" public:\n");
   printer->Indent();
   printer->Print(*vars,
@@ -538,7 +505,7 @@
                  "~WithAsyncMethod_$Method$() GRPC_OVERRIDE {\n"
                  "  BaseClassMustBeDerivedFromService(this);\n"
                  "}\n");
-  if (NoStreaming(method)) {
+  if (method->NoStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -559,7 +526,7 @@
                    "  ::grpc::Service::RequestAsyncUnary($Idx$, context, "
                    "request, response, new_call_cq, notification_cq, tag);\n");
     printer->Print("}\n");
-  } else if (ClientOnlyStreaming(method)) {
+  } else if (method->ClientOnlyStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -581,7 +548,7 @@
                    "  ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
                    "context, reader, new_call_cq, notification_cq, tag);\n");
     printer->Print("}\n");
-  } else if (ServerOnlyStreaming(method)) {
+  } else if (method->ServerOnlyStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -604,7 +571,7 @@
         "  ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
         "context, request, writer, new_call_cq, notification_cq, tag);\n");
     printer->Print("}\n");
-  } else if (BidiStreaming(method)) {
+  } else if (method->BidiStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -632,20 +599,18 @@
 }
 
 void PrintHeaderServerMethodGeneric(
-    grpc::protobuf::io::Printer *printer,
-    const grpc::protobuf::MethodDescriptor *method,
+    Printer *printer,
+    const Method *method,
     std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
-  (*vars)["Request"] =
-      grpc_cpp_generator::ClassName(method->input_type(), true);
-  (*vars)["Response"] =
-      grpc_cpp_generator::ClassName(method->output_type(), true);
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
   printer->Print(*vars, "template <class BaseClass>\n");
   printer->Print(*vars,
                  "class WithGenericMethod_$Method$ : public BaseClass {\n");
   printer->Print(
       " private:\n"
-      "  void BaseClassMustBeDerivedFromService(Service *service) {}\n");
+      "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
   printer->Print(" public:\n");
   printer->Indent();
   printer->Print(*vars,
@@ -656,7 +621,7 @@
                  "~WithGenericMethod_$Method$() GRPC_OVERRIDE {\n"
                  "  BaseClassMustBeDerivedFromService(this);\n"
                  "}\n");
-  if (NoStreaming(method)) {
+  if (method->NoStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -666,7 +631,7 @@
         "  abort();\n"
         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
         "}\n");
-  } else if (ClientOnlyStreaming(method)) {
+  } else if (method->ClientOnlyStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -677,7 +642,7 @@
         "  abort();\n"
         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
         "}\n");
-  } else if (ServerOnlyStreaming(method)) {
+  } else if (method->ServerOnlyStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -688,7 +653,7 @@
         "  abort();\n"
         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
         "}\n");
-  } else if (BidiStreaming(method)) {
+  } else if (method->BidiStreaming()) {
     printer->Print(
         *vars,
         "// disable synchronous version of this method\n"
@@ -704,8 +669,8 @@
   printer->Print(*vars, "};\n");
 }
 
-void PrintHeaderService(grpc::protobuf::io::Printer *printer,
-                        const grpc::protobuf::ServiceDescriptor *service,
+void PrintHeaderService(Printer *printer,
+                        const Service *service,
                         std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Service"] = service->name();
 
@@ -721,13 +686,13 @@
   printer->Indent();
   printer->Print("virtual ~StubInterface() {}\n");
   for (int i = 0; i < service->method_count(); ++i) {
-    PrintHeaderClientMethodInterfaces(printer, service->method(i), vars, true);
+    PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true);
   }
   printer->Outdent();
   printer->Print("private:\n");
   printer->Indent();
   for (int i = 0; i < service->method_count(); ++i) {
-    PrintHeaderClientMethodInterfaces(printer, service->method(i), vars, false);
+    PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, false);
   }
   printer->Outdent();
   printer->Print("};\n");
@@ -737,17 +702,17 @@
   printer->Indent();
   printer->Print("Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
   for (int i = 0; i < service->method_count(); ++i) {
-    PrintHeaderClientMethod(printer, service->method(i), vars, true);
+    PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
   }
   printer->Outdent();
   printer->Print("\n private:\n");
   printer->Indent();
   printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
   for (int i = 0; i < service->method_count(); ++i) {
-    PrintHeaderClientMethod(printer, service->method(i), vars, false);
+    PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
   }
   for (int i = 0; i < service->method_count(); ++i) {
-    PrintHeaderClientMethodData(printer, service->method(i), vars);
+    PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
   }
   printer->Outdent();
   printer->Print("};\n");
@@ -766,7 +731,7 @@
   printer->Print("Service();\n");
   printer->Print("virtual ~Service();\n");
   for (int i = 0; i < service->method_count(); ++i) {
-    PrintHeaderServerMethodSync(printer, service->method(i), vars);
+    PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
   }
   printer->Outdent();
   printer->Print("};\n");
@@ -774,13 +739,13 @@
   // Server side - Asynchronous
   for (int i = 0; i < service->method_count(); ++i) {
     (*vars)["Idx"] = as_string(i);
-    PrintHeaderServerMethodAsync(printer, service->method(i), vars);
+    PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
   }
 
   printer->Print("typedef ");
 
   for (int i = 0; i < service->method_count(); ++i) {
-    (*vars)["method_name"] = service->method(i)->name();
+    (*vars)["method_name"] = service->method(i).get()->name();
     printer->Print(*vars, "WithAsyncMethod_$method_name$<");
   }
   printer->Print("Service");
@@ -792,20 +757,19 @@
   // Server side - Generic
   for (int i = 0; i < service->method_count(); ++i) {
     (*vars)["Idx"] = as_string(i);
-    PrintHeaderServerMethodGeneric(printer, service->method(i), vars);
+    PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
   }
 
   printer->Outdent();
   printer->Print("};\n");
 }
 
-grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file,
+grpc::string GetHeaderServices(File *file,
                                const Parameters &params) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
-    grpc::protobuf::io::StringOutputStream output_stream(&output);
-    grpc::protobuf::io::Printer printer(&output_stream, '$');
+    auto printer = file->CreatePrinter(&output);
     std::map<grpc::string, grpc::string> vars;
     // Package string is empty or ends with a dot. It is used to fully qualify
     // method names.
@@ -816,80 +780,77 @@
 
     if (!params.services_namespace.empty()) {
       vars["services_namespace"] = params.services_namespace;
-      printer.Print(vars, "\nnamespace $services_namespace$ {\n\n");
+      printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
     }
 
     for (int i = 0; i < file->service_count(); ++i) {
-      PrintHeaderService(&printer, file->service(i), &vars);
-      printer.Print("\n");
+      PrintHeaderService(printer.get(), file->service(i).get(), &vars);
+      printer->Print("\n");
     }
 
     if (!params.services_namespace.empty()) {
-      printer.Print(vars, "}  // namespace $services_namespace$\n\n");
+      printer->Print(vars, "}  // namespace $services_namespace$\n\n");
     }
   }
   return output;
 }
 
-grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params) {
+grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
-    grpc::protobuf::io::StringOutputStream output_stream(&output);
-    grpc::protobuf::io::Printer printer(&output_stream, '$');
+    auto printer = file->CreatePrinter(&output);
     std::map<grpc::string, grpc::string> vars;
 
-    vars["filename"] = file->name();
-    vars["filename_identifier"] = FilenameIdentifier(file->name());
+    vars["filename"] = file->filename();
+    vars["filename_identifier"] = FilenameIdentifier(file->filename());
 
     if (!file->package().empty()) {
-      std::vector<grpc::string> parts =
-          grpc_generator::tokenize(file->package(), ".");
+      std::vector<grpc::string> parts = file->package_parts();
 
       for (auto part = parts.rbegin(); part != parts.rend(); part++) {
         vars["part"] = *part;
-        printer.Print(vars, "}  // namespace $part$\n");
+        printer->Print(vars, "}  // namespace $part$\n");
       }
-      printer.Print(vars, "\n");
+      printer->Print(vars, "\n");
     }
 
-    printer.Print(vars, "\n");
-    printer.Print(vars, "#endif  // GRPC_$filename_identifier$__INCLUDED\n");
+    printer->Print(vars, "\n");
+    printer->Print(vars, "#endif  // GRPC_$filename_identifier$__INCLUDED\n");
   }
   return output;
 }
 
-grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params) {
+grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
-    grpc::protobuf::io::StringOutputStream output_stream(&output);
-    grpc::protobuf::io::Printer printer(&output_stream, '$');
+    auto printer = file->CreatePrinter(&output);
     std::map<grpc::string, grpc::string> vars;
 
-    vars["filename"] = file->name();
-    vars["filename_base"] = grpc_generator::StripProto(file->name());
+    vars["filename"] = file->filename();
+    vars["filename_base"] = file->filename_without_ext();
+    vars["message_header_ext"] = file->message_header_ext();
+    vars["service_header_ext"] = file->service_header_ext();
 
-    printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n");
-    printer.Print(vars,
+    printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
+    printer->Print(vars,
                   "// If you make any local change, they will be lost.\n");
-    printer.Print(vars, "// source: $filename$\n\n");
-    printer.Print(vars, "#include \"$filename_base$.pb.h\"\n");
-    printer.Print(vars, "#include \"$filename_base$.grpc.pb.h\"\n");
-    printer.Print(vars, "\n");
+    printer->Print(vars, "// source: $filename$\n\n");
+    printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+    printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
+    printer->Print(vars, file->additional_headers().c_str());
+    printer->Print(vars, "\n");
   }
   return output;
 }
 
-grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file,
+grpc::string GetSourceIncludes(File *file,
                                const Parameters &params) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
-    grpc::protobuf::io::StringOutputStream output_stream(&output);
-    grpc::protobuf::io::Printer printer(&output_stream, '$');
+    auto printer = file->CreatePrinter(&output);
     std::map<grpc::string, grpc::string> vars;
 
     static const char *headers_strs[] = {
@@ -903,32 +864,29 @@
       "grpc++/impl/codegen/sync_stream.h"
     };
     std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
-    PrintIncludes(&printer, headers, params);
+    PrintIncludes(printer.get(), headers, params);
 
     if (!file->package().empty()) {
-      std::vector<grpc::string> parts =
-          grpc_generator::tokenize(file->package(), ".");
+      std::vector<grpc::string> parts = file->package_parts();
 
       for (auto part = parts.begin(); part != parts.end(); part++) {
         vars["part"] = *part;
-        printer.Print(vars, "namespace $part$ {\n");
+        printer->Print(vars, "namespace $part$ {\n");
       }
     }
 
-    printer.Print(vars, "\n");
+    printer->Print(vars, "\n");
   }
   return output;
 }
 
-void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer,
-                             const grpc::protobuf::MethodDescriptor *method,
+void PrintSourceClientMethod(Printer *printer,
+                             const Method *method,
                              std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
-  (*vars)["Request"] =
-      grpc_cpp_generator::ClassName(method->input_type(), true);
-  (*vars)["Response"] =
-      grpc_cpp_generator::ClassName(method->output_type(), true);
-  if (NoStreaming(method)) {
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  if (method->NoStreaming()) {
     printer->Print(*vars,
                    "::grpc::Status $ns$$Service$::Stub::$Method$("
                    "::grpc::ClientContext* context, "
@@ -951,7 +909,7 @@
                    "rpcmethod_$Method$_, "
                    "context, request);\n"
                    "}\n\n");
-  } else if (ClientOnlyStreaming(method)) {
+  } else if (method->ClientOnlyStreaming()) {
     printer->Print(*vars,
                    "::grpc::ClientWriter< $Request$>* "
                    "$ns$$Service$::Stub::$Method$Raw("
@@ -973,7 +931,7 @@
                    "rpcmethod_$Method$_, "
                    "context, response, tag);\n"
                    "}\n\n");
-  } else if (ServerOnlyStreaming(method)) {
+  } else if (method->ServerOnlyStreaming()) {
     printer->Print(
         *vars,
         "::grpc::ClientReader< $Response$>* "
@@ -996,7 +954,7 @@
                    "rpcmethod_$Method$_, "
                    "context, request, tag);\n"
                    "}\n\n");
-  } else if (BidiStreaming(method)) {
+  } else if (method->BidiStreaming()) {
     printer->Print(
         *vars,
         "::grpc::ClientReaderWriter< $Request$, $Response$>* "
@@ -1023,15 +981,13 @@
   }
 }
 
-void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer,
-                             const grpc::protobuf::MethodDescriptor *method,
+void PrintSourceServerMethod(Printer *printer,
+                             const Method *method,
                              std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
-  (*vars)["Request"] =
-      grpc_cpp_generator::ClassName(method->input_type(), true);
-  (*vars)["Response"] =
-      grpc_cpp_generator::ClassName(method->output_type(), true);
-  if (NoStreaming(method)) {
+  (*vars)["Request"] = method->input_type_name();
+  (*vars)["Response"] = method->output_type_name();
+  if (method->NoStreaming()) {
     printer->Print(*vars,
                    "::grpc::Status $ns$$Service$::Service::$Method$("
                    "::grpc::ServerContext* context, "
@@ -1043,7 +999,7 @@
         "  return ::grpc::Status("
         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
     printer->Print("}\n\n");
-  } else if (ClientOnlyStreaming(method)) {
+  } else if (method->ClientOnlyStreaming()) {
     printer->Print(*vars,
                    "::grpc::Status $ns$$Service$::Service::$Method$("
                    "::grpc::ServerContext* context, "
@@ -1056,7 +1012,7 @@
         "  return ::grpc::Status("
         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
     printer->Print("}\n\n");
-  } else if (ServerOnlyStreaming(method)) {
+  } else if (method->ServerOnlyStreaming()) {
     printer->Print(*vars,
                    "::grpc::Status $ns$$Service$::Service::$Method$("
                    "::grpc::ServerContext* context, "
@@ -1069,7 +1025,7 @@
         "  return ::grpc::Status("
         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
     printer->Print("}\n\n");
-  } else if (BidiStreaming(method)) {
+  } else if (method->BidiStreaming()) {
     printer->Print(*vars,
                    "::grpc::Status $ns$$Service$::Service::$Method$("
                    "::grpc::ServerContext* context, "
@@ -1084,15 +1040,15 @@
   }
 }
 
-void PrintSourceService(grpc::protobuf::io::Printer *printer,
-                        const grpc::protobuf::ServiceDescriptor *service,
+void PrintSourceService(Printer *printer,
+                        const Service *service,
                         std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Service"] = service->name();
 
   printer->Print(*vars,
                  "static const char* $prefix$$Service$_method_names[] = {\n");
   for (int i = 0; i < service->method_count(); ++i) {
-    (*vars)["Method"] = service->method(i)->name();
+    (*vars)["Method"] = service->method(i).get()->name();
     printer->Print(*vars, "  \"/$Package$$Service$/$Method$\",\n");
   }
   printer->Print(*vars, "};\n\n");
@@ -1111,14 +1067,14 @@
   printer->Indent();
   printer->Print(": channel_(channel)");
   for (int i = 0; i < service->method_count(); ++i) {
-    const grpc::protobuf::MethodDescriptor *method = service->method(i);
+    auto method = service->method(i);
     (*vars)["Method"] = method->name();
     (*vars)["Idx"] = as_string(i);
-    if (NoStreaming(method)) {
+    if (method->NoStreaming()) {
       (*vars)["StreamingType"] = "NORMAL_RPC";
-    } else if (ClientOnlyStreaming(method)) {
+    } else if (method->ClientOnlyStreaming()) {
       (*vars)["StreamingType"] = "CLIENT_STREAMING";
-    } else if (ServerOnlyStreaming(method)) {
+    } else if (method->ServerOnlyStreaming()) {
       (*vars)["StreamingType"] = "SERVER_STREAMING";
     } else {
       (*vars)["StreamingType"] = "BIDI_STREAMING";
@@ -1135,21 +1091,19 @@
 
   for (int i = 0; i < service->method_count(); ++i) {
     (*vars)["Idx"] = as_string(i);
-    PrintSourceClientMethod(printer, service->method(i), vars);
+    PrintSourceClientMethod(printer, service->method(i).get(), vars);
   }
 
   printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
   printer->Indent();
   printer->Print(*vars, "(void)$prefix$$Service$_method_names;\n");
   for (int i = 0; i < service->method_count(); ++i) {
-    const grpc::protobuf::MethodDescriptor *method = service->method(i);
+    auto method = service->method(i);
     (*vars)["Idx"] = as_string(i);
     (*vars)["Method"] = method->name();
-    (*vars)["Request"] =
-        grpc_cpp_generator::ClassName(method->input_type(), true);
-    (*vars)["Response"] =
-        grpc_cpp_generator::ClassName(method->output_type(), true);
-    if (NoStreaming(method)) {
+    (*vars)["Request"] = method->input_type_name();
+    (*vars)["Response"] = method->output_type_name();
+    if (method->NoStreaming()) {
       printer->Print(
           *vars,
           "AddMethod(new ::grpc::RpcServiceMethod(\n"
@@ -1159,7 +1113,7 @@
           "$Request$, "
           "$Response$>(\n"
           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
-    } else if (ClientOnlyStreaming(method)) {
+    } else if (method->ClientOnlyStreaming()) {
       printer->Print(
           *vars,
           "AddMethod(new ::grpc::RpcServiceMethod(\n"
@@ -1168,7 +1122,7 @@
           "    new ::grpc::ClientStreamingHandler< "
           "$ns$$Service$::Service, $Request$, $Response$>(\n"
           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
-    } else if (ServerOnlyStreaming(method)) {
+    } else if (method->ServerOnlyStreaming()) {
       printer->Print(
           *vars,
           "AddMethod(new ::grpc::RpcServiceMethod(\n"
@@ -1177,7 +1131,7 @@
           "    new ::grpc::ServerStreamingHandler< "
           "$ns$$Service$::Service, $Request$, $Response$>(\n"
           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
-    } else if (BidiStreaming(method)) {
+    } else if (method->BidiStreaming()) {
       printer->Print(
           *vars,
           "AddMethod(new ::grpc::RpcServiceMethod(\n"
@@ -1195,17 +1149,16 @@
                  "}\n\n");
   for (int i = 0; i < service->method_count(); ++i) {
     (*vars)["Idx"] = as_string(i);
-    PrintSourceServerMethod(printer, service->method(i), vars);
+    PrintSourceServerMethod(printer, service->method(i).get(), vars);
   }
 }
 
-grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file,
+grpc::string GetSourceServices(File *file,
                                const Parameters &params) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
-    grpc::protobuf::io::StringOutputStream output_stream(&output);
-    grpc::protobuf::io::Printer printer(&output_stream, '$');
+    auto printer = file->CreatePrinter(&output);
     std::map<grpc::string, grpc::string> vars;
     // Package string is empty or ends with a dot. It is used to fully qualify
     // method names.
@@ -1222,20 +1175,18 @@
     }
 
     for (int i = 0; i < file->service_count(); ++i) {
-      PrintSourceService(&printer, file->service(i), &vars);
-      printer.Print("\n");
+      PrintSourceService(printer.get(), file->service(i).get(), &vars);
+      printer->Print("\n");
     }
   }
   return output;
 }
 
-grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params) {
+grpc::string GetSourceEpilogue(File *file, const Parameters & /*params*/) {
   grpc::string temp;
 
   if (!file->package().empty()) {
-    std::vector<grpc::string> parts =
-        grpc_generator::tokenize(file->package(), ".");
+    std::vector<grpc::string> parts = file->package_parts();
 
     for (auto part = parts.begin(); part != parts.end(); part++) {
       temp.append("}  // namespace ");
diff --git a/src/compiler/cpp_generator.h b/src/compiler/cpp_generator.h
index 4f9de9d..953ddfd 100644
--- a/src/compiler/cpp_generator.h
+++ b/src/compiler/cpp_generator.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,23 @@
 #ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H
 #define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H
 
-#include "src/compiler/config.h"
+// cpp_generator.h/.cc do not directly depend on GRPC/ProtoBuf, such that they
+// can be used to generate code for other serialization systems, such as
+// FlatBuffers.
+
+#include <memory>
+#include <vector>
+
+#ifndef GRPC_CUSTOM_STRING
+#include <string>
+#define GRPC_CUSTOM_STRING std::string
+#endif
+
+namespace grpc {
+
+typedef GRPC_CUSTOM_STRING string;
+
+}  // namespace grpc
 
 namespace grpc_cpp_generator {
 
@@ -48,37 +64,83 @@
   grpc::string grpc_search_path;
 };
 
+// An abstract interface representing a method.
+struct Method {
+  virtual ~Method() {}
+
+  virtual grpc::string name() const = 0;
+
+  virtual grpc::string input_type_name() const = 0;
+  virtual grpc::string output_type_name() const = 0;
+
+  virtual bool NoStreaming() const = 0;
+  virtual bool ClientOnlyStreaming() const = 0;
+  virtual bool ServerOnlyStreaming() const = 0;
+  virtual bool BidiStreaming() const = 0;
+};
+
+// An abstract interface representing a service.
+struct Service {
+  virtual ~Service() {}
+
+  virtual grpc::string name() const = 0;
+
+  virtual int method_count() const = 0;
+  virtual std::unique_ptr<const Method> method(int i) const = 0;
+};
+
+struct Printer {
+  virtual ~Printer() {}
+
+  virtual void Print(const std::map<grpc::string, grpc::string> &vars,
+                     const char *template_string) = 0;
+  virtual void Print(const char *string) = 0;
+  virtual void Indent() = 0;
+  virtual void Outdent() = 0;
+};
+
+// An interface that allows the source generated to be output using various
+// libraries/idls/serializers.
+struct File {
+  virtual ~File() {}
+
+  virtual grpc::string filename() const = 0;
+  virtual grpc::string filename_without_ext() const = 0;
+  virtual grpc::string message_header_ext() const = 0;
+  virtual grpc::string service_header_ext() const = 0;
+  virtual grpc::string package() const = 0;
+  virtual std::vector<grpc::string> package_parts() const = 0;
+  virtual grpc::string additional_headers() const = 0;
+
+  virtual int service_count() const = 0;
+  virtual std::unique_ptr<const Service> service(int i) const = 0;
+
+  virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
+};
+
 // Return the prologue of the generated header file.
-grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetHeaderPrologue(File *file, const Parameters &params);
 
 // Return the includes needed for generated header file.
-grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetHeaderIncludes(File *file, const Parameters &params);
 
 // Return the includes needed for generated source file.
-grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetSourceIncludes(File *file, const Parameters &params);
 
 // Return the epilogue of the generated header file.
-grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetHeaderEpilogue(File *file, const Parameters &params);
 
 // Return the prologue of the generated source file.
-grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetSourcePrologue(File *file, const Parameters &params);
 
 // Return the services for generated header file.
-grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetHeaderServices(File *file, const Parameters &params);
 
 // Return the services for generated source file.
-grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetSourceServices(File *file, const Parameters &params);
 
 // Return the epilogue of the generated source file.
-grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file,
-                               const Parameters &params);
+grpc::string GetSourceEpilogue(File *file, const Parameters &params);
 
 }  // namespace grpc_cpp_generator
 
diff --git a/src/compiler/cpp_plugin.cc b/src/compiler/cpp_plugin.cc
index d8ada48..e321c64 100644
--- a/src/compiler/cpp_plugin.cc
+++ b/src/compiler/cpp_plugin.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,110 @@
 #include "src/compiler/cpp_generator.h"
 #include "src/compiler/cpp_generator_helpers.h"
 
+class ProtoBufMethod : public grpc_cpp_generator::Method {
+ public:
+  ProtoBufMethod(const grpc::protobuf::MethodDescriptor *method)
+    : method_(method) {}
+
+  grpc::string name() const { return method_->name(); }
+
+  grpc::string input_type_name() const {
+    return grpc_cpp_generator::ClassName(method_->input_type(), true);
+  }
+  grpc::string output_type_name() const {
+    return grpc_cpp_generator::ClassName(method_->output_type(), true);
+  }
+
+  bool NoStreaming() const {
+    return !method_->client_streaming() && !method_->server_streaming();
+  }
+
+  bool ClientOnlyStreaming() const {
+    return method_->client_streaming() && !method_->server_streaming();
+  }
+
+  bool ServerOnlyStreaming() const {
+    return !method_->client_streaming() && method_->server_streaming();
+  }
+
+  bool BidiStreaming() const {
+    return method_->client_streaming() && method_->server_streaming();
+  }
+
+ private:
+  const grpc::protobuf::MethodDescriptor *method_;
+};
+
+class ProtoBufService : public grpc_cpp_generator::Service {
+ public:
+  ProtoBufService(const grpc::protobuf::ServiceDescriptor *service)
+    : service_(service) {}
+
+  grpc::string name() const { return service_->name(); }
+
+  int method_count() const { return service_->method_count(); };
+  std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const {
+    return std::unique_ptr<const grpc_cpp_generator::Method>(
+          new ProtoBufMethod(service_->method(i)));
+  };
+
+ private:
+  const grpc::protobuf::ServiceDescriptor *service_;
+};
+
+class ProtoBufPrinter : public grpc_cpp_generator::Printer {
+ public:
+  ProtoBufPrinter(grpc::string *str)
+    : output_stream_(str), printer_(&output_stream_, '$') {}
+
+  void Print(const std::map<grpc::string, grpc::string> &vars,
+             const char *string_template) {
+    printer_.Print(vars, string_template);
+  }
+
+  void Print(const char *string) { printer_.Print(string); }
+  void Indent() { printer_.Indent(); }
+  void Outdent() { printer_.Outdent(); }
+
+ private:
+  grpc::protobuf::io::StringOutputStream output_stream_;
+  grpc::protobuf::io::Printer printer_;
+};
+
+class ProtoBufFile : public grpc_cpp_generator::File {
+ public:
+  ProtoBufFile(const grpc::protobuf::FileDescriptor *file) : file_(file) {}
+
+  grpc::string filename() const { return file_->name(); }
+  grpc::string filename_without_ext() const {
+    return grpc_generator::StripProto(filename());
+  }
+
+  grpc::string message_header_ext() const { return ".pb.h"; }
+  grpc::string service_header_ext() const { return ".grpc.pb.h"; }
+
+  grpc::string package() const { return file_->package(); }
+  std::vector<grpc::string> package_parts() const {
+    return grpc_generator::tokenize(package(), ".");
+  }
+
+  grpc::string additional_headers() const { return ""; }
+
+  int service_count() const { return file_->service_count(); };
+  std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const {
+    return std::unique_ptr<const grpc_cpp_generator::Service> (
+          new ProtoBufService(file_->service(i)));
+  }
+
+  std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(grpc::string *str) const {
+    return std::unique_ptr<grpc_cpp_generator::Printer>(
+          new ProtoBufPrinter(str));
+  }
+
+ private:
+  const grpc::protobuf::FileDescriptor *file_;
+};
+
 class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
  public:
   CppGrpcGenerator() {}
@@ -61,6 +165,8 @@
     grpc_cpp_generator::Parameters generator_parameters;
     generator_parameters.use_system_headers = true;
 
+    ProtoBufFile pbfile(file);
+
     if (!parameter.empty()) {
       std::vector<grpc::string> parameters_list =
         grpc_generator::tokenize(parameter, ",");
@@ -92,10 +198,10 @@
     grpc::string file_name = grpc_generator::StripProto(file->name());
 
     grpc::string header_code =
-        grpc_cpp_generator::GetHeaderPrologue(file, generator_parameters) +
-        grpc_cpp_generator::GetHeaderIncludes(file, generator_parameters) +
-        grpc_cpp_generator::GetHeaderServices(file, generator_parameters) +
-        grpc_cpp_generator::GetHeaderEpilogue(file, generator_parameters);
+        grpc_cpp_generator::GetHeaderPrologue(&pbfile, generator_parameters) +
+        grpc_cpp_generator::GetHeaderIncludes(&pbfile, generator_parameters) +
+        grpc_cpp_generator::GetHeaderServices(&pbfile, generator_parameters) +
+        grpc_cpp_generator::GetHeaderEpilogue(&pbfile, generator_parameters);
     std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> header_output(
         context->Open(file_name + ".grpc.pb.h"));
     grpc::protobuf::io::CodedOutputStream header_coded_out(
@@ -103,10 +209,10 @@
     header_coded_out.WriteRaw(header_code.data(), header_code.size());
 
     grpc::string source_code =
-        grpc_cpp_generator::GetSourcePrologue(file, generator_parameters) +
-        grpc_cpp_generator::GetSourceIncludes(file, generator_parameters) +
-        grpc_cpp_generator::GetSourceServices(file, generator_parameters) +
-        grpc_cpp_generator::GetSourceEpilogue(file, generator_parameters);
+        grpc_cpp_generator::GetSourcePrologue(&pbfile, generator_parameters) +
+        grpc_cpp_generator::GetSourceIncludes(&pbfile, generator_parameters) +
+        grpc_cpp_generator::GetSourceServices(&pbfile, generator_parameters) +
+        grpc_cpp_generator::GetSourceEpilogue(&pbfile, generator_parameters);
     std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> source_output(
         context->Open(file_name + ".grpc.pb.cc"));
     grpc::protobuf::io::CodedOutputStream source_coded_out(
diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc
index f6079bd..69e2738 100644
--- a/src/compiler/csharp_generator.cc
+++ b/src/compiler/csharp_generator.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,6 +81,10 @@
   return "I" + service->name();
 }
 
+std::string GetServerClassName(const ServiceDescriptor* service) {
+  return service->name() + "Base";
+}
+
 std::string GetCSharpMethodType(MethodType method_type) {
   switch (method_type) {
     case METHODTYPE_NO_STREAMING:
@@ -108,10 +112,14 @@
   return "__Method_" + method->name();
 }
 
-std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) {
+std::string GetMethodRequestParamMaybe(const MethodDescriptor *method,
+                                       bool invocation_param=false) {
   if (method->client_streaming()) {
     return "";
   }
+  if (invocation_param) {
+    return "request, ";
+  }
   return GetClassName(method->input_type()) + " request, ";
 }
 
@@ -242,6 +250,8 @@
 
 void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
   out->Print("// client interface\n");
+  out->Print("[System.Obsolete(\"Client side interfaced will be removed "
+             "in the next release. Use client class directly.\")]\n");
   out->Print("public interface $name$\n", "name",
              GetClientInterfaceName(service));
   out->Print("{\n");
@@ -290,6 +300,8 @@
 
 void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
   out->Print("// server-side interface\n");
+  out->Print("[System.Obsolete(\"Service implementations should inherit"
+      " from the generated abstract base class instead.\")]\n");
   out->Print("public interface $name$\n", "name",
              GetServerInterfaceName(service));
   out->Print("{\n");
@@ -309,21 +321,64 @@
   out->Print("\n");
 }
 
+void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
+  out->Print("// server-side abstract class\n");
+  out->Print("public abstract class $name$\n", "name",
+             GetServerClassName(service));
+  out->Print("{\n");
+  out->Indent();
+  for (int i = 0; i < service->method_count(); i++) {
+    const MethodDescriptor *method = service->method(i);
+    out->Print(
+        "public virtual $returntype$ $methodname$($request$$response_stream_maybe$, "
+        "ServerCallContext context)\n",
+        "methodname", method->name(), "returntype",
+        GetMethodReturnTypeServer(method), "request",
+        GetMethodRequestParamServer(method), "response_stream_maybe",
+        GetMethodResponseStreamMaybe(method));
+    out->Print("{\n");
+    out->Indent();
+    out->Print("throw new RpcException("
+               "new Status(StatusCode.Unimplemented, \"\"));\n");
+    out->Outdent();
+    out->Print("}\n\n");
+  }
+  out->Outdent();
+  out->Print("}\n");
+  out->Print("\n");
+}
+
 void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
   out->Print("// client stub\n");
   out->Print(
-      "public class $name$ : ClientBase, $interface$\n",
-      "name", GetClientClassName(service), "interface",
-      GetClientInterfaceName(service));
+      "public class $name$ : ClientBase<$name$>, $interface$\n",
+      "name", GetClientClassName(service),
+      "interface", GetClientInterfaceName(service));
   out->Print("{\n");
   out->Indent();
 
   // constructors
-  out->Print(
-      "public $name$(Channel channel) : base(channel)\n",
-      "name", GetClientClassName(service));
+  out->Print("public $name$(Channel channel) : base(channel)\n",
+             "name", GetClientClassName(service));
   out->Print("{\n");
   out->Print("}\n");
+  out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n",
+             "name", GetClientClassName(service));
+  out->Print("{\n");
+  out->Print("}\n");
+  out->Print("///<summary>Protected parameterless constructor to allow creation"
+             " of test doubles.</summary>\n");
+  out->Print("protected $name$() : base()\n",
+             "name", GetClientClassName(service));
+  out->Print("{\n");
+  out->Print("}\n");
+  out->Print("///<summary>Protected constructor to allow creation of configured"
+             " clients.</summary>\n");
+  out->Print("protected $name$(ClientBaseConfiguration configuration)"
+             " : base(configuration)\n",
+             "name", GetClientClassName(service));
+  out->Print("{\n");
+  out->Print("}\n\n");
 
   for (int i = 0; i < service->method_count(); i++) {
     const MethodDescriptor *method = service->method(i);
@@ -331,30 +386,26 @@
 
     if (method_type == METHODTYPE_NO_STREAMING) {
       // unary calls have an extra synchronous stub method
-      out->Print(
-          "public $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
+      out->Print("public virtual $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
           "methodname", method->name(), "request",
           GetClassName(method->input_type()), "response",
           GetClassName(method->output_type()));
       out->Print("{\n");
       out->Indent();
-      out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
-                 "methodfield", GetMethodFieldName(method));
-      out->Print("return Calls.BlockingUnaryCall(call, request);\n");
+      out->Print("return $methodname$(request, new CallOptions(headers, deadline, cancellationToken));\n",
+                 "methodname", method->name());
       out->Outdent();
       out->Print("}\n");
 
       // overload taking CallOptions as a param
-      out->Print(
-                "public $response$ $methodname$($request$ request, CallOptions options)\n",
-                "methodname", method->name(), "request",
-                GetClassName(method->input_type()), "response",
-                GetClassName(method->output_type()));
+      out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n",
+          "methodname", method->name(), "request",
+          GetClassName(method->input_type()), "response",
+          GetClassName(method->output_type()));
       out->Print("{\n");
       out->Indent();
-      out->Print("var call = CreateCall($methodfield$, options);\n",
+      out->Print("return CallInvoker.BlockingUnaryCall($methodfield$, null, options, request);\n",
                  "methodfield", GetMethodFieldName(method));
-      out->Print("return Calls.BlockingUnaryCall(call, request);\n");
       out->Outdent();
       out->Print("}\n");
     }
@@ -364,57 +415,44 @@
       method_name += "Async";  // prevent name clash with synchronous method.
     }
     out->Print(
-        "public $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
-        "methodname", method_name, "request_maybe",
-        GetMethodRequestParamMaybe(method), "returntype",
-        GetMethodReturnTypeClient(method));
+            "public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
+            "methodname", method_name, "request_maybe",
+            GetMethodRequestParamMaybe(method), "returntype",
+            GetMethodReturnTypeClient(method));
     out->Print("{\n");
     out->Indent();
-    out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
-               "methodfield", GetMethodFieldName(method));
-    switch (GetMethodType(method)) {
-      case METHODTYPE_NO_STREAMING:
-        out->Print("return Calls.AsyncUnaryCall(call, request);\n");
-        break;
-      case METHODTYPE_CLIENT_STREAMING:
-        out->Print("return Calls.AsyncClientStreamingCall(call);\n");
-        break;
-      case METHODTYPE_SERVER_STREAMING:
-        out->Print(
-            "return Calls.AsyncServerStreamingCall(call, request);\n");
-        break;
-      case METHODTYPE_BIDI_STREAMING:
-        out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
-        break;
-      default:
-        GOOGLE_LOG(FATAL)<< "Can't get here.";
-    }
+
+    out->Print("return $methodname$($request_maybe$new CallOptions(headers, deadline, cancellationToken));\n",
+               "methodname", method_name,
+               "request_maybe", GetMethodRequestParamMaybe(method, true));
     out->Outdent();
     out->Print("}\n");
 
     // overload taking CallOptions as a param
     out->Print(
-        "public $returntype$ $methodname$($request_maybe$CallOptions options)\n",
+        "public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n",
         "methodname", method_name, "request_maybe",
         GetMethodRequestParamMaybe(method), "returntype",
         GetMethodReturnTypeClient(method));
     out->Print("{\n");
     out->Indent();
-    out->Print("var call = CreateCall($methodfield$, options);\n",
-               "methodfield", GetMethodFieldName(method));
     switch (GetMethodType(method)) {
       case METHODTYPE_NO_STREAMING:
-        out->Print("return Calls.AsyncUnaryCall(call, request);\n");
+        out->Print("return CallInvoker.AsyncUnaryCall($methodfield$, null, options, request);\n",
+                   "methodfield", GetMethodFieldName(method));
         break;
       case METHODTYPE_CLIENT_STREAMING:
-        out->Print("return Calls.AsyncClientStreamingCall(call);\n");
+        out->Print("return CallInvoker.AsyncClientStreamingCall($methodfield$, null, options);\n",
+                   "methodfield", GetMethodFieldName(method));
         break;
       case METHODTYPE_SERVER_STREAMING:
         out->Print(
-            "return Calls.AsyncServerStreamingCall(call, request);\n");
+            "return CallInvoker.AsyncServerStreamingCall($methodfield$, null, options, request);\n",
+            "methodfield", GetMethodFieldName(method));
         break;
       case METHODTYPE_BIDI_STREAMING:
-        out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
+        out->Print("return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, options);\n",
+                   "methodfield", GetMethodFieldName(method));
         break;
       default:
         GOOGLE_LOG(FATAL)<< "Can't get here.";
@@ -422,17 +460,30 @@
     out->Outdent();
     out->Print("}\n");
   }
+
+  // override NewInstance method
+  out->Print("protected override $name$ NewInstance(ClientBaseConfiguration configuration)\n",
+             "name", GetClientClassName(service));
+  out->Print("{\n");
+  out->Indent();
+  out->Print("return new $name$(configuration);\n",
+             "name", GetClientClassName(service));
+  out->Outdent();
+  out->Print("}\n");
+
   out->Outdent();
   out->Print("}\n");
   out->Print("\n");
 }
 
-void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
+void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service,
+                               bool use_server_class) {
   out->Print(
       "// creates service definition that can be registered with a server\n");
   out->Print(
       "public static ServerServiceDefinition BindService($interface$ serviceImpl)\n",
-      "interface", GetServerInterfaceName(service));
+      "interface", use_server_class ? GetServerClassName(service) :
+          GetServerInterfaceName(service));
   out->Print("{\n");
   out->Indent();
 
@@ -489,8 +540,10 @@
   GenerateServiceDescriptorProperty(out, service);
   GenerateClientInterface(out, service);
   GenerateServerInterface(out, service);
+  GenerateServerClass(out, service);
   GenerateClientStub(out, service);
-  GenerateBindServiceMethod(out, service);
+  GenerateBindServiceMethod(out, service, false);
+  GenerateBindServiceMethod(out, service, true);
   GenerateNewStubMethods(out, service);
 
   out->Outdent();
diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h
index e1bb66a..3ed0500 100644
--- a/src/compiler/generator_helpers.h
+++ b/src/compiler/generator_helpers.h
@@ -52,6 +52,16 @@
   return false;
 }
 
+inline bool StripPrefix(grpc::string *name, const grpc::string &prefix) {
+  if (name->length() >= prefix.length()) {
+    if (name->substr(0, prefix.size()) == prefix) {
+      *name = name->substr(prefix.size());
+      return true;
+    }
+  }
+  return false;
+}
+
 inline grpc::string StripProto(grpc::string filename) {
   if (!StripSuffix(&filename, ".protodevel")) {
     StripSuffix(&filename, ".proto");
diff --git a/src/compiler/node_generator.cc b/src/compiler/node_generator.cc
new file mode 100644
index 0000000..822622c
--- /dev/null
+++ b/src/compiler/node_generator.cc
@@ -0,0 +1,277 @@
+/*
+ *
+ * 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 <map>
+
+#include "src/compiler/config.h"
+#include "src/compiler/generator_helpers.h"
+#include "src/compiler/node_generator_helpers.h"
+
+using grpc::protobuf::FileDescriptor;
+using grpc::protobuf::ServiceDescriptor;
+using grpc::protobuf::MethodDescriptor;
+using grpc::protobuf::Descriptor;
+using grpc::protobuf::io::Printer;
+using grpc::protobuf::io::StringOutputStream;
+using std::map;
+
+namespace grpc_node_generator {
+namespace {
+
+// Returns the alias we assign to the module of the given .proto filename
+// when importing. Copied entirely from
+// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
+grpc::string ModuleAlias(const grpc::string filename) {
+  // This scheme could technically cause problems if a file includes any 2 of:
+  //   foo/bar_baz.proto
+  //   foo_bar_baz.proto
+  //   foo_bar/baz.proto
+  //
+  // We'll worry about this problem if/when we actually see it.  This name isn't
+  // exposed to users so we can change it later if we need to.
+  grpc::string basename = grpc_generator::StripProto(filename);
+  basename = grpc_generator::StringReplace(basename, "-", "$");
+  basename = grpc_generator::StringReplace(basename, "/", "_");
+  return basename + "_pb";
+}
+
+// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
+// message file foo/bar/baz.js
+grpc::string GetJSMessageFilename(const grpc::string& filename) {
+  grpc::string name = filename;
+  return grpc_generator::StripProto(name) + "_pb.js";
+}
+
+// Given a filename like foo/bar/baz.proto, returns the root directory
+// path ../../
+grpc::string GetRootPath(const grpc::string& filename) {
+  size_t slashes = std::count(filename.begin(), filename.end(), '/');
+  if (slashes == 0) {
+    return "./";
+  }
+  grpc::string result = "";
+  for (size_t i = 0; i < slashes; i++) {
+    result += "../";
+  }
+  return result;
+}
+
+// Return the relative path to load to_file from the directory containing
+// from_file, assuming that both paths are relative to the same directory
+grpc::string GetRelativePath(const grpc::string& from_file,
+                             const grpc::string& to_file) {
+  return GetRootPath(from_file) + to_file;
+}
+
+/* Finds all message types used in all services in the file, and returns them
+ * as a map of fully qualified message type name to message descriptor */
+map<grpc::string, const Descriptor*> GetAllMessages(const FileDescriptor *file) {
+  map<grpc::string, const Descriptor*> message_types;
+  for (int service_num = 0; service_num < file->service_count(); service_num++) {
+    const ServiceDescriptor* service = file->service(service_num);
+    for (int method_num = 0; method_num < service->method_count(); method_num++) {
+      const MethodDescriptor* method = service->method(method_num);
+      const Descriptor* input_type = method->input_type();
+      const Descriptor* output_type = method->output_type();
+      message_types[input_type->name()] = input_type;
+      message_types[output_type->name()] = output_type;
+    }
+  }
+  return message_types;
+}
+
+grpc::string MessageIdentifierName(const grpc::string& name) {
+  return grpc_generator::StringReplace(name, ".", "_");
+}
+
+grpc::string NodeObjectPath(const Descriptor *descriptor) {
+  grpc::string module_alias = ModuleAlias(descriptor->file()->name());
+  grpc::string name = descriptor->name();
+  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
+  return module_alias + "." + name;
+}
+
+// Prints out the message serializer and deserializer functions
+void PrintMessageTransformer(const Descriptor *descriptor, Printer *out) {
+  map<grpc::string, grpc::string> template_vars;
+  template_vars["identifier_name"] = MessageIdentifierName(descriptor->name());
+  template_vars["name"] = descriptor->name();
+  template_vars["node_name"] = NodeObjectPath(descriptor);
+  // Print the serializer
+  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
+  out->Indent();
+  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
+  out->Indent();
+  out->Print(template_vars,
+             "throw new Error('Expected argument of type $name$');\n");
+  out->Outdent();
+  out->Print("}\n");
+  out->Print("return new Buffer(arg.serializeBinary());\n");
+  out->Outdent();
+  out->Print("}\n\n");
+
+  // Print the deserializer
+  out->Print(template_vars,
+             "function deserialize_$identifier_name$(buffer_arg) {\n");
+  out->Indent();
+  out->Print(
+      template_vars,
+      "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
+  out->Outdent();
+  out->Print("}\n\n");
+}
+
+void PrintMethod(const MethodDescriptor *method, Printer *out) {
+  const Descriptor *input_type = method->input_type();
+  const Descriptor *output_type = method->output_type();
+  map<grpc::string, grpc::string> vars;
+  vars["service_name"] = method->service()->full_name();
+  vars["name"] = method->name();
+  vars["input_type"] = NodeObjectPath(input_type);
+  vars["input_type_id"] = MessageIdentifierName(input_type->name());
+  vars["output_type"] = NodeObjectPath(output_type);
+  vars["output_type_id"] = MessageIdentifierName(output_type->name());
+  vars["client_stream"] = method->client_streaming() ? "true" : "false";
+  vars["server_stream"] = method->server_streaming() ? "true" : "false";
+  out->Print("{\n");
+  out->Indent();
+  out->Print(vars, "path: '/$service_name$/$name$',\n");
+  out->Print(vars, "requestStream: $client_stream$,\n");
+  out->Print(vars, "responseStream: $server_stream$,\n");
+  out->Print(vars, "requestType: $input_type$,\n");
+  out->Print(vars, "responseType: $output_type$,\n");
+  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
+  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
+  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
+  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
+  out->Outdent();
+  out->Print("}");
+}
+
+// Prints out the service descriptor object
+void PrintService(const ServiceDescriptor *service, Printer *out) {
+  map<grpc::string, grpc::string> template_vars;
+  template_vars["name"] = service->name();
+  out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
+  out->Indent();
+  for (int i = 0; i < service->method_count(); i++) {
+    grpc::string method_name = grpc_generator::LowercaseFirstLetter(
+        service->method(i)->name());
+    out->Print("$method_name$: ",
+               "method_name", method_name);
+    PrintMethod(service->method(i), out);
+    out->Print(",\n");
+  }
+  out->Outdent();
+  out->Print("};\n\n");
+  out->Print(template_vars, "exports.$name$Client = "
+             "grpc.makeGenericClientConstructor($name$Service);\n");
+}
+
+}
+
+grpc::string GetImports(const FileDescriptor *file) {
+  grpc::string output;
+  {
+    StringOutputStream output_stream(&output);
+    Printer out(&output_stream, '$');
+
+    if (file->service_count() == 0) {
+      return output;
+    }
+
+    out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");
+
+    out.Print("'use strict';\n");
+
+    out.Print("var grpc = require('grpc');\n");
+    if (file->message_type_count() > 0) {
+      grpc::string file_path = GetRelativePath(file->name(),
+                                               GetJSMessageFilename(
+                                                   file->name()));
+      out.Print("var $module_alias$ = require('$file_path$');\n",
+                "module_alias", ModuleAlias(file->name()),
+                "file_path", file_path);
+    }
+
+    for (int i = 0; i < file->dependency_count(); i++) {
+      grpc::string file_path = GetRelativePath(
+          file->name(), GetJSMessageFilename(file->dependency(i)->name()));
+      out.Print("var $module_alias$ = require('$file_path$');\n",
+                "module_alias", ModuleAlias(file->dependency(i)->name()),
+                "file_path", file_path);
+    }
+    out.Print("\n");
+  }
+  return output;
+}
+
+grpc::string GetTransformers(const FileDescriptor *file) {
+  grpc::string output;
+  {
+    StringOutputStream output_stream(&output);
+    Printer out(&output_stream, '$');
+
+    if (file->service_count() == 0) {
+      return output;
+    }
+
+    map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
+    for (std::map<grpc::string, const Descriptor*>::iterator it =
+             messages.begin();
+         it != messages.end(); it++) {
+      PrintMessageTransformer(it->second, &out);
+    }
+    out.Print("\n");
+  }
+  return output;
+}
+
+grpc::string GetServices(const FileDescriptor *file) {
+  grpc::string output;
+  {
+    StringOutputStream output_stream(&output);
+    Printer out(&output_stream, '$');
+
+    if (file->service_count() == 0) {
+      return output;
+    }
+
+    for (int i = 0; i < file->service_count(); i++) {
+      PrintService(file->service(i), &out);
+    }
+  }
+  return output;
+}
+
+}  // namespace grpc_node_generator
diff --git a/src/compiler/node_generator.h b/src/compiler/node_generator.h
new file mode 100644
index 0000000..249a0d0
--- /dev/null
+++ b/src/compiler/node_generator.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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_INTERNAL_COMPILER_NODE_GENERATOR_H
+#define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H
+
+#include "src/compiler/config.h"
+
+namespace grpc_node_generator {
+
+grpc::string GetImports(const grpc::protobuf::FileDescriptor *file);
+
+grpc::string GetTransformers(const grpc::protobuf::FileDescriptor *file);
+
+grpc::string GetServices(const grpc::protobuf::FileDescriptor *file);
+
+}  // namespace grpc_node_generator
+
+#endif  // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H
diff --git a/src/compiler/node_generator_helpers.h b/src/compiler/node_generator_helpers.h
new file mode 100644
index 0000000..f41a2bc
--- /dev/null
+++ b/src/compiler/node_generator_helpers.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H
+#define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H
+
+#include <algorithm>
+
+#include "src/compiler/config.h"
+#include "src/compiler/generator_helpers.h"
+
+namespace grpc_node_generator {
+
+inline grpc::string GetJSServiceFilename(const grpc::string& filename) {
+  return grpc_generator::StripProto(filename) + "_grpc_pb.js";
+}
+
+}  // namespace grpc_node_generator
+
+#endif  // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H
diff --git a/src/compiler/node_plugin.cc b/src/compiler/node_plugin.cc
new file mode 100644
index 0000000..ac5ced3
--- /dev/null
+++ b/src/compiler/node_plugin.cc
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+// Generates Node gRPC service interface out of Protobuf IDL.
+
+#include <memory>
+
+#include "src/compiler/config.h"
+#include "src/compiler/node_generator.h"
+#include "src/compiler/node_generator_helpers.h"
+
+using grpc_node_generator::GetImports;
+using grpc_node_generator::GetJSServiceFilename;
+using grpc_node_generator::GetServices;
+using grpc_node_generator::GetTransformers;
+
+class NodeGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
+ public:
+  NodeGrpcGenerator() {}
+  ~NodeGrpcGenerator() {}
+
+  bool Generate(const grpc::protobuf::FileDescriptor *file,
+                const grpc::string &parameter,
+                grpc::protobuf::compiler::GeneratorContext *context,
+                grpc::string *error) const {
+    grpc::string code = GetImports(file) +
+        GetTransformers(file) +
+        GetServices(file);
+    if (code.size() == 0) {
+      return true;
+    }
+
+    // Get output file name
+    grpc::string file_name = GetJSServiceFilename(file->name());
+
+    std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
+        context->Open(file_name));
+    grpc::protobuf::io::CodedOutputStream coded_out(output.get());
+    coded_out.WriteRaw(code.data(), code.size());
+    return true;
+  }
+};
+
+int main(int argc, char *argv[]) {
+  NodeGrpcGenerator generator;
+  return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
+}
diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc
index 4fd5dfb..02c0328 100644
--- a/src/compiler/python_generator.cc
+++ b/src/compiler/python_generator.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -190,11 +190,10 @@
         "Documentation", doc,
       });
   out->Print("\n");
-  out->Print(dict, "class Beta$Service$Servicer(object):\n");
+  out->Print(dict, "class Beta$Service$Servicer(six.with_metaclass(abc.ABCMeta, object)):\n");
   {
     IndentScope raii_class_indent(out);
     out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
-    out->Print("__metaclass__ = abc.ABCMeta\n");
     for (int i = 0; i < service->method_count(); ++i) {
       auto meth = service->method(i);
       grpc::string arg_name = meth->client_streaming() ?
@@ -219,11 +218,10 @@
         "Documentation", doc,
       });
   out->Print("\n");
-  out->Print(dict, "class Beta$Service$Stub(object):\n");
+  out->Print(dict, "class Beta$Service$Stub(six.with_metaclass(abc.ABCMeta, object)):\n");
   {
     IndentScope raii_class_indent(out);
     out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
-    out->Print("__metaclass__ = abc.ABCMeta\n");
     for (int i = 0; i < service->method_count(); ++i) {
       const MethodDescriptor* meth = service->method(i);
       grpc::string arg_name = meth->client_streaming() ?
@@ -449,6 +447,7 @@
 bool PrintPreamble(const FileDescriptor* file,
                    const GeneratorConfiguration& config, Printer* out) {
   out->Print("import abc\n");
+  out->Print("import six\n");
   out->Print("from $Package$ import implementations as beta_implementations\n",
              "Package", config.beta_package_root);
   out->Print("from grpc.framework.common import cardinality\n");
diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h
index 68da18f..e56b679 100644
--- a/src/compiler/python_generator.h
+++ b/src/compiler/python_generator.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc
index d781ddb..92a07b2 100644
--- a/src/compiler/python_plugin.cc
+++ b/src/compiler/python_plugin.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc
index 2991375..5ac56ad 100644
--- a/src/compiler/ruby_generator.cc
+++ b/src/compiler/ruby_generator.cc
@@ -55,11 +55,11 @@
 // Prints out the method using the ruby gRPC DSL.
 void PrintMethod(const MethodDescriptor *method, const grpc::string &package,
                  Printer *out) {
-  grpc::string input_type = RubyTypeOf(method->input_type()->name(), package);
+  grpc::string input_type = RubyTypeOf(method->input_type()->full_name(), package);
   if (method->client_streaming()) {
     input_type = "stream(" + input_type + ")";
   }
-  grpc::string output_type = RubyTypeOf(method->output_type()->name(), package);
+  grpc::string output_type = RubyTypeOf(method->output_type()->full_name(), package);
   if (method->server_streaming()) {
     output_type = "stream(" + output_type + ")";
   }
diff --git a/src/compiler/ruby_generator_string-inl.h b/src/compiler/ruby_generator_string-inl.h
index 8da3a88..d1ad871 100644
--- a/src/compiler/ruby_generator_string-inl.h
+++ b/src/compiler/ruby_generator_string-inl.h
@@ -115,6 +115,7 @@
     return res;
   } else {
     std::vector<grpc::string> prefixes_and_type = Split(res, '.');
+    res.clear();
     for (unsigned int i = 0; i < prefixes_and_type.size(); ++i) {
       if (i != 0) {
         res += "::";  // switch '.' to the ruby module delim
diff --git a/src/core/census/aggregation.h b/src/core/census/aggregation.h
deleted file mode 100644
index e0ef963..0000000
--- a/src/core/census/aggregation.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *
- * 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 <stddef.h>
-
-#ifndef GRPC_CORE_CENSUS_AGGREGATION_H
-#define GRPC_CORE_CENSUS_AGGREGATION_H
-
-/** Structure used to describe an aggregation type. */
-struct census_aggregation_ops {
-  /* Create a new aggregation. The pointer returned can be used in future calls
-     to clone(), free(), record(), data() and reset(). */
-  void *(*create)(const void *create_arg);
-  /* Make a copy of an aggregation created by create() */
-  void *(*clone)(const void *aggregation);
-  /* Destroy an aggregation created by create() */
-  void (*free)(void *aggregation);
-  /* Record a new value against aggregation. */
-  void (*record)(void *aggregation, double value);
-  /* Return current aggregation data. The caller must cast this object into
-     the correct type for the aggregation result. The object returned can be
-     freed by using free_data(). */
-  void *(*data)(const void *aggregation);
-  /* free data returned by data() */
-  void (*free_data)(void *data);
-  /* Reset an aggregation to default (zero) values. */
-  void (*reset)(void *aggregation);
-  /* Merge 'from' aggregation into 'to'. Both aggregations must be compatible */
-  void (*merge)(void *to, const void *from);
-  /* Fill buffer with printable string version of aggregation contents. For
-     debugging only. Returns the number of bytes added to buffer (a value == n
-     implies the buffer was of insufficient size). */
-  size_t (*print)(const void *aggregation, char *buffer, size_t n);
-};
-
-#endif /* GRPC_CORE_CENSUS_AGGREGATION_H */
diff --git a/src/core/census/context.c b/src/core/census/context.c
deleted file mode 100644
index 89b8ee0..0000000
--- a/src/core/census/context.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- *
- * 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 <grpc/census.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/useful.h>
-#include <stdbool.h>
-#include <string.h>
-#include "src/core/support/string.h"
-
-// Functions in this file support the public context API, including
-// encoding/decoding as part of context propagation across RPC's. The overall
-// requirements (in approximate priority order) for the
-// context representation:
-// 1. Efficient conversion to/from wire format
-// 2. Minimal bytes used on-wire
-// 3. Efficient context creation
-// 4. Efficient lookup of tag value for a key
-// 5. Efficient iteration over tags
-// 6. Minimal memory footprint
-//
-// Notes on tradeoffs/decisions:
-// * tag includes 1 byte length of key, as well as nil-terminating byte. These
-//   are to aid in efficient parsing and the ability to directly return key
-//   strings. This is more important than saving a single byte/tag on the wire.
-// * The wire encoding uses only single byte values. This eliminates the need
-//   to handle endian-ness conversions. It also means there is a hard upper
-//   limit of 255 for both CENSUS_MAX_TAG_KV_LEN and CENSUS_MAX_PROPAGATED_TAGS.
-// * Keep all tag information (keys/values/flags) in a single memory buffer,
-//   that can be directly copied to the wire.
-
-// min and max valid chars in tag keys and values. All printable ASCII is OK.
-#define MIN_VALID_TAG_CHAR 32   // ' '
-#define MAX_VALID_TAG_CHAR 126  // '~'
-
-// Structure representing a set of tags. Essentially a count of number of tags
-// present, and pointer to a chunk of memory that contains the per-tag details.
-struct tag_set {
-  int ntags;        // number of tags.
-  int ntags_alloc;  // ntags + number of deleted tags (total number of tags
-  // in all of kvm). This will always be == ntags, except during the process
-  // of building a new tag set.
-  size_t kvm_size;  // number of bytes allocated for key/value storage.
-  size_t kvm_used;  // number of bytes of used key/value memory
-  char *kvm;        // key/value memory. Consists of repeated entries of:
-  //   Offset  Size  Description
-  //     0      1    Key length, including trailing 0. (K)
-  //     1      1    Value length, including trailing 0 (V)
-  //     2      1    Flags
-  //     3      K    Key bytes
-  //     3 + K  V    Value bytes
-  //
-  // We refer to the first 3 entries as the 'tag header'. If extra values are
-  // introduced in the header, you will need to modify the TAG_HEADER_SIZE
-  // constant, the raw_tag structure (and everything that uses it) and the
-  // encode/decode functions appropriately.
-};
-
-// Number of bytes in tag header.
-#define TAG_HEADER_SIZE 3  // key length (1) + value length (1) + flags (1)
-// Offsets to tag header entries.
-#define KEY_LEN_OFFSET 0
-#define VALUE_LEN_OFFSET 1
-#define FLAG_OFFSET 2
-
-// raw_tag represents the raw-storage form of a tag in the kvm of a tag_set.
-struct raw_tag {
-  uint8_t key_len;
-  uint8_t value_len;
-  uint8_t flags;
-  char *key;
-  char *value;
-};
-
-// Use a reserved flag bit for indication of deleted tag.
-#define CENSUS_TAG_DELETED CENSUS_TAG_RESERVED
-#define CENSUS_TAG_IS_DELETED(flags) (flags & CENSUS_TAG_DELETED)
-
-// Primary representation of a context. Composed of 2 underlying tag_set
-// structs, one each for propagated and local (non-propagated) tags. This is
-// to efficiently support tag encoding/decoding.
-// TODO(aveitch): need to add tracing id's/structure.
-struct census_context {
-  struct tag_set tags[2];
-  census_context_status status;
-};
-
-// Indices into the tags member of census_context
-#define PROPAGATED_TAGS 0
-#define LOCAL_TAGS 1
-
-// Validate (check all characters are in range and size is less than limit) a
-// key or value string. Returns 0 if the string is invalid, or the length
-// (including terminator) if valid.
-static size_t validate_tag(const char *kv) {
-  size_t len = 1;
-  char ch;
-  while ((ch = *kv++) != 0) {
-    if (ch < MIN_VALID_TAG_CHAR || ch > MAX_VALID_TAG_CHAR) {
-      return 0;
-    }
-    len++;
-  }
-  if (len > CENSUS_MAX_TAG_KV_LEN) {
-    return 0;
-  }
-  return len;
-}
-
-// Extract a raw tag given a pointer (raw) to the tag header. Allow for some
-// extra bytes in the tag header (see encode/decode functions for usage: this
-// allows for future expansion of the tag header).
-static char *decode_tag(struct raw_tag *tag, char *header, int offset) {
-  tag->key_len = (uint8_t)(*header++);
-  tag->value_len = (uint8_t)(*header++);
-  tag->flags = (uint8_t)(*header++);
-  header += offset;
-  tag->key = header;
-  header += tag->key_len;
-  tag->value = header;
-  return header + tag->value_len;
-}
-
-// Make a copy (in 'to') of an existing tag_set.
-static void tag_set_copy(struct tag_set *to, const struct tag_set *from) {
-  memcpy(to, from, sizeof(struct tag_set));
-  to->kvm = gpr_malloc(to->kvm_size);
-  memcpy(to->kvm, from->kvm, from->kvm_used);
-}
-
-// Delete a tag from a tag_set, if it exists (returns true if it did).
-static bool tag_set_delete_tag(struct tag_set *tags, const char *key,
-                               size_t key_len) {
-  char *kvp = tags->kvm;
-  for (int i = 0; i < tags->ntags_alloc; i++) {
-    uint8_t *flags = (uint8_t *)(kvp + FLAG_OFFSET);
-    struct raw_tag tag;
-    kvp = decode_tag(&tag, kvp, 0);
-    if (CENSUS_TAG_IS_DELETED(tag.flags)) continue;
-    if ((key_len == tag.key_len) && (memcmp(key, tag.key, key_len) == 0)) {
-      *flags |= CENSUS_TAG_DELETED;
-      tags->ntags--;
-      return true;
-    }
-  }
-  return false;
-}
-
-// Delete a tag from a context, return true if it existed.
-static bool context_delete_tag(census_context *context, const census_tag *tag,
-                               size_t key_len) {
-  return (
-      tag_set_delete_tag(&context->tags[LOCAL_TAGS], tag->key, key_len) ||
-      tag_set_delete_tag(&context->tags[PROPAGATED_TAGS], tag->key, key_len));
-}
-
-// Add a tag to a tag_set. Return true on success, false if the tag could
-// not be added because of constraints on tag set size. This function should
-// not be called if the tag may already exist (in a non-deleted state) in
-// the tag_set, as that would result in two tags with the same key.
-static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
-                            size_t key_len, size_t value_len) {
-  if (tags->ntags == CENSUS_MAX_PROPAGATED_TAGS) {
-    return false;
-  }
-  const size_t tag_size = key_len + value_len + TAG_HEADER_SIZE;
-  if (tags->kvm_used + tag_size > tags->kvm_size) {
-    // allocate new memory if needed
-    tags->kvm_size += 2 * CENSUS_MAX_TAG_KV_LEN + TAG_HEADER_SIZE;
-    char *new_kvm = gpr_malloc(tags->kvm_size);
-    memcpy(new_kvm, tags->kvm, tags->kvm_used);
-    gpr_free(tags->kvm);
-    tags->kvm = new_kvm;
-  }
-  char *kvp = tags->kvm + tags->kvm_used;
-  *kvp++ = (char)key_len;
-  *kvp++ = (char)value_len;
-  // ensure reserved flags are not used.
-  *kvp++ = (char)(tag->flags & (CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS));
-  memcpy(kvp, tag->key, key_len);
-  kvp += key_len;
-  memcpy(kvp, tag->value, value_len);
-  tags->kvm_used += tag_size;
-  tags->ntags++;
-  tags->ntags_alloc++;
-  return true;
-}
-
-// Add/modify/delete a tag to/in a context. Caller must validate that tag key
-// etc. are valid.
-static void context_modify_tag(census_context *context, const census_tag *tag,
-                               size_t key_len, size_t value_len) {
-  // First delete the tag if it is already present.
-  bool deleted = context_delete_tag(context, tag, key_len);
-  bool added = false;
-  if (CENSUS_TAG_IS_PROPAGATED(tag->flags)) {
-    added = tag_set_add_tag(&context->tags[PROPAGATED_TAGS], tag, key_len,
-                            value_len);
-  } else {
-    added =
-        tag_set_add_tag(&context->tags[LOCAL_TAGS], tag, key_len, value_len);
-  }
-
-  if (deleted) {
-    context->status.n_modified_tags++;
-  } else {
-    if (added) {
-      context->status.n_added_tags++;
-    } else {
-      context->status.n_ignored_tags++;
-    }
-  }
-}
-
-// Remove memory used for deleted tags from a tag set. Basic algorithm:
-// 1) Walk through tag set to find first deleted tag. Record where it is.
-// 2) Find the next not-deleted tag. Copy all of kvm from there to the end
-//    "over" the deleted tags
-// 3) repeat #1 and #2 until we have seen all tags
-// 4) if we are still looking for a not-deleted tag, then all the end portion
-//    of the kvm is deleted. Just reduce the used amount of memory by the
-//    appropriate amount.
-static void tag_set_flatten(struct tag_set *tags) {
-  if (tags->ntags == tags->ntags_alloc) return;
-  bool found_deleted = false;  // found a deleted tag.
-  char *kvp = tags->kvm;
-  char *dbase = NULL;  // record location of deleted tag
-  for (int i = 0; i < tags->ntags_alloc; i++) {
-    struct raw_tag tag;
-    char *next_kvp = decode_tag(&tag, kvp, 0);
-    if (found_deleted) {
-      if (!CENSUS_TAG_IS_DELETED(tag.flags)) {
-        ptrdiff_t reduce = kvp - dbase;  // #bytes in deleted tags
-        GPR_ASSERT(reduce > 0);
-        ptrdiff_t copy_size = tags->kvm + tags->kvm_used - kvp;
-        GPR_ASSERT(copy_size > 0);
-        memmove(dbase, kvp, (size_t)copy_size);
-        tags->kvm_used -= (size_t)reduce;
-        next_kvp -= reduce;
-        found_deleted = false;
-      }
-    } else {
-      if (CENSUS_TAG_IS_DELETED(tag.flags)) {
-        dbase = kvp;
-        found_deleted = true;
-      }
-    }
-    kvp = next_kvp;
-  }
-  if (found_deleted) {
-    GPR_ASSERT(dbase > tags->kvm);
-    tags->kvm_used = (size_t)(dbase - tags->kvm);
-  }
-  tags->ntags_alloc = tags->ntags;
-}
-
-census_context *census_context_create(const census_context *base,
-                                      const census_tag *tags, int ntags,
-                                      census_context_status const **status) {
-  census_context *context = gpr_malloc(sizeof(census_context));
-  // If we are given a base, copy it into our new tag set. Otherwise set it
-  // to zero/NULL everything.
-  if (base == NULL) {
-    memset(context, 0, sizeof(census_context));
-  } else {
-    tag_set_copy(&context->tags[PROPAGATED_TAGS], &base->tags[PROPAGATED_TAGS]);
-    tag_set_copy(&context->tags[LOCAL_TAGS], &base->tags[LOCAL_TAGS]);
-    memset(&context->status, 0, sizeof(context->status));
-  }
-  // Walk over the additional tags and, for those that aren't invalid, modify
-  // the context to add/replace/delete as required.
-  for (int i = 0; i < ntags; i++) {
-    const census_tag *tag = &tags[i];
-    size_t key_len = validate_tag(tag->key);
-    // ignore the tag if it is invalid or too short.
-    if (key_len <= 1) {
-      context->status.n_invalid_tags++;
-    } else {
-      if (tag->value != NULL) {
-        size_t value_len = validate_tag(tag->value);
-        if (value_len != 0) {
-          context_modify_tag(context, tag, key_len, value_len);
-        } else {
-          context->status.n_invalid_tags++;
-        }
-      } else {
-        if (context_delete_tag(context, tag, key_len)) {
-          context->status.n_deleted_tags++;
-        }
-      }
-    }
-  }
-  // Remove any deleted tags, update status if needed, and return.
-  tag_set_flatten(&context->tags[PROPAGATED_TAGS]);
-  tag_set_flatten(&context->tags[LOCAL_TAGS]);
-  context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
-  context->status.n_local_tags = context->tags[LOCAL_TAGS].ntags;
-  if (status) {
-    *status = &context->status;
-  }
-  return context;
-}
-
-const census_context_status *census_context_get_status(
-    const census_context *context) {
-  return &context->status;
-}
-
-void census_context_destroy(census_context *context) {
-  gpr_free(context->tags[PROPAGATED_TAGS].kvm);
-  gpr_free(context->tags[LOCAL_TAGS].kvm);
-  gpr_free(context);
-}
-
-void census_context_initialize_iterator(const census_context *context,
-                                        census_context_iterator *iterator) {
-  iterator->context = context;
-  iterator->index = 0;
-  if (context->tags[PROPAGATED_TAGS].ntags != 0) {
-    iterator->base = PROPAGATED_TAGS;
-    iterator->kvm = context->tags[PROPAGATED_TAGS].kvm;
-  } else if (context->tags[LOCAL_TAGS].ntags != 0) {
-    iterator->base = LOCAL_TAGS;
-    iterator->kvm = context->tags[LOCAL_TAGS].kvm;
-  } else {
-    iterator->base = -1;
-  }
-}
-
-int census_context_next_tag(census_context_iterator *iterator,
-                            census_tag *tag) {
-  if (iterator->base < 0) {
-    return 0;
-  }
-  struct raw_tag raw;
-  iterator->kvm = decode_tag(&raw, iterator->kvm, 0);
-  tag->key = raw.key;
-  tag->value = raw.value;
-  tag->flags = raw.flags;
-  if (++iterator->index == iterator->context->tags[iterator->base].ntags) {
-    do {
-      if (iterator->base == LOCAL_TAGS) {
-        iterator->base = -1;
-        return 1;
-      }
-    } while (iterator->context->tags[++iterator->base].ntags == 0);
-    iterator->index = 0;
-    iterator->kvm = iterator->context->tags[iterator->base].kvm;
-  }
-  return 1;
-}
-
-// Find a tag in a tag_set by key. Return true if found, false otherwise.
-static bool tag_set_get_tag(const struct tag_set *tags, const char *key,
-                            size_t key_len, census_tag *tag) {
-  char *kvp = tags->kvm;
-  for (int i = 0; i < tags->ntags; i++) {
-    struct raw_tag raw;
-    kvp = decode_tag(&raw, kvp, 0);
-    if (key_len == raw.key_len && memcmp(raw.key, key, key_len) == 0) {
-      tag->key = raw.key;
-      tag->value = raw.value;
-      tag->flags = raw.flags;
-      return true;
-    }
-  }
-  return false;
-}
-
-int census_context_get_tag(const census_context *context, const char *key,
-                           census_tag *tag) {
-  size_t key_len = strlen(key) + 1;
-  if (key_len == 1) {
-    return 0;
-  }
-  if (tag_set_get_tag(&context->tags[PROPAGATED_TAGS], key, key_len, tag) ||
-      tag_set_get_tag(&context->tags[LOCAL_TAGS], key, key_len, tag)) {
-    return 1;
-  }
-  return 0;
-}
-
-// Context encoding and decoding functions.
-//
-// Wire format for tag_set's on the wire:
-//
-// First, a tag set header:
-//
-// offset   bytes  description
-//   0        1    version number
-//   1        1    number of bytes in this header. This allows for future
-//                 expansion.
-//   2        1    number of bytes in each tag header.
-//   3        1    ntags value from tag set.
-//
-//   This is followed by the key/value memory from struct tag_set.
-
-#define ENCODED_VERSION 0      // Version number
-#define ENCODED_HEADER_SIZE 4  // size of tag set header
-
-// Encode a tag set. Returns 0 if buffer is too small.
-static size_t tag_set_encode(const struct tag_set *tags, char *buffer,
-                             size_t buf_size) {
-  if (buf_size < ENCODED_HEADER_SIZE + tags->kvm_used) {
-    return 0;
-  }
-  buf_size -= ENCODED_HEADER_SIZE;
-  *buffer++ = (char)ENCODED_VERSION;
-  *buffer++ = (char)ENCODED_HEADER_SIZE;
-  *buffer++ = (char)TAG_HEADER_SIZE;
-  *buffer++ = (char)tags->ntags;
-  if (tags->ntags == 0) {
-    return ENCODED_HEADER_SIZE;
-  }
-  memcpy(buffer, tags->kvm, tags->kvm_used);
-  return ENCODED_HEADER_SIZE + tags->kvm_used;
-}
-
-size_t census_context_encode(const census_context *context, char *buffer,
-                             size_t buf_size) {
-  return tag_set_encode(&context->tags[PROPAGATED_TAGS], buffer, buf_size);
-}
-
-// Decode a tag set.
-static void tag_set_decode(struct tag_set *tags, const char *buffer,
-                           size_t size) {
-  uint8_t version = (uint8_t)(*buffer++);
-  uint8_t header_size = (uint8_t)(*buffer++);
-  uint8_t tag_header_size = (uint8_t)(*buffer++);
-  tags->ntags = tags->ntags_alloc = (int)(*buffer++);
-  if (tags->ntags == 0) {
-    tags->ntags_alloc = 0;
-    tags->kvm_size = 0;
-    tags->kvm_used = 0;
-    tags->kvm = NULL;
-    return;
-  }
-  if (header_size != ENCODED_HEADER_SIZE) {
-    GPR_ASSERT(version != ENCODED_VERSION);
-    GPR_ASSERT(ENCODED_HEADER_SIZE < header_size);
-    buffer += (header_size - ENCODED_HEADER_SIZE);
-  }
-  tags->kvm_used = size - header_size;
-  tags->kvm_size = tags->kvm_used + CENSUS_MAX_TAG_KV_LEN;
-  tags->kvm = gpr_malloc(tags->kvm_size);
-  if (tag_header_size != TAG_HEADER_SIZE) {
-    // something new in the tag information. I don't understand it, so
-    // don't copy it over.
-    GPR_ASSERT(version != ENCODED_VERSION);
-    GPR_ASSERT(tag_header_size > TAG_HEADER_SIZE);
-    char *kvp = tags->kvm;
-    for (int i = 0; i < tags->ntags; i++) {
-      memcpy(kvp, buffer, TAG_HEADER_SIZE);
-      kvp += header_size;
-      struct raw_tag raw;
-      buffer =
-          decode_tag(&raw, (char *)buffer, tag_header_size - TAG_HEADER_SIZE);
-      memcpy(kvp, raw.key, (size_t)raw.key_len + raw.value_len);
-      kvp += raw.key_len + raw.value_len;
-    }
-  } else {
-    memcpy(tags->kvm, buffer, tags->kvm_used);
-  }
-}
-
-census_context *census_context_decode(const char *buffer, size_t size) {
-  census_context *context = gpr_malloc(sizeof(census_context));
-  memset(&context->tags[LOCAL_TAGS], 0, sizeof(struct tag_set));
-  if (buffer == NULL) {
-    memset(&context->tags[PROPAGATED_TAGS], 0, sizeof(struct tag_set));
-  } else {
-    tag_set_decode(&context->tags[PROPAGATED_TAGS], buffer, size);
-  }
-  memset(&context->status, 0, sizeof(context->status));
-  context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
-  return context;
-}
diff --git a/src/core/census/grpc_context.c b/src/core/census/grpc_context.c
deleted file mode 100644
index 4b61382..0000000
--- a/src/core/census/grpc_context.c
+++ /dev/null
@@ -1,53 +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/census.h>
-#include <grpc/grpc.h>
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/call.h"
-
-void grpc_census_call_set_context(grpc_call *call, census_context *context) {
-  GRPC_API_TRACE("grpc_census_call_set_context(call=%p, census_context=%p)", 2,
-                 (call, context));
-  if (census_enabled() == CENSUS_FEATURE_NONE) {
-    return;
-  }
-  if (context != NULL) {
-    grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context, NULL);
-  }
-}
-
-census_context *grpc_census_call_get_context(grpc_call *call) {
-  GRPC_API_TRACE("grpc_census_call_get_context(call=%p)", 1, (call));
-  return (census_context *)grpc_call_context_get(call, GRPC_CONTEXT_TRACING);
-}
diff --git a/src/core/census/grpc_filter.c b/src/core/census/grpc_filter.c
deleted file mode 100644
index c8aaf31..0000000
--- a/src/core/census/grpc_filter.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- *
- * 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/census/grpc_filter.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/census.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/time.h>
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/statistics/census_interface.h"
-#include "src/core/statistics/census_rpc_stats.h"
-#include "src/core/transport/static_metadata.h"
-
-typedef struct call_data {
-  census_op_id op_id;
-  census_context *ctxt;
-  gpr_timespec start_ts;
-  int error;
-
-  /* recv callback */
-  grpc_metadata_batch *recv_initial_metadata;
-  grpc_closure *on_done_recv;
-  grpc_closure finish_recv;
-} call_data;
-
-typedef struct channel_data { uint8_t unused; } channel_data;
-
-static void extract_and_annotate_method_tag(grpc_metadata_batch *md,
-                                            call_data *calld,
-                                            channel_data *chand) {
-  grpc_linked_mdelem *m;
-  for (m = md->list.head; m != NULL; m = m->next) {
-    if (m->md->key == GRPC_MDSTR_PATH) {
-      gpr_log(GPR_DEBUG, "%s",
-              (const char *)GPR_SLICE_START_PTR(m->md->value->slice));
-      /* Add method tag here */
-    }
-  }
-}
-
-static void client_mutate_op(grpc_call_element *elem,
-                             grpc_transport_stream_op *op) {
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  if (op->send_initial_metadata) {
-    extract_and_annotate_method_tag(op->send_initial_metadata, calld, chand);
-  }
-}
-
-static void client_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                      grpc_call_element *elem,
-                                      grpc_transport_stream_op *op) {
-  client_mutate_op(elem, op);
-  grpc_call_next_op(exec_ctx, elem, op);
-}
-
-static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
-                                bool success) {
-  grpc_call_element *elem = ptr;
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  if (success) {
-    extract_and_annotate_method_tag(calld->recv_initial_metadata, calld, chand);
-  }
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
-}
-
-static void server_mutate_op(grpc_call_element *elem,
-                             grpc_transport_stream_op *op) {
-  call_data *calld = elem->call_data;
-  if (op->recv_initial_metadata) {
-    /* substitute our callback for the op callback */
-    calld->recv_initial_metadata = op->recv_initial_metadata;
-    calld->on_done_recv = op->recv_initial_metadata_ready;
-    op->recv_initial_metadata_ready = &calld->finish_recv;
-  }
-}
-
-static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                      grpc_call_element *elem,
-                                      grpc_transport_stream_op *op) {
-  /* TODO(ctiller): this code fails. I don't know why. I expect it's
-                    incomplete, and someone should look at it soon.
-
-  call_data *calld = elem->call_data;
-  GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); */
-  server_mutate_op(elem, op);
-  grpc_call_next_op(exec_ctx, elem, op);
-}
-
-static void client_init_call_elem(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
-  call_data *d = elem->call_data;
-  GPR_ASSERT(d != NULL);
-  memset(d, 0, sizeof(*d));
-  d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
-}
-
-static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                                     grpc_call_element *elem) {
-  call_data *d = elem->call_data;
-  GPR_ASSERT(d != NULL);
-  /* TODO(hongyu): record rpc client stats and census_rpc_end_op here */
-}
-
-static void server_init_call_elem(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
-  call_data *d = elem->call_data;
-  GPR_ASSERT(d != NULL);
-  memset(d, 0, sizeof(*d));
-  d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
-  /* TODO(hongyu): call census_tracing_start_op here. */
-  grpc_closure_init(&d->finish_recv, server_on_done_recv, elem);
-}
-
-static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                                     grpc_call_element *elem) {
-  call_data *d = elem->call_data;
-  GPR_ASSERT(d != NULL);
-  /* TODO(hongyu): record rpc server stats and census_tracing_end_op here */
-}
-
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  channel_data *chand = elem->channel_data;
-  GPR_ASSERT(chand != NULL);
-}
-
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  channel_data *chand = elem->channel_data;
-  GPR_ASSERT(chand != NULL);
-}
-
-const grpc_channel_filter grpc_client_census_filter = {
-    client_start_transport_op, grpc_channel_next_op, sizeof(call_data),
-    client_init_call_elem, grpc_call_stack_ignore_set_pollset,
-    client_destroy_call_elem, sizeof(channel_data), init_channel_elem,
-    destroy_channel_elem, grpc_call_next_get_peer, "census-client"};
-
-const grpc_channel_filter grpc_server_census_filter = {
-    server_start_transport_op, grpc_channel_next_op, sizeof(call_data),
-    server_init_call_elem, grpc_call_stack_ignore_set_pollset,
-    server_destroy_call_elem, sizeof(channel_data), init_channel_elem,
-    destroy_channel_elem, grpc_call_next_get_peer, "census-server"};
diff --git a/src/core/census/grpc_filter.h b/src/core/census/grpc_filter.h
deleted file mode 100644
index 4699e4d..0000000
--- a/src/core/census/grpc_filter.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CENSUS_GRPC_FILTER_H
-#define GRPC_CORE_CENSUS_GRPC_FILTER_H
-
-#include "src/core/channel/channel_stack.h"
-
-/* Census filters: provides tracing and stats collection functionalities. It
-   needs to reside right below the surface filter in the channel stack. */
-extern const grpc_channel_filter grpc_client_census_filter;
-extern const grpc_channel_filter grpc_server_census_filter;
-
-#endif /* GRPC_CORE_CENSUS_GRPC_FILTER_H */
diff --git a/src/core/census/grpc_plugin.c b/src/core/census/grpc_plugin.c
deleted file mode 100644
index 3be2a48..0000000
--- a/src/core/census/grpc_plugin.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *
- * 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/census/grpc_plugin.h"
-
-#include <limits.h>
-
-#include <grpc/census.h>
-
-#include "src/core/census/grpc_filter.h"
-#include "src/core/surface/channel_init.h"
-#include "src/core/channel/channel_stack_builder.h"
-
-static bool maybe_add_census_filter(grpc_channel_stack_builder *builder,
-                                    void *arg_must_be_null) {
-  const grpc_channel_args *args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  if (grpc_channel_args_is_census_enabled(args)) {
-    return grpc_channel_stack_builder_prepend_filter(
-        builder, &grpc_client_census_filter, NULL, NULL);
-  }
-  return true;
-}
-
-void census_grpc_plugin_init(void) {
-  /* Only initialize census if no one else has and some features are
-   * available. */
-  if (census_enabled() == CENSUS_FEATURE_NONE &&
-      census_supported() != CENSUS_FEATURE_NONE) {
-    if (census_initialize(census_supported())) { /* enable all features. */
-      gpr_log(GPR_ERROR, "Could not initialize census.");
-    }
-  }
-  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
-                                   maybe_add_census_filter, NULL);
-  grpc_channel_init_register_stage(GRPC_CLIENT_UCHANNEL, INT_MAX,
-                                   maybe_add_census_filter, NULL);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
-                                   maybe_add_census_filter, NULL);
-}
-
-void census_grpc_plugin_destroy(void) { census_shutdown(); }
diff --git a/src/core/census/grpc_plugin.h b/src/core/census/grpc_plugin.h
deleted file mode 100644
index 9321c2c..0000000
--- a/src/core/census/grpc_plugin.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CENSUS_GRPC_PLUGIN_H
-#define GRPC_CORE_CENSUS_GRPC_PLUGIN_H
-
-void census_grpc_plugin_init(void);
-void census_grpc_plugin_destroy(void);
-
-#endif /* GRPC_CORE_CENSUS_GRPC_PLUGIN_H */
diff --git a/src/core/census/initialize.c b/src/core/census/initialize.c
deleted file mode 100644
index ce7ec09..0000000
--- a/src/core/census/initialize.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *
- * 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 <grpc/census.h>
-
-static int features_enabled = CENSUS_FEATURE_NONE;
-
-int census_initialize(int features) {
-  if (features_enabled != CENSUS_FEATURE_NONE) {
-    // Must have been a previous call to census_initialize; return error
-    return 1;
-  }
-  features_enabled = features;
-  return 0;
-}
-
-void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; }
-
-int census_supported(void) {
-  /* TODO(aveitch): improve this as we implement features... */
-  return CENSUS_FEATURE_NONE;
-}
-
-int census_enabled(void) { return features_enabled; }
diff --git a/src/core/census/mlog.c b/src/core/census/mlog.c
deleted file mode 100644
index a2cc46d..0000000
--- a/src/core/census/mlog.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-// Implements an efficient in-memory log, optimized for multiple writers and
-// a single reader. Available log space is divided up in blocks of
-// CENSUS_LOG_2_MAX_RECORD_SIZE bytes. A block can be in one of the following
-// three data structures:
-// - Free blocks (free_block_list)
-// - Blocks with unread data (dirty_block_list)
-// - Blocks currently attached to cores (core_local_blocks[])
-//
-// census_log_start_write() moves a block from core_local_blocks[] to the end of
-// dirty_block_list when block:
-// - is out-of-space OR
-// - has an incomplete record (an incomplete record occurs when a thread calls
-//   census_log_start_write() and is context-switched before calling
-//   census_log_end_write()
-// So, blocks in dirty_block_list are ordered, from oldest to newest, by the
-// time when block is detached from the core.
-//
-// census_log_read_next() first iterates over dirty_block_list and then
-// core_local_blocks[]. It moves completely read blocks from dirty_block_list
-// to free_block_list. Blocks in core_local_blocks[] are not freed, even when
-// completely read.
-//
-// If the log is configured to discard old records and free_block_list is empty,
-// census_log_start_write() iterates over dirty_block_list to allocate a
-// new block. It moves the oldest available block (no pending read/write) to
-// core_local_blocks[].
-//
-// core_local_block_struct is used to implement a map from core id to the block
-// associated with that core. This mapping is advisory. It is possible that the
-// block returned by this mapping is no longer associated with that core. This
-// mapping is updated, lazily, by census_log_start_write().
-//
-// Locking in block struct:
-//
-// Exclusive g_log.lock must be held before calling any functions operating on
-// block structs except census_log_start_write() and census_log_end_write().
-//
-// Writes to a block are serialized via writer_lock. census_log_start_write()
-// acquires this lock and census_log_end_write() releases it. On failure to
-// acquire the lock, writer allocates a new block for the current core and
-// updates core_local_block accordingly.
-//
-// Simultaneous read and write access is allowed. Readers can safely read up to
-// committed bytes (bytes_committed).
-//
-// reader_lock protects the block, currently being read, from getting recycled.
-// start_read() acquires reader_lock and end_read() releases the lock.
-//
-// Read/write access to a block is disabled via try_disable_access(). It returns
-// with both writer_lock and reader_lock held. These locks are subsequently
-// released by enable_access() to enable access to the block.
-//
-// A note on naming: Most function/struct names are prepended by cl_
-// (shorthand for census_log). Further, functions that manipulate structures
-// include the name of the structure, which will be passed as the first
-// argument. E.g. cl_block_initialize() will initialize a cl_block.
-
-#include "src/core/census/mlog.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/cpu.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/useful.h>
-#include <stdbool.h>
-#include <string.h>
-
-// End of platform specific code
-
-typedef struct census_log_block_list_struct {
-  struct census_log_block_list_struct* next;
-  struct census_log_block_list_struct* prev;
-  struct census_log_block* block;
-} cl_block_list_struct;
-
-typedef struct census_log_block {
-  // Pointer to underlying buffer.
-  char* buffer;
-  gpr_atm writer_lock;
-  gpr_atm reader_lock;
-  // Keeps completely written bytes. Declared atomic because accessed
-  // simultaneously by reader and writer.
-  gpr_atm bytes_committed;
-  // Bytes already read.
-  size_t bytes_read;
-  // Links for list.
-  cl_block_list_struct link;
-// We want this structure to be cacheline aligned. We assume the following
-// sizes for the various parts on 32/64bit systems:
-// type                 32b size    64b size
-// char*                   4           8
-// 3x gpr_atm             12          24
-// size_t                  4           8
-// cl_block_list_struct   12          24
-// TOTAL                  32          64
-//
-// Depending on the size of our cacheline and the architecture, we
-// selectively add char buffering to this structure. The size is checked
-// via assert in census_log_initialize().
-#if defined(GPR_ARCH_64)
-#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 64)
-#else
-#if defined(GPR_ARCH_32)
-#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 32)
-#else
-#error "Unknown architecture"
-#endif
-#endif
-#if CL_BLOCK_PAD_SIZE > 0
-  char padding[CL_BLOCK_PAD_SIZE];
-#endif
-} cl_block;
-
-// A list of cl_blocks, doubly-linked through cl_block::link.
-typedef struct census_log_block_list {
-  int32_t count;            // Number of items in list.
-  cl_block_list_struct ht;  // head/tail of linked list.
-} cl_block_list;
-
-// Cacheline aligned block pointers to avoid false sharing. Block pointer must
-// be initialized via set_block(), before calling other functions
-typedef struct census_log_core_local_block {
-  gpr_atm block;
-// Ensure cachline alignment: we assume sizeof(gpr_atm) == 4 or 8
-#if defined(GPR_ARCH_64)
-#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 8)
-#else
-#if defined(GPR_ARCH_32)
-#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 4)
-#else
-#error "Unknown architecture"
-#endif
-#endif
-#if CL_CORE_LOCAL_BLOCK_PAD_SIZE > 0
-  char padding[CL_CORE_LOCAL_BLOCK_PAD_SIZE];
-#endif
-} cl_core_local_block;
-
-struct census_log {
-  int discard_old_records;
-  // Number of cores (aka hardware-contexts)
-  unsigned num_cores;
-  // number of CENSUS_LOG_2_MAX_RECORD_SIZE blocks in log
-  uint32_t num_blocks;
-  cl_block* blocks;                        // Block metadata.
-  cl_core_local_block* core_local_blocks;  // Keeps core to block mappings.
-  gpr_mu lock;
-  int initialized;  // has log been initialized?
-  // Keeps the state of the reader iterator. A value of 0 indicates that
-  // iterator has reached the end. census_log_init_reader() resets the value
-  // to num_core to restart iteration.
-  uint32_t read_iterator_state;
-  // Points to the block being read. If non-NULL, the block is locked for
-  // reading(block_being_read_->reader_lock is held).
-  cl_block* block_being_read;
-  char* buffer;
-  cl_block_list free_block_list;
-  cl_block_list dirty_block_list;
-  gpr_atm out_of_space_count;
-};
-
-// Single internal log.
-static struct census_log g_log;
-
-// Functions that operate on an atomic memory location used as a lock.
-
-// Returns non-zero if lock is acquired.
-static int cl_try_lock(gpr_atm* lock) { return gpr_atm_acq_cas(lock, 0, 1); }
-
-static void cl_unlock(gpr_atm* lock) { gpr_atm_rel_store(lock, 0); }
-
-// Functions that operate on cl_core_local_block's.
-
-static void cl_core_local_block_set_block(cl_core_local_block* clb,
-                                          cl_block* block) {
-  gpr_atm_rel_store(&clb->block, (gpr_atm)block);
-}
-
-static cl_block* cl_core_local_block_get_block(cl_core_local_block* clb) {
-  return (cl_block*)gpr_atm_acq_load(&clb->block);
-}
-
-// Functions that operate on cl_block_list_struct's.
-
-static void cl_block_list_struct_initialize(cl_block_list_struct* bls,
-                                            cl_block* block) {
-  bls->next = bls->prev = bls;
-  bls->block = block;
-}
-
-// Functions that operate on cl_block_list's.
-
-static void cl_block_list_initialize(cl_block_list* list) {
-  list->count = 0;
-  cl_block_list_struct_initialize(&list->ht, NULL);
-}
-
-// Returns head of *this, or NULL if empty.
-static cl_block* cl_block_list_head(cl_block_list* list) {
-  return list->ht.next->block;
-}
-
-// Insert element *e after *pos.
-static void cl_block_list_insert(cl_block_list* list, cl_block_list_struct* pos,
-                                 cl_block_list_struct* e) {
-  list->count++;
-  e->next = pos->next;
-  e->prev = pos;
-  e->next->prev = e;
-  e->prev->next = e;
-}
-
-// Insert block at the head of the list
-static void cl_block_list_insert_at_head(cl_block_list* list, cl_block* block) {
-  cl_block_list_insert(list, &list->ht, &block->link);
-}
-
-// Insert block at the tail of the list.
-static void cl_block_list_insert_at_tail(cl_block_list* list, cl_block* block) {
-  cl_block_list_insert(list, list->ht.prev, &block->link);
-}
-
-// Removes block *b. Requires *b be in the list.
-static void cl_block_list_remove(cl_block_list* list, cl_block* b) {
-  list->count--;
-  b->link.next->prev = b->link.prev;
-  b->link.prev->next = b->link.next;
-}
-
-// Functions that operate on cl_block's
-
-static void cl_block_initialize(cl_block* block, char* buffer) {
-  block->buffer = buffer;
-  gpr_atm_rel_store(&block->writer_lock, 0);
-  gpr_atm_rel_store(&block->reader_lock, 0);
-  gpr_atm_rel_store(&block->bytes_committed, 0);
-  block->bytes_read = 0;
-  cl_block_list_struct_initialize(&block->link, block);
-}
-
-// Guards against exposing partially written buffer to the reader.
-static void cl_block_set_bytes_committed(cl_block* block,
-                                         size_t bytes_committed) {
-  gpr_atm_rel_store(&block->bytes_committed, (gpr_atm)bytes_committed);
-}
-
-static size_t cl_block_get_bytes_committed(cl_block* block) {
-  return (size_t)gpr_atm_acq_load(&block->bytes_committed);
-}
-
-// Tries to disable future read/write access to this block. Succeeds if:
-// - no in-progress write AND
-// - no in-progress read AND
-// - 'discard_data' set to true OR no unread data
-// On success, clears the block state and returns with writer_lock_ and
-// reader_lock_ held. These locks are released by a subsequent
-// cl_block_access_enable() call.
-static bool cl_block_try_disable_access(cl_block* block, int discard_data) {
-  if (!cl_try_lock(&block->writer_lock)) {
-    return false;
-  }
-  if (!cl_try_lock(&block->reader_lock)) {
-    cl_unlock(&block->writer_lock);
-    return false;
-  }
-  if (!discard_data &&
-      (block->bytes_read != cl_block_get_bytes_committed(block))) {
-    cl_unlock(&block->reader_lock);
-    cl_unlock(&block->writer_lock);
-    return false;
-  }
-  cl_block_set_bytes_committed(block, 0);
-  block->bytes_read = 0;
-  return true;
-}
-
-static void cl_block_enable_access(cl_block* block) {
-  cl_unlock(&block->reader_lock);
-  cl_unlock(&block->writer_lock);
-}
-
-// Returns with writer_lock held.
-static void* cl_block_start_write(cl_block* block, size_t size) {
-  if (!cl_try_lock(&block->writer_lock)) {
-    return NULL;
-  }
-  size_t bytes_committed = cl_block_get_bytes_committed(block);
-  if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) {
-    cl_unlock(&block->writer_lock);
-    return NULL;
-  }
-  return block->buffer + bytes_committed;
-}
-
-// Releases writer_lock and increments committed bytes by 'bytes_written'.
-// 'bytes_written' must be <= 'size' specified in the corresponding
-// StartWrite() call. This function is thread-safe.
-static void cl_block_end_write(cl_block* block, size_t bytes_written) {
-  cl_block_set_bytes_committed(
-      block, cl_block_get_bytes_committed(block) + bytes_written);
-  cl_unlock(&block->writer_lock);
-}
-
-// Returns a pointer to the first unread byte in buffer. The number of bytes
-// available are returned in 'bytes_available'. Acquires reader lock that is
-// released by a subsequent cl_block_end_read() call. Returns NULL if:
-// - read in progress
-// - no data available
-static void* cl_block_start_read(cl_block* block, size_t* bytes_available) {
-  if (!cl_try_lock(&block->reader_lock)) {
-    return NULL;
-  }
-  // bytes_committed may change from under us. Use bytes_available to update
-  // bytes_read below.
-  size_t bytes_committed = cl_block_get_bytes_committed(block);
-  GPR_ASSERT(bytes_committed >= block->bytes_read);
-  *bytes_available = bytes_committed - block->bytes_read;
-  if (*bytes_available == 0) {
-    cl_unlock(&block->reader_lock);
-    return NULL;
-  }
-  void* record = block->buffer + block->bytes_read;
-  block->bytes_read += *bytes_available;
-  return record;
-}
-
-static void cl_block_end_read(cl_block* block) {
-  cl_unlock(&block->reader_lock);
-}
-
-// Internal functions operating on g_log
-
-// Allocates a new free block (or recycles an available dirty block if log is
-// configured to discard old records). Returns NULL if out-of-space.
-static cl_block* cl_allocate_block(void) {
-  cl_block* block = cl_block_list_head(&g_log.free_block_list);
-  if (block != NULL) {
-    cl_block_list_remove(&g_log.free_block_list, block);
-    return block;
-  }
-  if (!g_log.discard_old_records) {
-    // No free block and log is configured to keep old records.
-    return NULL;
-  }
-  // Recycle dirty block. Start from the oldest.
-  for (block = cl_block_list_head(&g_log.dirty_block_list); block != NULL;
-       block = block->link.next->block) {
-    if (cl_block_try_disable_access(block, 1 /* discard data */)) {
-      cl_block_list_remove(&g_log.dirty_block_list, block);
-      return block;
-    }
-  }
-  return NULL;
-}
-
-// Allocates a new block and updates core id => block mapping. 'old_block'
-// points to the block that the caller thinks is attached to
-// 'core_id'. 'old_block' may be NULL. Returns true if:
-// - allocated a new block OR
-// - 'core_id' => 'old_block' mapping changed (another thread allocated a
-//   block before lock was acquired).
-static bool cl_allocate_core_local_block(uint32_t core_id,
-                                         cl_block* old_block) {
-  // Now that we have the lock, check if core-local mapping has changed.
-  cl_core_local_block* core_local_block = &g_log.core_local_blocks[core_id];
-  cl_block* block = cl_core_local_block_get_block(core_local_block);
-  if ((block != NULL) && (block != old_block)) {
-    return true;
-  }
-  if (block != NULL) {
-    cl_core_local_block_set_block(core_local_block, NULL);
-    cl_block_list_insert_at_tail(&g_log.dirty_block_list, block);
-  }
-  block = cl_allocate_block();
-  if (block == NULL) {
-    return false;
-  }
-  cl_core_local_block_set_block(core_local_block, block);
-  cl_block_enable_access(block);
-  return true;
-}
-
-static cl_block* cl_get_block(void* record) {
-  uintptr_t p = (uintptr_t)((char*)record - g_log.buffer);
-  uintptr_t index = p >> CENSUS_LOG_2_MAX_RECORD_SIZE;
-  return &g_log.blocks[index];
-}
-
-// Gets the next block to read and tries to free 'prev' block (if not NULL).
-// Returns NULL if reached the end.
-static cl_block* cl_next_block_to_read(cl_block* prev) {
-  cl_block* block = NULL;
-  if (g_log.read_iterator_state == g_log.num_cores) {
-    // We are traversing dirty list; find the next dirty block.
-    if (prev != NULL) {
-      // Try to free the previous block if there is no unread data. This
-      // block
-      // may have unread data if previously incomplete record completed
-      // between
-      // read_next() calls.
-      block = prev->link.next->block;
-      if (cl_block_try_disable_access(prev, 0 /* do not discard data */)) {
-        cl_block_list_remove(&g_log.dirty_block_list, prev);
-        cl_block_list_insert_at_head(&g_log.free_block_list, prev);
-      }
-    } else {
-      block = cl_block_list_head(&g_log.dirty_block_list);
-    }
-    if (block != NULL) {
-      return block;
-    }
-    // We are done with the dirty list; moving on to core-local blocks.
-  }
-  while (g_log.read_iterator_state > 0) {
-    g_log.read_iterator_state--;
-    block = cl_core_local_block_get_block(
-        &g_log.core_local_blocks[g_log.read_iterator_state]);
-    if (block != NULL) {
-      return block;
-    }
-  }
-  return NULL;
-}
-
-#define CL_LOG_2_MB 20  // 2^20 = 1MB
-
-// External functions: primary stats_log interface
-void census_log_initialize(size_t size_in_mb, int discard_old_records) {
-  // Check cacheline alignment.
-  GPR_ASSERT(sizeof(cl_block) % GPR_CACHELINE_SIZE == 0);
-  GPR_ASSERT(sizeof(cl_core_local_block) % GPR_CACHELINE_SIZE == 0);
-  GPR_ASSERT(!g_log.initialized);
-  g_log.discard_old_records = discard_old_records;
-  g_log.num_cores = gpr_cpu_num_cores();
-  // Ensure that we will not get any overflow in calaculating num_blocks
-  GPR_ASSERT(CL_LOG_2_MB >= CENSUS_LOG_2_MAX_RECORD_SIZE);
-  GPR_ASSERT(size_in_mb < 1000);
-  // Ensure at least 2x as many blocks as there are cores.
-  g_log.num_blocks =
-      (uint32_t)GPR_MAX(2 * g_log.num_cores, (size_in_mb << CL_LOG_2_MB) >>
-                                                 CENSUS_LOG_2_MAX_RECORD_SIZE);
-  gpr_mu_init(&g_log.lock);
-  g_log.read_iterator_state = 0;
-  g_log.block_being_read = NULL;
-  g_log.core_local_blocks = (cl_core_local_block*)gpr_malloc_aligned(
-      g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG);
-  memset(g_log.core_local_blocks, 0,
-         g_log.num_cores * sizeof(cl_core_local_block));
-  g_log.blocks = (cl_block*)gpr_malloc_aligned(
-      g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG);
-  memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block));
-  g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
-  memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
-  cl_block_list_initialize(&g_log.free_block_list);
-  cl_block_list_initialize(&g_log.dirty_block_list);
-  for (uint32_t i = 0; i < g_log.num_blocks; ++i) {
-    cl_block* block = g_log.blocks + i;
-    cl_block_initialize(block, g_log.buffer + (CENSUS_LOG_MAX_RECORD_SIZE * i));
-    cl_block_try_disable_access(block, 1 /* discard data */);
-    cl_block_list_insert_at_tail(&g_log.free_block_list, block);
-  }
-  gpr_atm_rel_store(&g_log.out_of_space_count, 0);
-  g_log.initialized = 1;
-}
-
-void census_log_shutdown(void) {
-  GPR_ASSERT(g_log.initialized);
-  gpr_mu_destroy(&g_log.lock);
-  gpr_free_aligned(g_log.core_local_blocks);
-  g_log.core_local_blocks = NULL;
-  gpr_free_aligned(g_log.blocks);
-  g_log.blocks = NULL;
-  gpr_free(g_log.buffer);
-  g_log.buffer = NULL;
-  g_log.initialized = 0;
-}
-
-void* census_log_start_write(size_t size) {
-  // Used to bound number of times block allocation is attempted.
-  GPR_ASSERT(size > 0);
-  GPR_ASSERT(g_log.initialized);
-  if (size > CENSUS_LOG_MAX_RECORD_SIZE) {
-    return NULL;
-  }
-  uint32_t attempts_remaining = g_log.num_blocks;
-  uint32_t core_id = gpr_cpu_current_cpu();
-  do {
-    void* record = NULL;
-    cl_block* block =
-        cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]);
-    if (block && (record = cl_block_start_write(block, size))) {
-      return record;
-    }
-    // Need to allocate a new block. We are here if:
-    // - No block associated with the core OR
-    // - Write in-progress on the block OR
-    // - block is out of space
-    gpr_mu_lock(&g_log.lock);
-    bool allocated = cl_allocate_core_local_block(core_id, block);
-    gpr_mu_unlock(&g_log.lock);
-    if (!allocated) {
-      gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
-      return NULL;
-    }
-  } while (attempts_remaining--);
-  // Give up.
-  gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
-  return NULL;
-}
-
-void census_log_end_write(void* record, size_t bytes_written) {
-  GPR_ASSERT(g_log.initialized);
-  cl_block_end_write(cl_get_block(record), bytes_written);
-}
-
-void census_log_init_reader(void) {
-  GPR_ASSERT(g_log.initialized);
-  gpr_mu_lock(&g_log.lock);
-  // If a block is locked for reading unlock it.
-  if (g_log.block_being_read != NULL) {
-    cl_block_end_read(g_log.block_being_read);
-    g_log.block_being_read = NULL;
-  }
-  g_log.read_iterator_state = g_log.num_cores;
-  gpr_mu_unlock(&g_log.lock);
-}
-
-const void* census_log_read_next(size_t* bytes_available) {
-  GPR_ASSERT(g_log.initialized);
-  gpr_mu_lock(&g_log.lock);
-  if (g_log.block_being_read != NULL) {
-    cl_block_end_read(g_log.block_being_read);
-  }
-  do {
-    g_log.block_being_read = cl_next_block_to_read(g_log.block_being_read);
-    if (g_log.block_being_read != NULL) {
-      void* record =
-          cl_block_start_read(g_log.block_being_read, bytes_available);
-      if (record != NULL) {
-        gpr_mu_unlock(&g_log.lock);
-        return record;
-      }
-    }
-  } while (g_log.block_being_read != NULL);
-  gpr_mu_unlock(&g_log.lock);
-  return NULL;
-}
-
-size_t census_log_remaining_space(void) {
-  GPR_ASSERT(g_log.initialized);
-  size_t space = 0;
-  gpr_mu_lock(&g_log.lock);
-  if (g_log.discard_old_records) {
-    // Remaining space is not meaningful; just return the entire log space.
-    space = g_log.num_blocks << CENSUS_LOG_2_MAX_RECORD_SIZE;
-  } else {
-    GPR_ASSERT(g_log.free_block_list.count >= 0);
-    space = (size_t)g_log.free_block_list.count * CENSUS_LOG_MAX_RECORD_SIZE;
-  }
-  gpr_mu_unlock(&g_log.lock);
-  return space;
-}
-
-int64_t census_log_out_of_space_count(void) {
-  GPR_ASSERT(g_log.initialized);
-  return gpr_atm_acq_load(&g_log.out_of_space_count);
-}
diff --git a/src/core/census/mlog.h b/src/core/census/mlog.h
deleted file mode 100644
index bc6eaea..0000000
--- a/src/core/census/mlog.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* A very fast in-memory log, optimized for multiple writers. */
-
-#ifndef GRPC_CORE_CENSUS_MLOG_H
-#define GRPC_CORE_CENSUS_MLOG_H
-
-#include <grpc/support/port_platform.h>
-#include <stddef.h>
-
-/* Maximum record size, in bytes. */
-#define CENSUS_LOG_2_MAX_RECORD_SIZE 14 /* 2^14 = 16KB */
-#define CENSUS_LOG_MAX_RECORD_SIZE (1 << CENSUS_LOG_2_MAX_RECORD_SIZE)
-
-/* Initialize the statistics logging subsystem with the given log size. A log
-   size of 0 will result in the smallest possible log for the platform
-   (approximately CENSUS_LOG_MAX_RECORD_SIZE * gpr_cpu_num_cores()). If
-   discard_old_records is non-zero, then new records will displace older ones
-   when the log is full. This function must be called before any other
-   census_log functions.
-*/
-void census_log_initialize(size_t size_in_mb, int discard_old_records);
-
-/* Shutdown the logging subsystem. Caller must ensure that:
-   - no in progress or future call to any census_log functions
-   - no incomplete records
-*/
-void census_log_shutdown(void);
-
-/* Allocates and returns a 'size' bytes record and marks it in use. A
-   subsequent census_log_end_write() marks the record complete. The
-   'bytes_written' census_log_end_write() argument must be <=
-   'size'. Returns NULL if out-of-space AND:
-       - log is configured to keep old records OR
-       - all blocks are pinned by incomplete records.
-*/
-void* census_log_start_write(size_t size);
-
-void census_log_end_write(void* record, size_t bytes_written);
-
-void census_log_init_reader(void);
-
-/* census_log_read_next() iterates over blocks with data and for each block
-   returns a pointer to the first unread byte. The number of bytes that can be
-   read are returned in 'bytes_available'. Reader is expected to read all
-   available data. Reading the data consumes it i.e. it cannot be read again.
-   census_log_read_next() returns NULL if the end is reached i.e last block
-   is read. census_log_init_reader() starts the iteration or aborts the
-   current iteration.
-*/
-const void* census_log_read_next(size_t* bytes_available);
-
-/* Returns estimated remaining space across all blocks, in bytes. If log is
-   configured to discard old records, returns total log space. Otherwise,
-   returns space available in empty blocks (partially filled blocks are
-   treated as full).
-*/
-size_t census_log_remaining_space(void);
-
-/* Returns the number of times gprc_stats_log_start_write() failed due to
-   out-of-space. */
-int64_t census_log_out_of_space_count(void);
-
-#endif /* GRPC_CORE_CENSUS_MLOG_H */
diff --git a/src/core/census/rpc_metric_id.h b/src/core/census/rpc_metric_id.h
deleted file mode 100644
index f8d8dad..0000000
--- a/src/core/census/rpc_metric_id.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CENSUS_RPC_METRIC_ID_H
-#define GRPC_CORE_CENSUS_RPC_METRIC_ID_H
-
-/* Metric ID's used for RPC measurements. */
-/* Count of client requests sent. */
-#define CENSUS_METRIC_RPC_CLIENT_REQUESTS ((uint32_t)0)
-/* Count of server requests sent. */
-#define CENSUS_METRIC_RPC_SERVER_REQUESTS ((uint32_t)1)
-/* Client error counts. */
-#define CENSUS_METRIC_RPC_CLIENT_ERRORS ((uint32_t)2)
-/* Server error counts. */
-#define CENSUS_METRIC_RPC_SERVER_ERRORS ((uint32_t)3)
-/* Client side request latency. */
-#define CENSUS_METRIC_RPC_CLIENT_LATENCY ((uint32_t)4)
-/* Server side request latency. */
-#define CENSUS_METRIC_RPC_SERVER_LATENCY ((uint32_t)5)
-
-#endif /* GRPC_CORE_CENSUS_RPC_METRIC_ID_H */
diff --git a/src/core/channel/channel_args.c b/src/core/channel/channel_args.c
deleted file mode 100644
index bae7a90..0000000
--- a/src/core/channel/channel_args.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- *
- * 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 <grpc/grpc.h>
-#include "src/core/channel/channel_args.h"
-#include "src/core/support/string.h"
-
-#include <grpc/census.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-#include <string.h>
-
-static grpc_arg copy_arg(const grpc_arg *src) {
-  grpc_arg dst;
-  dst.type = src->type;
-  dst.key = gpr_strdup(src->key);
-  switch (dst.type) {
-    case GRPC_ARG_STRING:
-      dst.value.string = gpr_strdup(src->value.string);
-      break;
-    case GRPC_ARG_INTEGER:
-      dst.value.integer = src->value.integer;
-      break;
-    case GRPC_ARG_POINTER:
-      dst.value.pointer = src->value.pointer;
-      dst.value.pointer.p =
-          src->value.pointer.vtable->copy(src->value.pointer.p);
-      break;
-  }
-  return dst;
-}
-
-grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
-                                                  const grpc_arg *to_add,
-                                                  size_t num_to_add) {
-  grpc_channel_args *dst = gpr_malloc(sizeof(grpc_channel_args));
-  size_t i;
-  size_t src_num_args = (src == NULL) ? 0 : src->num_args;
-  if (!src && !to_add) {
-    dst->num_args = 0;
-    dst->args = NULL;
-    return dst;
-  }
-  dst->num_args = src_num_args + num_to_add;
-  dst->args = gpr_malloc(sizeof(grpc_arg) * dst->num_args);
-  for (i = 0; i < src_num_args; i++) {
-    dst->args[i] = copy_arg(&src->args[i]);
-  }
-  for (i = 0; i < num_to_add; i++) {
-    dst->args[i + src_num_args] = copy_arg(&to_add[i]);
-  }
-  return dst;
-}
-
-grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src) {
-  return grpc_channel_args_copy_and_add(src, NULL, 0);
-}
-
-grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a,
-                                           const grpc_channel_args *b) {
-  return grpc_channel_args_copy_and_add(a, b->args, b->num_args);
-}
-
-static int cmp_arg(const grpc_arg *a, const grpc_arg *b) {
-  int c = GPR_ICMP(a->type, b->type);
-  if (c != 0) return c;
-  c = strcmp(a->key, b->key);
-  if (c != 0) return c;
-  switch (a->type) {
-    case GRPC_ARG_STRING:
-      return strcmp(a->value.string, b->value.string);
-    case GRPC_ARG_INTEGER:
-      return GPR_ICMP(a->value.integer, b->value.integer);
-    case GRPC_ARG_POINTER:
-      c = GPR_ICMP(a->value.pointer.p, b->value.pointer.p);
-      if (c != 0) {
-        c = GPR_ICMP(a->value.pointer.vtable, b->value.pointer.vtable);
-        if (c == 0) {
-          c = a->value.pointer.vtable->cmp(a->value.pointer.p,
-                                           b->value.pointer.p);
-        }
-      }
-      return c;
-  }
-  GPR_UNREACHABLE_CODE(return 0);
-}
-
-/* stabilizing comparison function: since channel_args ordering matters for
- * keys with the same name, we need to preserve that ordering */
-static int cmp_key_stable(const void *ap, const void *bp) {
-  const grpc_arg *const *a = ap;
-  const grpc_arg *const *b = bp;
-  int c = strcmp((*a)->key, (*b)->key);
-  if (c == 0) c = GPR_ICMP(*a, *b);
-  return c;
-}
-
-grpc_channel_args *grpc_channel_args_normalize(const grpc_channel_args *a) {
-  grpc_arg **args = gpr_malloc(sizeof(grpc_arg *) * a->num_args);
-  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);
-
-  grpc_channel_args *b = gpr_malloc(sizeof(grpc_channel_args));
-  b->num_args = a->num_args;
-  b->args = gpr_malloc(sizeof(grpc_arg) * b->num_args);
-  for (size_t i = 0; i < a->num_args; i++) {
-    b->args[i] = copy_arg(args[i]);
-  }
-
-  gpr_free(args);
-  return b;
-}
-
-void grpc_channel_args_destroy(grpc_channel_args *a) {
-  size_t i;
-  for (i = 0; i < a->num_args; i++) {
-    switch (a->args[i].type) {
-      case GRPC_ARG_STRING:
-        gpr_free(a->args[i].value.string);
-        break;
-      case GRPC_ARG_INTEGER:
-        break;
-      case GRPC_ARG_POINTER:
-        a->args[i].value.pointer.vtable->destroy(a->args[i].value.pointer.p);
-        break;
-    }
-    gpr_free(a->args[i].key);
-  }
-  gpr_free(a->args);
-  gpr_free(a);
-}
-
-int grpc_channel_args_is_census_enabled(const grpc_channel_args *a) {
-  size_t i;
-  if (a == NULL) return 0;
-  for (i = 0; i < a->num_args; i++) {
-    if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_CENSUS)) {
-      return a->args[i].value.integer != 0 && census_enabled();
-    }
-  }
-  return census_enabled();
-}
-
-grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
-    const grpc_channel_args *a) {
-  size_t i;
-  if (a == NULL) return 0;
-  for (i = 0; i < a->num_args; ++i) {
-    if (a->args[i].type == GRPC_ARG_INTEGER &&
-        !strcmp(GRPC_COMPRESSION_ALGORITHM_ARG, a->args[i].key)) {
-      return (grpc_compression_algorithm)a->args[i].value.integer;
-      break;
-    }
-  }
-  return GRPC_COMPRESS_NONE;
-}
-
-grpc_channel_args *grpc_channel_args_set_compression_algorithm(
-    grpc_channel_args *a, grpc_compression_algorithm algorithm) {
-  grpc_arg tmp;
-  tmp.type = GRPC_ARG_INTEGER;
-  tmp.key = GRPC_COMPRESSION_ALGORITHM_ARG;
-  tmp.value.integer = algorithm;
-  return grpc_channel_args_copy_and_add(a, &tmp, 1);
-}
-
-/** Returns 1 if the argument for compression algorithm's enabled states bitset
- * was found in \a a, returning the arg's value in \a states. Otherwise, returns
- * 0. */
-static int find_compression_algorithm_states_bitset(const grpc_channel_args *a,
-                                                    int **states_arg) {
-  if (a != NULL) {
-    size_t i;
-    for (i = 0; i < a->num_args; ++i) {
-      if (a->args[i].type == GRPC_ARG_INTEGER &&
-          !strcmp(GRPC_COMPRESSION_ALGORITHM_STATE_ARG, a->args[i].key)) {
-        *states_arg = &a->args[i].value.integer;
-        return 1; /* GPR_TRUE */
-      }
-    }
-  }
-  return 0; /* GPR_FALSE */
-}
-
-grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
-    grpc_channel_args **a, grpc_compression_algorithm algorithm, int state) {
-  int *states_arg;
-  grpc_channel_args *result = *a;
-  const int states_arg_found =
-      find_compression_algorithm_states_bitset(*a, &states_arg);
-
-  if (states_arg_found) {
-    if (state != 0) {
-      GPR_BITSET((unsigned *)states_arg, algorithm);
-    } else {
-      GPR_BITCLEAR((unsigned *)states_arg, algorithm);
-    }
-  } else {
-    /* create a new arg */
-    grpc_arg tmp;
-    tmp.type = GRPC_ARG_INTEGER;
-    tmp.key = GRPC_COMPRESSION_ALGORITHM_STATE_ARG;
-    /* all enabled by default */
-    tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
-    if (state != 0) {
-      GPR_BITSET((unsigned *)&tmp.value.integer, algorithm);
-    } else {
-      GPR_BITCLEAR((unsigned *)&tmp.value.integer, algorithm);
-    }
-    result = grpc_channel_args_copy_and_add(*a, &tmp, 1);
-    grpc_channel_args_destroy(*a);
-    *a = result;
-  }
-  return result;
-}
-
-int grpc_channel_args_compression_algorithm_get_states(
-    const grpc_channel_args *a) {
-  int *states_arg;
-  if (find_compression_algorithm_states_bitset(a, &states_arg)) {
-    return *states_arg;
-  } else {
-    return (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; /* All algs. enabled */
-  }
-}
-
-int grpc_channel_args_compare(const grpc_channel_args *a,
-                              const grpc_channel_args *b) {
-  int c = GPR_ICMP(a->num_args, b->num_args);
-  if (c != 0) return c;
-  for (size_t i = 0; i < a->num_args; i++) {
-    c = cmp_arg(&a->args[i], &b->args[i]);
-    if (c != 0) return c;
-  }
-  return 0;
-}
diff --git a/src/core/channel/channel_args.h b/src/core/channel/channel_args.h
deleted file mode 100644
index e19440f..0000000
--- a/src/core/channel/channel_args.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_CHANNEL_ARGS_H
-#define GRPC_CORE_CHANNEL_CHANNEL_ARGS_H
-
-#include <grpc/compression.h>
-#include <grpc/grpc.h>
-
-/* Copy some arguments */
-grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src);
-
-/* Copy some arguments, stably sorting keys */
-grpc_channel_args *grpc_channel_args_normalize(const grpc_channel_args *a);
-
-/** Copy some arguments and add the to_add parameter in the end.
-   If to_add is NULL, it is equivalent to call grpc_channel_args_copy. */
-grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
-                                                  const grpc_arg *to_add,
-                                                  size_t num_to_add);
-
-/** Copy args from a then args from b into a new channel args */
-grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a,
-                                           const grpc_channel_args *b);
-
-/** Destroy arguments created by grpc_channel_args_copy */
-void grpc_channel_args_destroy(grpc_channel_args *a);
-
-/** Reads census_enabled settings from channel args. Returns 1 if census_enabled
- * is specified in channel args, otherwise returns 0. */
-int grpc_channel_args_is_census_enabled(const grpc_channel_args *a);
-
-/** Returns the compression algorithm set in \a a. */
-grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
-    const grpc_channel_args *a);
-
-/** Returns a channel arg instance with compression enabled. If \a a is
- * non-NULL, its args are copied. N.B. GRPC_COMPRESS_NONE disables compression
- * for the channel. */
-grpc_channel_args *grpc_channel_args_set_compression_algorithm(
-    grpc_channel_args *a, grpc_compression_algorithm algorithm);
-
-/** Sets the support for the given compression algorithm. By default, all
- * compression algorithms are enabled. It's an error to disable an algorithm set
- * by grpc_channel_args_set_compression_algorithm.
- *
- * Returns an instance with the updated algorithm states. The \a a pointer is
- * modified to point to the returned instance (which may be different from the
- * input value of \a a). */
-grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
-    grpc_channel_args **a, grpc_compression_algorithm algorithm, int enabled);
-
-/** Returns the bitset representing the support state (true for enabled, false
- * for disabled) for compression algorithms.
- *
- * The i-th bit of the returned bitset corresponds to the i-th entry in the
- * grpc_compression_algorithm enum. */
-int grpc_channel_args_compression_algorithm_get_states(
-    const grpc_channel_args *a);
-
-int grpc_channel_args_compare(const grpc_channel_args *a,
-                              const grpc_channel_args *b);
-
-#endif /* GRPC_CORE_CHANNEL_CHANNEL_ARGS_H */
diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c
deleted file mode 100644
index 3e61688..0000000
--- a/src/core/channel/channel_stack.c
+++ /dev/null
@@ -1,262 +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/channel/channel_stack.h"
-#include <grpc/support/log.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-int grpc_trace_channel = 0;
-
-/* Memory layouts.
-
-   Channel stack is laid out as: {
-     grpc_channel_stack stk;
-     padding to GPR_MAX_ALIGNMENT
-     grpc_channel_element[stk.count];
-     per-filter memory, aligned to GPR_MAX_ALIGNMENT
-   }
-
-   Call stack is laid out as: {
-     grpc_call_stack stk;
-     padding to GPR_MAX_ALIGNMENT
-     grpc_call_element[stk.count];
-     per-filter memory, aligned to GPR_MAX_ALIGNMENT
-   } */
-
-/* Given a size, round up to the next multiple of sizeof(void*) */
-#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
-  (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
-
-size_t grpc_channel_stack_size(const grpc_channel_filter **filters,
-                               size_t filter_count) {
-  /* always need the header, and size for the channel elements */
-  size_t size =
-      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
-      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
-  size_t i;
-
-  GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
-             "GPR_MAX_ALIGNMENT must be a power of two");
-
-  /* add the size for each filter */
-  for (i = 0; i < filter_count; i++) {
-    size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
-  }
-
-  return size;
-}
-
-#define CHANNEL_ELEMS_FROM_STACK(stk)                                   \
-  ((grpc_channel_element *)((char *)(stk) + ROUND_UP_TO_ALIGNMENT_SIZE( \
-                                                sizeof(grpc_channel_stack))))
-
-#define CALL_ELEMS_FROM_STACK(stk)       \
-  ((grpc_call_element *)((char *)(stk) + \
-                         ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack))))
-
-grpc_channel_element *grpc_channel_stack_element(
-    grpc_channel_stack *channel_stack, size_t index) {
-  return CHANNEL_ELEMS_FROM_STACK(channel_stack) + index;
-}
-
-grpc_channel_element *grpc_channel_stack_last_element(
-    grpc_channel_stack *channel_stack) {
-  return grpc_channel_stack_element(channel_stack, channel_stack->count - 1);
-}
-
-grpc_call_element *grpc_call_stack_element(grpc_call_stack *call_stack,
-                                           size_t index) {
-  return CALL_ELEMS_FROM_STACK(call_stack) + index;
-}
-
-void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
-                             grpc_iomgr_cb_func destroy, void *destroy_arg,
-                             const grpc_channel_filter **filters,
-                             size_t filter_count,
-                             const grpc_channel_args *channel_args,
-                             const char *name, grpc_channel_stack *stack) {
-  size_t call_size =
-      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
-      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
-  grpc_channel_element *elems;
-  grpc_channel_element_args args;
-  char *user_data;
-  size_t i;
-
-  stack->count = filter_count;
-  GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg,
-                       name);
-  elems = CHANNEL_ELEMS_FROM_STACK(stack);
-  user_data =
-      ((char *)elems) +
-      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
-
-  /* init per-filter data */
-  for (i = 0; i < filter_count; i++) {
-    args.channel_stack = stack;
-    args.channel_args = channel_args;
-    args.is_first = i == 0;
-    args.is_last = i == (filter_count - 1);
-    elems[i].filter = filters[i];
-    elems[i].channel_data = user_data;
-    elems[i].filter->init_channel_elem(exec_ctx, &elems[i], &args);
-    user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
-    call_size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
-  }
-
-  GPR_ASSERT(user_data > (char *)stack);
-  GPR_ASSERT((uintptr_t)(user_data - (char *)stack) ==
-             grpc_channel_stack_size(filters, filter_count));
-
-  stack->call_stack_size = call_size;
-}
-
-void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
-                                grpc_channel_stack *stack) {
-  grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(stack);
-  size_t count = stack->count;
-  size_t i;
-
-  /* destroy per-filter data */
-  for (i = 0; i < count; i++) {
-    channel_elems[i].filter->destroy_channel_elem(exec_ctx, &channel_elems[i]);
-  }
-}
-
-void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
-                          grpc_channel_stack *channel_stack, int initial_refs,
-                          grpc_iomgr_cb_func destroy, void *destroy_arg,
-                          grpc_call_context_element *context,
-                          const void *transport_server_data,
-                          grpc_call_stack *call_stack) {
-  grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
-  grpc_call_element_args args;
-  size_t count = channel_stack->count;
-  grpc_call_element *call_elems;
-  char *user_data;
-  size_t i;
-
-  call_stack->count = count;
-  GRPC_STREAM_REF_INIT(&call_stack->refcount, initial_refs, destroy,
-                       destroy_arg, "CALL_STACK");
-  call_elems = CALL_ELEMS_FROM_STACK(call_stack);
-  user_data = ((char *)call_elems) +
-              ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
-
-  /* init per-filter data */
-  for (i = 0; i < count; i++) {
-    args.call_stack = call_stack;
-    args.server_transport_data = transport_server_data;
-    args.context = context;
-    call_elems[i].filter = channel_elems[i].filter;
-    call_elems[i].channel_data = channel_elems[i].channel_data;
-    call_elems[i].call_data = user_data;
-    call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args);
-    user_data +=
-        ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
-  }
-}
-
-void grpc_call_stack_set_pollset(grpc_exec_ctx *exec_ctx,
-                                 grpc_call_stack *call_stack,
-                                 grpc_pollset *pollset) {
-  size_t count = call_stack->count;
-  grpc_call_element *call_elems;
-  char *user_data;
-  size_t i;
-
-  call_elems = CALL_ELEMS_FROM_STACK(call_stack);
-  user_data = ((char *)call_elems) +
-              ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
-
-  /* init per-filter data */
-  for (i = 0; i < count; i++) {
-    call_elems[i].filter->set_pollset(exec_ctx, &call_elems[i], pollset);
-    user_data +=
-        ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
-  }
-}
-
-void grpc_call_stack_ignore_set_pollset(grpc_exec_ctx *exec_ctx,
-                                        grpc_call_element *elem,
-                                        grpc_pollset *pollset) {}
-
-void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack) {
-  grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack);
-  size_t count = stack->count;
-  size_t i;
-
-  /* destroy per-filter data */
-  for (i = 0; i < count; i++) {
-    elems[i].filter->destroy_call_elem(exec_ctx, &elems[i]);
-  }
-}
-
-void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                       grpc_transport_stream_op *op) {
-  grpc_call_element *next_elem = elem + 1;
-  next_elem->filter->start_transport_stream_op(exec_ctx, next_elem, op);
-}
-
-char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {
-  grpc_call_element *next_elem = elem + 1;
-  return next_elem->filter->get_peer(exec_ctx, next_elem);
-}
-
-void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
-                          grpc_transport_op *op) {
-  grpc_channel_element *next_elem = elem + 1;
-  next_elem->filter->start_transport_op(exec_ctx, next_elem, op);
-}
-
-grpc_channel_stack *grpc_channel_stack_from_top_element(
-    grpc_channel_element *elem) {
-  return (grpc_channel_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
-      sizeof(grpc_channel_stack)));
-}
-
-grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) {
-  return (grpc_call_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
-      sizeof(grpc_call_stack)));
-}
-
-void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
-                                   grpc_call_element *cur_elem) {
-  grpc_transport_stream_op op;
-  memset(&op, 0, sizeof(op));
-  op.cancel_with_status = GRPC_STATUS_CANCELLED;
-  grpc_call_next_op(exec_ctx, cur_elem, &op);
-}
diff --git a/src/core/channel/channel_stack.h b/src/core/channel/channel_stack.h
deleted file mode 100644
index 52362f0..0000000
--- a/src/core/channel/channel_stack.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_CHANNEL_STACK_H
-#define GRPC_CORE_CHANNEL_CHANNEL_STACK_H
-
-/* A channel filter defines how operations on a channel are implemented.
-   Channel filters are chained together to create full channels, and if those
-   chains are linear, then channel stacks provide a mechanism to minimize
-   allocations for that chain.
-   Call stacks are created by channel stacks and represent the per-call data
-   for that stack. */
-
-#include <stddef.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
-#include "src/core/debug/trace.h"
-#include "src/core/transport/transport.h"
-
-typedef struct grpc_channel_element grpc_channel_element;
-typedef struct grpc_call_element grpc_call_element;
-
-typedef struct grpc_channel_stack grpc_channel_stack;
-typedef struct grpc_call_stack grpc_call_stack;
-
-typedef struct {
-  grpc_channel_stack *channel_stack;
-  const grpc_channel_args *channel_args;
-  int is_first;
-  int is_last;
-} grpc_channel_element_args;
-
-typedef struct {
-  grpc_call_stack *call_stack;
-  const void *server_transport_data;
-  grpc_call_context_element *context;
-} grpc_call_element_args;
-
-/* Channel filters specify:
-   1. the amount of memory needed in the channel & call (via the sizeof_XXX
-      members)
-   2. functions to initialize and destroy channel & call data
-      (init_XXX, destroy_XXX)
-   3. functions to implement call operations and channel operations (call_op,
-      channel_op)
-   4. a name, which is useful when debugging
-
-   Members are laid out in approximate frequency of use order. */
-typedef struct {
-  /* Called to eg. send/receive data on a call.
-     See grpc_call_next_op on how to call the next element in the stack */
-  void (*start_transport_stream_op)(grpc_exec_ctx *exec_ctx,
-                                    grpc_call_element *elem,
-                                    grpc_transport_stream_op *op);
-  /* Called to handle channel level operations - e.g. new calls, or transport
-     closure.
-     See grpc_channel_next_op on how to call the next element in the stack */
-  void (*start_transport_op)(grpc_exec_ctx *exec_ctx,
-                             grpc_channel_element *elem, grpc_transport_op *op);
-
-  /* sizeof(per call data) */
-  size_t sizeof_call_data;
-  /* Initialize per call data.
-     elem is initialized at the start of the call, and elem->call_data is what
-     needs initializing.
-     The filter does not need to do any chaining.
-     server_transport_data is an opaque pointer. If it is NULL, this call is
-     on a client; if it is non-NULL, then it points to memory owned by the
-     transport and is on the server. Most filters want to ignore this
-     argument. */
-  void (*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                         grpc_call_element_args *args);
-  void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                      grpc_pollset *pollset);
-  /* Destroy per call data.
-     The filter does not need to do any chaining */
-  void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
-
-  /* sizeof(per channel data) */
-  size_t sizeof_channel_data;
-  /* Initialize per-channel data.
-     elem is initialized at the start of the call, and elem->channel_data is
-     what needs initializing.
-     is_first, is_last designate this elements position in the stack, and are
-     useful for asserting correct configuration by upper layer code.
-     The filter does not need to do any chaining */
-  void (*init_channel_elem)(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
-                            grpc_channel_element_args *args);
-  /* Destroy per channel data.
-     The filter does not need to do any chaining */
-  void (*destroy_channel_elem)(grpc_exec_ctx *exec_ctx,
-                               grpc_channel_element *elem);
-
-  /* Implement grpc_call_get_peer() */
-  char *(*get_peer)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
-
-  /* The name of this filter */
-  const char *name;
-} grpc_channel_filter;
-
-/* A channel_element tracks its filter and the filter requested memory within
-   a channel allocation */
-struct grpc_channel_element {
-  const grpc_channel_filter *filter;
-  void *channel_data;
-};
-
-/* A call_element tracks its filter, the filter requested memory within
-   a channel allocation, and the filter requested memory within a call
-   allocation */
-struct grpc_call_element {
-  const grpc_channel_filter *filter;
-  void *channel_data;
-  void *call_data;
-};
-
-/* A channel stack tracks a set of related filters for one channel, and
-   guarantees they live within a single malloc() allocation */
-struct grpc_channel_stack {
-  grpc_stream_refcount refcount;
-  size_t count;
-  /* Memory required for a call stack (computed at channel stack
-     initialization) */
-  size_t call_stack_size;
-};
-
-/* A call stack tracks a set of related filters for one call, and guarantees
-   they live within a single malloc() allocation */
-struct grpc_call_stack {
-  /* shared refcount for this channel stack.
-     MUST be the first element: the underlying code calls destroy
-     with the address of the refcount, but higher layers prefer to think
-     about the address of the call stack itself. */
-  grpc_stream_refcount refcount;
-  size_t count;
-};
-
-/* Get a channel element given a channel stack and its index */
-grpc_channel_element *grpc_channel_stack_element(grpc_channel_stack *stack,
-                                                 size_t i);
-/* Get the last channel element in a channel stack */
-grpc_channel_element *grpc_channel_stack_last_element(
-    grpc_channel_stack *stack);
-/* Get a call stack element given a call stack and an index */
-grpc_call_element *grpc_call_stack_element(grpc_call_stack *stack, size_t i);
-
-/* Determine memory required for a channel stack containing a set of filters */
-size_t grpc_channel_stack_size(const grpc_channel_filter **filters,
-                               size_t filter_count);
-/* Initialize a channel stack given some filters */
-void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
-                             grpc_iomgr_cb_func destroy, void *destroy_arg,
-                             const grpc_channel_filter **filters,
-                             size_t filter_count, const grpc_channel_args *args,
-                             const char *name, grpc_channel_stack *stack);
-/* Destroy a channel stack */
-void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
-                                grpc_channel_stack *stack);
-
-/* Initialize a call stack given a channel stack. transport_server_data is
-   expected to be NULL on a client, or an opaque transport owned pointer on the
-   server. */
-void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
-                          grpc_channel_stack *channel_stack, int initial_refs,
-                          grpc_iomgr_cb_func destroy, void *destroy_arg,
-                          grpc_call_context_element *context,
-                          const void *transport_server_data,
-                          grpc_call_stack *call_stack);
-/* Set a pollset for a call stack: must occur before the first op is started */
-void grpc_call_stack_set_pollset(grpc_exec_ctx *exec_ctx,
-                                 grpc_call_stack *call_stack,
-                                 grpc_pollset *pollset);
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-#define GRPC_CALL_STACK_REF(call_stack, reason) \
-  grpc_stream_ref(&(call_stack)->refcount, reason)
-#define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \
-  grpc_stream_unref(exec_ctx, &(call_stack)->refcount, reason)
-#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
-  grpc_stream_ref(&(channel_stack)->refcount, reason)
-#define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \
-  grpc_stream_unref(exec_ctx, &(channel_stack)->refcount, reason)
-#else
-#define GRPC_CALL_STACK_REF(call_stack, reason) \
-  grpc_stream_ref(&(call_stack)->refcount)
-#define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \
-  grpc_stream_unref(exec_ctx, &(call_stack)->refcount)
-#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
-  grpc_stream_ref(&(channel_stack)->refcount)
-#define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \
-  grpc_stream_unref(exec_ctx, &(channel_stack)->refcount)
-#endif
-
-/* Destroy a call stack */
-void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack);
-
-/* Ignore set pollset - used by filters to implement the set_pollset method
-   if they don't care about pollsets at all. Does nothing. */
-void grpc_call_stack_ignore_set_pollset(grpc_exec_ctx *exec_ctx,
-                                        grpc_call_element *elem,
-                                        grpc_pollset *pollset);
-/* Call the next operation in a call stack */
-void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                       grpc_transport_stream_op *op);
-/* Call the next operation (depending on call directionality) in a channel
-   stack */
-void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
-                          grpc_transport_op *op);
-/* Pass through a request to get_peer to the next child element */
-char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
-
-/* Given the top element of a channel stack, get the channel stack itself */
-grpc_channel_stack *grpc_channel_stack_from_top_element(
-    grpc_channel_element *elem);
-/* Given the top element of a call stack, get the call stack itself */
-grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem);
-
-void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
-                      grpc_call_element *elem, grpc_transport_stream_op *op);
-
-void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
-                                   grpc_call_element *cur_elem);
-
-extern int grpc_trace_channel;
-
-#define GRPC_CALL_LOG_OP(sev, elem, op) \
-  if (grpc_trace_channel) grpc_call_log_op(sev, elem, op)
-
-#endif /* GRPC_CORE_CHANNEL_CHANNEL_STACK_H */
diff --git a/src/core/channel/channel_stack_builder.c b/src/core/channel/channel_stack_builder.c
deleted file mode 100644
index 1b1004e..0000000
--- a/src/core/channel/channel_stack_builder.c
+++ /dev/null
@@ -1,258 +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 "src/core/channel/channel_stack_builder.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-int grpc_trace_channel_stack_builder = 0;
-
-typedef struct filter_node {
-  struct filter_node *next;
-  struct filter_node *prev;
-  const grpc_channel_filter *filter;
-  grpc_post_filter_create_init_func init;
-  void *init_arg;
-} filter_node;
-
-struct grpc_channel_stack_builder {
-  // sentinel nodes for filters that have been added
-  filter_node begin;
-  filter_node end;
-  // various set/get-able parameters
-  const grpc_channel_args *args;
-  grpc_transport *transport;
-  const char *name;
-};
-
-struct grpc_channel_stack_builder_iterator {
-  grpc_channel_stack_builder *builder;
-  filter_node *node;
-};
-
-grpc_channel_stack_builder *grpc_channel_stack_builder_create(void) {
-  grpc_channel_stack_builder *b = gpr_malloc(sizeof(*b));
-  memset(b, 0, sizeof(*b));
-
-  b->begin.filter = NULL;
-  b->end.filter = NULL;
-  b->begin.next = &b->end;
-  b->begin.prev = &b->end;
-  b->end.next = &b->begin;
-  b->end.prev = &b->begin;
-
-  return b;
-}
-
-static grpc_channel_stack_builder_iterator *create_iterator_at_filter_node(
-    grpc_channel_stack_builder *builder, filter_node *node) {
-  grpc_channel_stack_builder_iterator *it = gpr_malloc(sizeof(*it));
-  it->builder = builder;
-  it->node = node;
-  return it;
-}
-
-void grpc_channel_stack_builder_iterator_destroy(
-    grpc_channel_stack_builder_iterator *it) {
-  gpr_free(it);
-}
-
-grpc_channel_stack_builder_iterator *
-grpc_channel_stack_builder_create_iterator_at_first(
-    grpc_channel_stack_builder *builder) {
-  return create_iterator_at_filter_node(builder, &builder->begin);
-}
-
-grpc_channel_stack_builder_iterator *
-grpc_channel_stack_builder_create_iterator_at_last(
-    grpc_channel_stack_builder *builder) {
-  return create_iterator_at_filter_node(builder, &builder->end);
-}
-
-bool grpc_channel_stack_builder_move_next(
-    grpc_channel_stack_builder_iterator *iterator) {
-  if (iterator->node == &iterator->builder->end) return false;
-  iterator->node = iterator->node->next;
-  return true;
-}
-
-bool grpc_channel_stack_builder_move_prev(
-    grpc_channel_stack_builder_iterator *iterator) {
-  if (iterator->node == &iterator->builder->begin) return false;
-  iterator->node = iterator->node->prev;
-  return true;
-}
-
-bool grpc_channel_stack_builder_move_prev(
-    grpc_channel_stack_builder_iterator *iterator);
-
-void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder *builder,
-                                         const char *name) {
-  GPR_ASSERT(builder->name == NULL);
-  builder->name = name;
-}
-
-void grpc_channel_stack_builder_set_channel_arguments(
-    grpc_channel_stack_builder *builder, const grpc_channel_args *args) {
-  GPR_ASSERT(builder->args == NULL);
-  builder->args = args;
-}
-
-void grpc_channel_stack_builder_set_transport(
-    grpc_channel_stack_builder *builder, grpc_transport *transport) {
-  GPR_ASSERT(builder->transport == NULL);
-  builder->transport = transport;
-}
-
-grpc_transport *grpc_channel_stack_builder_get_transport(
-    grpc_channel_stack_builder *builder) {
-  return builder->transport;
-}
-
-const grpc_channel_args *grpc_channel_stack_builder_get_channel_arguments(
-    grpc_channel_stack_builder *builder) {
-  return builder->args;
-}
-
-bool grpc_channel_stack_builder_append_filter(
-    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func, void *user_data) {
-  grpc_channel_stack_builder_iterator *it =
-      grpc_channel_stack_builder_create_iterator_at_last(builder);
-  bool ok = grpc_channel_stack_builder_add_filter_before(
-      it, filter, post_init_func, user_data);
-  grpc_channel_stack_builder_iterator_destroy(it);
-  return ok;
-}
-
-bool grpc_channel_stack_builder_prepend_filter(
-    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func, void *user_data) {
-  grpc_channel_stack_builder_iterator *it =
-      grpc_channel_stack_builder_create_iterator_at_first(builder);
-  bool ok = grpc_channel_stack_builder_add_filter_after(
-      it, filter, post_init_func, user_data);
-  grpc_channel_stack_builder_iterator_destroy(it);
-  return ok;
-}
-
-static void add_after(filter_node *before, const grpc_channel_filter *filter,
-                      grpc_post_filter_create_init_func post_init_func,
-                      void *user_data) {
-  filter_node *new = gpr_malloc(sizeof(*new));
-  new->next = before->next;
-  new->prev = before;
-  new->next->prev = new->prev->next = new;
-  new->filter = filter;
-  new->init = post_init_func;
-  new->init_arg = user_data;
-}
-
-bool grpc_channel_stack_builder_add_filter_before(
-    grpc_channel_stack_builder_iterator *iterator,
-    const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func, void *user_data) {
-  if (iterator->node == &iterator->builder->begin) return false;
-  add_after(iterator->node->prev, filter, post_init_func, user_data);
-  return true;
-}
-
-bool grpc_channel_stack_builder_add_filter_after(
-    grpc_channel_stack_builder_iterator *iterator,
-    const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func, void *user_data) {
-  if (iterator->node == &iterator->builder->end) return false;
-  add_after(iterator->node, filter, post_init_func, user_data);
-  return true;
-}
-
-void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder *builder) {
-  filter_node *p = builder->begin.next;
-  while (p != &builder->end) {
-    filter_node *next = p->next;
-    gpr_free(p);
-    p = next;
-  }
-  gpr_free(builder);
-}
-
-void *grpc_channel_stack_builder_finish(grpc_exec_ctx *exec_ctx,
-                                        grpc_channel_stack_builder *builder,
-                                        size_t prefix_bytes, int initial_refs,
-                                        grpc_iomgr_cb_func destroy,
-                                        void *destroy_arg) {
-  // count the number of filters
-  size_t num_filters = 0;
-  for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) {
-    num_filters++;
-  }
-
-  // create an array of filters
-  const grpc_channel_filter **filters =
-      gpr_malloc(sizeof(*filters) * num_filters);
-  size_t i = 0;
-  for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) {
-    filters[i++] = p->filter;
-  }
-
-  // calculate the size of the channel stack
-  size_t channel_stack_size = grpc_channel_stack_size(filters, num_filters);
-
-  // allocate memory, with prefix_bytes followed by channel_stack_size
-  char *result = gpr_malloc(prefix_bytes + channel_stack_size);
-  // fetch a pointer to the channel stack
-  grpc_channel_stack *channel_stack =
-      (grpc_channel_stack *)(result + prefix_bytes);
-  // and initialize it
-  grpc_channel_stack_init(exec_ctx, initial_refs, destroy,
-                          destroy_arg == NULL ? result : destroy_arg, filters,
-                          num_filters, builder->args, builder->name,
-                          channel_stack);
-
-  // run post-initialization functions
-  i = 0;
-  for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) {
-    if (p->init != NULL) {
-      p->init(channel_stack, grpc_channel_stack_element(channel_stack, i),
-              p->init_arg);
-    }
-    i++;
-  }
-
-  grpc_channel_stack_builder_destroy(builder);
-  gpr_free((grpc_channel_filter **)filters);
-
-  return result;
-}
diff --git a/src/core/channel/channel_stack_builder.h b/src/core/channel/channel_stack_builder.h
deleted file mode 100644
index 15f395e..0000000
--- a/src/core/channel/channel_stack_builder.h
+++ /dev/null
@@ -1,155 +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_CORE_CHANNEL_CHANNEL_STACK_BUILDER_H
-#define GRPC_CORE_CHANNEL_CHANNEL_STACK_BUILDER_H
-
-#include <stdbool.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/channel_stack.h"
-
-/// grpc_channel_stack_builder offers a programmatic interface to selected
-/// and order channel filters
-typedef struct grpc_channel_stack_builder grpc_channel_stack_builder;
-typedef struct grpc_channel_stack_builder_iterator
-    grpc_channel_stack_builder_iterator;
-
-/// Create a new channel stack builder
-grpc_channel_stack_builder *grpc_channel_stack_builder_create(void);
-
-/// Assign a name to the channel stack: \a name must be statically allocated
-void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder *builder,
-                                         const char *name);
-
-/// Attach \a transport to the builder (does not take ownership)
-void grpc_channel_stack_builder_set_transport(
-    grpc_channel_stack_builder *builder, grpc_transport *transport);
-
-/// Fetch attached transport
-grpc_transport *grpc_channel_stack_builder_get_transport(
-    grpc_channel_stack_builder *builder);
-
-/// Set channel arguments: \a args must continue to exist until after
-/// grpc_channel_stack_builder_finish returns
-void grpc_channel_stack_builder_set_channel_arguments(
-    grpc_channel_stack_builder *builder, const grpc_channel_args *args);
-
-/// Return a borrowed pointer to the channel arguments
-const grpc_channel_args *grpc_channel_stack_builder_get_channel_arguments(
-    grpc_channel_stack_builder *builder);
-
-/// Begin iterating over already defined filters in the builder at the beginning
-grpc_channel_stack_builder_iterator *
-grpc_channel_stack_builder_create_iterator_at_first(
-    grpc_channel_stack_builder *builder);
-
-/// Begin iterating over already defined filters in the builder at the end
-grpc_channel_stack_builder_iterator *
-grpc_channel_stack_builder_create_iterator_at_last(
-    grpc_channel_stack_builder *builder);
-
-/// Is an iterator at the first element?
-bool grpc_channel_stack_builder_iterator_is_first(
-    grpc_channel_stack_builder_iterator *iterator);
-
-/// Is an iterator at the end?
-bool grpc_channel_stack_builder_iterator_is_end(
-    grpc_channel_stack_builder_iterator *iterator);
-
-/// Move an iterator to the next item
-bool grpc_channel_stack_builder_move_next(
-    grpc_channel_stack_builder_iterator *iterator);
-
-/// Move an iterator to the previous item
-bool grpc_channel_stack_builder_move_prev(
-    grpc_channel_stack_builder_iterator *iterator);
-
-typedef void (*grpc_post_filter_create_init_func)(
-    grpc_channel_stack *channel_stack, grpc_channel_element *elem, void *arg);
-
-/// Add \a filter to the stack, after \a iterator.
-/// Call \a post_init_func(..., \a user_data) once the channel stack is
-/// created.
-bool grpc_channel_stack_builder_add_filter_after(
-    grpc_channel_stack_builder_iterator *iterator,
-    const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func,
-    void *user_data) GRPC_MUST_USE_RESULT;
-
-/// Add \a filter to the stack, before \a iterator.
-/// Call \a post_init_func(..., \a user_data) once the channel stack is
-/// created.
-bool grpc_channel_stack_builder_add_filter_before(
-    grpc_channel_stack_builder_iterator *iterator,
-    const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func,
-    void *user_data) GRPC_MUST_USE_RESULT;
-
-/// Add \a filter to the beginning of the filter list.
-/// Call \a post_init_func(..., \a user_data) once the channel stack is
-/// created.
-bool grpc_channel_stack_builder_prepend_filter(
-    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func,
-    void *user_data) GRPC_MUST_USE_RESULT;
-
-/// Add \a filter to the end of the filter list.
-/// Call \a post_init_func(..., \a user_data) once the channel stack is
-/// created.
-bool grpc_channel_stack_builder_append_filter(
-    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
-    grpc_post_filter_create_init_func post_init_func,
-    void *user_data) GRPC_MUST_USE_RESULT;
-
-/// Terminate iteration and destroy \a iterator
-void grpc_channel_stack_builder_iterator_destroy(
-    grpc_channel_stack_builder_iterator *iterator);
-
-/// Destroy the builder, return the freshly minted channel stack
-/// Allocates \a prefix_bytes bytes before the channel stack
-/// Returns the base pointer of the allocated block
-/// \a initial_refs, \a destroy, \a destroy_arg are as per
-/// grpc_channel_stack_init
-void *grpc_channel_stack_builder_finish(grpc_exec_ctx *exec_ctx,
-                                        grpc_channel_stack_builder *builder,
-                                        size_t prefix_bytes, int initial_refs,
-                                        grpc_iomgr_cb_func destroy,
-                                        void *destroy_arg);
-
-/// Destroy the builder without creating a channel stack
-void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder *builder);
-
-extern int grpc_trace_channel_stack_builder;
-
-#endif /* GRPC_CORE_CHANNEL_CHANNEL_STACK_BUILDER_H */
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
deleted file mode 100644
index f021a8a..0000000
--- a/src/core/channel/client_channel.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- *
- * 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/channel/client_channel.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/subchannel_call_holder.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/channel.h"
-#include "src/core/transport/connectivity_state.h"
-
-/* Client channel implementation */
-
-typedef grpc_subchannel_call_holder call_data;
-
-typedef struct client_channel_channel_data {
-  /** resolver for this channel */
-  grpc_resolver *resolver;
-  /** have we started resolving this channel */
-  int started_resolving;
-
-  /** mutex protecting client configuration, including all
-      variables below in this data structure */
-  gpr_mu mu_config;
-  /** currently active load balancer - guarded by mu_config */
-  grpc_lb_policy *lb_policy;
-  /** incoming configuration - set by resolver.next
-      guarded by mu_config */
-  grpc_client_config *incoming_configuration;
-  /** a list of closures that are all waiting for config to come in */
-  grpc_closure_list waiting_for_config_closures;
-  /** resolver callback */
-  grpc_closure on_config_changed;
-  /** connectivity state being tracked */
-  grpc_connectivity_state_tracker state_tracker;
-  /** when an lb_policy arrives, should we try to exit idle */
-  int exit_idle_when_lb_policy_arrives;
-  /** owning stack */
-  grpc_channel_stack *owning_stack;
-  /** interested parties (owned) */
-  grpc_pollset_set *interested_parties;
-} channel_data;
-
-/** We create one watcher for each new lb_policy that is returned from a
-   resolver,
-    to watch for state changes from the lb_policy. When a state change is seen,
-   we
-    update the channel, and create a new watcher */
-typedef struct {
-  channel_data *chand;
-  grpc_closure on_changed;
-  grpc_connectivity_state state;
-  grpc_lb_policy *lb_policy;
-} lb_policy_connectivity_watcher;
-
-typedef struct {
-  grpc_closure closure;
-  grpc_call_element *elem;
-} waiting_call;
-
-static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
-  return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
-}
-
-static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
-                                         grpc_call_element *elem,
-                                         grpc_transport_stream_op *op) {
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
-}
-
-static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
-                            grpc_lb_policy *lb_policy,
-                            grpc_connectivity_state current_state);
-
-static void on_lb_policy_state_changed_locked(
-    grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
-  grpc_connectivity_state publish_state = w->state;
-  /* check if the notification is for a stale policy */
-  if (w->lb_policy != w->chand->lb_policy) return;
-
-  if (publish_state == GRPC_CHANNEL_FATAL_FAILURE &&
-      w->chand->resolver != NULL) {
-    publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
-    grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
-    GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
-    w->chand->lb_policy = NULL;
-  }
-  grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, publish_state,
-                              "lb_changed");
-  if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
-    watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
-  }
-}
-
-static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                       bool iomgr_success) {
-  lb_policy_connectivity_watcher *w = arg;
-
-  gpr_mu_lock(&w->chand->mu_config);
-  on_lb_policy_state_changed_locked(exec_ctx, w);
-  gpr_mu_unlock(&w->chand->mu_config);
-
-  GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
-  gpr_free(w);
-}
-
-static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
-                            grpc_lb_policy *lb_policy,
-                            grpc_connectivity_state current_state) {
-  lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
-  GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
-
-  w->chand = chand;
-  grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
-  w->state = current_state;
-  w->lb_policy = lb_policy;
-  grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
-                                        &w->on_changed);
-}
-
-static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                 bool iomgr_success) {
-  channel_data *chand = arg;
-  grpc_lb_policy *lb_policy = NULL;
-  grpc_lb_policy *old_lb_policy;
-  grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
-  int exit_idle = 0;
-
-  if (chand->incoming_configuration != NULL) {
-    lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
-    if (lb_policy != NULL) {
-      GRPC_LB_POLICY_REF(lb_policy, "channel");
-      GRPC_LB_POLICY_REF(lb_policy, "config_change");
-      state = grpc_lb_policy_check_connectivity(exec_ctx, lb_policy);
-    }
-
-    grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
-  }
-
-  chand->incoming_configuration = NULL;
-
-  if (lb_policy != NULL) {
-    grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
-                                     chand->interested_parties);
-  }
-
-  gpr_mu_lock(&chand->mu_config);
-  old_lb_policy = chand->lb_policy;
-  chand->lb_policy = lb_policy;
-  if (lb_policy != NULL || chand->resolver == NULL /* disconnected */) {
-    grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
-                               NULL);
-  }
-  if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
-    GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
-    exit_idle = 1;
-    chand->exit_idle_when_lb_policy_arrives = 0;
-  }
-
-  if (iomgr_success && chand->resolver) {
-    grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
-                                "new_lb+resolver");
-    if (lb_policy != NULL) {
-      watch_lb_policy(exec_ctx, chand, lb_policy, state);
-    }
-    GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-    grpc_resolver_next(exec_ctx, chand->resolver,
-                       &chand->incoming_configuration,
-                       &chand->on_config_changed);
-    gpr_mu_unlock(&chand->mu_config);
-  } else {
-    if (chand->resolver != NULL) {
-      grpc_resolver_shutdown(exec_ctx, chand->resolver);
-      GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
-      chand->resolver = NULL;
-    }
-    grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
-                                GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
-    gpr_mu_unlock(&chand->mu_config);
-  }
-
-  if (exit_idle) {
-    grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
-    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
-  }
-
-  if (old_lb_policy != NULL) {
-    grpc_pollset_set_del_pollset_set(
-        exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
-    GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
-  }
-
-  if (lb_policy != NULL) {
-    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
-  }
-
-  GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
-}
-
-static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                  grpc_channel_element *elem,
-                                  grpc_transport_op *op) {
-  channel_data *chand = elem->channel_data;
-
-  grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
-
-  GPR_ASSERT(op->set_accept_stream == false);
-  if (op->bind_pollset != NULL) {
-    grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
-                                 op->bind_pollset);
-  }
-
-  gpr_mu_lock(&chand->mu_config);
-  if (op->on_connectivity_state_change != NULL) {
-    grpc_connectivity_state_notify_on_state_change(
-        exec_ctx, &chand->state_tracker, op->connectivity_state,
-        op->on_connectivity_state_change);
-    op->on_connectivity_state_change = NULL;
-    op->connectivity_state = NULL;
-  }
-
-  if (op->send_ping != NULL) {
-    if (chand->lb_policy == NULL) {
-      grpc_exec_ctx_enqueue(exec_ctx, op->send_ping, false, NULL);
-    } else {
-      grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
-      op->bind_pollset = NULL;
-    }
-    op->send_ping = NULL;
-  }
-
-  if (op->disconnect && chand->resolver != NULL) {
-    grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
-                                GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
-    grpc_resolver_shutdown(exec_ctx, chand->resolver);
-    GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
-    chand->resolver = NULL;
-    if (chand->lb_policy != NULL) {
-      grpc_pollset_set_del_pollset_set(exec_ctx,
-                                       chand->lb_policy->interested_parties,
-                                       chand->interested_parties);
-      GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
-      chand->lb_policy = NULL;
-    }
-  }
-  gpr_mu_unlock(&chand->mu_config);
-}
-
-typedef struct {
-  grpc_metadata_batch *initial_metadata;
-  grpc_connected_subchannel **connected_subchannel;
-  grpc_closure *on_ready;
-  grpc_call_element *elem;
-  grpc_closure closure;
-} continue_picking_args;
-
-static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
-                              grpc_metadata_batch *initial_metadata,
-                              grpc_connected_subchannel **connected_subchannel,
-                              grpc_closure *on_ready);
-
-static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  continue_picking_args *cpa = arg;
-  if (!success) {
-    grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
-  } else if (cpa->connected_subchannel == NULL) {
-    /* cancelled, do nothing */
-  } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
-                                cpa->connected_subchannel, cpa->on_ready)) {
-    grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, true, NULL);
-  }
-  gpr_free(cpa);
-}
-
-static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
-                              grpc_metadata_batch *initial_metadata,
-                              grpc_connected_subchannel **connected_subchannel,
-                              grpc_closure *on_ready) {
-  grpc_call_element *elem = elemp;
-  channel_data *chand = elem->channel_data;
-  call_data *calld = elem->call_data;
-  continue_picking_args *cpa;
-  grpc_closure *closure;
-
-  GPR_ASSERT(connected_subchannel);
-
-  gpr_mu_lock(&chand->mu_config);
-  if (initial_metadata == NULL) {
-    if (chand->lb_policy != NULL) {
-      grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
-                                 connected_subchannel);
-    }
-    for (closure = chand->waiting_for_config_closures.head; closure != NULL;
-         closure = grpc_closure_next(closure)) {
-      cpa = closure->cb_arg;
-      if (cpa->connected_subchannel == connected_subchannel) {
-        cpa->connected_subchannel = NULL;
-        grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
-      }
-    }
-    gpr_mu_unlock(&chand->mu_config);
-    return 1;
-  }
-  if (chand->lb_policy != NULL) {
-    grpc_lb_policy *lb_policy = chand->lb_policy;
-    int r;
-    GRPC_LB_POLICY_REF(lb_policy, "cc_pick_subchannel");
-    gpr_mu_unlock(&chand->mu_config);
-    r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollset,
-                            initial_metadata, connected_subchannel, on_ready);
-    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel");
-    return r;
-  }
-  if (chand->resolver != NULL && !chand->started_resolving) {
-    chand->started_resolving = 1;
-    GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-    grpc_resolver_next(exec_ctx, chand->resolver,
-                       &chand->incoming_configuration,
-                       &chand->on_config_changed);
-  }
-  cpa = gpr_malloc(sizeof(*cpa));
-  cpa->initial_metadata = initial_metadata;
-  cpa->connected_subchannel = connected_subchannel;
-  cpa->on_ready = on_ready;
-  cpa->elem = elem;
-  grpc_closure_init(&cpa->closure, continue_picking, cpa);
-  grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure, 1);
-  gpr_mu_unlock(&chand->mu_config);
-  return 0;
-}
-
-/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
-  grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem,
-                                   args->call_stack);
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {
-  grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
-}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  channel_data *chand = elem->channel_data;
-
-  memset(chand, 0, sizeof(*chand));
-
-  GPR_ASSERT(args->is_last);
-  GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
-
-  gpr_mu_init(&chand->mu_config);
-  grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
-  chand->owning_stack = args->channel_stack;
-
-  grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
-                               "client_channel");
-  chand->interested_parties = grpc_pollset_set_create();
-}
-
-/* Destructor for channel_data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  channel_data *chand = elem->channel_data;
-
-  if (chand->resolver != NULL) {
-    grpc_resolver_shutdown(exec_ctx, chand->resolver);
-    GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
-  }
-  if (chand->lb_policy != NULL) {
-    grpc_pollset_set_del_pollset_set(exec_ctx,
-                                     chand->lb_policy->interested_parties,
-                                     chand->interested_parties);
-    GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
-  }
-  grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
-  grpc_pollset_set_destroy(chand->interested_parties);
-  gpr_mu_destroy(&chand->mu_config);
-}
-
-static void cc_set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_pollset *pollset) {
-  call_data *calld = elem->call_data;
-  calld->pollset = pollset;
-}
-
-const grpc_channel_filter grpc_client_channel_filter = {
-    cc_start_transport_stream_op, cc_start_transport_op, sizeof(call_data),
-    init_call_elem, cc_set_pollset, destroy_call_elem, sizeof(channel_data),
-    init_channel_elem, destroy_channel_elem, cc_get_peer, "client-channel",
-};
-
-void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
-                                      grpc_channel_stack *channel_stack,
-                                      grpc_resolver *resolver) {
-  /* post construction initialization: set the transport setup pointer */
-  grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
-  channel_data *chand = elem->channel_data;
-  gpr_mu_lock(&chand->mu_config);
-  GPR_ASSERT(!chand->resolver);
-  chand->resolver = resolver;
-  GRPC_RESOLVER_REF(resolver, "channel");
-  if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
-      chand->exit_idle_when_lb_policy_arrives) {
-    chand->started_resolving = 1;
-    GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-    grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
-                       &chand->on_config_changed);
-  }
-  gpr_mu_unlock(&chand->mu_config);
-}
-
-grpc_connectivity_state grpc_client_channel_check_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
-  channel_data *chand = elem->channel_data;
-  grpc_connectivity_state out;
-  gpr_mu_lock(&chand->mu_config);
-  out = grpc_connectivity_state_check(&chand->state_tracker);
-  if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
-    if (chand->lb_policy != NULL) {
-      grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
-    } else {
-      chand->exit_idle_when_lb_policy_arrives = 1;
-      if (!chand->started_resolving && chand->resolver != NULL) {
-        GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-        chand->started_resolving = 1;
-        grpc_resolver_next(exec_ctx, chand->resolver,
-                           &chand->incoming_configuration,
-                           &chand->on_config_changed);
-      }
-    }
-  }
-  gpr_mu_unlock(&chand->mu_config);
-  return out;
-}
-
-typedef struct {
-  channel_data *chand;
-  grpc_pollset *pollset;
-  grpc_closure *on_complete;
-  grpc_closure my_closure;
-} external_connectivity_watcher;
-
-static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
-                                       bool iomgr_success) {
-  external_connectivity_watcher *w = arg;
-  grpc_closure *follow_up = w->on_complete;
-  grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
-                               w->pollset);
-  GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
-                           "external_connectivity_watcher");
-  gpr_free(w);
-  follow_up->cb(exec_ctx, follow_up->cb_arg, iomgr_success);
-}
-
-void grpc_client_channel_watch_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
-    grpc_connectivity_state *state, grpc_closure *on_complete) {
-  channel_data *chand = elem->channel_data;
-  external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
-  w->chand = chand;
-  w->pollset = pollset;
-  w->on_complete = on_complete;
-  grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
-  grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
-  GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
-                         "external_connectivity_watcher");
-  gpr_mu_lock(&chand->mu_config);
-  grpc_connectivity_state_notify_on_state_change(
-      exec_ctx, &chand->state_tracker, state, &w->my_closure);
-  gpr_mu_unlock(&chand->mu_config);
-}
diff --git a/src/core/channel/client_channel.h b/src/core/channel/client_channel.h
deleted file mode 100644
index 422f7f8..0000000
--- a/src/core/channel/client_channel.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_CLIENT_CHANNEL_H
-#define GRPC_CORE_CHANNEL_CLIENT_CHANNEL_H
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/client_config/resolver.h"
-
-/* A client channel is a channel that begins disconnected, and can connect
-   to some endpoint on demand. If that endpoint disconnects, it will be
-   connected to again later.
-
-   Calls on a disconnected client channel are queued until a connection is
-   established. */
-
-extern const grpc_channel_filter grpc_client_channel_filter;
-
-/* post-construction initializer to let the client channel know which
-   transport setup it should cancel upon destruction, or initiate when it needs
-   a connection */
-void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
-                                      grpc_channel_stack *channel_stack,
-                                      grpc_resolver *resolver);
-
-grpc_connectivity_state grpc_client_channel_check_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
-
-void grpc_client_channel_watch_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
-    grpc_connectivity_state *state, grpc_closure *on_complete);
-
-#endif /* GRPC_CORE_CHANNEL_CLIENT_CHANNEL_H */
diff --git a/src/core/channel/client_uchannel.c b/src/core/channel/client_uchannel.c
deleted file mode 100644
index d323272..0000000
--- a/src/core/channel/client_uchannel.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- *
- * 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/channel/client_uchannel.h"
-
-#include <string.h>
-
-#include "src/core/census/grpc_filter.h"
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/channel/subchannel_call_holder.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/channel.h"
-#include "src/core/transport/connectivity_state.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/useful.h>
-
-/** Microchannel (uchannel) implementation: a lightweight channel without any
- * load-balancing mechanisms meant for communication from within the core. */
-
-typedef struct client_uchannel_channel_data {
-  /** master channel - the grpc_channel instance that ultimately owns
-      this channel_data via its channel stack.
-      We occasionally use this to bump the refcount on the master channel
-      to keep ourselves alive through an asynchronous operation. */
-  grpc_channel_stack *owning_stack;
-
-  /** connectivity state being tracked */
-  grpc_connectivity_state_tracker state_tracker;
-
-  /** the subchannel wrapped by the microchannel */
-  grpc_connected_subchannel *connected_subchannel;
-
-  /** the callback used to stay subscribed to subchannel connectivity
-   * notifications */
-  grpc_closure connectivity_cb;
-
-  /** the current connectivity state of the wrapped subchannel */
-  grpc_connectivity_state subchannel_connectivity;
-
-  gpr_mu mu_state;
-} channel_data;
-
-typedef grpc_subchannel_call_holder call_data;
-
-static void monitor_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
-                               bool iomgr_success) {
-  channel_data *chand = arg;
-  grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
-                              chand->subchannel_connectivity,
-                              "uchannel_monitor_subchannel");
-  grpc_connected_subchannel_notify_on_state_change(
-      exec_ctx, chand->connected_subchannel, NULL,
-      &chand->subchannel_connectivity, &chand->connectivity_cb);
-}
-
-static char *cuc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
-  return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
-}
-
-static void cuc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
-                                          grpc_call_element *elem,
-                                          grpc_transport_stream_op *op) {
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
-}
-
-static void cuc_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                   grpc_channel_element *elem,
-                                   grpc_transport_op *op) {
-  channel_data *chand = elem->channel_data;
-
-  grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
-
-  GPR_ASSERT(op->set_accept_stream == false);
-  GPR_ASSERT(op->bind_pollset == NULL);
-
-  if (op->on_connectivity_state_change != NULL) {
-    grpc_connectivity_state_notify_on_state_change(
-        exec_ctx, &chand->state_tracker, op->connectivity_state,
-        op->on_connectivity_state_change);
-    op->on_connectivity_state_change = NULL;
-    op->connectivity_state = NULL;
-  }
-
-  if (op->disconnect) {
-    grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
-                                GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
-  }
-}
-
-static int cuc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
-                               grpc_metadata_batch *initial_metadata,
-                               grpc_connected_subchannel **connected_subchannel,
-                               grpc_closure *on_ready) {
-  channel_data *chand = arg;
-  GPR_ASSERT(initial_metadata != NULL);
-  *connected_subchannel = chand->connected_subchannel;
-  return 1;
-}
-
-/* Constructor for call_data */
-static void cuc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                               grpc_call_element_args *args) {
-  grpc_subchannel_call_holder_init(elem->call_data, cuc_pick_subchannel,
-                                   elem->channel_data, args->call_stack);
-}
-
-/* Destructor for call_data */
-static void cuc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem) {
-  grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
-}
-
-/* Constructor for channel_data */
-static void cuc_init_channel_elem(grpc_exec_ctx *exec_ctx,
-                                  grpc_channel_element *elem,
-                                  grpc_channel_element_args *args) {
-  channel_data *chand = elem->channel_data;
-  memset(chand, 0, sizeof(*chand));
-  grpc_closure_init(&chand->connectivity_cb, monitor_subchannel, chand);
-  GPR_ASSERT(args->is_last);
-  GPR_ASSERT(elem->filter == &grpc_client_uchannel_filter);
-  chand->owning_stack = args->channel_stack;
-  grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
-                               "client_uchannel");
-  gpr_mu_init(&chand->mu_state);
-}
-
-/* Destructor for channel_data */
-static void cuc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                     grpc_channel_element *elem) {
-  channel_data *chand = elem->channel_data;
-  /* cancel subscription */
-  grpc_connected_subchannel_notify_on_state_change(
-      exec_ctx, chand->connected_subchannel, NULL, NULL,
-      &chand->connectivity_cb);
-  grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
-  gpr_mu_destroy(&chand->mu_state);
-  GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, chand->connected_subchannel,
-                                  "uchannel");
-}
-
-static void cuc_set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                            grpc_pollset *pollset) {
-  call_data *calld = elem->call_data;
-  calld->pollset = pollset;
-}
-
-const grpc_channel_filter grpc_client_uchannel_filter = {
-    cuc_start_transport_stream_op, cuc_start_transport_op, sizeof(call_data),
-    cuc_init_call_elem, cuc_set_pollset, cuc_destroy_call_elem,
-    sizeof(channel_data), cuc_init_channel_elem, cuc_destroy_channel_elem,
-    cuc_get_peer, "client-uchannel",
-};
-
-grpc_connectivity_state grpc_client_uchannel_check_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
-  channel_data *chand = elem->channel_data;
-  grpc_connectivity_state out;
-  gpr_mu_lock(&chand->mu_state);
-  out = grpc_connectivity_state_check(&chand->state_tracker);
-  gpr_mu_unlock(&chand->mu_state);
-  return out;
-}
-
-void grpc_client_uchannel_watch_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
-    grpc_connectivity_state *state, grpc_closure *on_complete) {
-  channel_data *chand = elem->channel_data;
-  gpr_mu_lock(&chand->mu_state);
-  grpc_connectivity_state_notify_on_state_change(
-      exec_ctx, &chand->state_tracker, state, on_complete);
-  gpr_mu_unlock(&chand->mu_state);
-}
-
-grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel,
-                                          grpc_channel_args *args) {
-  grpc_channel *channel = NULL;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  channel =
-      grpc_channel_create(&exec_ctx, NULL, args, GRPC_CLIENT_UCHANNEL, NULL);
-
-  return channel;
-}
-
-void grpc_client_uchannel_set_connected_subchannel(
-    grpc_channel *uchannel, grpc_connected_subchannel *connected_subchannel) {
-  grpc_channel_element *elem =
-      grpc_channel_stack_last_element(grpc_channel_get_channel_stack(uchannel));
-  channel_data *chand = elem->channel_data;
-  GPR_ASSERT(elem->filter == &grpc_client_uchannel_filter);
-  gpr_mu_lock(&chand->mu_state);
-  chand->connected_subchannel = connected_subchannel;
-  GRPC_CONNECTED_SUBCHANNEL_REF(connected_subchannel, "uchannel");
-  gpr_mu_unlock(&chand->mu_state);
-}
diff --git a/src/core/channel/client_uchannel.h b/src/core/channel/client_uchannel.h
deleted file mode 100644
index 8bb288e..0000000
--- a/src/core/channel/client_uchannel.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_CLIENT_UCHANNEL_H
-#define GRPC_CORE_CHANNEL_CLIENT_UCHANNEL_H
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/client_config/resolver.h"
-
-#define GRPC_MICROCHANNEL_SUBCHANNEL_ARG "grpc.microchannel_subchannel_key"
-
-/* A client microchannel (aka uchannel) is a channel wrapping a subchannel, for
- * the purposes of lightweight RPC communications from within the core.*/
-
-extern const grpc_channel_filter grpc_client_uchannel_filter;
-
-grpc_connectivity_state grpc_client_uchannel_check_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
-
-void grpc_client_uchannel_watch_connectivity_state(
-    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
-    grpc_connectivity_state *state, grpc_closure *on_complete);
-
-grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel,
-                                          grpc_channel_args *args);
-
-void grpc_client_uchannel_set_connected_subchannel(
-    grpc_channel *uchannel, grpc_connected_subchannel *connected_subchannel);
-
-#endif /* GRPC_CORE_CHANNEL_CLIENT_UCHANNEL_H */
diff --git a/src/core/channel/compress_filter.c b/src/core/channel/compress_filter.c
deleted file mode 100644
index 3e7ca08..0000000
--- a/src/core/channel/compress_filter.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- *
- * 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 <assert.h>
-#include <string.h>
-
-#include <grpc/compression.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/compression/algorithm_metadata.h"
-#include "src/core/compression/message_compress.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-#include "src/core/transport/static_metadata.h"
-
-typedef struct call_data {
-  gpr_slice_buffer slices; /**< Buffers up input slices to be compressed */
-  grpc_linked_mdelem compression_algorithm_storage;
-  grpc_linked_mdelem accept_encoding_storage;
-  uint32_t remaining_slice_bytes;
-  /** Compression algorithm we'll try to use. It may be given by incoming
-   * metadata, or by the channel's default compression settings. */
-  grpc_compression_algorithm compression_algorithm;
-  /** If true, contents of \a compression_algorithm are authoritative */
-  int has_compression_algorithm;
-
-  grpc_transport_stream_op send_op;
-  uint32_t send_length;
-  uint32_t send_flags;
-  gpr_slice incoming_slice;
-  grpc_slice_buffer_stream replacement_stream;
-  grpc_closure *post_send;
-  grpc_closure send_done;
-  grpc_closure got_slice;
-} call_data;
-
-typedef struct channel_data {
-  /** The default, channel-level, compression algorithm */
-  grpc_compression_algorithm default_compression_algorithm;
-  /** Compression options for the channel */
-  grpc_compression_options compression_options;
-  /** Supported compression algorithms */
-  uint32_t supported_compression_algorithms;
-} channel_data;
-
-/** For each \a md element from the incoming metadata, filter out the entry for
- * "grpc-encoding", using its value to populate the call data's
- * compression_algorithm field. */
-static grpc_mdelem *compression_md_filter(void *user_data, grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  channel_data *channeld = elem->channel_data;
-
-  if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
-    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
-    if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
-                                          &calld->compression_algorithm)) {
-      gpr_log(GPR_ERROR,
-              "Invalid compression algorithm: '%s' (unknown). Ignoring.",
-              md_c_str);
-      calld->compression_algorithm = GRPC_COMPRESS_NONE;
-    }
-    if (grpc_compression_options_is_algorithm_enabled(
-            &channeld->compression_options, calld->compression_algorithm) ==
-        0) {
-      gpr_log(GPR_ERROR,
-              "Invalid compression algorithm: '%s' (previously disabled). "
-              "Ignoring.",
-              md_c_str);
-      calld->compression_algorithm = GRPC_COMPRESS_NONE;
-    }
-    calld->has_compression_algorithm = 1;
-    return NULL;
-  }
-
-  return md;
-}
-
-static int skip_compression(grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
-  channel_data *channeld = elem->channel_data;
-  if (calld->has_compression_algorithm) {
-    if (calld->compression_algorithm == GRPC_COMPRESS_NONE) {
-      return 1;
-    }
-    return 0; /* we have an actual call-specific algorithm */
-  }
-  /* no per-call compression override */
-  return channeld->default_compression_algorithm == GRPC_COMPRESS_NONE;
-}
-
-/** Filter initial metadata */
-static void process_send_initial_metadata(
-    grpc_call_element *elem, grpc_metadata_batch *initial_metadata) {
-  call_data *calld = elem->call_data;
-  channel_data *channeld = elem->channel_data;
-  /* Parse incoming request for compression. If any, it'll be available
-   * at calld->compression_algorithm */
-  grpc_metadata_batch_filter(initial_metadata, compression_md_filter, elem);
-  if (!calld->has_compression_algorithm) {
-    /* If no algorithm was found in the metadata and we aren't
-     * exceptionally skipping compression, fall back to the channel
-     * default */
-    calld->compression_algorithm = channeld->default_compression_algorithm;
-    calld->has_compression_algorithm = 1; /* GPR_TRUE */
-  }
-  /* hint compression algorithm */
-  grpc_metadata_batch_add_tail(
-      initial_metadata, &calld->compression_algorithm_storage,
-      grpc_compression_encoding_mdelem(calld->compression_algorithm));
-
-  /* convey supported compression algorithms */
-  grpc_metadata_batch_add_tail(initial_metadata,
-                               &calld->accept_encoding_storage,
-                               GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
-                                   channeld->supported_compression_algorithms));
-}
-
-static void continue_send_message(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem);
-
-static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
-  grpc_call_element *elem = elemp;
-  call_data *calld = elem->call_data;
-  gpr_slice_buffer_reset_and_unref(&calld->slices);
-  calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, success);
-}
-
-static void finish_send_message(grpc_exec_ctx *exec_ctx,
-                                grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
-  int did_compress;
-  gpr_slice_buffer tmp;
-  gpr_slice_buffer_init(&tmp);
-  did_compress =
-      grpc_msg_compress(calld->compression_algorithm, &calld->slices, &tmp);
-  if (did_compress) {
-    gpr_slice_buffer_swap(&calld->slices, &tmp);
-    calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
-  }
-  gpr_slice_buffer_destroy(&tmp);
-
-  grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
-                                calld->send_flags);
-  calld->send_op.send_message = &calld->replacement_stream.base;
-  calld->post_send = calld->send_op.on_complete;
-  calld->send_op.on_complete = &calld->send_done;
-
-  grpc_call_next_op(exec_ctx, elem, &calld->send_op);
-}
-
-static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
-  grpc_call_element *elem = elemp;
-  call_data *calld = elem->call_data;
-  gpr_slice_buffer_add(&calld->slices, calld->incoming_slice);
-  if (calld->send_length == calld->slices.length) {
-    finish_send_message(exec_ctx, elem);
-  } else {
-    continue_send_message(exec_ctx, elem);
-  }
-}
-
-static void continue_send_message(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
-  while (grpc_byte_stream_next(exec_ctx, calld->send_op.send_message,
-                               &calld->incoming_slice, ~(size_t)0,
-                               &calld->got_slice)) {
-    gpr_slice_buffer_add(&calld->slices, calld->incoming_slice);
-    if (calld->send_length == calld->slices.length) {
-      finish_send_message(exec_ctx, elem);
-      break;
-    }
-  }
-}
-
-static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
-                                               grpc_call_element *elem,
-                                               grpc_transport_stream_op *op) {
-  call_data *calld = elem->call_data;
-
-  GPR_TIMER_BEGIN("compress_start_transport_stream_op", 0);
-
-  if (op->send_initial_metadata) {
-    process_send_initial_metadata(elem, op->send_initial_metadata);
-  }
-  if (op->send_message != NULL && !skip_compression(elem) &&
-      0 == (op->send_message->flags & GRPC_WRITE_NO_COMPRESS)) {
-    calld->send_op = *op;
-    calld->send_length = op->send_message->length;
-    calld->send_flags = op->send_message->flags;
-    continue_send_message(exec_ctx, elem);
-  } else {
-    /* pass control down the stack */
-    grpc_call_next_op(exec_ctx, elem, op);
-  }
-
-  GPR_TIMER_END("compress_start_transport_stream_op", 0);
-}
-
-/* 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;
-
-  /* initialize members */
-  gpr_slice_buffer_init(&calld->slices);
-  calld->has_compression_algorithm = 0;
-  grpc_closure_init(&calld->got_slice, got_slice, elem);
-  grpc_closure_init(&calld->send_done, send_done, elem);
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {
-  /* grab pointers to our data from the call element */
-  call_data *calld = elem->call_data;
-  gpr_slice_buffer_destroy(&calld->slices);
-}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  channel_data *channeld = elem->channel_data;
-  grpc_compression_algorithm algo_idx;
-
-  grpc_compression_options_init(&channeld->compression_options);
-  channeld->compression_options.enabled_algorithms_bitset =
-      (uint32_t)grpc_channel_args_compression_algorithm_get_states(
-          args->channel_args);
-
-  channeld->default_compression_algorithm =
-      grpc_channel_args_get_compression_algorithm(args->channel_args);
-  /* Make sure the default isn't disabled. */
-  GPR_ASSERT(grpc_compression_options_is_algorithm_enabled(
-      &channeld->compression_options, channeld->default_compression_algorithm));
-  channeld->compression_options.default_compression_algorithm =
-      channeld->default_compression_algorithm;
-
-  channeld->supported_compression_algorithms = 0;
-  for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
-    /* skip disabled algorithms */
-    if (grpc_compression_options_is_algorithm_enabled(
-            &channeld->compression_options, algo_idx) == 0) {
-      continue;
-    }
-    channeld->supported_compression_algorithms |= 1u << algo_idx;
-  }
-
-  GPR_ASSERT(!args->is_last);
-}
-
-/* Destructor for channel data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {}
-
-const grpc_channel_filter grpc_compress_filter = {
-    compress_start_transport_stream_op, grpc_channel_next_op, sizeof(call_data),
-    init_call_elem, grpc_call_stack_ignore_set_pollset, destroy_call_elem,
-    sizeof(channel_data), init_channel_elem, destroy_channel_elem,
-    grpc_call_next_get_peer, "compress"};
diff --git a/src/core/channel/compress_filter.h b/src/core/channel/compress_filter.h
deleted file mode 100644
index 8c208ac..0000000
--- a/src/core/channel/compress_filter.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_COMPRESS_FILTER_H
-#define GRPC_CORE_CHANNEL_COMPRESS_FILTER_H
-
-#include "src/core/channel/channel_stack.h"
-
-#define GRPC_COMPRESS_REQUEST_ALGORITHM_KEY "grpc-internal-encoding-request"
-
-/** Compression filter for outgoing data.
- *
- * See <grpc/compression.h> for the available compression settings.
- *
- * Compression settings may come from:
- *  - Channel configuration, as established at channel creation time.
- *  - The metadata accompanying the outgoing data to be compressed. This is
- *    taken as a request only. We may choose not to honor it. The metadata key
- *    is given by \a GRPC_COMPRESS_REQUEST_ALGORITHM_KEY.
- *
- * Compression can be disabled for concrete messages (for instance in order to
- * prevent CRIME/BEAST type attacks) by having the GRPC_WRITE_NO_COMPRESS set in
- * the BEGIN_MESSAGE flags.
- *
- * The attempted compression mechanism is added to the resulting initial
- * metadata under the'grpc-encoding' key.
- *
- * If compression is actually performed, BEGIN_MESSAGE's flag is modified to
- * incorporate GRPC_WRITE_INTERNAL_COMPRESS. Otherwise, and regardless of the
- * aforementioned 'grpc-encoding' metadata value, data will pass through
- * uncompressed. */
-
-extern const grpc_channel_filter grpc_compress_filter;
-
-#endif /* GRPC_CORE_CHANNEL_COMPRESS_FILTER_H */
diff --git a/src/core/channel/connected_channel.c b/src/core/channel/connected_channel.c
deleted file mode 100644
index e7ed3cc..0000000
--- a/src/core/channel/connected_channel.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- *
- * 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/channel/connected_channel.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "src/core/support/string.h"
-#include "src/core/transport/transport.h"
-#include "src/core/profiling/timers.h"
-#include <grpc/byte_buffer.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-
-#define MAX_BUFFER_LENGTH 8192
-
-typedef struct connected_channel_channel_data {
-  grpc_transport *transport;
-} channel_data;
-
-typedef struct connected_channel_call_data { void *unused; } call_data;
-
-/* We perform a small hack to locate transport data alongside the connected
-   channel data in call allocations, to allow everything to be pulled in minimal
-   cache line requests */
-#define TRANSPORT_STREAM_FROM_CALL_DATA(calld) ((grpc_stream *)((calld) + 1))
-#define CALL_DATA_FROM_TRANSPORT_STREAM(transport_stream) \
-  (((call_data *)(transport_stream)) - 1)
-
-/* Intercept a call operation and either push it directly up or translate it
-   into transport stream operations */
-static void con_start_transport_stream_op(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_CALL_LOG_OP(GPR_INFO, elem, op);
-
-  grpc_transport_perform_stream_op(exec_ctx, chand->transport,
-                                   TRANSPORT_STREAM_FROM_CALL_DATA(calld), op);
-}
-
-static void con_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                   grpc_channel_element *elem,
-                                   grpc_transport_op *op) {
-  channel_data *chand = elem->channel_data;
-  grpc_transport_perform_op(exec_ctx, chand->transport, 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;
-  channel_data *chand = elem->channel_data;
-  int r;
-
-  r = grpc_transport_init_stream(
-      exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld),
-      &args->call_stack->refcount, args->server_transport_data);
-  GPR_ASSERT(r == 0);
-}
-
-static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                        grpc_pollset *pollset) {
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  grpc_transport_set_pollset(exec_ctx, chand->transport,
-                             TRANSPORT_STREAM_FROM_CALL_DATA(calld), pollset);
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  grpc_transport_destroy_stream(exec_ctx, chand->transport,
-                                TRANSPORT_STREAM_FROM_CALL_DATA(calld));
-}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  channel_data *cd = (channel_data *)elem->channel_data;
-  GPR_ASSERT(args->is_last);
-  cd->transport = NULL;
-}
-
-/* Destructor for channel_data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  channel_data *cd = (channel_data *)elem->channel_data;
-  grpc_transport_destroy(exec_ctx, cd->transport);
-}
-
-static char *con_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
-  channel_data *chand = elem->channel_data;
-  return grpc_transport_get_peer(exec_ctx, chand->transport);
-}
-
-static const grpc_channel_filter connected_channel_filter = {
-    con_start_transport_stream_op, con_start_transport_op, sizeof(call_data),
-    init_call_elem, set_pollset, destroy_call_elem, sizeof(channel_data),
-    init_channel_elem, destroy_channel_elem, con_get_peer, "connected",
-};
-
-static void bind_transport(grpc_channel_stack *channel_stack,
-                           grpc_channel_element *elem, void *t) {
-  channel_data *cd = (channel_data *)elem->channel_data;
-  GPR_ASSERT(elem->filter == &connected_channel_filter);
-  GPR_ASSERT(cd->transport == NULL);
-  cd->transport = t;
-
-  /* HACK(ctiller): increase call stack size for the channel to make space
-     for channel data. We need a cleaner (but performant) way to do this,
-     and I'm not sure what that is yet.
-     This is only "safe" because call stacks place no additional data after
-     the last call element, and the last call element MUST be the connected
-     channel. */
-  channel_stack->call_stack_size += grpc_transport_stream_size(t);
-}
-
-bool grpc_add_connected_filter(grpc_channel_stack_builder *builder,
-                               void *arg_must_be_null) {
-  GPR_ASSERT(arg_must_be_null == NULL);
-  grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
-  GPR_ASSERT(t != NULL);
-  return grpc_channel_stack_builder_append_filter(
-      builder, &connected_channel_filter, bind_transport, t);
-}
-
-grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
-  return TRANSPORT_STREAM_FROM_CALL_DATA(calld);
-}
diff --git a/src/core/channel/connected_channel.h b/src/core/channel/connected_channel.h
deleted file mode 100644
index 7c0c835..0000000
--- a/src/core/channel/connected_channel.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_CONNECTED_CHANNEL_H
-#define GRPC_CORE_CHANNEL_CONNECTED_CHANNEL_H
-
-#include "src/core/channel/channel_stack_builder.h"
-
-bool grpc_add_connected_filter(grpc_channel_stack_builder *builder,
-                               void *arg_must_be_null);
-
-#endif /* GRPC_CORE_CHANNEL_CONNECTED_CHANNEL_H */
diff --git a/src/core/channel/context.h b/src/core/channel/context.h
deleted file mode 100644
index db217dc..0000000
--- a/src/core/channel/context.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_CONTEXT_H
-#define GRPC_CORE_CHANNEL_CONTEXT_H
-
-/* Call object context pointers */
-typedef enum {
-  GRPC_CONTEXT_SECURITY = 0,
-  GRPC_CONTEXT_TRACING,
-  GRPC_CONTEXT_COUNT
-} grpc_context_index;
-
-typedef struct {
-  void *value;
-  void (*destroy)(void *);
-} grpc_call_context_element;
-
-#endif /* GRPC_CORE_CHANNEL_CONTEXT_H */
diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c
deleted file mode 100644
index 1aa2720..0000000
--- a/src/core/channel/http_client_filter.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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/channel/http_client_filter.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <string.h>
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-#include "src/core/transport/static_metadata.h"
-
-typedef struct call_data {
-  grpc_linked_mdelem method;
-  grpc_linked_mdelem scheme;
-  grpc_linked_mdelem authority;
-  grpc_linked_mdelem te_trailers;
-  grpc_linked_mdelem content_type;
-  grpc_linked_mdelem user_agent;
-
-  grpc_metadata_batch *recv_initial_metadata;
-
-  /** Closure to call when finished with the hc_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 hc_on_recv;
-} call_data;
-
-typedef struct channel_data {
-  grpc_mdelem *static_scheme;
-  grpc_mdelem *user_agent;
-} channel_data;
-
-typedef struct {
-  grpc_call_element *elem;
-  grpc_exec_ctx *exec_ctx;
-} client_recv_filter_args;
-
-static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
-  client_recv_filter_args *a = user_data;
-  if (md == GRPC_MDELEM_STATUS_200) {
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_STATUS) {
-    grpc_call_element_send_cancel(a->exec_ctx, a->elem);
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
-    return NULL;
-  }
-  return md;
-}
-
-static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  client_recv_filter_args a;
-  a.elem = elem;
-  a.exec_ctx = exec_ctx;
-  grpc_metadata_batch_filter(calld->recv_initial_metadata, client_recv_filter,
-                             &a);
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
-}
-
-static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
-  /* eat the things we'd like to set ourselves */
-  if (md->key == GRPC_MDSTR_METHOD) return NULL;
-  if (md->key == GRPC_MDSTR_SCHEME) return NULL;
-  if (md->key == GRPC_MDSTR_TE) return NULL;
-  if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL;
-  if (md->key == GRPC_MDSTR_USER_AGENT) return NULL;
-  return md;
-}
-
-static void hc_mutate_op(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 *channeld = elem->channel_data;
-  if (op->send_initial_metadata != NULL) {
-    grpc_metadata_batch_filter(op->send_initial_metadata, client_strip_filter,
-                               elem);
-    /* Send : prefixed headers, which have to be before any application
-       layer headers. */
-    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method,
-                                 GRPC_MDELEM_METHOD_POST);
-    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme,
-                                 channeld->static_scheme);
-    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers,
-                                 GRPC_MDELEM_TE_TRAILERS);
-    grpc_metadata_batch_add_tail(
-        op->send_initial_metadata, &calld->content_type,
-        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
-    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent,
-                                 GRPC_MDELEM_REF(channeld->user_agent));
-  }
-
-  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->hc_on_recv;
-  }
-}
-
-static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem,
-                                  grpc_transport_stream_op *op) {
-  GPR_TIMER_BEGIN("hc_start_transport_op", 0);
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  hc_mutate_op(elem, op);
-  GPR_TIMER_END("hc_start_transport_op", 0);
-  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;
-  calld->on_done_recv = NULL;
-  grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {}
-
-static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) {
-  unsigned i;
-  size_t j;
-  grpc_mdelem *valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP,
-                                  GRPC_MDELEM_SCHEME_HTTPS};
-  if (args != NULL) {
-    for (i = 0; i < args->num_args; ++i) {
-      if (args->args[i].type == GRPC_ARG_STRING &&
-          strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) {
-        for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) {
-          if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value),
-                          args->args[i].value.string)) {
-            return valid_schemes[j];
-          }
-        }
-      }
-    }
-  }
-  return GRPC_MDELEM_SCHEME_HTTP;
-}
-
-static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args) {
-  gpr_strvec v;
-  size_t i;
-  int is_first = 1;
-  char *tmp;
-  grpc_mdstr *result;
-
-  gpr_strvec_init(&v);
-
-  for (i = 0; args && i < args->num_args; i++) {
-    if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
-      if (args->args[i].type != GRPC_ARG_STRING) {
-        gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
-                GRPC_ARG_PRIMARY_USER_AGENT_STRING);
-      } else {
-        if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
-        is_first = 0;
-        gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
-      }
-    }
-  }
-
-  gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ",
-               grpc_version_string(), GPR_PLATFORM_STRING);
-  is_first = 0;
-  gpr_strvec_add(&v, tmp);
-
-  for (i = 0; args && i < args->num_args; i++) {
-    if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
-      if (args->args[i].type != GRPC_ARG_STRING) {
-        gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
-                GRPC_ARG_SECONDARY_USER_AGENT_STRING);
-      } else {
-        if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
-        is_first = 0;
-        gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
-      }
-    }
-  }
-
-  tmp = gpr_strvec_flatten(&v, NULL);
-  gpr_strvec_destroy(&v);
-  result = grpc_mdstr_from_string(tmp);
-  gpr_free(tmp);
-
-  return result;
-}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  channel_data *chand = elem->channel_data;
-  GPR_ASSERT(!args->is_last);
-  chand->static_scheme = scheme_from_args(args->channel_args);
-  chand->user_agent = grpc_mdelem_from_metadata_strings(
-      GRPC_MDSTR_USER_AGENT, user_agent_from_args(args->channel_args));
-}
-
-/* Destructor for channel data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  channel_data *chand = elem->channel_data;
-  GRPC_MDELEM_UNREF(chand->user_agent);
-}
-
-const grpc_channel_filter grpc_http_client_filter = {
-    hc_start_transport_op, grpc_channel_next_op, sizeof(call_data),
-    init_call_elem, grpc_call_stack_ignore_set_pollset, destroy_call_elem,
-    sizeof(channel_data), init_channel_elem, destroy_channel_elem,
-    grpc_call_next_get_peer, "http-client"};
diff --git a/src/core/channel/http_client_filter.h b/src/core/channel/http_client_filter.h
deleted file mode 100644
index 6f619bb..0000000
--- a/src/core/channel/http_client_filter.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_HTTP_CLIENT_FILTER_H
-#define GRPC_CORE_CHANNEL_HTTP_CLIENT_FILTER_H
-
-#include "src/core/channel/channel_stack.h"
-
-/* Processes metadata on the client side for HTTP2 transports */
-extern const grpc_channel_filter grpc_http_client_filter;
-
-#define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme"
-
-#endif /* GRPC_CORE_CHANNEL_HTTP_CLIENT_FILTER_H */
diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c
deleted file mode 100644
index 370f8db..0000000
--- a/src/core/channel/http_server_filter.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- *
- * 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/channel/http_server_filter.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <string.h>
-#include "src/core/profiling/timers.h"
-#include "src/core/transport/static_metadata.h"
-
-typedef struct call_data {
-  uint8_t seen_path;
-  uint8_t seen_post;
-  uint8_t sent_status;
-  uint8_t seen_scheme;
-  uint8_t seen_te_trailers;
-  uint8_t seen_authority;
-  grpc_linked_mdelem status;
-  grpc_linked_mdelem content_type;
-
-  grpc_metadata_batch *recv_initial_metadata;
-  /** Closure to call when finished with the hs_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 hs_on_recv;
-} call_data;
-
-typedef struct channel_data { uint8_t unused; } channel_data;
-
-typedef struct {
-  grpc_call_element *elem;
-  grpc_exec_ctx *exec_ctx;
-} server_filter_args;
-
-static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
-  server_filter_args *a = user_data;
-  grpc_call_element *elem = a->elem;
-  call_data *calld = elem->call_data;
-
-  /* Check if it is one of the headers we care about. */
-  if (md == GRPC_MDELEM_TE_TRAILERS || md == GRPC_MDELEM_METHOD_POST ||
-      md == GRPC_MDELEM_SCHEME_HTTP || md == GRPC_MDELEM_SCHEME_HTTPS ||
-      md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
-    /* swallow it */
-    if (md == GRPC_MDELEM_METHOD_POST) {
-      calld->seen_post = 1;
-    } else if (md->key == GRPC_MDSTR_SCHEME) {
-      calld->seen_scheme = 1;
-    } else if (md == GRPC_MDELEM_TE_TRAILERS) {
-      calld->seen_te_trailers = 1;
-    }
-    /* TODO(klempner): Track that we've seen all the headers we should
-       require */
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
-    if (strncmp(grpc_mdstr_as_c_string(md->value), "application/grpc+", 17) ==
-        0) {
-      /* Although the C implementation doesn't (currently) generate them,
-         any custom +-suffix is explicitly valid. */
-      /* TODO(klempner): We should consider preallocating common values such
-         as +proto or +json, or at least stashing them if we see them. */
-      /* TODO(klempner): Should we be surfacing this to application code? */
-    } else {
-      /* TODO(klempner): We're currently allowing this, but we shouldn't
-         see it without a proxy so log for now. */
-      gpr_log(GPR_INFO, "Unexpected content-type %s",
-              grpc_mdstr_as_c_string(md->value));
-    }
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD ||
-             md->key == GRPC_MDSTR_SCHEME) {
-    gpr_log(GPR_ERROR, "Invalid %s: header: '%s'",
-            grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value));
-    /* swallow it and error everything out. */
-    /* TODO(klempner): We ought to generate more descriptive error messages
-       on the wire here. */
-    grpc_call_element_send_cancel(a->exec_ctx, elem);
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_PATH) {
-    if (calld->seen_path) {
-      gpr_log(GPR_ERROR, "Received :path twice");
-      return NULL;
-    }
-    calld->seen_path = 1;
-    return md;
-  } else if (md->key == GRPC_MDSTR_AUTHORITY) {
-    calld->seen_authority = 1;
-    return md;
-  } else if (md->key == GRPC_MDSTR_HOST) {
-    /* translate host to :authority since :authority may be
-       omitted */
-    grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
-        GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value));
-    calld->seen_authority = 1;
-    return authority;
-  } else {
-    return md;
-  }
-}
-
-static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  if (success) {
-    server_filter_args a;
-    a.elem = elem;
-    a.exec_ctx = exec_ctx;
-    grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, &a);
-    /* Have we seen the required http2 transport headers?
-       (:method, :scheme, content-type, with :path and :authority covered
-       at the channel level right now) */
-    if (calld->seen_post && calld->seen_scheme && calld->seen_te_trailers &&
-        calld->seen_path && calld->seen_authority) {
-      /* do nothing */
-    } else {
-      if (!calld->seen_path) {
-        gpr_log(GPR_ERROR, "Missing :path header");
-      }
-      if (!calld->seen_authority) {
-        gpr_log(GPR_ERROR, "Missing :authority header");
-      }
-      if (!calld->seen_post) {
-        gpr_log(GPR_ERROR, "Missing :method header");
-      }
-      if (!calld->seen_scheme) {
-        gpr_log(GPR_ERROR, "Missing :scheme header");
-      }
-      if (!calld->seen_te_trailers) {
-        gpr_log(GPR_ERROR, "Missing te trailers header");
-      }
-      /* Error this call out */
-      success = 0;
-      grpc_call_element_send_cancel(exec_ctx, elem);
-    }
-  }
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
-}
-
-static void hs_mutate_op(grpc_call_element *elem,
-                         grpc_transport_stream_op *op) {
-  /* grab pointers to our data from the call element */
-  call_data *calld = elem->call_data;
-
-  if (op->send_initial_metadata != NULL && !calld->sent_status) {
-    calld->sent_status = 1;
-    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->status,
-                                 GRPC_MDELEM_STATUS_200);
-    grpc_metadata_batch_add_tail(
-        op->send_initial_metadata, &calld->content_type,
-        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
-  }
-
-  if (op->recv_initial_metadata) {
-    /* 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->hs_on_recv;
-  }
-}
-
-static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem,
-                                  grpc_transport_stream_op *op) {
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  GPR_TIMER_BEGIN("hs_start_transport_op", 0);
-  hs_mutate_op(elem, op);
-  grpc_call_next_op(exec_ctx, elem, op);
-  GPR_TIMER_END("hs_start_transport_op", 0);
-}
-
-/* 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;
-  /* initialize members */
-  memset(calld, 0, sizeof(*calld));
-  grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem);
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  GPR_ASSERT(!args->is_last);
-}
-
-/* Destructor for channel data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {}
-
-const grpc_channel_filter grpc_http_server_filter = {
-    hs_start_transport_op, grpc_channel_next_op, sizeof(call_data),
-    init_call_elem, grpc_call_stack_ignore_set_pollset, destroy_call_elem,
-    sizeof(channel_data), init_channel_elem, destroy_channel_elem,
-    grpc_call_next_get_peer, "http-server"};
diff --git a/src/core/channel/http_server_filter.h b/src/core/channel/http_server_filter.h
deleted file mode 100644
index 528c864..0000000
--- a/src/core/channel/http_server_filter.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_HTTP_SERVER_FILTER_H
-#define GRPC_CORE_CHANNEL_HTTP_SERVER_FILTER_H
-
-#include "src/core/channel/channel_stack.h"
-
-/* Processes metadata on the client side for HTTP2 transports */
-extern const grpc_channel_filter grpc_http_server_filter;
-
-#endif /* GRPC_CORE_CHANNEL_HTTP_SERVER_FILTER_H */
diff --git a/src/core/channel/subchannel_call_holder.c b/src/core/channel/subchannel_call_holder.c
deleted file mode 100644
index 9c087dc..0000000
--- a/src/core/channel/subchannel_call_holder.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- *
- * 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/channel/subchannel_call_holder.h"
-
-#include <grpc/support/alloc.h>
-
-#include "src/core/profiling/timers.h"
-
-#define GET_CALL(holder) \
-  ((grpc_subchannel_call *)(gpr_atm_acq_load(&(holder)->subchannel_call)))
-
-#define CANCELLED_CALL ((grpc_subchannel_call *)1)
-
-static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *holder,
-                             bool success);
-static void retry_ops(grpc_exec_ctx *exec_ctx, void *retry_ops_args,
-                      bool success);
-
-static void add_waiting_locked(grpc_subchannel_call_holder *holder,
-                               grpc_transport_stream_op *op);
-static void fail_locked(grpc_exec_ctx *exec_ctx,
-                        grpc_subchannel_call_holder *holder);
-static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
-                                 grpc_subchannel_call_holder *holder);
-
-void grpc_subchannel_call_holder_init(
-    grpc_subchannel_call_holder *holder,
-    grpc_subchannel_call_holder_pick_subchannel pick_subchannel,
-    void *pick_subchannel_arg, grpc_call_stack *owning_call) {
-  gpr_atm_rel_store(&holder->subchannel_call, 0);
-  holder->pick_subchannel = pick_subchannel;
-  holder->pick_subchannel_arg = pick_subchannel_arg;
-  gpr_mu_init(&holder->mu);
-  holder->connected_subchannel = NULL;
-  holder->waiting_ops = NULL;
-  holder->waiting_ops_count = 0;
-  holder->waiting_ops_capacity = 0;
-  holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
-  holder->owning_call = owning_call;
-}
-
-void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
-                                         grpc_subchannel_call_holder *holder) {
-  grpc_subchannel_call *call = GET_CALL(holder);
-  if (call != NULL && call != CANCELLED_CALL) {
-    GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "holder");
-  }
-  GPR_ASSERT(holder->creation_phase ==
-             GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
-  gpr_mu_destroy(&holder->mu);
-  GPR_ASSERT(holder->waiting_ops_count == 0);
-  gpr_free(holder->waiting_ops);
-}
-
-void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
-                                            grpc_subchannel_call_holder *holder,
-                                            grpc_transport_stream_op *op) {
-  /* try to (atomically) get the call */
-  grpc_subchannel_call *call = GET_CALL(holder);
-  GPR_TIMER_BEGIN("grpc_subchannel_call_holder_perform_op", 0);
-  if (call == CANCELLED_CALL) {
-    grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
-    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
-    return;
-  }
-  if (call != NULL) {
-    grpc_subchannel_call_process_op(exec_ctx, call, op);
-    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
-    return;
-  }
-  /* we failed; lock and figure out what to do */
-  gpr_mu_lock(&holder->mu);
-retry:
-  /* need to recheck that another thread hasn't set the call */
-  call = GET_CALL(holder);
-  if (call == CANCELLED_CALL) {
-    gpr_mu_unlock(&holder->mu);
-    grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
-    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
-    return;
-  }
-  if (call != NULL) {
-    gpr_mu_unlock(&holder->mu);
-    grpc_subchannel_call_process_op(exec_ctx, call, op);
-    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
-    return;
-  }
-  /* if this is a cancellation, then we can raise our cancelled flag */
-  if (op->cancel_with_status != GRPC_STATUS_OK) {
-    if (!gpr_atm_rel_cas(&holder->subchannel_call, 0, 1)) {
-      goto retry;
-    } else {
-      switch (holder->creation_phase) {
-        case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
-          fail_locked(exec_ctx, holder);
-          break;
-        case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
-          holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL,
-                                  &holder->connected_subchannel, NULL);
-          break;
-      }
-      gpr_mu_unlock(&holder->mu);
-      grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
-      GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
-      return;
-    }
-  }
-  /* if we don't have a subchannel, try to get one */
-  if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
-      holder->connected_subchannel == NULL &&
-      op->send_initial_metadata != NULL) {
-    holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
-    grpc_closure_init(&holder->next_step, subchannel_ready, holder);
-    GRPC_CALL_STACK_REF(holder->owning_call, "pick_subchannel");
-    if (holder->pick_subchannel(
-            exec_ctx, holder->pick_subchannel_arg, op->send_initial_metadata,
-            &holder->connected_subchannel, &holder->next_step)) {
-      holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
-      GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
-    }
-  }
-  /* if we've got a subchannel, then let's ask it to create a call */
-  if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
-      holder->connected_subchannel != NULL) {
-    gpr_atm_rel_store(
-        &holder->subchannel_call,
-        (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
-            exec_ctx, holder->connected_subchannel, holder->pollset));
-    retry_waiting_locked(exec_ctx, holder);
-    goto retry;
-  }
-  /* nothing to be done but wait */
-  add_waiting_locked(holder, op);
-  gpr_mu_unlock(&holder->mu);
-  GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
-}
-
-static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  grpc_subchannel_call_holder *holder = arg;
-  gpr_mu_lock(&holder->mu);
-  GPR_ASSERT(holder->creation_phase ==
-             GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
-  holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
-  if (holder->connected_subchannel == NULL) {
-    fail_locked(exec_ctx, holder);
-  } else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
-    /* already cancelled before subchannel became ready */
-    fail_locked(exec_ctx, holder);
-  } else {
-    gpr_atm_rel_store(
-        &holder->subchannel_call,
-        (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
-            exec_ctx, holder->connected_subchannel, holder->pollset));
-    retry_waiting_locked(exec_ctx, holder);
-  }
-  gpr_mu_unlock(&holder->mu);
-  GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
-}
-
-typedef struct {
-  grpc_transport_stream_op *ops;
-  size_t nops;
-  grpc_subchannel_call *call;
-} retry_ops_args;
-
-static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
-                                 grpc_subchannel_call_holder *holder) {
-  retry_ops_args *a = gpr_malloc(sizeof(*a));
-  a->ops = holder->waiting_ops;
-  a->nops = holder->waiting_ops_count;
-  a->call = GET_CALL(holder);
-  if (a->call == CANCELLED_CALL) {
-    gpr_free(a);
-    fail_locked(exec_ctx, holder);
-    return;
-  }
-  holder->waiting_ops = NULL;
-  holder->waiting_ops_count = 0;
-  holder->waiting_ops_capacity = 0;
-  GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
-  grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(retry_ops, a), true,
-                        NULL);
-}
-
-static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, bool success) {
-  retry_ops_args *a = args;
-  size_t i;
-  for (i = 0; i < a->nops; i++) {
-    grpc_subchannel_call_process_op(exec_ctx, a->call, &a->ops[i]);
-  }
-  GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
-  gpr_free(a->ops);
-  gpr_free(a);
-}
-
-static void add_waiting_locked(grpc_subchannel_call_holder *holder,
-                               grpc_transport_stream_op *op) {
-  GPR_TIMER_BEGIN("add_waiting_locked", 0);
-  if (holder->waiting_ops_count == holder->waiting_ops_capacity) {
-    holder->waiting_ops_capacity = GPR_MAX(3, 2 * holder->waiting_ops_capacity);
-    holder->waiting_ops =
-        gpr_realloc(holder->waiting_ops, holder->waiting_ops_capacity *
-                                             sizeof(*holder->waiting_ops));
-  }
-  holder->waiting_ops[holder->waiting_ops_count++] = *op;
-  GPR_TIMER_END("add_waiting_locked", 0);
-}
-
-static void fail_locked(grpc_exec_ctx *exec_ctx,
-                        grpc_subchannel_call_holder *holder) {
-  size_t i;
-  for (i = 0; i < holder->waiting_ops_count; i++) {
-    grpc_transport_stream_op_finish_with_failure(exec_ctx,
-                                                 &holder->waiting_ops[i]);
-  }
-  holder->waiting_ops_count = 0;
-}
-
-char *grpc_subchannel_call_holder_get_peer(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder) {
-  grpc_subchannel_call *subchannel_call = GET_CALL(holder);
-
-  if (subchannel_call) {
-    return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
-  } else {
-    return NULL;
-  }
-}
diff --git a/src/core/channel/subchannel_call_holder.h b/src/core/channel/subchannel_call_holder.h
deleted file mode 100644
index 9086cdc..0000000
--- a/src/core/channel/subchannel_call_holder.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CHANNEL_SUBCHANNEL_CALL_HOLDER_H
-#define GRPC_CORE_CHANNEL_SUBCHANNEL_CALL_HOLDER_H
-
-#include "src/core/client_config/subchannel.h"
-
-/** Pick a subchannel for grpc_subchannel_call_holder;
-    Return 1 if subchannel is available immediately (in which case on_ready
-    should not be called), or 0 otherwise (in which case on_ready should be
-    called when the subchannel is available) */
-typedef int (*grpc_subchannel_call_holder_pick_subchannel)(
-    grpc_exec_ctx *exec_ctx, void *arg, grpc_metadata_batch *initial_metadata,
-    grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready);
-
-typedef enum {
-  GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
-  GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
-} grpc_subchannel_call_holder_creation_phase;
-
-/** Wrapper for holding a pointer to grpc_subchannel_call, and the
-    associated machinery to create such a pointer.
-    Handles queueing of stream ops until a call object is ready, waiting
-    for initial metadata before trying to create a call object,
-    and handling cancellation gracefully.
-
-    Both the channel and uchannel filter use this as their call_data. */
-typedef struct grpc_subchannel_call_holder {
-  /** either 0 for no call, 1 for cancelled, or a pointer to a
-      grpc_subchannel_call */
-  gpr_atm subchannel_call;
-  /** Helper function to choose the subchannel on which to create
-      the call object. Channel filter delegates to the load
-      balancing policy (once it's ready); uchannel returns
-      immediately */
-  grpc_subchannel_call_holder_pick_subchannel pick_subchannel;
-  void *pick_subchannel_arg;
-
-  gpr_mu mu;
-
-  grpc_subchannel_call_holder_creation_phase creation_phase;
-  grpc_connected_subchannel *connected_subchannel;
-  grpc_pollset *pollset;
-
-  grpc_transport_stream_op *waiting_ops;
-  size_t waiting_ops_count;
-  size_t waiting_ops_capacity;
-
-  grpc_closure next_step;
-
-  grpc_call_stack *owning_call;
-} grpc_subchannel_call_holder;
-
-void grpc_subchannel_call_holder_init(
-    grpc_subchannel_call_holder *holder,
-    grpc_subchannel_call_holder_pick_subchannel pick_subchannel,
-    void *pick_subchannel_arg, grpc_call_stack *owning_call);
-void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
-                                         grpc_subchannel_call_holder *holder);
-
-void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
-                                            grpc_subchannel_call_holder *holder,
-                                            grpc_transport_stream_op *op);
-char *grpc_subchannel_call_holder_get_peer(grpc_exec_ctx *exec_ctx,
-                                           grpc_subchannel_call_holder *holder);
-
-#endif /* GRPC_CORE_CHANNEL_SUBCHANNEL_CALL_HOLDER_H */
diff --git a/src/core/client_config/README.md b/src/core/client_config/README.md
deleted file mode 100644
index fff7a5a..0000000
--- a/src/core/client_config/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-Client Configuration Support for GRPC
-=====================================
-
-This library provides high level configuration machinery to construct client
-channels and load balance between them.
-
-Each grpc_channel is created with a grpc_resolver. It is the resolver's duty
-to resolve a name into configuration data for the channel. Such configuration
-data might include:
-
-- a list of (ip, port) addresses to connect to
-- a load balancing policy to decide which server to send a request to
-- a set of filters to mutate outgoing requests (say, by adding metadata)
-
-The resolver provides this data as a stream of grpc_client_config objects to
-the channel. We represent configuration as a stream so that it can be changed
-by the resolver during execution, by reacting to external events (such as a
-new configuration file being pushed to some store).
-
-
-Load Balancing
---------------
-
-Load balancing configuration is provided by a grpc_lb_policy object, stored as
-part of grpc_client_config.
-
-The primary job of the load balancing policies is to pick a target server given only the
-initial metadata for a request. It does this by providing a grpc_subchannel
-object to the owning channel.
-
-
-Sub-Channels
-------------
-
-A sub-channel provides a connection to a server for a client channel. It has a
-connectivity state like a regular channel, and so can be connected or
-disconnected. This connectivity state can be used to inform load balancing
-decisions (for example, by avoiding disconnected backends).
-
-Configured sub-channels are fully setup to participate in the grpc data plane.
-Their behavior is specified by a set of grpc channel filters defined at their
-construction. To customize this behavior, resolvers build
-grpc_subchannel_factory objects, which use the decorator pattern to customize
-construction arguments for concrete grpc_subchannel instances.
-
-
-Naming for GRPC
-===============
-
-Names in GRPC are represented by a URI (as defined in
-[RFC 3986](https://tools.ietf.org/html/rfc3986)).
-
-The following schemes are currently supported:
-
-dns:///host:port - dns schemes are currently supported so long as authority is
-                   empty (authority based dns resolution is expected in a future
-                   release)
-
-unix:path        - the unix scheme is used to create and connect to unix domain
-                   sockets - the authority must be empty, and the path
-                   represents the absolute or relative path to the desired
-                   socket
-
-ipv4:host:port   - a pre-resolved ipv4 dotted decimal address/port combination
-
-ipv6:[host]:port - a pre-resolved ipv6 address/port combination
diff --git a/src/core/client_config/client_config.c b/src/core/client_config/client_config.c
deleted file mode 100644
index c500af2..0000000
--- a/src/core/client_config/client_config.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *
- * 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/client_config/client_config.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-struct grpc_client_config {
-  gpr_refcount refs;
-  grpc_lb_policy *lb_policy;
-};
-
-grpc_client_config *grpc_client_config_create() {
-  grpc_client_config *c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
-  gpr_ref_init(&c->refs, 1);
-  return c;
-}
-
-void grpc_client_config_ref(grpc_client_config *c) { gpr_ref(&c->refs); }
-
-void grpc_client_config_unref(grpc_exec_ctx *exec_ctx, grpc_client_config *c) {
-  if (gpr_unref(&c->refs)) {
-    if (c->lb_policy != NULL) {
-      GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
-    }
-    gpr_free(c);
-  }
-}
-
-void grpc_client_config_set_lb_policy(grpc_client_config *c,
-                                      grpc_lb_policy *lb_policy) {
-  GPR_ASSERT(c->lb_policy == NULL);
-  if (lb_policy) {
-    GRPC_LB_POLICY_REF(lb_policy, "client_config");
-  }
-  c->lb_policy = lb_policy;
-}
-
-grpc_lb_policy *grpc_client_config_get_lb_policy(grpc_client_config *c) {
-  return c->lb_policy;
-}
diff --git a/src/core/client_config/client_config.h b/src/core/client_config/client_config.h
deleted file mode 100644
index 9b37fdc..0000000
--- a/src/core/client_config/client_config.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_CLIENT_CONFIG_H
-#define GRPC_CORE_CLIENT_CONFIG_CLIENT_CONFIG_H
-
-#include "src/core/client_config/lb_policy.h"
-
-/** Total configuration for a client. Provided, and updated, by
-    grpc_resolver */
-typedef struct grpc_client_config grpc_client_config;
-
-grpc_client_config *grpc_client_config_create();
-void grpc_client_config_ref(grpc_client_config *client_config);
-void grpc_client_config_unref(grpc_exec_ctx *exec_ctx,
-                              grpc_client_config *client_config);
-
-void grpc_client_config_set_lb_policy(grpc_client_config *client_config,
-                                      grpc_lb_policy *lb_policy);
-grpc_lb_policy *grpc_client_config_get_lb_policy(
-    grpc_client_config *client_config);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_CLIENT_CONFIG_H */
diff --git a/src/core/client_config/connector.c b/src/core/client_config/connector.c
deleted file mode 100644
index aa34aa7..0000000
--- a/src/core/client_config/connector.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * 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/client_config/connector.h"
-
-grpc_connector* grpc_connector_ref(grpc_connector* connector) {
-  connector->vtable->ref(connector);
-  return connector;
-}
-
-void grpc_connector_unref(grpc_exec_ctx* exec_ctx, grpc_connector* connector) {
-  connector->vtable->unref(exec_ctx, connector);
-}
-
-void grpc_connector_connect(grpc_exec_ctx* exec_ctx, grpc_connector* connector,
-                            const grpc_connect_in_args* in_args,
-                            grpc_connect_out_args* out_args,
-                            grpc_closure* notify) {
-  connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify);
-}
-
-void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx,
-                             grpc_connector* connector) {
-  connector->vtable->shutdown(exec_ctx, connector);
-}
diff --git a/src/core/client_config/connector.h b/src/core/client_config/connector.h
deleted file mode 100644
index 93248fc..0000000
--- a/src/core/client_config/connector.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_CONNECTOR_H
-#define GRPC_CORE_CLIENT_CONFIG_CONNECTOR_H
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/iomgr/sockaddr.h"
-#include "src/core/transport/transport.h"
-
-typedef struct grpc_connector grpc_connector;
-typedef struct grpc_connector_vtable grpc_connector_vtable;
-
-struct grpc_connector {
-  const grpc_connector_vtable *vtable;
-};
-
-typedef struct {
-  /** set of pollsets interested in this connection */
-  grpc_pollset_set *interested_parties;
-  /** address to connect to */
-  const struct sockaddr *addr;
-  size_t addr_len;
-  /** initial connect string to send */
-  gpr_slice initial_connect_string;
-  /** deadline for connection */
-  gpr_timespec deadline;
-  /** channel arguments (to be passed to transport) */
-  const grpc_channel_args *channel_args;
-} grpc_connect_in_args;
-
-typedef struct {
-  /** the connected transport */
-  grpc_transport *transport;
-
-  /** channel arguments (to be passed to the filters) */
-  const grpc_channel_args *channel_args;
-} grpc_connect_out_args;
-
-struct grpc_connector_vtable {
-  void (*ref)(grpc_connector *connector);
-  void (*unref)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
-  /** Implementation of grpc_connector_shutdown */
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
-  /** Implementation of grpc_connector_connect */
-  void (*connect)(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
-                  const grpc_connect_in_args *in_args,
-                  grpc_connect_out_args *out_args, grpc_closure *notify);
-};
-
-grpc_connector *grpc_connector_ref(grpc_connector *connector);
-void grpc_connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
-/** Connect using the connector: max one outstanding call at a time */
-void grpc_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
-                            const grpc_connect_in_args *in_args,
-                            grpc_connect_out_args *out_args,
-                            grpc_closure *notify);
-/** Cancel any pending connection */
-void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx,
-                             grpc_connector *connector);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_CONNECTOR_H */
diff --git a/src/core/client_config/default_initial_connect_string.c b/src/core/client_config/default_initial_connect_string.c
deleted file mode 100644
index 6a4e23e..0000000
--- a/src/core/client_config/default_initial_connect_string.c
+++ /dev/null
@@ -1,39 +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/slice.h>
-#include "src/core/iomgr/sockaddr.h"
-
-void grpc_set_default_initial_connect_string(struct sockaddr **addr,
-                                             size_t *addr_len,
-                                             gpr_slice *initial_str) {}
diff --git a/src/core/client_config/initial_connect_string.c b/src/core/client_config/initial_connect_string.c
deleted file mode 100644
index 19afa16..0000000
--- a/src/core/client_config/initial_connect_string.c
+++ /dev/null
@@ -1,53 +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/client_config/initial_connect_string.h"
-
-#include <stddef.h>
-
-extern void grpc_set_default_initial_connect_string(struct sockaddr **addr,
-                                                    size_t *addr_len,
-                                                    gpr_slice *initial_str);
-
-static grpc_set_initial_connect_string_func g_set_initial_connect_string_func =
-    grpc_set_default_initial_connect_string;
-
-void grpc_test_set_initial_connect_string_function(
-    grpc_set_initial_connect_string_func func) {
-  g_set_initial_connect_string_func = func;
-}
-
-void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
-                                     gpr_slice *initial_str) {
-  g_set_initial_connect_string_func(addr, addr_len, initial_str);
-}
diff --git a/src/core/client_config/initial_connect_string.h b/src/core/client_config/initial_connect_string.h
deleted file mode 100644
index e6d2d8f..0000000
--- a/src/core/client_config/initial_connect_string.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H
-#define GRPC_CORE_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H
-
-#include <grpc/support/slice.h>
-#include "src/core/iomgr/sockaddr.h"
-
-typedef void (*grpc_set_initial_connect_string_func)(struct sockaddr **addr,
-                                                     size_t *addr_len,
-                                                     gpr_slice *initial_str);
-void grpc_test_set_initial_connect_string_function(
-    grpc_set_initial_connect_string_func func);
-
-/** Set a string to be sent once connected. Optionally reset addr. */
-void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
-                                     gpr_slice *connect_string);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H */
diff --git a/src/core/client_config/lb_policies/load_balancer_api.c b/src/core/client_config/lb_policies/load_balancer_api.c
deleted file mode 100644
index a6b5785..0000000
--- a/src/core/client_config/lb_policies/load_balancer_api.c
+++ /dev/null
@@ -1,163 +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 "src/core/client_config/lb_policies/load_balancer_api.h"
-#include "third_party/nanopb/pb_decode.h"
-#include "third_party/nanopb/pb_encode.h"
-
-#include <grpc/support/alloc.h>
-
-typedef struct decode_serverlist_arg {
-  int first_pass;
-  int i;
-  size_t num_servers;
-  grpc_grpclb_server **servers;
-} decode_serverlist_arg;
-
-/* invoked once for every Server in ServerList */
-static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
-                              void **arg) {
-  decode_serverlist_arg *dec_arg = *arg;
-  if (dec_arg->first_pass != 0) { /* first pass */
-    grpc_grpclb_server server;
-    if (!pb_decode(stream, grpc_lb_v0_Server_fields, &server)) {
-      return false;
-    }
-    dec_arg->num_servers++;
-  } else { /* second pass */
-    grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
-    GPR_ASSERT(dec_arg->num_servers > 0);
-    if (dec_arg->i == 0) { /* first iteration of second pass */
-      dec_arg->servers =
-          gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers);
-    }
-    if (!pb_decode(stream, grpc_lb_v0_Server_fields, server)) {
-      return false;
-    }
-    dec_arg->servers[dec_arg->i++] = server;
-  }
-
-  return true;
-}
-
-grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name) {
-  grpc_grpclb_request *req = gpr_malloc(sizeof(grpc_grpclb_request));
-
-  req->has_client_stats = 0; /* TODO(dgq): add support for stats once defined */
-  req->has_initial_request = 1;
-  req->initial_request.has_name = 1;
-  strncpy(req->initial_request.name, lb_service_name,
-          GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH);
-  return req;
-}
-
-gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) {
-  size_t encoded_length;
-  pb_ostream_t sizestream;
-  pb_ostream_t outputstream;
-  gpr_slice slice;
-  memset(&sizestream, 0, sizeof(pb_ostream_t));
-  pb_encode(&sizestream, grpc_lb_v0_LoadBalanceRequest_fields, request);
-  encoded_length = sizestream.bytes_written;
-
-  slice = gpr_slice_malloc(encoded_length);
-  outputstream =
-      pb_ostream_from_buffer(GPR_SLICE_START_PTR(slice), encoded_length);
-  GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v0_LoadBalanceRequest_fields,
-                       request) != 0);
-  return slice;
-}
-
-void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
-  gpr_free(request);
-}
-
-grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) {
-  bool status;
-  pb_istream_t stream =
-      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
-                             GPR_SLICE_LENGTH(encoded_response));
-  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
-  memset(res, 0, sizeof(*res));
-  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
-  GPR_ASSERT(status == true);
-  return res;
-}
-
-grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
-    gpr_slice encoded_response) {
-  grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
-  bool status;
-  decode_serverlist_arg arg;
-  pb_istream_t stream =
-      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
-                             GPR_SLICE_LENGTH(encoded_response));
-  pb_istream_t stream_at_start = stream;
-  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
-  memset(res, 0, sizeof(*res));
-  memset(&arg, 0, sizeof(decode_serverlist_arg));
-
-  res->server_list.servers.funcs.decode = decode_serverlist;
-  res->server_list.servers.arg = &arg;
-  arg.first_pass = 1;
-  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
-  GPR_ASSERT(status == true);
-  GPR_ASSERT(arg.num_servers > 0);
-
-  arg.first_pass = 0;
-  status =
-      pb_decode(&stream_at_start, grpc_lb_v0_LoadBalanceResponse_fields, res);
-  GPR_ASSERT(status == true);
-  GPR_ASSERT(arg.servers != NULL);
-
-  sl->num_servers = arg.num_servers;
-  sl->servers = arg.servers;
-  if (res->server_list.has_expiration_interval) {
-    sl->expiration_interval = res->server_list.expiration_interval;
-  }
-  grpc_grpclb_response_destroy(res);
-  return sl;
-}
-
-void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) {
-  size_t i;
-  for (i = 0; i < serverlist->num_servers; i++) {
-    gpr_free(serverlist->servers[i]);
-  }
-  gpr_free(serverlist->servers);
-  gpr_free(serverlist);
-}
-
-void grpc_grpclb_response_destroy(grpc_grpclb_response *response) {
-  gpr_free(response);
-}
diff --git a/src/core/client_config/lb_policies/load_balancer_api.h b/src/core/client_config/lb_policies/load_balancer_api.h
deleted file mode 100644
index b7a4c9c..0000000
--- a/src/core/client_config/lb_policies/load_balancer_api.h
+++ /dev/null
@@ -1,85 +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_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H
-#define GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H
-
-#include <grpc/support/slice_buffer.h>
-
-#include "src/core/client_config/lb_policy_factory.h"
-#include "src/core/proto/grpc/lb/v0/load_balancer.pb.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128
-
-typedef grpc_lb_v0_LoadBalanceRequest grpc_grpclb_request;
-typedef grpc_lb_v0_LoadBalanceResponse grpc_grpclb_response;
-typedef grpc_lb_v0_Server grpc_grpclb_server;
-typedef grpc_lb_v0_Duration grpc_grpclb_duration;
-typedef struct grpc_grpclb_serverlist {
-  grpc_grpclb_server **servers;
-  size_t num_servers;
-  grpc_grpclb_duration expiration_interval;
-} grpc_grpclb_serverlist;
-
-/** Create a request for a gRPC LB service under \a lb_service_name */
-grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name);
-
-/** Protocol Buffers v3-encode \a request */
-gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request);
-
-/** Destroy \a request */
-void grpc_grpclb_request_destroy(grpc_grpclb_request *request);
-
-/** Parse (ie, decode) the bytes in \a encoded_response as a \a
- * grpc_grpclb_response */
-grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response);
-
-/** Destroy \a serverlist */
-void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist);
-
-/** Parse the list of servers from an encoded \a grpc_grpclb_response */
-grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
-    gpr_slice encoded_response);
-
-/** Destroy \a response */
-void grpc_grpclb_response_destroy(grpc_grpclb_response *response);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H */
diff --git a/src/core/client_config/lb_policies/pick_first.c b/src/core/client_config/lb_policies/pick_first.c
deleted file mode 100644
index 8ed1223..0000000
--- a/src/core/client_config/lb_policies/pick_first.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- *
- * 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/client_config/lb_policies/pick_first.h"
-#include "src/core/client_config/lb_policy_factory.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include "src/core/transport/connectivity_state.h"
-
-typedef struct pending_pick {
-  struct pending_pick *next;
-  grpc_pollset *pollset;
-  grpc_connected_subchannel **target;
-  grpc_closure *on_complete;
-} pending_pick;
-
-typedef struct {
-  /** base policy: must be first */
-  grpc_lb_policy base;
-  /** all our subchannels */
-  grpc_subchannel **subchannels;
-  size_t num_subchannels;
-
-  grpc_closure connectivity_changed;
-
-  /** the selected channel (a grpc_connected_subchannel) */
-  gpr_atm selected;
-
-  /** mutex protecting remaining members */
-  gpr_mu mu;
-  /** have we started picking? */
-  int started_picking;
-  /** are we shut down? */
-  int shutdown;
-  /** which subchannel are we watching? */
-  size_t checking_subchannel;
-  /** what is the connectivity of that channel? */
-  grpc_connectivity_state checking_connectivity;
-  /** list of picks that are waiting on connectivity */
-  pending_pick *pending_picks;
-
-  /** our connectivity state tracker */
-  grpc_connectivity_state_tracker state_tracker;
-} pick_first_lb_policy;
-
-#define GET_SELECTED(p) \
-  ((grpc_connected_subchannel *)gpr_atm_acq_load(&(p)->selected))
-
-void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  grpc_connected_subchannel *selected = GET_SELECTED(p);
-  size_t i;
-  GPR_ASSERT(p->pending_picks == NULL);
-  for (i = 0; i < p->num_subchannels; i++) {
-    GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
-  }
-  if (selected != NULL) {
-    GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, selected, "picked_first");
-  }
-  grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
-  gpr_free(p->subchannels);
-  gpr_mu_destroy(&p->mu);
-  gpr_free(p);
-}
-
-void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  pending_pick *pp;
-  grpc_connected_subchannel *selected;
-  gpr_mu_lock(&p->mu);
-  selected = GET_SELECTED(p);
-  p->shutdown = 1;
-  pp = p->pending_picks;
-  p->pending_picks = NULL;
-  grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                              GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
-  /* cancel subscription */
-  if (selected != NULL) {
-    grpc_connected_subchannel_notify_on_state_change(
-        exec_ctx, selected, NULL, NULL, &p->connectivity_changed);
-  } else {
-    grpc_subchannel_notify_on_state_change(
-        exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
-        &p->connectivity_changed);
-  }
-  gpr_mu_unlock(&p->mu);
-  while (pp != NULL) {
-    pending_pick *next = pp->next;
-    *pp->target = NULL;
-    grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
-                                 pp->pollset);
-    grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
-    gpr_free(pp);
-    pp = next;
-  }
-}
-
-static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                           grpc_connected_subchannel **target) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  pending_pick *pp;
-  gpr_mu_lock(&p->mu);
-  pp = p->pending_picks;
-  p->pending_picks = NULL;
-  while (pp != NULL) {
-    pending_pick *next = pp->next;
-    if (pp->target == target) {
-      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
-                                   pp->pollset);
-      *target = NULL;
-      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
-      gpr_free(pp);
-    } else {
-      pp->next = p->pending_picks;
-      p->pending_picks = pp;
-    }
-    pp = next;
-  }
-  gpr_mu_unlock(&p->mu);
-}
-
-static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
-  p->started_picking = 1;
-  p->checking_subchannel = 0;
-  p->checking_connectivity = GRPC_CHANNEL_IDLE;
-  GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
-  grpc_subchannel_notify_on_state_change(
-      exec_ctx, p->subchannels[p->checking_subchannel],
-      p->base.interested_parties, &p->checking_connectivity,
-      &p->connectivity_changed);
-}
-
-void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
-  if (!p->started_picking) {
-    start_picking(exec_ctx, p);
-  }
-  gpr_mu_unlock(&p->mu);
-}
-
-int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
-            grpc_metadata_batch *initial_metadata,
-            grpc_connected_subchannel **target, grpc_closure *on_complete) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  pending_pick *pp;
-
-  /* Check atomically for a selected channel */
-  grpc_connected_subchannel *selected = GET_SELECTED(p);
-  if (selected != NULL) {
-    *target = selected;
-    return 1;
-  }
-
-  /* No subchannel selected yet, so acquire lock and then attempt again */
-  gpr_mu_lock(&p->mu);
-  selected = GET_SELECTED(p);
-  if (selected) {
-    gpr_mu_unlock(&p->mu);
-    *target = selected;
-    return 1;
-  } else {
-    if (!p->started_picking) {
-      start_picking(exec_ctx, p);
-    }
-    grpc_pollset_set_add_pollset(exec_ctx, p->base.interested_parties, pollset);
-    pp = gpr_malloc(sizeof(*pp));
-    pp->next = p->pending_picks;
-    pp->pollset = pollset;
-    pp->target = target;
-    pp->on_complete = on_complete;
-    p->pending_picks = pp;
-    gpr_mu_unlock(&p->mu);
-    return 0;
-  }
-}
-
-static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
-                                bool iomgr_success) {
-  pick_first_lb_policy *p = arg;
-  size_t i;
-  size_t num_subchannels = p->num_subchannels;
-  grpc_subchannel **subchannels;
-
-  gpr_mu_lock(&p->mu);
-  subchannels = p->subchannels;
-  p->num_subchannels = 0;
-  p->subchannels = NULL;
-  gpr_mu_unlock(&p->mu);
-  GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
-
-  for (i = 0; i < num_subchannels; i++) {
-    GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
-  }
-
-  gpr_free(subchannels);
-}
-
-static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                    bool iomgr_success) {
-  pick_first_lb_policy *p = arg;
-  grpc_subchannel *selected_subchannel;
-  pending_pick *pp;
-  grpc_connected_subchannel *selected;
-
-  gpr_mu_lock(&p->mu);
-
-  selected = GET_SELECTED(p);
-
-  if (p->shutdown) {
-    gpr_mu_unlock(&p->mu);
-    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
-    return;
-  } else if (selected != NULL) {
-    if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
-      /* if the selected channel goes bad, we're done */
-      p->checking_connectivity = GRPC_CHANNEL_FATAL_FAILURE;
-    }
-    grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                p->checking_connectivity, "selected_changed");
-    if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
-      grpc_connected_subchannel_notify_on_state_change(
-          exec_ctx, selected, p->base.interested_parties,
-          &p->checking_connectivity, &p->connectivity_changed);
-    } else {
-      GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
-    }
-  } else {
-  loop:
-    switch (p->checking_connectivity) {
-      case GRPC_CHANNEL_READY:
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_READY, "connecting_ready");
-        selected_subchannel = p->subchannels[p->checking_subchannel];
-        selected =
-            grpc_subchannel_get_connected_subchannel(selected_subchannel);
-        GPR_ASSERT(selected != NULL);
-        GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked_first");
-        /* drop the pick list: we are connected now */
-        GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
-        gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
-        grpc_exec_ctx_enqueue(
-            exec_ctx, grpc_closure_create(destroy_subchannels, p), true, NULL);
-        /* update any calls that were waiting for a pick */
-        while ((pp = p->pending_picks)) {
-          p->pending_picks = pp->next;
-          *pp->target = selected;
-          grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
-                                       pp->pollset);
-          grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
-          gpr_free(pp);
-        }
-        grpc_connected_subchannel_notify_on_state_change(
-            exec_ctx, selected, p->base.interested_parties,
-            &p->checking_connectivity, &p->connectivity_changed);
-        break;
-      case GRPC_CHANNEL_TRANSIENT_FAILURE:
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                    "connecting_transient_failure");
-        p->checking_subchannel =
-            (p->checking_subchannel + 1) % p->num_subchannels;
-        p->checking_connectivity = grpc_subchannel_check_connectivity(
-            p->subchannels[p->checking_subchannel]);
-        if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
-          grpc_subchannel_notify_on_state_change(
-              exec_ctx, p->subchannels[p->checking_subchannel],
-              p->base.interested_parties, &p->checking_connectivity,
-              &p->connectivity_changed);
-        } else {
-          goto loop;
-        }
-        break;
-      case GRPC_CHANNEL_CONNECTING:
-      case GRPC_CHANNEL_IDLE:
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_CONNECTING,
-                                    "connecting_changed");
-        grpc_subchannel_notify_on_state_change(
-            exec_ctx, p->subchannels[p->checking_subchannel],
-            p->base.interested_parties, &p->checking_connectivity,
-            &p->connectivity_changed);
-        break;
-      case GRPC_CHANNEL_FATAL_FAILURE:
-        p->num_subchannels--;
-        GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
-                 p->subchannels[p->num_subchannels]);
-        GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
-                              "pick_first");
-        if (p->num_subchannels == 0) {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_FATAL_FAILURE,
-                                      "no_more_channels");
-          while ((pp = p->pending_picks)) {
-            p->pending_picks = pp->next;
-            *pp->target = NULL;
-            grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
-            gpr_free(pp);
-          }
-          GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
-                                    "pick_first_connectivity");
-        } else {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                      "subchannel_failed");
-          p->checking_subchannel %= p->num_subchannels;
-          p->checking_connectivity = grpc_subchannel_check_connectivity(
-              p->subchannels[p->checking_subchannel]);
-          goto loop;
-        }
-    }
-  }
-
-  gpr_mu_unlock(&p->mu);
-}
-
-static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
-                                                     grpc_lb_policy *pol) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  grpc_connectivity_state st;
-  gpr_mu_lock(&p->mu);
-  st = grpc_connectivity_state_check(&p->state_tracker);
-  gpr_mu_unlock(&p->mu);
-  return st;
-}
-
-void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                               grpc_connectivity_state *current,
-                               grpc_closure *notify) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
-  grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
-                                                 current, notify);
-  gpr_mu_unlock(&p->mu);
-}
-
-void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                 grpc_closure *closure) {
-  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  grpc_connected_subchannel *selected = GET_SELECTED(p);
-  if (selected) {
-    grpc_connected_subchannel_ping(exec_ctx, selected, closure);
-  } else {
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
-  }
-}
-
-static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
-    pf_destroy, pf_shutdown, pf_pick, pf_cancel_pick, pf_ping_one, pf_exit_idle,
-    pf_check_connectivity, pf_notify_on_state_change};
-
-static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
-
-static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
-
-static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory,
-                                         grpc_lb_policy_args *args) {
-  if (args->num_subchannels == 0) return NULL;
-  pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
-  memset(p, 0, sizeof(*p));
-  grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
-  p->subchannels =
-      gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
-  p->num_subchannels = args->num_subchannels;
-  grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
-                               "pick_first");
-  memcpy(p->subchannels, args->subchannels,
-         sizeof(grpc_subchannel *) * args->num_subchannels);
-  grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);
-  gpr_mu_init(&p->mu);
-  return &p->base;
-}
-
-static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = {
-    pick_first_factory_ref, pick_first_factory_unref, create_pick_first,
-    "pick_first"};
-
-static grpc_lb_policy_factory pick_first_lb_policy_factory = {
-    &pick_first_factory_vtable};
-
-grpc_lb_policy_factory *grpc_pick_first_lb_factory_create() {
-  return &pick_first_lb_policy_factory;
-}
diff --git a/src/core/client_config/lb_policies/pick_first.h b/src/core/client_config/lb_policies/pick_first.h
deleted file mode 100644
index 3a3f195..0000000
--- a/src/core/client_config/lb_policies/pick_first.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_PICK_FIRST_H
-#define GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_PICK_FIRST_H
-
-#include "src/core/client_config/lb_policy_factory.h"
-
-/** Returns a load balancing factory for the pick first policy, which picks up
- * the first subchannel from \a subchannels to succesfully connect */
-grpc_lb_policy_factory *grpc_pick_first_lb_factory_create();
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_PICK_FIRST_H */
diff --git a/src/core/client_config/lb_policies/round_robin.c b/src/core/client_config/lb_policies/round_robin.c
deleted file mode 100644
index 98d9acc..0000000
--- a/src/core/client_config/lb_policies/round_robin.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- *
- * 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/client_config/lb_policies/round_robin.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include "src/core/transport/connectivity_state.h"
-
-typedef struct round_robin_lb_policy round_robin_lb_policy;
-
-int grpc_lb_round_robin_trace = 0;
-
-/** List of entities waiting for a pick.
- *
- * Once a pick is available, \a target is updated and \a on_complete called. */
-typedef struct pending_pick {
-  struct pending_pick *next;
-  grpc_pollset *pollset;
-  grpc_connected_subchannel **target;
-  grpc_closure *on_complete;
-} pending_pick;
-
-/** List of subchannels in a connectivity READY state */
-typedef struct ready_list {
-  grpc_subchannel *subchannel;
-  struct ready_list *next;
-  struct ready_list *prev;
-} ready_list;
-
-typedef struct {
-  /** index within policy->subchannels */
-  size_t index;
-  /** backpointer to owning policy */
-  round_robin_lb_policy *policy;
-  /** subchannel itself */
-  grpc_subchannel *subchannel;
-  /** notification that connectivity has changed on subchannel */
-  grpc_closure connectivity_changed_closure;
-  /** this subchannels current position in subchannel->ready_list */
-  ready_list *ready_list_node;
-  /** last observed connectivity */
-  grpc_connectivity_state connectivity_state;
-} subchannel_data;
-
-struct round_robin_lb_policy {
-  /** base policy: must be first */
-  grpc_lb_policy base;
-
-  /** all our subchannels */
-  size_t num_subchannels;
-  subchannel_data **subchannels;
-
-  /** mutex protecting remaining members */
-  gpr_mu mu;
-  /** have we started picking? */
-  int started_picking;
-  /** are we shutting down? */
-  int shutdown;
-  /** List of picks that are waiting on connectivity */
-  pending_pick *pending_picks;
-
-  /** our connectivity state tracker */
-  grpc_connectivity_state_tracker state_tracker;
-
-  /** (Dummy) root of the doubly linked list containing READY subchannels */
-  ready_list ready_list;
-  /** Last pick from the ready list. */
-  ready_list *ready_list_last_pick;
-};
-
-/** Returns the next subchannel from the connected list or NULL if the list is
- * empty.
- *
- * Note that this function does *not* advance p->ready_list_last_pick. Use \a
- * advance_last_picked_locked() for that. */
-static ready_list *peek_next_connected_locked(const round_robin_lb_policy *p) {
-  ready_list *selected;
-  selected = p->ready_list_last_pick->next;
-
-  while (selected != NULL) {
-    if (selected == &p->ready_list) {
-      GPR_ASSERT(selected->subchannel == NULL);
-      /* skip dummy root */
-      selected = selected->next;
-    } else {
-      GPR_ASSERT(selected->subchannel != NULL);
-      return selected;
-    }
-  }
-  return NULL;
-}
-
-/** Advance the \a ready_list picking head. */
-static void advance_last_picked_locked(round_robin_lb_policy *p) {
-  if (p->ready_list_last_pick->next != NULL) { /* non-empty list */
-    p->ready_list_last_pick = p->ready_list_last_pick->next;
-    if (p->ready_list_last_pick == &p->ready_list) {
-      /* skip dummy root */
-      p->ready_list_last_pick = p->ready_list_last_pick->next;
-    }
-  } else { /* should be an empty list */
-    GPR_ASSERT(p->ready_list_last_pick == &p->ready_list);
-  }
-
-  if (grpc_lb_round_robin_trace) {
-    gpr_log(GPR_DEBUG, "[READYLIST] ADVANCED LAST PICK. NOW AT NODE %p (SC %p)",
-            p->ready_list_last_pick, p->ready_list_last_pick->subchannel);
-  }
-}
-
-/** Prepends (relative to the root at p->ready_list) the connected subchannel \a
- * csc to the list of ready subchannels. */
-static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
-                                           grpc_subchannel *sc) {
-  ready_list *new_elem = gpr_malloc(sizeof(ready_list));
-  new_elem->subchannel = sc;
-  if (p->ready_list.prev == NULL) {
-    /* first element */
-    new_elem->next = &p->ready_list;
-    new_elem->prev = &p->ready_list;
-    p->ready_list.next = new_elem;
-    p->ready_list.prev = new_elem;
-  } else {
-    new_elem->next = &p->ready_list;
-    new_elem->prev = p->ready_list.prev;
-    p->ready_list.prev->next = new_elem;
-    p->ready_list.prev = new_elem;
-  }
-  if (grpc_lb_round_robin_trace) {
-    gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (SC %p)", new_elem, sc);
-  }
-  return new_elem;
-}
-
-/** Removes \a node from the list of connected subchannels */
-static void remove_disconnected_sc_locked(round_robin_lb_policy *p,
-                                          ready_list *node) {
-  if (node == NULL) {
-    return;
-  }
-  if (node == p->ready_list_last_pick) {
-    /* If removing the lastly picked node, reset the last pick pointer to the
-     * dummy root of the list */
-    p->ready_list_last_pick = &p->ready_list;
-  }
-
-  /* removing last item */
-  if (node->next == &p->ready_list && node->prev == &p->ready_list) {
-    GPR_ASSERT(p->ready_list.next == node);
-    GPR_ASSERT(p->ready_list.prev == node);
-    p->ready_list.next = NULL;
-    p->ready_list.prev = NULL;
-  } else {
-    node->prev->next = node->next;
-    node->next->prev = node->prev;
-  }
-
-  if (grpc_lb_round_robin_trace) {
-    gpr_log(GPR_DEBUG, "[READYLIST] REMOVED NODE %p (SC %p)", node,
-            node->subchannel);
-  }
-
-  node->next = NULL;
-  node->prev = NULL;
-  node->subchannel = NULL;
-
-  gpr_free(node);
-}
-
-void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  size_t i;
-  ready_list *elem;
-  for (i = 0; i < p->num_subchannels; i++) {
-    subchannel_data *sd = p->subchannels[i];
-    GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "round_robin");
-    gpr_free(sd);
-  }
-
-  grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
-  gpr_free(p->subchannels);
-  gpr_mu_destroy(&p->mu);
-
-  elem = p->ready_list.next;
-  while (elem != NULL && elem != &p->ready_list) {
-    ready_list *tmp;
-    tmp = elem->next;
-    elem->next = NULL;
-    elem->prev = NULL;
-    elem->subchannel = NULL;
-    gpr_free(elem);
-    elem = tmp;
-  }
-  gpr_free(p);
-}
-
-void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  pending_pick *pp;
-  size_t i;
-
-  gpr_mu_lock(&p->mu);
-
-  p->shutdown = 1;
-  while ((pp = p->pending_picks)) {
-    p->pending_picks = pp->next;
-    *pp->target = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
-    gpr_free(pp);
-  }
-  grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                              GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
-  for (i = 0; i < p->num_subchannels; i++) {
-    subchannel_data *sd = p->subchannels[i];
-    grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL,
-                                           &sd->connectivity_changed_closure);
-  }
-  gpr_mu_unlock(&p->mu);
-}
-
-static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                           grpc_connected_subchannel **target) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  pending_pick *pp;
-  gpr_mu_lock(&p->mu);
-  pp = p->pending_picks;
-  p->pending_picks = NULL;
-  while (pp != NULL) {
-    pending_pick *next = pp->next;
-    if (pp->target == target) {
-      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
-                                   pp->pollset);
-      *target = NULL;
-      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
-      gpr_free(pp);
-    } else {
-      pp->next = p->pending_picks;
-      p->pending_picks = pp;
-    }
-    pp = next;
-  }
-  gpr_mu_unlock(&p->mu);
-}
-
-static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
-  size_t i;
-  p->started_picking = 1;
-
-  gpr_log(GPR_DEBUG, "LB_POLICY: p=%p num_subchannels=%d", p,
-          p->num_subchannels);
-
-  for (i = 0; i < p->num_subchannels; i++) {
-    subchannel_data *sd = p->subchannels[i];
-    sd->connectivity_state = GRPC_CHANNEL_IDLE;
-    grpc_subchannel_notify_on_state_change(
-        exec_ctx, sd->subchannel, p->base.interested_parties,
-        &sd->connectivity_state, &sd->connectivity_changed_closure);
-    GRPC_LB_POLICY_WEAK_REF(&p->base, "round_robin_connectivity");
-  }
-}
-
-void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
-  if (!p->started_picking) {
-    start_picking(exec_ctx, p);
-  }
-  gpr_mu_unlock(&p->mu);
-}
-
-int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
-            grpc_metadata_batch *initial_metadata,
-            grpc_connected_subchannel **target, grpc_closure *on_complete) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  pending_pick *pp;
-  ready_list *selected;
-  gpr_mu_lock(&p->mu);
-  if ((selected = peek_next_connected_locked(p))) {
-    gpr_mu_unlock(&p->mu);
-    *target = grpc_subchannel_get_connected_subchannel(selected->subchannel);
-    if (grpc_lb_round_robin_trace) {
-      gpr_log(GPR_DEBUG,
-              "[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (NODE %p)",
-              selected->subchannel, selected);
-    }
-    /* only advance the last picked pointer if the selection was used */
-    advance_last_picked_locked(p);
-    return 1;
-  } else {
-    if (!p->started_picking) {
-      start_picking(exec_ctx, p);
-    }
-    grpc_pollset_set_add_pollset(exec_ctx, p->base.interested_parties, pollset);
-    pp = gpr_malloc(sizeof(*pp));
-    pp->next = p->pending_picks;
-    pp->pollset = pollset;
-    pp->target = target;
-    pp->on_complete = on_complete;
-    p->pending_picks = pp;
-    gpr_mu_unlock(&p->mu);
-    return 0;
-  }
-}
-
-static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                    bool iomgr_success) {
-  subchannel_data *sd = arg;
-  round_robin_lb_policy *p = sd->policy;
-  pending_pick *pp;
-  ready_list *selected;
-
-  int unref = 0;
-
-  gpr_mu_lock(&p->mu);
-
-  if (p->shutdown) {
-    unref = 1;
-  } else {
-    switch (sd->connectivity_state) {
-      case GRPC_CHANNEL_READY:
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_READY, "connecting_ready");
-        /* add the newly connected subchannel to the list of connected ones.
-         * Note that it goes to the "end of the line". */
-        sd->ready_list_node = add_connected_sc_locked(p, sd->subchannel);
-        /* at this point we know there's at least one suitable subchannel. Go
-         * ahead and pick one and notify the pending suitors in
-         * p->pending_picks. This preemtively replicates rr_pick()'s actions. */
-        selected = peek_next_connected_locked(p);
-        if (p->pending_picks != NULL) {
-          /* if the selected subchannel is going to be used for the pending
-           * picks, update the last picked pointer */
-          advance_last_picked_locked(p);
-        }
-        while ((pp = p->pending_picks)) {
-          p->pending_picks = pp->next;
-          *pp->target =
-              grpc_subchannel_get_connected_subchannel(selected->subchannel);
-          if (grpc_lb_round_robin_trace) {
-            gpr_log(GPR_DEBUG,
-                    "[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)",
-                    selected->subchannel, selected);
-          }
-          grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
-                                       pp->pollset);
-          grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
-          gpr_free(pp);
-        }
-        grpc_subchannel_notify_on_state_change(
-            exec_ctx, sd->subchannel, p->base.interested_parties,
-            &sd->connectivity_state, &sd->connectivity_changed_closure);
-        break;
-      case GRPC_CHANNEL_CONNECTING:
-      case GRPC_CHANNEL_IDLE:
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    sd->connectivity_state,
-                                    "connecting_changed");
-        grpc_subchannel_notify_on_state_change(
-            exec_ctx, sd->subchannel, p->base.interested_parties,
-            &sd->connectivity_state, &sd->connectivity_changed_closure);
-        break;
-      case GRPC_CHANNEL_TRANSIENT_FAILURE:
-        /* renew state notification */
-        grpc_subchannel_notify_on_state_change(
-            exec_ctx, sd->subchannel, p->base.interested_parties,
-            &sd->connectivity_state, &sd->connectivity_changed_closure);
-
-        /* remove from ready list if still present */
-        if (sd->ready_list_node != NULL) {
-          remove_disconnected_sc_locked(p, sd->ready_list_node);
-          sd->ready_list_node = NULL;
-        }
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                    "connecting_transient_failure");
-        break;
-      case GRPC_CHANNEL_FATAL_FAILURE:
-        if (sd->ready_list_node != NULL) {
-          remove_disconnected_sc_locked(p, sd->ready_list_node);
-          sd->ready_list_node = NULL;
-        }
-
-        p->num_subchannels--;
-        GPR_SWAP(subchannel_data *, p->subchannels[sd->index],
-                 p->subchannels[p->num_subchannels]);
-        GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "round_robin");
-        p->subchannels[sd->index]->index = sd->index;
-        gpr_free(sd);
-
-        unref = 1;
-        if (p->num_subchannels == 0) {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_FATAL_FAILURE,
-                                      "no_more_channels");
-          while ((pp = p->pending_picks)) {
-            p->pending_picks = pp->next;
-            *pp->target = NULL;
-            grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
-            gpr_free(pp);
-          }
-        } else {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                      "subchannel_failed");
-        }
-    } /* switch */
-  }   /* !unref */
-
-  gpr_mu_unlock(&p->mu);
-
-  if (unref) {
-    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "round_robin_connectivity");
-  }
-}
-
-static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
-                                                     grpc_lb_policy *pol) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  grpc_connectivity_state st;
-  gpr_mu_lock(&p->mu);
-  st = grpc_connectivity_state_check(&p->state_tracker);
-  gpr_mu_unlock(&p->mu);
-  return st;
-}
-
-static void rr_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                      grpc_lb_policy *pol,
-                                      grpc_connectivity_state *current,
-                                      grpc_closure *notify) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
-  grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
-                                                 current, notify);
-  gpr_mu_unlock(&p->mu);
-}
-
-static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                        grpc_closure *closure) {
-  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  ready_list *selected;
-  grpc_connected_subchannel *target;
-  gpr_mu_lock(&p->mu);
-  if ((selected = peek_next_connected_locked(p))) {
-    gpr_mu_unlock(&p->mu);
-    target = grpc_subchannel_get_connected_subchannel(selected->subchannel);
-    grpc_connected_subchannel_ping(exec_ctx, target, closure);
-  } else {
-    gpr_mu_unlock(&p->mu);
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
-  }
-}
-
-static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
-    rr_destroy, rr_shutdown, rr_pick, rr_cancel_pick, rr_ping_one, rr_exit_idle,
-    rr_check_connectivity, rr_notify_on_state_change};
-
-static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}
-
-static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {}
-
-static grpc_lb_policy *create_round_robin(grpc_lb_policy_factory *factory,
-                                          grpc_lb_policy_args *args) {
-  size_t i;
-  round_robin_lb_policy *p = gpr_malloc(sizeof(*p));
-  GPR_ASSERT(args->num_subchannels > 0);
-  memset(p, 0, sizeof(*p));
-  grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable);
-  p->num_subchannels = args->num_subchannels;
-  p->subchannels = gpr_malloc(sizeof(*p->subchannels) * p->num_subchannels);
-  memset(p->subchannels, 0, sizeof(*p->subchannels) * p->num_subchannels);
-  grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
-                               "round_robin");
-
-  gpr_mu_init(&p->mu);
-  for (i = 0; i < args->num_subchannels; i++) {
-    subchannel_data *sd = gpr_malloc(sizeof(*sd));
-    memset(sd, 0, sizeof(*sd));
-    p->subchannels[i] = sd;
-    sd->policy = p;
-    sd->index = i;
-    sd->subchannel = args->subchannels[i];
-    grpc_closure_init(&sd->connectivity_changed_closure,
-                      rr_connectivity_changed, sd);
-  }
-
-  /* The (dummy node) root of the ready list */
-  p->ready_list.subchannel = NULL;
-  p->ready_list.prev = NULL;
-  p->ready_list.next = NULL;
-  p->ready_list_last_pick = &p->ready_list;
-
-  return &p->base;
-}
-
-static const grpc_lb_policy_factory_vtable round_robin_factory_vtable = {
-    round_robin_factory_ref, round_robin_factory_unref, create_round_robin,
-    "round_robin"};
-
-static grpc_lb_policy_factory round_robin_lb_policy_factory = {
-    &round_robin_factory_vtable};
-
-grpc_lb_policy_factory *grpc_round_robin_lb_factory_create() {
-  return &round_robin_lb_policy_factory;
-}
diff --git a/src/core/client_config/lb_policies/round_robin.h b/src/core/client_config/lb_policies/round_robin.h
deleted file mode 100644
index 7e6f176..0000000
--- a/src/core/client_config/lb_policies/round_robin.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_ROUND_ROBIN_H
-#define GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_ROUND_ROBIN_H
-
-#include "src/core/client_config/lb_policy.h"
-
-extern int grpc_lb_round_robin_trace;
-
-#include "src/core/client_config/lb_policy_factory.h"
-
-/** Returns a load balancing factory for the round robin policy */
-grpc_lb_policy_factory *grpc_round_robin_lb_factory_create();
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_LB_POLICIES_ROUND_ROBIN_H */
diff --git a/src/core/client_config/lb_policy.c b/src/core/client_config/lb_policy.c
deleted file mode 100644
index 0d8b007..0000000
--- a/src/core/client_config/lb_policy.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *
- * 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/client_config/lb_policy.h"
-
-#define WEAK_REF_BITS 16
-
-void grpc_lb_policy_init(grpc_lb_policy *policy,
-                         const grpc_lb_policy_vtable *vtable) {
-  policy->vtable = vtable;
-  gpr_atm_no_barrier_store(&policy->ref_pair, 1 << WEAK_REF_BITS);
-  policy->interested_parties = grpc_pollset_set_create();
-}
-
-#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
-#define REF_FUNC_EXTRA_ARGS , const char *file, int line, const char *reason
-#define REF_MUTATE_EXTRA_ARGS REF_FUNC_EXTRA_ARGS, const char *purpose
-#define REF_FUNC_PASS_ARGS(new_reason) , file, line, new_reason
-#define REF_MUTATE_PASS_ARGS(purpose) , file, line, reason, purpose
-#else
-#define REF_FUNC_EXTRA_ARGS
-#define REF_MUTATE_EXTRA_ARGS
-#define REF_FUNC_PASS_ARGS(new_reason)
-#define REF_MUTATE_PASS_ARGS(x)
-#endif
-
-static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta,
-                          int barrier REF_MUTATE_EXTRA_ARGS) {
-  gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
-                            : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
-#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "LB_POLICY: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
-          old_val + delta, reason);
-#endif
-  return old_val;
-}
-
-void grpc_lb_policy_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
-  ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF"));
-}
-
-void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx,
-                          grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
-  gpr_atm old_val =
-      ref_mutate(policy, (gpr_atm)1 - (gpr_atm)(1 << WEAK_REF_BITS),
-                 1 REF_MUTATE_PASS_ARGS("STRONG_UNREF"));
-  gpr_atm mask = ~(gpr_atm)((1 << WEAK_REF_BITS) - 1);
-  gpr_atm check = 1 << WEAK_REF_BITS;
-  if ((old_val & mask) == check) {
-    policy->vtable->shutdown(exec_ctx, policy);
-  }
-  grpc_lb_policy_weak_unref(exec_ctx,
-                            policy REF_FUNC_PASS_ARGS("strong-unref"));
-}
-
-void grpc_lb_policy_weak_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
-  ref_mutate(policy, 1, 0 REF_MUTATE_PASS_ARGS("WEAK_REF"));
-}
-
-void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
-                               grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
-  gpr_atm old_val =
-      ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
-  if (old_val == 1) {
-    grpc_pollset_set_destroy(policy->interested_parties);
-    policy->vtable->destroy(exec_ctx, policy);
-  }
-}
-
-int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                        grpc_pollset *pollset,
-                        grpc_metadata_batch *initial_metadata,
-                        grpc_connected_subchannel **target,
-                        grpc_closure *on_complete) {
-  return policy->vtable->pick(exec_ctx, policy, pollset, initial_metadata,
-                              target, on_complete);
-}
-
-void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                                grpc_connected_subchannel **target) {
-  policy->vtable->cancel_pick(exec_ctx, policy, target);
-}
-
-void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
-  policy->vtable->exit_idle(exec_ctx, policy);
-}
-
-void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                             grpc_closure *closure) {
-  policy->vtable->ping_one(exec_ctx, policy, closure);
-}
-
-void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                           grpc_lb_policy *policy,
-                                           grpc_connectivity_state *state,
-                                           grpc_closure *closure) {
-  policy->vtable->notify_on_state_change(exec_ctx, policy, state, closure);
-}
-
-grpc_connectivity_state grpc_lb_policy_check_connectivity(
-    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
-  return policy->vtable->check_connectivity(exec_ctx, policy);
-}
diff --git a/src/core/client_config/lb_policy.h b/src/core/client_config/lb_policy.h
deleted file mode 100644
index ffebc2a..0000000
--- a/src/core/client_config/lb_policy.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_LB_POLICY_H
-#define GRPC_CORE_CLIENT_CONFIG_LB_POLICY_H
-
-#include "src/core/client_config/subchannel.h"
-#include "src/core/transport/connectivity_state.h"
-
-/** A load balancing policy: specified by a vtable and a struct (which
-    is expected to be extended to contain some parameters) */
-typedef struct grpc_lb_policy grpc_lb_policy;
-typedef struct grpc_lb_policy_vtable grpc_lb_policy_vtable;
-
-typedef void (*grpc_lb_completion)(void *cb_arg, grpc_subchannel *subchannel,
-                                   grpc_status_code status, const char *errmsg);
-
-struct grpc_lb_policy {
-  const grpc_lb_policy_vtable *vtable;
-  gpr_atm ref_pair;
-  /* owned pointer to interested parties in load balancing decisions */
-  grpc_pollset_set *interested_parties;
-};
-
-struct grpc_lb_policy_vtable {
-  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-
-  /** implement grpc_lb_policy_pick */
-  int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-              grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
-              grpc_connected_subchannel **target, grpc_closure *on_complete);
-  void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                      grpc_connected_subchannel **target);
-
-  void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                   grpc_closure *closure);
-
-  /** try to enter a READY connectivity state */
-  void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-
-  /** check the current connectivity of the lb_policy */
-  grpc_connectivity_state (*check_connectivity)(grpc_exec_ctx *exec_ctx,
-                                                grpc_lb_policy *policy);
-
-  /** call notify when the connectivity state of a channel changes from *state.
-      Updates *state with the new state of the policy */
-  void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx,
-                                 grpc_lb_policy *policy,
-                                 grpc_connectivity_state *state,
-                                 grpc_closure *closure);
-};
-
-/*#define GRPC_LB_POLICY_REFCOUNT_DEBUG*/
-#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
-#define GRPC_LB_POLICY_REF(p, r) \
-  grpc_lb_policy_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_LB_POLICY_UNREF(exec_ctx, p, r) \
-  grpc_lb_policy_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
-#define GRPC_LB_POLICY_WEAK_REF(p, r) \
-  grpc_lb_policy_weak_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, p, r) \
-  grpc_lb_policy_weak_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
-void grpc_lb_policy_ref(grpc_lb_policy *policy, const char *file, int line,
-                        const char *reason);
-void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                          const char *file, int line, const char *reason);
-void grpc_lb_policy_weak_ref(grpc_lb_policy *policy, const char *file, int line,
-                             const char *reason);
-void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                               const char *file, int line, const char *reason);
-#else
-#define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p))
-#define GRPC_LB_POLICY_UNREF(cl, p, r) grpc_lb_policy_unref((cl), (p))
-#define GRPC_LB_POLICY_WEAK_REF(p, r) grpc_lb_policy_weak_ref((p))
-#define GRPC_LB_POLICY_WEAK_UNREF(cl, p, r) grpc_lb_policy_weak_unref((cl), (p))
-void grpc_lb_policy_ref(grpc_lb_policy *policy);
-void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-void grpc_lb_policy_weak_ref(grpc_lb_policy *policy);
-void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-#endif
-
-/** called by concrete implementations to initialize the base struct */
-void grpc_lb_policy_init(grpc_lb_policy *policy,
-                         const grpc_lb_policy_vtable *vtable);
-
-/** Given initial metadata in \a initial_metadata, find an appropriate
-    target for this rpc, and 'return' it by calling \a on_complete after setting
-    \a target.
-    Picking can be asynchronous. Any IO should be done under \a pollset. */
-int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                        grpc_pollset *pollset,
-                        grpc_metadata_batch *initial_metadata,
-                        grpc_connected_subchannel **target,
-                        grpc_closure *on_complete);
-
-void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                             grpc_closure *closure);
-
-void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                                grpc_connected_subchannel **target);
-
-void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-
-void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                           grpc_lb_policy *policy,
-                                           grpc_connectivity_state *state,
-                                           grpc_closure *closure);
-
-grpc_connectivity_state grpc_lb_policy_check_connectivity(
-    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_LB_POLICY_H */
diff --git a/src/core/client_config/lb_policy_factory.c b/src/core/client_config/lb_policy_factory.c
deleted file mode 100644
index e49de54..0000000
--- a/src/core/client_config/lb_policy_factory.c
+++ /dev/null
@@ -1,48 +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/client_config/lb_policy_factory.h"
-
-void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
-  factory->vtable->ref(factory);
-}
-
-void grpc_lb_policy_factory_unref(grpc_lb_policy_factory* factory) {
-  factory->vtable->unref(factory);
-}
-
-grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy(
-    grpc_lb_policy_factory* factory, grpc_lb_policy_args* args) {
-  if (factory == NULL) return NULL;
-  return factory->vtable->create_lb_policy(factory, args);
-}
diff --git a/src/core/client_config/lb_policy_factory.h b/src/core/client_config/lb_policy_factory.h
deleted file mode 100644
index 842ba96..0000000
--- a/src/core/client_config/lb_policy_factory.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_LB_POLICY_FACTORY_H
-#define GRPC_CORE_CLIENT_CONFIG_LB_POLICY_FACTORY_H
-
-#include "src/core/client_config/lb_policy.h"
-#include "src/core/client_config/subchannel.h"
-
-typedef struct grpc_lb_policy_factory grpc_lb_policy_factory;
-typedef struct grpc_lb_policy_factory_vtable grpc_lb_policy_factory_vtable;
-
-/** grpc_lb_policy provides grpc_client_config objects to grpc_channel
-    objects */
-struct grpc_lb_policy_factory {
-  const grpc_lb_policy_factory_vtable *vtable;
-};
-
-typedef struct grpc_lb_policy_args {
-  grpc_subchannel **subchannels;
-  size_t num_subchannels;
-} grpc_lb_policy_args;
-
-struct grpc_lb_policy_factory_vtable {
-  void (*ref)(grpc_lb_policy_factory *factory);
-  void (*unref)(grpc_lb_policy_factory *factory);
-
-  /** Implementation of grpc_lb_policy_factory_create_lb_policy */
-  grpc_lb_policy *(*create_lb_policy)(grpc_lb_policy_factory *factory,
-                                      grpc_lb_policy_args *args);
-
-  /** Name for the LB policy this factory implements */
-  const char *name;
-};
-
-void grpc_lb_policy_factory_ref(grpc_lb_policy_factory *factory);
-void grpc_lb_policy_factory_unref(grpc_lb_policy_factory *factory);
-
-/** Create a lb_policy instance. */
-grpc_lb_policy *grpc_lb_policy_factory_create_lb_policy(
-    grpc_lb_policy_factory *factory, grpc_lb_policy_args *args);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_LB_POLICY_FACTORY_H */
diff --git a/src/core/client_config/lb_policy_registry.c b/src/core/client_config/lb_policy_registry.c
deleted file mode 100644
index fc302e8..0000000
--- a/src/core/client_config/lb_policy_registry.c
+++ /dev/null
@@ -1,88 +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/client_config/lb_policy_registry.h"
-
-#include <string.h>
-
-#define MAX_POLICIES 10
-
-static grpc_lb_policy_factory *g_all_of_the_lb_policies[MAX_POLICIES];
-static int g_number_of_lb_policies = 0;
-
-static grpc_lb_policy_factory *g_default_lb_policy_factory;
-
-void grpc_lb_policy_registry_init(grpc_lb_policy_factory *default_factory) {
-  g_number_of_lb_policies = 0;
-  g_default_lb_policy_factory = default_factory;
-}
-
-void grpc_lb_policy_registry_shutdown(void) {
-  int i;
-  for (i = 0; i < g_number_of_lb_policies; i++) {
-    grpc_lb_policy_factory_unref(g_all_of_the_lb_policies[i]);
-  }
-}
-
-void grpc_register_lb_policy(grpc_lb_policy_factory *factory) {
-  int i;
-  for (i = 0; i < g_number_of_lb_policies; i++) {
-    GPR_ASSERT(0 != strcmp(factory->vtable->name,
-                           g_all_of_the_lb_policies[i]->vtable->name));
-  }
-  GPR_ASSERT(g_number_of_lb_policies != MAX_POLICIES);
-  grpc_lb_policy_factory_ref(factory);
-  g_all_of_the_lb_policies[g_number_of_lb_policies++] = factory;
-}
-
-static grpc_lb_policy_factory *lookup_factory(const char *name) {
-  int i;
-
-  if (name == NULL) return NULL;
-
-  for (i = 0; i < g_number_of_lb_policies; i++) {
-    if (0 == strcmp(name, g_all_of_the_lb_policies[i]->vtable->name)) {
-      return g_all_of_the_lb_policies[i];
-    }
-  }
-
-  return NULL;
-}
-
-grpc_lb_policy *grpc_lb_policy_create(const char *name,
-                                      grpc_lb_policy_args *args) {
-  grpc_lb_policy_factory *factory = lookup_factory(name);
-  grpc_lb_policy *lb_policy =
-      grpc_lb_policy_factory_create_lb_policy(factory, args);
-  return lb_policy;
-}
diff --git a/src/core/client_config/lb_policy_registry.h b/src/core/client_config/lb_policy_registry.h
deleted file mode 100644
index f3a08a3..0000000
--- a/src/core/client_config/lb_policy_registry.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_LB_POLICY_REGISTRY_H
-#define GRPC_CORE_CLIENT_CONFIG_LB_POLICY_REGISTRY_H
-
-#include "src/core/client_config/lb_policy_factory.h"
-
-/** Initialize the registry and set \a default_factory as the factory to be
- * returned when no name is provided in a lookup */
-void grpc_lb_policy_registry_init(grpc_lb_policy_factory *default_factory);
-void grpc_lb_policy_registry_shutdown(void);
-
-/** Register a LB policy factory. */
-void grpc_register_lb_policy(grpc_lb_policy_factory *factory);
-
-/** Create a \a grpc_lb_policy instance.
- *
- * If \a name is NULL, the default factory from \a grpc_lb_policy_registry_init
- * will be returned. */
-grpc_lb_policy *grpc_lb_policy_create(const char *name,
-                                      grpc_lb_policy_args *args);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_LB_POLICY_REGISTRY_H */
diff --git a/src/core/client_config/resolver.c b/src/core/client_config/resolver.c
deleted file mode 100644
index eda01e7..0000000
--- a/src/core/client_config/resolver.c
+++ /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 "src/core/client_config/resolver.h"
-
-void grpc_resolver_init(grpc_resolver *resolver,
-                        const grpc_resolver_vtable *vtable) {
-  resolver->vtable = vtable;
-  gpr_ref_init(&resolver->refs, 1);
-}
-
-#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
-void grpc_resolver_ref(grpc_resolver *resolver, grpc_closure_list *closure_list,
-                       const char *file, int line, const char *reason) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p   ref %d -> %d %s",
-          resolver, (int)resolver->refs.count, (int)resolver->refs.count + 1,
-          reason);
-#else
-void grpc_resolver_ref(grpc_resolver *resolver) {
-#endif
-  gpr_ref(&resolver->refs);
-}
-
-#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
-void grpc_resolver_unref(grpc_resolver *resolver,
-                         grpc_closure_list *closure_list, const char *file,
-                         int line, const char *reason) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p unref %d -> %d %s",
-          resolver, (int)resolver->refs.count, (int)resolver->refs.count - 1,
-          reason);
-#else
-void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
-#endif
-  if (gpr_unref(&resolver->refs)) {
-    resolver->vtable->destroy(exec_ctx, resolver);
-  }
-}
-
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
-  resolver->vtable->shutdown(exec_ctx, resolver);
-}
-
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                     grpc_resolver *resolver) {
-  resolver->vtable->channel_saw_error(exec_ctx, resolver);
-}
-
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                        grpc_client_config **target_config,
-                        grpc_closure *on_complete) {
-  resolver->vtable->next(exec_ctx, resolver, target_config, on_complete);
-}
diff --git a/src/core/client_config/resolver.h b/src/core/client_config/resolver.h
deleted file mode 100644
index 96f88fe..0000000
--- a/src/core/client_config/resolver.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_RESOLVER_H
-#define GRPC_CORE_CLIENT_CONFIG_RESOLVER_H
-
-#include "src/core/client_config/client_config.h"
-#include "src/core/client_config/subchannel.h"
-#include "src/core/iomgr/iomgr.h"
-
-typedef struct grpc_resolver grpc_resolver;
-typedef struct grpc_resolver_vtable grpc_resolver_vtable;
-
-/** grpc_resolver provides grpc_client_config objects to grpc_channel
-    objects */
-struct grpc_resolver {
-  const grpc_resolver_vtable *vtable;
-  gpr_refcount refs;
-};
-
-struct grpc_resolver_vtable {
-  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
-  void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
-  void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-               grpc_client_config **target_config, grpc_closure *on_complete);
-};
-
-#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
-#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_RESOLVER_UNREF(cl, p, r) \
-  grpc_resolver_unref((cl), (p), __FILE__, __LINE__, (r))
-void grpc_resolver_ref(grpc_resolver *policy, const char *file, int line,
-                       const char *reason);
-void grpc_resolver_unref(grpc_resolver *policy, grpc_closure_list *closure_list,
-                         const char *file, int line, const char *reason);
-#else
-#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p))
-#define GRPC_RESOLVER_UNREF(cl, p, r) grpc_resolver_unref((cl), (p))
-void grpc_resolver_ref(grpc_resolver *policy);
-void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy);
-#endif
-
-void grpc_resolver_init(grpc_resolver *resolver,
-                        const grpc_resolver_vtable *vtable);
-
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
-
-/** Notification that the channel has seen an error on some address.
-    Can be used as a hint that re-resolution is desirable soon. */
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                     grpc_resolver *resolver);
-
-/** Get the next client config. Called by the channel to fetch a new
-    configuration. Expected to set *target_config with a new configuration,
-    and then schedule on_complete for execution.
-
-    If resolution is fatally broken, set *target_config to NULL and
-    schedule on_complete. */
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                        grpc_client_config **target_config,
-                        grpc_closure *on_complete);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_RESOLVER_H */
diff --git a/src/core/client_config/resolver_factory.c b/src/core/client_config/resolver_factory.c
deleted file mode 100644
index e7e9196..0000000
--- a/src/core/client_config/resolver_factory.c
+++ /dev/null
@@ -1,55 +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/client_config/resolver_factory.h"
-
-void grpc_resolver_factory_ref(grpc_resolver_factory* factory) {
-  factory->vtable->ref(factory);
-}
-
-void grpc_resolver_factory_unref(grpc_resolver_factory* factory) {
-  factory->vtable->unref(factory);
-}
-
-/** Create a resolver instance for a name */
-grpc_resolver* grpc_resolver_factory_create_resolver(
-    grpc_resolver_factory* factory, grpc_resolver_args* args) {
-  if (factory == NULL) return NULL;
-  return factory->vtable->create_resolver(factory, args);
-}
-
-char* grpc_resolver_factory_get_default_authority(
-    grpc_resolver_factory* factory, grpc_uri* uri) {
-  if (factory == NULL) return NULL;
-  return factory->vtable->get_default_authority(factory, uri);
-}
diff --git a/src/core/client_config/resolver_factory.h b/src/core/client_config/resolver_factory.h
deleted file mode 100644
index 477f8db..0000000
--- a/src/core/client_config/resolver_factory.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_RESOLVER_FACTORY_H
-#define GRPC_CORE_CLIENT_CONFIG_RESOLVER_FACTORY_H
-
-#include "src/core/client_config/resolver.h"
-#include "src/core/client_config/subchannel_factory.h"
-#include "src/core/client_config/uri_parser.h"
-
-typedef struct grpc_resolver_factory grpc_resolver_factory;
-typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable;
-
-/** grpc_resolver provides grpc_client_config objects to grpc_channel
-    objects */
-struct grpc_resolver_factory {
-  const grpc_resolver_factory_vtable *vtable;
-};
-
-typedef struct grpc_resolver_args {
-  grpc_uri *uri;
-  grpc_subchannel_factory *subchannel_factory;
-} grpc_resolver_args;
-
-struct grpc_resolver_factory_vtable {
-  void (*ref)(grpc_resolver_factory *factory);
-  void (*unref)(grpc_resolver_factory *factory);
-
-  /** Implementation of grpc_resolver_factory_create_resolver */
-  grpc_resolver *(*create_resolver)(grpc_resolver_factory *factory,
-                                    grpc_resolver_args *args);
-
-  /** Implementation of grpc_resolver_factory_get_default_authority */
-  char *(*get_default_authority)(grpc_resolver_factory *factory, grpc_uri *uri);
-
-  /** URI scheme that this factory implements */
-  const char *scheme;
-};
-
-void grpc_resolver_factory_ref(grpc_resolver_factory *resolver);
-void grpc_resolver_factory_unref(grpc_resolver_factory *resolver);
-
-/** Create a resolver instance for a name */
-grpc_resolver *grpc_resolver_factory_create_resolver(
-    grpc_resolver_factory *factory, grpc_resolver_args *args);
-
-/** Return a (freshly allocated with gpr_malloc) string representing
-    the default authority to use for this scheme. */
-char *grpc_resolver_factory_get_default_authority(
-    grpc_resolver_factory *factory, grpc_uri *uri);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_RESOLVER_FACTORY_H */
diff --git a/src/core/client_config/resolver_registry.c b/src/core/client_config/resolver_registry.c
deleted file mode 100644
index 89a945c..0000000
--- a/src/core/client_config/resolver_registry.c
+++ /dev/null
@@ -1,137 +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/client_config/resolver_registry.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#define MAX_RESOLVERS 10
-
-static grpc_resolver_factory *g_all_of_the_resolvers[MAX_RESOLVERS];
-static int g_number_of_resolvers = 0;
-
-static char *g_default_resolver_prefix;
-
-void grpc_resolver_registry_init(const char *default_resolver_prefix) {
-  g_number_of_resolvers = 0;
-  g_default_resolver_prefix = gpr_strdup(default_resolver_prefix);
-}
-
-void grpc_resolver_registry_shutdown(void) {
-  int i;
-  for (i = 0; i < g_number_of_resolvers; i++) {
-    grpc_resolver_factory_unref(g_all_of_the_resolvers[i]);
-  }
-  gpr_free(g_default_resolver_prefix);
-}
-
-void grpc_register_resolver_type(grpc_resolver_factory *factory) {
-  int i;
-  for (i = 0; i < g_number_of_resolvers; i++) {
-    GPR_ASSERT(0 != strcmp(factory->vtable->scheme,
-                           g_all_of_the_resolvers[i]->vtable->scheme));
-  }
-  GPR_ASSERT(g_number_of_resolvers != MAX_RESOLVERS);
-  grpc_resolver_factory_ref(factory);
-  g_all_of_the_resolvers[g_number_of_resolvers++] = factory;
-}
-
-static grpc_resolver_factory *lookup_factory(grpc_uri *uri) {
-  int i;
-
-  /* handling NULL uri's here simplifies grpc_resolver_create */
-  if (!uri) return NULL;
-
-  for (i = 0; i < g_number_of_resolvers; i++) {
-    if (0 == strcmp(uri->scheme, g_all_of_the_resolvers[i]->vtable->scheme)) {
-      return g_all_of_the_resolvers[i];
-    }
-  }
-
-  return NULL;
-}
-
-static grpc_resolver_factory *resolve_factory(const char *target,
-                                              grpc_uri **uri) {
-  char *tmp;
-  grpc_resolver_factory *factory = NULL;
-
-  GPR_ASSERT(uri != NULL);
-  *uri = grpc_uri_parse(target, 1);
-  factory = lookup_factory(*uri);
-  if (factory == NULL) {
-    if (g_default_resolver_prefix != NULL) {
-      grpc_uri_destroy(*uri);
-      gpr_asprintf(&tmp, "%s%s", g_default_resolver_prefix, target);
-      *uri = grpc_uri_parse(tmp, 1);
-      factory = lookup_factory(*uri);
-      if (factory == NULL) {
-        grpc_uri_destroy(grpc_uri_parse(target, 0));
-        grpc_uri_destroy(grpc_uri_parse(tmp, 0));
-        gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target,
-                tmp);
-      }
-      gpr_free(tmp);
-    } else {
-      grpc_uri_destroy(grpc_uri_parse(target, 0));
-      gpr_log(GPR_ERROR, "don't know how to resolve '%s'", target);
-    }
-  }
-  return factory;
-}
-
-grpc_resolver *grpc_resolver_create(
-    const char *target, grpc_subchannel_factory *subchannel_factory) {
-  grpc_uri *uri = NULL;
-  grpc_resolver_factory *factory = resolve_factory(target, &uri);
-  grpc_resolver *resolver;
-  grpc_resolver_args args;
-  memset(&args, 0, sizeof(args));
-  args.uri = uri;
-  args.subchannel_factory = subchannel_factory;
-  resolver = grpc_resolver_factory_create_resolver(factory, &args);
-  grpc_uri_destroy(uri);
-  return resolver;
-}
-
-char *grpc_get_default_authority(const char *target) {
-  grpc_uri *uri = NULL;
-  grpc_resolver_factory *factory = resolve_factory(target, &uri);
-  char *authority = grpc_resolver_factory_get_default_authority(factory, uri);
-  grpc_uri_destroy(uri);
-  return authority;
-}
diff --git a/src/core/client_config/resolver_registry.h b/src/core/client_config/resolver_registry.h
deleted file mode 100644
index 1e4cebe..0000000
--- a/src/core/client_config/resolver_registry.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_RESOLVER_REGISTRY_H
-#define GRPC_CORE_CLIENT_CONFIG_RESOLVER_REGISTRY_H
-
-#include "src/core/client_config/resolver_factory.h"
-
-void grpc_resolver_registry_init(const char *default_prefix);
-void grpc_resolver_registry_shutdown(void);
-
-/** Register a resolver type.
-    URI's of \a scheme will be resolved with the given resolver.
-    If \a priority is greater than zero, then the resolver will be eligible
-    to resolve names that are passed in with no scheme. Higher priority
-    resolvers will be tried before lower priority schemes. */
-void grpc_register_resolver_type(grpc_resolver_factory *factory);
-
-/** Create a resolver given \a target.
-    First tries to parse \a target as a URI. If this succeeds, tries
-    to locate a registered resolver factory based on the URI scheme.
-    If parsing or location fails, prefixes default_prefix from
-    grpc_resolver_registry_init to target, and tries again (if default_prefix
-    was not NULL).
-    If a resolver factory was found, use it to instantiate a resolver and
-    return it.
-    If a resolver factory was not found, return NULL. */
-grpc_resolver *grpc_resolver_create(
-    const char *target, grpc_subchannel_factory *subchannel_factory);
-
-/** Given a target, return a (freshly allocated with gpr_malloc) string
-    representing the default authority to pass from a client. */
-char *grpc_get_default_authority(const char *target);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_RESOLVER_REGISTRY_H */
diff --git a/src/core/client_config/resolvers/dns_resolver.c b/src/core/client_config/resolvers/dns_resolver.c
deleted file mode 100644
index e28e475..0000000
--- a/src/core/client_config/resolvers/dns_resolver.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- *
- * 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/client_config/resolvers/dns_resolver.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/client_config/lb_policy_registry.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/timer.h"
-#include "src/core/support/string.h"
-
-typedef struct {
-  /** base class: must be first */
-  grpc_resolver base;
-  /** refcount */
-  gpr_refcount refs;
-  /** name to resolve */
-  char *name;
-  /** default port to use */
-  char *default_port;
-  /** subchannel factory */
-  grpc_subchannel_factory *subchannel_factory;
-  /** load balancing policy name */
-  char *lb_policy_name;
-
-  /** mutex guarding the rest of the state */
-  gpr_mu mu;
-  /** are we currently resolving? */
-  int resolving;
-  /** which version of resolved_config have we published? */
-  int published_version;
-  /** which version of resolved_config is current? */
-  int resolved_version;
-  /** pending next completion, or NULL */
-  grpc_closure *next_completion;
-  /** target config address for next completion */
-  grpc_client_config **target_config;
-  /** current (fully resolved) config */
-  grpc_client_config *resolved_config;
-  /** retry timer */
-  bool have_retry_timer;
-  grpc_timer retry_timer;
-} dns_resolver;
-
-static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-
-static void dns_start_resolving_locked(dns_resolver *r);
-static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                         dns_resolver *r);
-
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                     grpc_client_config **target_config,
-                     grpc_closure *on_complete);
-
-static const grpc_resolver_vtable dns_resolver_vtable = {
-    dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
-
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
-  dns_resolver *r = (dns_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  if (r->have_retry_timer) {
-    grpc_timer_cancel(exec_ctx, &r->retry_timer);
-  }
-  if (r->next_completion != NULL) {
-    *r->target_config = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
-    r->next_completion = NULL;
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                  grpc_resolver *resolver) {
-  dns_resolver *r = (dns_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  if (!r->resolving) {
-    dns_start_resolving_locked(r);
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                     grpc_client_config **target_config,
-                     grpc_closure *on_complete) {
-  dns_resolver *r = (dns_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  GPR_ASSERT(!r->next_completion);
-  r->next_completion = on_complete;
-  r->target_config = target_config;
-  if (r->resolved_version == 0 && !r->resolving) {
-    dns_start_resolving_locked(r);
-  } else {
-    dns_maybe_finish_next_locked(exec_ctx, r);
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
-                               bool success) {
-  dns_resolver *r = arg;
-
-  gpr_mu_lock(&r->mu);
-  r->have_retry_timer = false;
-  if (success) {
-    if (!r->resolving) {
-      dns_start_resolving_locked(r);
-    }
-  }
-  gpr_mu_unlock(&r->mu);
-
-  GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
-}
-
-static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                            grpc_resolved_addresses *addresses) {
-  dns_resolver *r = arg;
-  grpc_client_config *config = NULL;
-  grpc_subchannel **subchannels;
-  grpc_subchannel_args args;
-  grpc_lb_policy *lb_policy;
-  size_t i;
-  gpr_mu_lock(&r->mu);
-  GPR_ASSERT(r->resolving);
-  r->resolving = 0;
-  if (addresses != NULL) {
-    grpc_lb_policy_args lb_policy_args;
-    config = grpc_client_config_create();
-    subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
-    size_t naddrs = 0;
-    for (i = 0; i < addresses->naddrs; i++) {
-      memset(&args, 0, sizeof(args));
-      args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
-      args.addr_len = (size_t)addresses->addrs[i].len;
-      grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
-          exec_ctx, r->subchannel_factory, &args);
-      if (subchannel != NULL) {
-        subchannels[naddrs++] = subchannel;
-      }
-    }
-    memset(&lb_policy_args, 0, sizeof(lb_policy_args));
-    lb_policy_args.subchannels = subchannels;
-    lb_policy_args.num_subchannels = naddrs;
-    lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
-    if (lb_policy != NULL) {
-      grpc_client_config_set_lb_policy(config, lb_policy);
-      GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
-    }
-    grpc_resolved_addresses_destroy(addresses);
-    gpr_free(subchannels);
-  } else {
-    int retry_seconds = 15;
-    gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d seconds",
-            retry_seconds);
-    GPR_ASSERT(!r->have_retry_timer);
-    r->have_retry_timer = true;
-    gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
-    GRPC_RESOLVER_REF(&r->base, "retry-timer");
-    grpc_timer_init(
-        exec_ctx, &r->retry_timer,
-        gpr_time_add(now, gpr_time_from_seconds(retry_seconds, GPR_TIMESPAN)),
-        dns_on_retry_timer, r, now);
-  }
-  if (r->resolved_config) {
-    grpc_client_config_unref(exec_ctx, r->resolved_config);
-  }
-  r->resolved_config = config;
-  r->resolved_version++;
-  dns_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
-
-  GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
-}
-
-static void dns_start_resolving_locked(dns_resolver *r) {
-  GRPC_RESOLVER_REF(&r->base, "dns-resolving");
-  GPR_ASSERT(!r->resolving);
-  r->resolving = 1;
-  grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
-}
-
-static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                         dns_resolver *r) {
-  if (r->next_completion != NULL &&
-      r->resolved_version != r->published_version) {
-    *r->target_config = r->resolved_config;
-    if (r->resolved_config) {
-      grpc_client_config_ref(r->resolved_config);
-    }
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
-    r->next_completion = NULL;
-    r->published_version = r->resolved_version;
-  }
-}
-
-static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
-  dns_resolver *r = (dns_resolver *)gr;
-  gpr_mu_destroy(&r->mu);
-  if (r->resolved_config) {
-    grpc_client_config_unref(exec_ctx, r->resolved_config);
-  }
-  grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
-  gpr_free(r->name);
-  gpr_free(r->default_port);
-  gpr_free(r->lb_policy_name);
-  gpr_free(r);
-}
-
-static grpc_resolver *dns_create(grpc_resolver_args *args,
-                                 const char *default_port,
-                                 const char *lb_policy_name) {
-  dns_resolver *r;
-  const char *path = args->uri->path;
-
-  if (0 != strcmp(args->uri->authority, "")) {
-    gpr_log(GPR_ERROR, "authority based dns uri's not supported");
-    return NULL;
-  }
-
-  if (path[0] == '/') ++path;
-
-  r = gpr_malloc(sizeof(dns_resolver));
-  memset(r, 0, sizeof(*r));
-  gpr_ref_init(&r->refs, 1);
-  gpr_mu_init(&r->mu);
-  grpc_resolver_init(&r->base, &dns_resolver_vtable);
-  r->name = gpr_strdup(path);
-  r->default_port = gpr_strdup(default_port);
-  r->subchannel_factory = args->subchannel_factory;
-  grpc_subchannel_factory_ref(r->subchannel_factory);
-  r->lb_policy_name = gpr_strdup(lb_policy_name);
-  return &r->base;
-}
-
-/*
- * FACTORY
- */
-
-static void dns_factory_ref(grpc_resolver_factory *factory) {}
-
-static void dns_factory_unref(grpc_resolver_factory *factory) {}
-
-static grpc_resolver *dns_factory_create_resolver(
-    grpc_resolver_factory *factory, grpc_resolver_args *args) {
-  return dns_create(args, "https", "pick_first");
-}
-
-char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
-                                        grpc_uri *uri) {
-  const char *path = uri->path;
-  if (path[0] == '/') ++path;
-  return gpr_strdup(path);
-}
-
-static const grpc_resolver_factory_vtable dns_factory_vtable = {
-    dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
-    dns_factory_get_default_host_name, "dns"};
-static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
-
-grpc_resolver_factory *grpc_dns_resolver_factory_create() {
-  return &dns_resolver_factory;
-}
diff --git a/src/core/client_config/resolvers/dns_resolver.h b/src/core/client_config/resolvers/dns_resolver.h
deleted file mode 100644
index b24280b..0000000
--- a/src/core/client_config/resolvers/dns_resolver.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_RESOLVERS_DNS_RESOLVER_H
-#define GRPC_CORE_CLIENT_CONFIG_RESOLVERS_DNS_RESOLVER_H
-
-#include "src/core/client_config/resolver_factory.h"
-
-/** Create a dns resolver factory */
-grpc_resolver_factory *grpc_dns_resolver_factory_create(void);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_RESOLVERS_DNS_RESOLVER_H */
diff --git a/src/core/client_config/resolvers/sockaddr_resolver.c b/src/core/client_config/resolvers/sockaddr_resolver.c
deleted file mode 100644
index 68910ad..0000000
--- a/src/core/client_config/resolvers/sockaddr_resolver.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#include "src/core/client_config/resolvers/sockaddr_resolver.h"
-
-#include <stdio.h>
-#include <string.h>
-#ifdef GPR_POSIX_SOCKET
-#include <sys/un.h>
-#endif
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/client_config/lb_policy_registry.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/support/string.h"
-
-typedef struct {
-  /** base class: must be first */
-  grpc_resolver base;
-  /** refcount */
-  gpr_refcount refs;
-  /** subchannel factory */
-  grpc_subchannel_factory *subchannel_factory;
-  /** load balancing policy name */
-  char *lb_policy_name;
-
-  /** the addresses that we've 'resolved' */
-  struct sockaddr_storage *addrs;
-  /** the corresponding length of the addresses */
-  size_t *addrs_len;
-  /** how many elements in \a addrs */
-  size_t num_addrs;
-
-  /** mutex guarding the rest of the state */
-  gpr_mu mu;
-  /** have we published? */
-  int published;
-  /** pending next completion, or NULL */
-  grpc_closure *next_completion;
-  /** target config address for next completion */
-  grpc_client_config **target_config;
-} sockaddr_resolver;
-
-static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-
-static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                              sockaddr_resolver *r);
-
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                       grpc_resolver *r);
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                          grpc_client_config **target_config,
-                          grpc_closure *on_complete);
-
-static const grpc_resolver_vtable sockaddr_resolver_vtable = {
-    sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
-    sockaddr_next};
-
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
-                              grpc_resolver *resolver) {
-  sockaddr_resolver *r = (sockaddr_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  if (r->next_completion != NULL) {
-    *r->target_config = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
-    r->next_completion = NULL;
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                       grpc_resolver *resolver) {
-  sockaddr_resolver *r = (sockaddr_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  r->published = 0;
-  sockaddr_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
-}
-
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                          grpc_client_config **target_config,
-                          grpc_closure *on_complete) {
-  sockaddr_resolver *r = (sockaddr_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  GPR_ASSERT(!r->next_completion);
-  r->next_completion = on_complete;
-  r->target_config = target_config;
-  sockaddr_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
-}
-
-static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                              sockaddr_resolver *r) {
-  grpc_client_config *cfg;
-  grpc_lb_policy *lb_policy;
-  grpc_lb_policy_args lb_policy_args;
-  grpc_subchannel **subchannels;
-  grpc_subchannel_args args;
-
-  if (r->next_completion != NULL && !r->published) {
-    size_t i;
-    cfg = grpc_client_config_create();
-    subchannels = gpr_malloc(sizeof(grpc_subchannel *) * r->num_addrs);
-    for (i = 0; i < r->num_addrs; i++) {
-      memset(&args, 0, sizeof(args));
-      args.addr = (struct sockaddr *)&r->addrs[i];
-      args.addr_len = r->addrs_len[i];
-      subchannels[i] = grpc_subchannel_factory_create_subchannel(
-          exec_ctx, r->subchannel_factory, &args);
-    }
-    memset(&lb_policy_args, 0, sizeof(lb_policy_args));
-    lb_policy_args.subchannels = subchannels;
-    lb_policy_args.num_subchannels = r->num_addrs;
-    lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
-    gpr_free(subchannels);
-    grpc_client_config_set_lb_policy(cfg, lb_policy);
-    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
-    r->published = 1;
-    *r->target_config = cfg;
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
-    r->next_completion = NULL;
-  }
-}
-
-static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
-  sockaddr_resolver *r = (sockaddr_resolver *)gr;
-  gpr_mu_destroy(&r->mu);
-  grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
-  gpr_free(r->addrs);
-  gpr_free(r->addrs_len);
-  gpr_free(r->lb_policy_name);
-  gpr_free(r);
-}
-
-#ifdef GPR_POSIX_SOCKET
-static int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr,
-                      size_t *len) {
-  struct sockaddr_un *un = (struct sockaddr_un *)addr;
-
-  un->sun_family = AF_UNIX;
-  strcpy(un->sun_path, uri->path);
-  *len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
-
-  return 1;
-}
-
-static char *unix_get_default_authority(grpc_resolver_factory *factory,
-                                        grpc_uri *uri) {
-  return gpr_strdup("localhost");
-}
-#endif
-
-static char *ip_get_default_authority(grpc_uri *uri) {
-  const char *path = uri->path;
-  if (path[0] == '/') ++path;
-  return gpr_strdup(path);
-}
-
-static char *ipv4_get_default_authority(grpc_resolver_factory *factory,
-                                        grpc_uri *uri) {
-  return ip_get_default_authority(uri);
-}
-
-static char *ipv6_get_default_authority(grpc_resolver_factory *factory,
-                                        grpc_uri *uri) {
-  return ip_get_default_authority(uri);
-}
-
-static int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr,
-                      size_t *len) {
-  const char *host_port = uri->path;
-  char *host;
-  char *port;
-  int port_num;
-  int result = 0;
-  struct sockaddr_in *in = (struct sockaddr_in *)addr;
-
-  if (*host_port == '/') ++host_port;
-  if (!gpr_split_host_port(host_port, &host, &port)) {
-    return 0;
-  }
-
-  memset(in, 0, sizeof(*in));
-  *len = sizeof(*in);
-  in->sin_family = AF_INET;
-  if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
-    gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
-    goto done;
-  }
-
-  if (port != NULL) {
-    if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
-        port_num > 65535) {
-      gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
-      goto done;
-    }
-    in->sin_port = htons((uint16_t)port_num);
-  } else {
-    gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
-    goto done;
-  }
-
-  result = 1;
-done:
-  gpr_free(host);
-  gpr_free(port);
-  return result;
-}
-
-static int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr,
-                      size_t *len) {
-  const char *host_port = uri->path;
-  char *host;
-  char *port;
-  int port_num;
-  int result = 0;
-  struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
-
-  if (*host_port == '/') ++host_port;
-  if (!gpr_split_host_port(host_port, &host, &port)) {
-    return 0;
-  }
-
-  memset(in6, 0, sizeof(*in6));
-  *len = sizeof(*in6);
-  in6->sin6_family = AF_INET6;
-  if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
-    gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
-    goto done;
-  }
-
-  if (port != NULL) {
-    if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
-        port_num > 65535) {
-      gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
-      goto done;
-    }
-    in6->sin6_port = htons((uint16_t)port_num);
-  } else {
-    gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
-    goto done;
-  }
-
-  result = 1;
-done:
-  gpr_free(host);
-  gpr_free(port);
-  return result;
-}
-
-static void do_nothing(void *ignored) {}
-
-static grpc_resolver *sockaddr_create(
-    grpc_resolver_args *args, const char *default_lb_policy_name,
-    int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) {
-  size_t i;
-  int errors_found = 0; /* GPR_FALSE */
-  sockaddr_resolver *r;
-  gpr_slice path_slice;
-  gpr_slice_buffer path_parts;
-
-  if (0 != strcmp(args->uri->authority, "")) {
-    gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme",
-            args->uri->scheme);
-    return NULL;
-  }
-
-  r = gpr_malloc(sizeof(sockaddr_resolver));
-  memset(r, 0, sizeof(*r));
-
-  r->lb_policy_name = NULL;
-  if (0 != strcmp(args->uri->query, "")) {
-    gpr_slice query_slice;
-    gpr_slice_buffer query_parts;
-
-    query_slice =
-        gpr_slice_new(args->uri->query, strlen(args->uri->query), do_nothing);
-    gpr_slice_buffer_init(&query_parts);
-    gpr_slice_split(query_slice, "=", &query_parts);
-    GPR_ASSERT(query_parts.count == 2);
-    if (0 == gpr_slice_str_cmp(query_parts.slices[0], "lb_policy")) {
-      r->lb_policy_name = gpr_dump_slice(query_parts.slices[1], GPR_DUMP_ASCII);
-    }
-    gpr_slice_buffer_destroy(&query_parts);
-    gpr_slice_unref(query_slice);
-  }
-  if (r->lb_policy_name == NULL) {
-    r->lb_policy_name = gpr_strdup(default_lb_policy_name);
-  }
-
-  path_slice =
-      gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing);
-  gpr_slice_buffer_init(&path_parts);
-
-  gpr_slice_split(path_slice, ",", &path_parts);
-  r->num_addrs = path_parts.count;
-  r->addrs = gpr_malloc(sizeof(struct sockaddr_storage) * r->num_addrs);
-  r->addrs_len = gpr_malloc(sizeof(*r->addrs_len) * r->num_addrs);
-
-  for (i = 0; i < r->num_addrs; i++) {
-    grpc_uri ith_uri = *args->uri;
-    char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
-    ith_uri.path = part_str;
-    if (!parse(&ith_uri, &r->addrs[i], &r->addrs_len[i])) {
-      errors_found = 1; /* GPR_TRUE */
-    }
-    gpr_free(part_str);
-    if (errors_found) break;
-  }
-
-  gpr_slice_buffer_destroy(&path_parts);
-  gpr_slice_unref(path_slice);
-  if (errors_found) {
-    gpr_free(r->lb_policy_name);
-    gpr_free(r->addrs);
-    gpr_free(r->addrs_len);
-    gpr_free(r);
-    return NULL;
-  }
-
-  gpr_ref_init(&r->refs, 1);
-  gpr_mu_init(&r->mu);
-  grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
-  r->subchannel_factory = args->subchannel_factory;
-  grpc_subchannel_factory_ref(r->subchannel_factory);
-
-  return &r->base;
-}
-
-/*
- * FACTORY
- */
-
-static void sockaddr_factory_ref(grpc_resolver_factory *factory) {}
-
-static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
-
-#define DECL_FACTORY(name)                                                  \
-  static grpc_resolver *name##_factory_create_resolver(                     \
-      grpc_resolver_factory *factory, grpc_resolver_args *args) {           \
-    return sockaddr_create(args, "pick_first", parse_##name);               \
-  }                                                                         \
-  static const grpc_resolver_factory_vtable name##_factory_vtable = {       \
-      sockaddr_factory_ref, sockaddr_factory_unref,                         \
-      name##_factory_create_resolver, name##_get_default_authority, #name}; \
-  static grpc_resolver_factory name##_resolver_factory = {                  \
-      &name##_factory_vtable};                                              \
-  grpc_resolver_factory *grpc_##name##_resolver_factory_create() {          \
-    return &name##_resolver_factory;                                        \
-  }
-
-#ifdef GPR_POSIX_SOCKET
-DECL_FACTORY(unix)
-#endif
-DECL_FACTORY(ipv4) DECL_FACTORY(ipv6)
diff --git a/src/core/client_config/resolvers/sockaddr_resolver.h b/src/core/client_config/resolvers/sockaddr_resolver.h
deleted file mode 100644
index f050329..0000000
--- a/src/core/client_config/resolvers/sockaddr_resolver.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_RESOLVERS_SOCKADDR_RESOLVER_H
-#define GRPC_CORE_CLIENT_CONFIG_RESOLVERS_SOCKADDR_RESOLVER_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/client_config/resolver_factory.h"
-
-grpc_resolver_factory *grpc_ipv4_resolver_factory_create(void);
-
-grpc_resolver_factory *grpc_ipv6_resolver_factory_create(void);
-
-#ifdef GPR_POSIX_SOCKET
-/** Create a unix resolver factory */
-grpc_resolver_factory *grpc_unix_resolver_factory_create(void);
-#endif
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_RESOLVERS_SOCKADDR_RESOLVER_H */
diff --git a/src/core/client_config/resolvers/zookeeper_resolver.c b/src/core/client_config/resolvers/zookeeper_resolver.c
deleted file mode 100644
index 166738e..0000000
--- a/src/core/client_config/resolvers/zookeeper_resolver.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- *
- * 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/client_config/resolvers/zookeeper_resolver.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/string_util.h>
-
-#include <grpc/grpc_zookeeper.h>
-#include <zookeeper/zookeeper.h>
-
-#include "src/core/client_config/lb_policy_registry.h"
-#include "src/core/client_config/resolver_registry.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/json/json.h"
-
-/** Zookeeper session expiration time in milliseconds */
-#define GRPC_ZOOKEEPER_SESSION_TIMEOUT 15000
-
-typedef struct {
-  /** base class: must be first */
-  grpc_resolver base;
-  /** refcount */
-  gpr_refcount refs;
-  /** name to resolve */
-  char *name;
-  /** subchannel factory */
-  grpc_subchannel_factory *subchannel_factory;
-  /** load balancing policy name */
-  char *lb_policy_name;
-
-  /** mutex guarding the rest of the state */
-  gpr_mu mu;
-  /** are we currently resolving? */
-  int resolving;
-  /** which version of resolved_config have we published? */
-  int published_version;
-  /** which version of resolved_config is current? */
-  int resolved_version;
-  /** pending next completion, or NULL */
-  grpc_closure *next_completion;
-  /** target config address for next completion */
-  grpc_client_config **target_config;
-  /** current (fully resolved) config */
-  grpc_client_config *resolved_config;
-
-  /** zookeeper handle */
-  zhandle_t *zookeeper_handle;
-  /** zookeeper resolved addresses */
-  grpc_resolved_addresses *resolved_addrs;
-  /** total number of addresses to be resolved */
-  int resolved_total;
-  /** number of addresses resolved */
-  int resolved_num;
-} zookeeper_resolver;
-
-static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-
-static void zookeeper_start_resolving_locked(zookeeper_resolver *r);
-static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                               zookeeper_resolver *r);
-
-static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                        grpc_resolver *r);
-static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                           grpc_client_config **target_config,
-                           grpc_closure *on_complete);
-
-static const grpc_resolver_vtable zookeeper_resolver_vtable = {
-    zookeeper_destroy, zookeeper_shutdown, zookeeper_channel_saw_error,
-    zookeeper_next};
-
-static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx,
-                               grpc_resolver *resolver) {
-  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
-  grpc_closure *call = NULL;
-  gpr_mu_lock(&r->mu);
-  if (r->next_completion != NULL) {
-    *r->target_config = NULL;
-    call = r->next_completion;
-    r->next_completion = NULL;
-  }
-  zookeeper_close(r->zookeeper_handle);
-  gpr_mu_unlock(&r->mu);
-  if (call != NULL) {
-    call->cb(exec_ctx, call->cb_arg, 1);
-  }
-}
-
-static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                        grpc_resolver *resolver) {
-  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  if (r->resolving == 0) {
-    zookeeper_start_resolving_locked(r);
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                           grpc_client_config **target_config,
-                           grpc_closure *on_complete) {
-  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  GPR_ASSERT(r->next_completion == NULL);
-  r->next_completion = on_complete;
-  r->target_config = target_config;
-  if (r->resolved_version == 0 && r->resolving == 0) {
-    zookeeper_start_resolving_locked(r);
-  } else {
-    zookeeper_maybe_finish_next_locked(exec_ctx, r);
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-/** Zookeeper global watcher for connection management
-    TODO: better connection management besides logs */
-static void zookeeper_global_watcher(zhandle_t *zookeeper_handle, int type,
-                                     int state, const char *path,
-                                     void *watcher_ctx) {
-  if (type == ZOO_SESSION_EVENT) {
-    if (state == ZOO_EXPIRED_SESSION_STATE) {
-      gpr_log(GPR_ERROR, "Zookeeper session expired");
-    } else if (state == ZOO_AUTH_FAILED_STATE) {
-      gpr_log(GPR_ERROR, "Zookeeper authentication failed");
-    }
-  }
-}
-
-/** Zookeeper watcher triggered by changes to watched nodes
-    Once triggered, it tries to resolve again to get updated addresses */
-static void zookeeper_watcher(zhandle_t *zookeeper_handle, int type, int state,
-                              const char *path, void *watcher_ctx) {
-  if (watcher_ctx != NULL) {
-    zookeeper_resolver *r = (zookeeper_resolver *)watcher_ctx;
-    if (state == ZOO_CONNECTED_STATE) {
-      gpr_mu_lock(&r->mu);
-      if (r->resolving == 0) {
-        zookeeper_start_resolving_locked(r);
-      }
-      gpr_mu_unlock(&r->mu);
-    }
-  }
-}
-
-/** Callback function after getting all resolved addresses
-    Creates a subchannel for each address */
-static void zookeeper_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                                  grpc_resolved_addresses *addresses) {
-  zookeeper_resolver *r = arg;
-  grpc_client_config *config = NULL;
-  grpc_subchannel **subchannels;
-  grpc_subchannel_args args;
-  grpc_lb_policy *lb_policy;
-  size_t i;
-  if (addresses != NULL) {
-    grpc_lb_policy_args lb_policy_args;
-    config = grpc_client_config_create();
-    subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
-    for (i = 0; i < addresses->naddrs; i++) {
-      memset(&args, 0, sizeof(args));
-      args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
-      args.addr_len = addresses->addrs[i].len;
-      subchannels[i] = grpc_subchannel_factory_create_subchannel(
-          exec_ctx, r->subchannel_factory, &args);
-    }
-    lb_policy_args.subchannels = subchannels;
-    lb_policy_args.num_subchannels = addresses->naddrs;
-    lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
-    grpc_client_config_set_lb_policy(config, lb_policy);
-    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
-    grpc_resolved_addresses_destroy(addresses);
-    gpr_free(subchannels);
-  }
-  gpr_mu_lock(&r->mu);
-  GPR_ASSERT(r->resolving == 1);
-  r->resolving = 0;
-  if (r->resolved_config != NULL) {
-    grpc_client_config_unref(exec_ctx, r->resolved_config);
-  }
-  r->resolved_config = config;
-  r->resolved_version++;
-  zookeeper_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
-
-  GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "zookeeper-resolving");
-}
-
-/** Callback function for each DNS resolved address */
-static void zookeeper_dns_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                                   grpc_resolved_addresses *addresses) {
-  size_t i;
-  zookeeper_resolver *r = arg;
-  int resolve_done = 0;
-
-  gpr_mu_lock(&r->mu);
-  r->resolved_num++;
-  r->resolved_addrs->addrs =
-      gpr_realloc(r->resolved_addrs->addrs,
-                  sizeof(grpc_resolved_address) *
-                      (r->resolved_addrs->naddrs + addresses->naddrs));
-  for (i = 0; i < addresses->naddrs; i++) {
-    memcpy(r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].addr,
-           addresses->addrs[i].addr, addresses->addrs[i].len);
-    r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].len =
-        addresses->addrs[i].len;
-  }
-
-  r->resolved_addrs->naddrs += addresses->naddrs;
-  grpc_resolved_addresses_destroy(addresses);
-
-  /** Wait for all addresses to be resolved */
-  resolve_done = (r->resolved_num == r->resolved_total);
-  gpr_mu_unlock(&r->mu);
-  if (resolve_done) {
-    zookeeper_on_resolved(exec_ctx, r, r->resolved_addrs);
-  }
-}
-
-/** Parses JSON format address of a zookeeper node */
-static char *zookeeper_parse_address(const char *value, size_t value_len) {
-  grpc_json *json;
-  grpc_json *cur;
-  const char *host;
-  const char *port;
-  char *buffer;
-  char *address = NULL;
-
-  buffer = gpr_malloc(value_len);
-  memcpy(buffer, value, value_len);
-  json = grpc_json_parse_string_with_len(buffer, value_len);
-  if (json != NULL) {
-    host = NULL;
-    port = NULL;
-    for (cur = json->child; cur != NULL; cur = cur->next) {
-      if (!strcmp(cur->key, "host")) {
-        host = cur->value;
-        if (port != NULL) {
-          break;
-        }
-      } else if (!strcmp(cur->key, "port")) {
-        port = cur->value;
-        if (host != NULL) {
-          break;
-        }
-      }
-    }
-    if (host != NULL && port != NULL) {
-      gpr_asprintf(&address, "%s:%s", host, port);
-    }
-    grpc_json_destroy(json);
-  }
-  gpr_free(buffer);
-
-  return address;
-}
-
-static void zookeeper_get_children_node_completion(int rc, const char *value,
-                                                   int value_len,
-                                                   const struct Stat *stat,
-                                                   const void *arg) {
-  char *address = NULL;
-  zookeeper_resolver *r = (zookeeper_resolver *)arg;
-  int resolve_done = 0;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  if (rc != 0) {
-    gpr_log(GPR_ERROR, "Error in getting a child node of %s", r->name);
-    grpc_exec_ctx_finish(&exec_ctx);
-    return;
-  }
-
-  address = zookeeper_parse_address(value, (size_t)value_len);
-  if (address != NULL) {
-    /** Further resolves address by DNS */
-    grpc_resolve_address(address, NULL, zookeeper_dns_resolved, r);
-    gpr_free(address);
-  } else {
-    gpr_log(GPR_ERROR, "Error in resolving a child node of %s", r->name);
-    gpr_mu_lock(&r->mu);
-    r->resolved_total--;
-    resolve_done = (r->resolved_num == r->resolved_total);
-    gpr_mu_unlock(&r->mu);
-    if (resolve_done) {
-      zookeeper_on_resolved(&exec_ctx, r, r->resolved_addrs);
-    }
-  }
-
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void zookeeper_get_children_completion(
-    int rc, const struct String_vector *children, const void *arg) {
-  char *path;
-  int status;
-  int i;
-  zookeeper_resolver *r = (zookeeper_resolver *)arg;
-
-  if (rc != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
-    return;
-  }
-
-  if (children->count == 0) {
-    gpr_log(GPR_ERROR, "Error in resolving zookeeper address %s", r->name);
-    return;
-  }
-
-  r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-  r->resolved_addrs->addrs = NULL;
-  r->resolved_addrs->naddrs = 0;
-  r->resolved_total = children->count;
-
-  /** TODO: Replace expensive heap allocation with stack
-      if we can get maximum length of zookeeper path */
-  for (i = 0; i < children->count; i++) {
-    gpr_asprintf(&path, "%s/%s", r->name, children->data[i]);
-    status = zoo_awget(r->zookeeper_handle, path, zookeeper_watcher, r,
-                       zookeeper_get_children_node_completion, r);
-    gpr_free(path);
-    if (status != 0) {
-      gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", path);
-    }
-  }
-}
-
-static void zookeeper_get_node_completion(int rc, const char *value,
-                                          int value_len,
-                                          const struct Stat *stat,
-                                          const void *arg) {
-  int status;
-  char *address = NULL;
-  zookeeper_resolver *r = (zookeeper_resolver *)arg;
-  r->resolved_addrs = NULL;
-  r->resolved_total = 0;
-  r->resolved_num = 0;
-
-  if (rc != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
-    return;
-  }
-
-  /** If zookeeper node of path r->name does not have address
-      (i.e. service node), get its children */
-  address = zookeeper_parse_address(value, (size_t)value_len);
-  if (address != NULL) {
-    r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-    r->resolved_addrs->addrs = NULL;
-    r->resolved_addrs->naddrs = 0;
-    r->resolved_total = 1;
-    /** Further resolves address by DNS */
-    grpc_resolve_address(address, NULL, zookeeper_dns_resolved, r);
-    gpr_free(address);
-    return;
-  }
-
-  status = zoo_awget_children(r->zookeeper_handle, r->name, zookeeper_watcher,
-                              r, zookeeper_get_children_completion, r);
-  if (status != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
-  }
-}
-
-static void zookeeper_resolve_address(zookeeper_resolver *r) {
-  int status;
-  status = zoo_awget(r->zookeeper_handle, r->name, zookeeper_watcher, r,
-                     zookeeper_get_node_completion, r);
-  if (status != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
-  }
-}
-
-static void zookeeper_start_resolving_locked(zookeeper_resolver *r) {
-  GRPC_RESOLVER_REF(&r->base, "zookeeper-resolving");
-  GPR_ASSERT(r->resolving == 0);
-  r->resolving = 1;
-  zookeeper_resolve_address(r);
-}
-
-static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                               zookeeper_resolver *r) {
-  if (r->next_completion != NULL &&
-      r->resolved_version != r->published_version) {
-    *r->target_config = r->resolved_config;
-    if (r->resolved_config != NULL) {
-      grpc_client_config_ref(r->resolved_config);
-    }
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
-    r->next_completion = NULL;
-    r->published_version = r->resolved_version;
-  }
-}
-
-static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
-  zookeeper_resolver *r = (zookeeper_resolver *)gr;
-  gpr_mu_destroy(&r->mu);
-  if (r->resolved_config != NULL) {
-    grpc_client_config_unref(exec_ctx, r->resolved_config);
-  }
-  grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
-  gpr_free(r->name);
-  gpr_free(r->lb_policy_name);
-  gpr_free(r);
-}
-
-static grpc_resolver *zookeeper_create(grpc_resolver_args *args,
-                                       const char *lb_policy_name) {
-  zookeeper_resolver *r;
-  size_t length;
-  char *path = args->uri->path;
-
-  if (0 == strcmp(args->uri->authority, "")) {
-    gpr_log(GPR_ERROR, "No authority specified in zookeeper uri");
-    return NULL;
-  }
-
-  /** Removes the trailing slash if exists */
-  length = strlen(path);
-  if (length > 1 && path[length - 1] == '/') {
-    path[length - 1] = 0;
-  }
-
-  r = gpr_malloc(sizeof(zookeeper_resolver));
-  memset(r, 0, sizeof(*r));
-  gpr_ref_init(&r->refs, 1);
-  gpr_mu_init(&r->mu);
-  grpc_resolver_init(&r->base, &zookeeper_resolver_vtable);
-  r->name = gpr_strdup(path);
-
-  r->subchannel_factory = args->subchannel_factory;
-  grpc_subchannel_factory_ref(r->subchannel_factory);
-
-  r->lb_policy_name = gpr_strdup(lb_policy_name);
-
-  /** Initializes zookeeper client */
-  zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
-  r->zookeeper_handle =
-      zookeeper_init(args->uri->authority, zookeeper_global_watcher,
-                     GRPC_ZOOKEEPER_SESSION_TIMEOUT, 0, 0, 0);
-  if (r->zookeeper_handle == NULL) {
-    gpr_log(GPR_ERROR, "Unable to connect to zookeeper server");
-    return NULL;
-  }
-
-  return &r->base;
-}
-
-static void zookeeper_plugin_init() {
-  grpc_register_resolver_type(grpc_zookeeper_resolver_factory_create());
-}
-
-void grpc_zookeeper_register() {
-  GRPC_API_TRACE("grpc_zookeeper_register(void)", 0, ());
-  grpc_register_plugin(zookeeper_plugin_init, NULL);
-}
-
-/*
- * FACTORY
- */
-
-static void zookeeper_factory_ref(grpc_resolver_factory *factory) {}
-
-static void zookeeper_factory_unref(grpc_resolver_factory *factory) {}
-
-static char *zookeeper_factory_get_default_hostname(
-    grpc_resolver_factory *factory, grpc_uri *uri) {
-  return NULL;
-}
-
-static grpc_resolver *zookeeper_factory_create_resolver(
-    grpc_resolver_factory *factory, grpc_resolver_args *args) {
-  return zookeeper_create(args, "pick_first");
-}
-
-static const grpc_resolver_factory_vtable zookeeper_factory_vtable = {
-    zookeeper_factory_ref, zookeeper_factory_unref,
-    zookeeper_factory_create_resolver, zookeeper_factory_get_default_hostname,
-    "zookeeper"};
-
-static grpc_resolver_factory zookeeper_resolver_factory = {
-    &zookeeper_factory_vtable};
-
-grpc_resolver_factory *grpc_zookeeper_resolver_factory_create() {
-  return &zookeeper_resolver_factory;
-}
diff --git a/src/core/client_config/resolvers/zookeeper_resolver.h b/src/core/client_config/resolvers/zookeeper_resolver.h
deleted file mode 100644
index 04bd3ca..0000000
--- a/src/core/client_config/resolvers/zookeeper_resolver.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_RESOLVERS_ZOOKEEPER_RESOLVER_H
-#define GRPC_CORE_CLIENT_CONFIG_RESOLVERS_ZOOKEEPER_RESOLVER_H
-
-#include "src/core/client_config/resolver_factory.h"
-
-/** Create a zookeeper resolver factory */
-grpc_resolver_factory *grpc_zookeeper_resolver_factory_create(void);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_RESOLVERS_ZOOKEEPER_RESOLVER_H */
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c
deleted file mode 100644
index 8f150a8..0000000
--- a/src/core/client_config/subchannel.c
+++ /dev/null
@@ -1,678 +0,0 @@
-/*
- *
- * 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/client_config/subchannel.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/avl.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/client_config/initial_connect_string.h"
-#include "src/core/client_config/subchannel_index.h"
-#include "src/core/iomgr/timer.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/backoff.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/channel_init.h"
-#include "src/core/transport/connectivity_state.h"
-
-#define INTERNAL_REF_BITS 16
-#define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
-
-#define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20
-#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
-#define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
-#define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
-#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
-
-#define GET_CONNECTED_SUBCHANNEL(subchannel, barrier)      \
-  ((grpc_connected_subchannel *)(gpr_atm_##barrier##_load( \
-      &(subchannel)->connected_subchannel)))
-
-typedef struct {
-  grpc_closure closure;
-  grpc_subchannel *subchannel;
-  grpc_connectivity_state connectivity_state;
-} state_watcher;
-
-typedef struct external_state_watcher {
-  grpc_subchannel *subchannel;
-  grpc_pollset_set *pollset_set;
-  grpc_closure *notify;
-  grpc_closure closure;
-  struct external_state_watcher *next;
-  struct external_state_watcher *prev;
-} external_state_watcher;
-
-struct grpc_subchannel {
-  grpc_connector *connector;
-
-  /** refcount
-      - lower INTERNAL_REF_BITS bits are for internal references:
-        these do not keep the subchannel open.
-      - upper remaining bits are for public references: these do
-        keep the subchannel open */
-  gpr_atm ref_pair;
-
-  /** non-transport related channel filters */
-  const grpc_channel_filter **filters;
-  size_t num_filters;
-  /** channel arguments */
-  grpc_channel_args *args;
-  /** address to connect to */
-  struct sockaddr *addr;
-  size_t addr_len;
-
-  grpc_subchannel_key *key;
-
-  /** initial string to send to peer */
-  gpr_slice initial_connect_string;
-
-  /** set during connection */
-  grpc_connect_out_args connecting_result;
-
-  /** callback for connection finishing */
-  grpc_closure connected;
-
-  /** pollset_set tracking who's interested in a connection
-      being setup */
-  grpc_pollset_set *pollset_set;
-
-  /** active connection, or null; of type grpc_connected_subchannel */
-  gpr_atm connected_subchannel;
-
-  /** mutex protecting remaining elements */
-  gpr_mu mu;
-
-  /** have we seen a disconnection? */
-  int disconnected;
-  /** are we connecting */
-  int connecting;
-  /** connectivity state tracking */
-  grpc_connectivity_state_tracker state_tracker;
-
-  external_state_watcher root_external_state_watcher;
-
-  /** next connect attempt time */
-  gpr_timespec next_attempt;
-  /** backoff state */
-  gpr_backoff backoff_state;
-  /** do we have an active alarm? */
-  int have_alarm;
-  /** our alarm */
-  grpc_timer alarm;
-  /** current random value */
-  uint32_t random;
-};
-
-struct grpc_subchannel_call {
-  grpc_connected_subchannel *connection;
-};
-
-#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
-#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)(con))
-#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
-  (((grpc_subchannel_call *)(callstack)) - 1)
-
-static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
-                                 bool iomgr_success);
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-#define REF_REASON reason
-#define REF_LOG(name, p)                                                  \
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p   ref %d -> %d %s", \
-          (name), (p), (p)->refs.count, (p)->refs.count + 1, reason)
-#define UNREF_LOG(name, p)                                                \
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p unref %d -> %d %s", \
-          (name), (p), (p)->refs.count, (p)->refs.count - 1, reason)
-#define REF_MUTATE_EXTRA_ARGS \
-  GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char *purpose
-#define REF_MUTATE_PURPOSE(x) , file, line, reason, x
-#else
-#define REF_REASON ""
-#define REF_LOG(name, p) \
-  do {                   \
-  } while (0)
-#define UNREF_LOG(name, p) \
-  do {                     \
-  } while (0)
-#define REF_MUTATE_EXTRA_ARGS
-#define REF_MUTATE_PURPOSE(x)
-#endif
-
-/*
- * connection implementation
- */
-
-static void connection_destroy(grpc_exec_ctx *exec_ctx, void *arg,
-                               bool success) {
-  grpc_connected_subchannel *c = arg;
-  grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c));
-  gpr_free(c);
-}
-
-void grpc_connected_subchannel_ref(grpc_connected_subchannel *c
-                                       GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON);
-}
-
-void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_connected_subchannel *c
-                                         GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c),
-                           REF_REASON);
-}
-
-/*
- * grpc_subchannel implementation
- */
-
-static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
-                               bool success) {
-  grpc_subchannel *c = arg;
-  gpr_free((void *)c->filters);
-  grpc_channel_args_destroy(c->args);
-  gpr_free(c->addr);
-  gpr_slice_unref(c->initial_connect_string);
-  grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
-  grpc_connector_unref(exec_ctx, c->connector);
-  grpc_pollset_set_destroy(c->pollset_set);
-  grpc_subchannel_key_destroy(exec_ctx, c->key);
-  gpr_free(c);
-}
-
-static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta,
-                          int barrier REF_MUTATE_EXTRA_ARGS) {
-  gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
-                            : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "SUBCHANNEL: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
-          old_val + delta, reason);
-#endif
-  return old_val;
-}
-
-grpc_subchannel *grpc_subchannel_ref(grpc_subchannel *c
-                                         GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  gpr_atm old_refs;
-  old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS),
-                        0 REF_MUTATE_PURPOSE("STRONG_REF"));
-  GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
-  return c;
-}
-
-grpc_subchannel *grpc_subchannel_weak_ref(grpc_subchannel *c
-                                              GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  gpr_atm old_refs;
-  old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF"));
-  GPR_ASSERT(old_refs != 0);
-  return c;
-}
-
-grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
-    grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  if (!c) return NULL;
-  for (;;) {
-    gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair);
-    if (old_refs >= (1 << INTERNAL_REF_BITS)) {
-      gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
-      if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) {
-        return c;
-      }
-    } else {
-      return NULL;
-    }
-  }
-}
-
-static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
-  grpc_connected_subchannel *con;
-  grpc_subchannel_index_unregister(exec_ctx, c->key, c);
-  gpr_mu_lock(&c->mu);
-  GPR_ASSERT(!c->disconnected);
-  c->disconnected = 1;
-  grpc_connector_shutdown(exec_ctx, c->connector);
-  con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
-  if (con != NULL) {
-    GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection");
-    gpr_atm_no_barrier_store(&c->connected_subchannel, 0xdeadbeef);
-  }
-  gpr_mu_unlock(&c->mu);
-}
-
-void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
-                           grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  gpr_atm old_refs;
-  old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS),
-                        1 REF_MUTATE_PURPOSE("STRONG_UNREF"));
-  if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
-    disconnect(exec_ctx, c);
-  }
-  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "strong-unref");
-}
-
-void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
-                                grpc_subchannel *c
-                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  gpr_atm old_refs;
-  old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
-  if (old_refs == 1) {
-    grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(subchannel_destroy, c),
-                          true, NULL);
-  }
-}
-
-static uint32_t random_seed() {
-  return (uint32_t)(gpr_time_to_millis(gpr_now(GPR_CLOCK_MONOTONIC)));
-}
-
-grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
-                                        grpc_connector *connector,
-                                        grpc_subchannel_args *args) {
-  grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
-  grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
-  if (c) {
-    grpc_subchannel_key_destroy(exec_ctx, key);
-    return c;
-  }
-
-  c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
-  c->key = key;
-  gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
-  c->connector = connector;
-  grpc_connector_ref(c->connector);
-  c->num_filters = args->filter_count;
-  if (c->num_filters > 0) {
-    c->filters = gpr_malloc(sizeof(grpc_channel_filter *) * c->num_filters);
-    memcpy((void *)c->filters, args->filters,
-           sizeof(grpc_channel_filter *) * c->num_filters);
-  } else {
-    c->filters = NULL;
-  }
-  c->addr = gpr_malloc(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,
-                                  &c->initial_connect_string);
-  c->args = grpc_channel_args_copy(args->args);
-  c->random = random_seed();
-  c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
-      &c->root_external_state_watcher;
-  grpc_closure_init(&c->connected, subchannel_connected, c);
-  grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
-                               "subchannel");
-  gpr_backoff_init(&c->backoff_state,
-                   GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
-                   GRPC_SUBCHANNEL_RECONNECT_JITTER,
-                   GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
-                   GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
-  if (c->args) {
-    for (size_t i = 0; i < c->args->num_args; i++) {
-      if (0 == strcmp(c->args->args[i].key,
-                      "grpc.testing.fixed_reconnect_backoff")) {
-        GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
-        gpr_backoff_init(&c->backoff_state, 1.0, 0.0,
-                         c->args->args[i].value.integer,
-                         c->args->args[i].value.integer);
-      }
-    }
-  }
-  gpr_mu_init(&c->mu);
-
-  return grpc_subchannel_index_register(exec_ctx, key, c);
-}
-
-static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
-  grpc_connect_in_args args;
-
-  args.interested_parties = c->pollset_set;
-  args.addr = c->addr;
-  args.addr_len = c->addr_len;
-  args.deadline = c->next_attempt;
-  args.channel_args = c->args;
-  args.initial_connect_string = c->initial_connect_string;
-
-  grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
-                              GRPC_CHANNEL_CONNECTING, "state_change");
-  grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
-                         &c->connected);
-}
-
-static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
-  c->next_attempt =
-      gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
-  continue_connect(exec_ctx, c);
-}
-
-grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c) {
-  grpc_connectivity_state state;
-  gpr_mu_lock(&c->mu);
-  state = grpc_connectivity_state_check(&c->state_tracker);
-  gpr_mu_unlock(&c->mu);
-  return state;
-}
-
-static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
-                                           bool success) {
-  external_state_watcher *w = arg;
-  grpc_closure *follow_up = w->notify;
-  if (w->pollset_set != NULL) {
-    grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set,
-                                     w->pollset_set);
-  }
-  gpr_mu_lock(&w->subchannel->mu);
-  w->next->prev = w->prev;
-  w->prev->next = w->next;
-  gpr_mu_unlock(&w->subchannel->mu);
-  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
-  gpr_free(w);
-  follow_up->cb(exec_ctx, follow_up->cb_arg, success);
-}
-
-void grpc_subchannel_notify_on_state_change(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
-    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
-    grpc_closure *notify) {
-  external_state_watcher *w;
-
-  if (state == NULL) {
-    gpr_mu_lock(&c->mu);
-    for (w = c->root_external_state_watcher.next;
-         w != &c->root_external_state_watcher; w = w->next) {
-      if (w->notify == notify) {
-        grpc_connectivity_state_notify_on_state_change(
-            exec_ctx, &c->state_tracker, NULL, &w->closure);
-      }
-    }
-    gpr_mu_unlock(&c->mu);
-  } else {
-    w = gpr_malloc(sizeof(*w));
-    w->subchannel = c;
-    w->pollset_set = interested_parties;
-    w->notify = notify;
-    grpc_closure_init(&w->closure, on_external_state_watcher_done, w);
-    if (interested_parties != NULL) {
-      grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set,
-                                       interested_parties);
-    }
-    GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
-    gpr_mu_lock(&c->mu);
-    w->next = &c->root_external_state_watcher;
-    w->prev = w->next->prev;
-    w->next->prev = w->prev->next = w;
-    if (grpc_connectivity_state_notify_on_state_change(
-            exec_ctx, &c->state_tracker, state, &w->closure)) {
-      c->connecting = 1;
-      /* released by connection */
-      GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
-      start_connect(exec_ctx, c);
-    }
-    gpr_mu_unlock(&c->mu);
-  }
-}
-
-void grpc_connected_subchannel_process_transport_op(
-    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
-    grpc_transport_op *op) {
-  grpc_channel_stack *channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
-  grpc_channel_element *top_elem = grpc_channel_stack_element(channel_stack, 0);
-  top_elem->filter->start_transport_op(exec_ctx, top_elem, op);
-}
-
-static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
-                                              bool iomgr_success) {
-  state_watcher *sw = p;
-  grpc_subchannel *c = sw->subchannel;
-  gpr_mu *mu = &c->mu;
-
-  gpr_mu_lock(mu);
-
-  /* if we failed just leave this closure */
-  if (iomgr_success) {
-    if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
-      /* any errors on a subchannel ==> we're done, create a new one */
-      sw->connectivity_state = GRPC_CHANNEL_FATAL_FAILURE;
-    }
-    grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
-                                sw->connectivity_state, "reflect_child");
-    if (sw->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
-      grpc_connected_subchannel_notify_on_state_change(
-          exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
-          &sw->connectivity_state, &sw->closure);
-      GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
-      sw = NULL;
-    }
-  }
-
-  gpr_mu_unlock(mu);
-  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "state_watcher");
-  gpr_free(sw);
-}
-
-static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx,
-                                          grpc_connected_subchannel *con,
-                                          grpc_pollset_set *interested_parties,
-                                          grpc_connectivity_state *state,
-                                          grpc_closure *closure) {
-  grpc_transport_op op;
-  grpc_channel_element *elem;
-  memset(&op, 0, sizeof(op));
-  op.connectivity_state = state;
-  op.on_connectivity_state_change = closure;
-  op.bind_pollset_set = interested_parties;
-  elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
-  elem->filter->start_transport_op(exec_ctx, elem, &op);
-}
-
-void grpc_connected_subchannel_notify_on_state_change(
-    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
-    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
-    grpc_closure *closure) {
-  connected_subchannel_state_op(exec_ctx, con, interested_parties, state,
-                                closure);
-}
-
-void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
-                                    grpc_connected_subchannel *con,
-                                    grpc_closure *closure) {
-  grpc_transport_op op;
-  grpc_channel_element *elem;
-  memset(&op, 0, sizeof(op));
-  op.send_ping = closure;
-  elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
-  elem->filter->start_transport_op(exec_ctx, elem, &op);
-}
-
-static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel *c) {
-  grpc_connected_subchannel *con;
-  grpc_channel_stack *stk;
-  state_watcher *sw_subchannel;
-
-  /* construct channel stack */
-  con = grpc_channel_init_create_stack(
-      exec_ctx, GRPC_CLIENT_SUBCHANNEL, 0, c->connecting_result.channel_args, 1,
-      connection_destroy, NULL, c->connecting_result.transport);
-  stk = CHANNEL_STACK_FROM_CONNECTION(con);
-  memset(&c->connecting_result, 0, sizeof(c->connecting_result));
-
-  /* initialize state watcher */
-  sw_subchannel = gpr_malloc(sizeof(*sw_subchannel));
-  sw_subchannel->subchannel = c;
-  sw_subchannel->connectivity_state = GRPC_CHANNEL_READY;
-  grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
-                    sw_subchannel);
-
-  if (c->disconnected) {
-    gpr_free(sw_subchannel);
-    grpc_channel_stack_destroy(exec_ctx, stk);
-    gpr_free(con);
-    GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
-    return;
-  }
-
-  /* publish */
-  /* TODO(ctiller): this full barrier seems to clear up a TSAN failure.
-                    I'd have expected the rel_cas below to be enough, but
-                    seemingly it's not.
-                    Re-evaluate if we really need this. */
-  gpr_atm_full_barrier();
-  GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
-  c->connecting = 0;
-
-  /* setup subchannel watching connected subchannel for changes; subchannel ref
-     for connecting is donated
-     to the state watcher */
-  GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
-  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
-  grpc_connected_subchannel_notify_on_state_change(
-      exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state,
-      &sw_subchannel->closure);
-
-  /* signal completion */
-  grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
-                              "connected");
-}
-
-static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
-  grpc_subchannel *c = arg;
-  gpr_mu_lock(&c->mu);
-  c->have_alarm = 0;
-  if (c->disconnected) {
-    iomgr_success = 0;
-  }
-  if (iomgr_success) {
-    c->next_attempt =
-        gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
-    continue_connect(exec_ctx, c);
-    gpr_mu_unlock(&c->mu);
-  } else {
-    gpr_mu_unlock(&c->mu);
-    GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
-  }
-}
-
-static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
-                                 bool iomgr_success) {
-  grpc_subchannel *c = arg;
-
-  GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
-  gpr_mu_lock(&c->mu);
-  if (c->connecting_result.transport != NULL) {
-    publish_transport_locked(exec_ctx, c);
-  } else if (c->disconnected) {
-    GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
-  } else {
-    gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
-    GPR_ASSERT(!c->have_alarm);
-    c->have_alarm = 1;
-    grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
-                                GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                "connect_failed");
-    grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
-  }
-  gpr_mu_unlock(&c->mu);
-  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
-}
-
-/*
- * grpc_subchannel_call implementation
- */
-
-static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
-                                    bool success) {
-  grpc_subchannel_call *c = call;
-  GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
-  grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c));
-  GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, c->connection, "subchannel_call");
-  gpr_free(c);
-  GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
-}
-
-void grpc_subchannel_call_ref(grpc_subchannel_call *c
-                                  GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
-}
-
-void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
-                                grpc_subchannel_call *c
-                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
-  GRPC_CALL_STACK_UNREF(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
-}
-
-char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
-                                    grpc_subchannel_call *call) {
-  grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
-  grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
-  return top_elem->filter->get_peer(exec_ctx, top_elem);
-}
-
-void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_call *call,
-                                     grpc_transport_stream_op *op) {
-  grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
-  grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
-  top_elem->filter->start_transport_stream_op(exec_ctx, top_elem, op);
-}
-
-grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
-    grpc_subchannel *c) {
-  return GET_CONNECTED_SUBCHANNEL(c, acq);
-}
-
-grpc_subchannel_call *grpc_connected_subchannel_create_call(
-    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
-    grpc_pollset *pollset) {
-  grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
-  grpc_subchannel_call *call =
-      gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
-  grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
-  call->connection = con;
-  GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
-  grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call,
-                       NULL, NULL, callstk);
-  grpc_call_stack_set_pollset(exec_ctx, callstk, pollset);
-  return call;
-}
-
-grpc_call_stack *grpc_subchannel_call_get_call_stack(
-    grpc_subchannel_call *subchannel_call) {
-  return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
-}
diff --git a/src/core/client_config/subchannel.h b/src/core/client_config/subchannel.h
deleted file mode 100644
index ef9f2f1..0000000
--- a/src/core/client_config/subchannel.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_H
-#define GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_H
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/client_config/connector.h"
-#include "src/core/transport/connectivity_state.h"
-
-/** A (sub-)channel that knows how to connect to exactly one target
-    address. Provides a target for load balancing. */
-typedef struct grpc_subchannel grpc_subchannel;
-typedef struct grpc_connected_subchannel grpc_connected_subchannel;
-typedef struct grpc_subchannel_call grpc_subchannel_call;
-typedef struct grpc_subchannel_args grpc_subchannel_args;
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-#define GRPC_SUBCHANNEL_REF(p, r) \
-  grpc_subchannel_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
-  grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_SUBCHANNEL_UNREF(cl, p, r) \
-  grpc_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
-#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \
-  grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \
-  grpc_subchannel_weak_unref((cl), (p), __FILE__, __LINE__, (r))
-#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) \
-  grpc_connected_subchannel_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \
-  grpc_connected_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
-#define GRPC_SUBCHANNEL_CALL_REF(p, r) \
-  grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
-  grpc_subchannel_call_unref((cl), (p), __FILE__, __LINE__, (r))
-#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \
-  , const char *file, int line, const char *reason
-#else
-#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p))
-#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
-  grpc_subchannel_ref_from_weak_ref((p))
-#define GRPC_SUBCHANNEL_UNREF(cl, p, r) grpc_subchannel_unref((cl), (p))
-#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p))
-#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \
-  grpc_subchannel_weak_unref((cl), (p))
-#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) grpc_connected_subchannel_ref((p))
-#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \
-  grpc_connected_subchannel_unref((cl), (p))
-#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p))
-#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
-  grpc_subchannel_call_unref((cl), (p))
-#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS
-#endif
-
-grpc_subchannel *grpc_subchannel_ref(grpc_subchannel *channel
-                                         GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
-    grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
-                           grpc_subchannel *channel
-                               GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-grpc_subchannel *grpc_subchannel_weak_ref(grpc_subchannel *channel
-                                              GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
-                                grpc_subchannel *channel
-                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-void grpc_connected_subchannel_ref(grpc_connected_subchannel *channel
-                                       GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_connected_subchannel *channel
-                                         GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-void grpc_subchannel_call_ref(grpc_subchannel_call *call
-                                  GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
-                                grpc_subchannel_call *call
-                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
-
-/** construct a subchannel call */
-grpc_subchannel_call *grpc_connected_subchannel_create_call(
-    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
-    grpc_pollset *pollset);
-
-/** process a transport level op */
-void grpc_connected_subchannel_process_transport_op(
-    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *subchannel,
-    grpc_transport_op *op);
-
-/** poll the current connectivity state of a channel */
-grpc_connectivity_state grpc_subchannel_check_connectivity(
-    grpc_subchannel *channel);
-
-/** call notify when the connectivity state of a channel changes from *state.
-    Updates *state with the new state of the channel */
-void grpc_subchannel_notify_on_state_change(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel *channel,
-    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
-    grpc_closure *notify);
-void grpc_connected_subchannel_notify_on_state_change(
-    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *channel,
-    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
-    grpc_closure *notify);
-void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
-                                    grpc_connected_subchannel *channel,
-                                    grpc_closure *notify);
-
-/** retrieve the grpc_connected_subchannel - or NULL if called before
-    the subchannel becomes connected */
-grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
-    grpc_subchannel *subchannel);
-
-/** continue processing a transport op */
-void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_call *subchannel_call,
-                                     grpc_transport_stream_op *op);
-
-/** continue querying for peer */
-char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
-                                    grpc_subchannel_call *subchannel_call);
-
-grpc_call_stack *grpc_subchannel_call_get_call_stack(
-    grpc_subchannel_call *subchannel_call);
-
-struct grpc_subchannel_args {
-  /* When updating this struct, also update subchannel_index.c */
-
-  /** Channel filters for this channel - wrapped factories will likely
-      want to mutate this */
-  const grpc_channel_filter **filters;
-  /** The number of filters in the above array */
-  size_t filter_count;
-  /** Channel arguments to be supplied to the newly created channel */
-  const grpc_channel_args *args;
-  /** Address to connect to */
-  struct sockaddr *addr;
-  size_t addr_len;
-};
-
-/** create a subchannel given a connector */
-grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
-                                        grpc_connector *connector,
-                                        grpc_subchannel_args *args);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_H */
diff --git a/src/core/client_config/subchannel_factory.c b/src/core/client_config/subchannel_factory.c
deleted file mode 100644
index 2c64219..0000000
--- a/src/core/client_config/subchannel_factory.c
+++ /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.
- *
- */
-
-#include "src/core/client_config/subchannel_factory.h"
-
-void grpc_subchannel_factory_ref(grpc_subchannel_factory* factory) {
-  factory->vtable->ref(factory);
-}
-
-void grpc_subchannel_factory_unref(grpc_exec_ctx* exec_ctx,
-                                   grpc_subchannel_factory* factory) {
-  factory->vtable->unref(exec_ctx, factory);
-}
-
-grpc_subchannel* grpc_subchannel_factory_create_subchannel(
-    grpc_exec_ctx* exec_ctx, grpc_subchannel_factory* factory,
-    grpc_subchannel_args* args) {
-  return factory->vtable->create_subchannel(exec_ctx, factory, args);
-}
diff --git a/src/core/client_config/subchannel_factory.h b/src/core/client_config/subchannel_factory.h
deleted file mode 100644
index c638f37..0000000
--- a/src/core/client_config/subchannel_factory.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H
-#define GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/client_config/subchannel.h"
-
-typedef struct grpc_subchannel_factory grpc_subchannel_factory;
-typedef struct grpc_subchannel_factory_vtable grpc_subchannel_factory_vtable;
-
-/** Constructor for new configured channels.
-    Creating decorators around this type is encouraged to adapt behavior. */
-struct grpc_subchannel_factory {
-  const grpc_subchannel_factory_vtable *vtable;
-};
-
-struct grpc_subchannel_factory_vtable {
-  void (*ref)(grpc_subchannel_factory *factory);
-  void (*unref)(grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory);
-  grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
-                                        grpc_subchannel_factory *factory,
-                                        grpc_subchannel_args *args);
-};
-
-void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory);
-void grpc_subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                   grpc_subchannel_factory *factory);
-
-/** Create a new grpc_subchannel */
-grpc_subchannel *grpc_subchannel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
-    grpc_subchannel_args *args);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H */
diff --git a/src/core/client_config/subchannel_index.c b/src/core/client_config/subchannel_index.c
deleted file mode 100644
index 24cc76c..0000000
--- a/src/core/client_config/subchannel_index.c
+++ /dev/null
@@ -1,262 +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 "src/core/client_config/subchannel_index.h"
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/avl.h>
-#include <grpc/support/tls.h>
-
-#include "src/core/channel/channel_args.h"
-
-// a map of subchannel_key --> subchannel, used for detecting connections
-// to the same destination in order to share them
-static gpr_avl g_subchannel_index;
-
-static gpr_mu g_mu;
-
-struct grpc_subchannel_key {
-  grpc_connector *connector;
-  grpc_subchannel_args args;
-};
-
-GPR_TLS_DECL(subchannel_index_exec_ctx);
-
-static void enter_ctx(grpc_exec_ctx *exec_ctx) {
-  GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == 0);
-  gpr_tls_set(&subchannel_index_exec_ctx, (intptr_t)exec_ctx);
-}
-
-static void leave_ctx(grpc_exec_ctx *exec_ctx) {
-  GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == (intptr_t)exec_ctx);
-  gpr_tls_set(&subchannel_index_exec_ctx, 0);
-}
-
-static grpc_exec_ctx *current_ctx() {
-  grpc_exec_ctx *c = (grpc_exec_ctx *)gpr_tls_get(&subchannel_index_exec_ctx);
-  GPR_ASSERT(c != NULL);
-  return c;
-}
-
-static grpc_subchannel_key *create_key(
-    grpc_connector *connector, grpc_subchannel_args *args,
-    grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) {
-  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);
-  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);
-  k->args.args = copy_channel_args(args->args);
-  return k;
-}
-
-grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector,
-                                                grpc_subchannel_args *args) {
-  return create_key(connector, args, grpc_channel_args_normalize);
-}
-
-static grpc_subchannel_key *subchannel_key_copy(grpc_subchannel_key *k) {
-  return create_key(k->connector, &k->args, grpc_channel_args_copy);
-}
-
-static int subchannel_key_compare(grpc_subchannel_key *a,
-                                  grpc_subchannel_key *b) {
-  int c = GPR_ICMP(a->connector, b->connector);
-  if (c != 0) return c;
-  c = GPR_ICMP(a->args.addr_len, b->args.addr_len);
-  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;
-  return grpc_channel_args_compare(a->args.args, b->args.args);
-}
-
-void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
-                                 grpc_subchannel_key *k) {
-  grpc_connector_unref(exec_ctx, k->connector);
-  gpr_free(k->args.addr);
-  gpr_free((grpc_channel_args *)k->args.filters);
-  grpc_channel_args_destroy((grpc_channel_args *)k->args.args);
-  gpr_free(k);
-}
-
-static void sck_avl_destroy(void *p) {
-  grpc_subchannel_key_destroy(current_ctx(), p);
-}
-
-static void *sck_avl_copy(void *p) { return subchannel_key_copy(p); }
-
-static long sck_avl_compare(void *a, void *b) {
-  return subchannel_key_compare(a, b);
-}
-
-static void scv_avl_destroy(void *p) {
-  GRPC_SUBCHANNEL_WEAK_UNREF(current_ctx(), p, "subchannel_index");
-}
-
-static void *scv_avl_copy(void *p) {
-  GRPC_SUBCHANNEL_WEAK_REF(p, "subchannel_index");
-  return p;
-}
-
-static const gpr_avl_vtable subchannel_avl_vtable = {
-    .destroy_key = sck_avl_destroy,
-    .copy_key = sck_avl_copy,
-    .compare_keys = sck_avl_compare,
-    .destroy_value = scv_avl_destroy,
-    .copy_value = scv_avl_copy};
-
-void grpc_subchannel_index_init(void) {
-  g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable);
-  gpr_mu_init(&g_mu);
-  gpr_tls_init(&subchannel_index_exec_ctx);
-}
-
-void grpc_subchannel_index_shutdown(void) {
-  gpr_mu_destroy(&g_mu);
-  gpr_avl_unref(g_subchannel_index);
-  gpr_tls_destroy(&subchannel_index_exec_ctx);
-}
-
-grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
-                                            grpc_subchannel_key *key) {
-  enter_ctx(exec_ctx);
-
-  // Lock, and take a reference to the subchannel index.
-  // We don't need to do the search under a lock as avl's are immutable.
-  gpr_mu_lock(&g_mu);
-  gpr_avl index = gpr_avl_ref(g_subchannel_index);
-  gpr_mu_unlock(&g_mu);
-
-  grpc_subchannel *c =
-      GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(gpr_avl_get(index, key), "index_find");
-  gpr_avl_unref(index);
-
-  leave_ctx(exec_ctx);
-  return c;
-}
-
-grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
-                                                grpc_subchannel_key *key,
-                                                grpc_subchannel *constructed) {
-  enter_ctx(exec_ctx);
-
-  grpc_subchannel *c = NULL;
-
-  while (c == NULL) {
-    // Compare and swap loop:
-    // - take a reference to the current index
-    gpr_mu_lock(&g_mu);
-    gpr_avl index = gpr_avl_ref(g_subchannel_index);
-    gpr_mu_unlock(&g_mu);
-
-    // - Check to see if a subchannel already exists
-    c = gpr_avl_get(index, key);
-    if (c != NULL) {
-      // yes -> we're done
-      GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register");
-    } else {
-      // no -> update the avl and compare/swap
-      gpr_avl updated =
-          gpr_avl_add(gpr_avl_ref(index), subchannel_key_copy(key),
-                      GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"));
-
-      // it may happen (but it's expected to be unlikely)
-      // that some other thread has changed the index:
-      // compare/swap here to check that, and retry as necessary
-      gpr_mu_lock(&g_mu);
-      if (index.root == g_subchannel_index.root) {
-        GPR_SWAP(gpr_avl, updated, g_subchannel_index);
-        c = constructed;
-      }
-      gpr_mu_unlock(&g_mu);
-
-      gpr_avl_unref(updated);
-    }
-    gpr_avl_unref(index);
-  }
-
-  leave_ctx(exec_ctx);
-
-  return c;
-}
-
-void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx,
-                                      grpc_subchannel_key *key,
-                                      grpc_subchannel *constructed) {
-  enter_ctx(exec_ctx);
-
-  bool done = false;
-  while (!done) {
-    // Compare and swap loop:
-    // - take a reference to the current index
-    gpr_mu_lock(&g_mu);
-    gpr_avl index = gpr_avl_ref(g_subchannel_index);
-    gpr_mu_unlock(&g_mu);
-
-    // Check to see if this key still refers to the previously
-    // registered subchannel
-    grpc_subchannel *c = gpr_avl_get(index, key);
-    if (c != constructed) {
-      gpr_avl_unref(index);
-      break;
-    }
-
-    // compare and swap the update (some other thread may have
-    // mutated the index behind us)
-    gpr_avl updated = gpr_avl_remove(gpr_avl_ref(index), key);
-
-    gpr_mu_lock(&g_mu);
-    if (index.root == g_subchannel_index.root) {
-      GPR_SWAP(gpr_avl, updated, g_subchannel_index);
-      done = true;
-    }
-    gpr_mu_unlock(&g_mu);
-
-    gpr_avl_unref(updated);
-    gpr_avl_unref(index);
-  }
-
-  leave_ctx(exec_ctx);
-}
diff --git a/src/core/client_config/subchannel_index.h b/src/core/client_config/subchannel_index.h
deleted file mode 100644
index 3cd5d12..0000000
--- a/src/core/client_config/subchannel_index.h
+++ /dev/null
@@ -1,77 +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_CORE_CLIENT_CONFIG_SUBCHANNEL_INDEX_H
-#define GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_INDEX_H
-
-#include "src/core/client_config/connector.h"
-#include "src/core/client_config/subchannel.h"
-
-/** \file Provides an index of active subchannels so that they can be
-    shared amongst channels */
-
-typedef struct grpc_subchannel_key grpc_subchannel_key;
-
-/** Create a key that can be used to uniquely identify a subchannel */
-grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *con,
-                                                grpc_subchannel_args *args);
-
-/** Destroy a subchannel key */
-void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
-                                 grpc_subchannel_key *key);
-
-/** Given a subchannel key, find the subchannel registered for it.
-    Returns NULL if no such channel exists.
-    Thread-safe. */
-grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
-                                            grpc_subchannel_key *key);
-
-/** Register a subchannel against a key.
-    Takes ownership of \a constructed.
-    Returns the registered subchannel. This may be different from
-    \a constructed in the case of a registration race. */
-grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
-                                                grpc_subchannel_key *key,
-                                                grpc_subchannel *constructed);
-
-/** Remove \a constructed as the registered subchannel for \a key. */
-void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx,
-                                      grpc_subchannel_key *key,
-                                      grpc_subchannel *constructed);
-
-/** Initialize the subchannel index (global) */
-void grpc_subchannel_index_init(void);
-/** Shutdown the subchannel index (global) */
-void grpc_subchannel_index_shutdown(void);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_SUBCHANNEL_INDEX_H */
diff --git a/src/core/client_config/uri_parser.c b/src/core/client_config/uri_parser.c
deleted file mode 100644
index cbdfffc..0000000
--- a/src/core/client_config/uri_parser.c
+++ /dev/null
@@ -1,242 +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/client_config/uri_parser.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/string_util.h>
-
-/** a size_t default value... maps to all 1's */
-#define NOT_SET (~(size_t)0)
-
-static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section,
-                         int suppress_errors) {
-  char *line_prefix;
-  size_t pfx_len;
-
-  if (!suppress_errors) {
-    gpr_asprintf(&line_prefix, "bad uri.%s: '", section);
-    pfx_len = strlen(line_prefix) + pos;
-    gpr_log(GPR_ERROR, "%s%s'", line_prefix, uri_text);
-    gpr_free(line_prefix);
-
-    line_prefix = gpr_malloc(pfx_len + 1);
-    memset(line_prefix, ' ', pfx_len);
-    line_prefix[pfx_len] = 0;
-    gpr_log(GPR_ERROR, "%s^ here", line_prefix);
-    gpr_free(line_prefix);
-  }
-
-  return NULL;
-}
-
-/** Returns a copy of \a src[begin, end) */
-static char *copy_component(const char *src, size_t begin, size_t end) {
-  char *out = gpr_malloc(end - begin + 1);
-  memcpy(out, src + begin, end - begin);
-  out[end - begin] = 0;
-  return out;
-}
-
-/** Returns how many chars to advance if \a uri_text[i] begins a valid \a pchar
- * production. If \a uri_text[i] introduces an invalid \a pchar (such as percent
- * sign not followed by two hex digits), NOT_SET is returned. */
-static size_t parse_pchar(const char *uri_text, size_t i) {
-  /* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
-   * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
-   * pct-encoded = "%" HEXDIG HEXDIG
-   * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
-   / "*" / "+" / "," / ";" / "=" */
-  char c = uri_text[i];
-  if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||
-      ((c >= '0') && (c <= '9')) ||
-      (c == '-' || c == '.' || c == '_' || c == '~') || /* unreserved */
-      (c == '!' || c == '$' || c == '&' || c == '\'' || c == '$' || c == '&' ||
-       c == '(' || c == ')' || c == '*' || c == '+' || c == ',' || c == ';' ||
-       c == '=') /* sub-delims */) {
-    return 1;
-  }
-  if (c == '%') { /* pct-encoded */
-    size_t j;
-    if (uri_text[i + 1] == 0 || uri_text[i + 2] == 0) {
-      return NOT_SET;
-    }
-    for (j = i + 1; j < 2; j++) {
-      c = uri_text[j];
-      if (!(((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) ||
-            ((c >= 'A') && (c <= 'F')))) {
-        return NOT_SET;
-      }
-    }
-    return 2;
-  }
-  return 0;
-}
-
-/* *( pchar / "?" / "/" ) */
-static int parse_fragment_or_query(const char *uri_text, size_t *i) {
-  char c;
-  while ((c = uri_text[*i]) != 0) {
-    const size_t advance = parse_pchar(uri_text, *i); /* pchar */
-    switch (advance) {
-      case 0: /* uri_text[i] isn't in pchar */
-        /* maybe it's ? or / */
-        if (uri_text[*i] == '?' || uri_text[*i] == '/') {
-          (*i)++;
-          break;
-        } else {
-          return 1;
-        }
-        GPR_UNREACHABLE_CODE(return 0);
-      default:
-        (*i) += advance;
-        break;
-      case NOT_SET: /* uri_text[i] introduces an invalid URI */
-        return 0;
-    }
-  }
-  /* *i is the first uri_text position past the \a query production, maybe \0 */
-  return 1;
-}
-
-grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
-  grpc_uri *uri;
-  size_t scheme_begin = 0;
-  size_t scheme_end = NOT_SET;
-  size_t authority_begin = NOT_SET;
-  size_t authority_end = NOT_SET;
-  size_t path_begin = NOT_SET;
-  size_t path_end = NOT_SET;
-  size_t query_begin = NOT_SET;
-  size_t query_end = NOT_SET;
-  size_t fragment_begin = NOT_SET;
-  size_t fragment_end = NOT_SET;
-  size_t i;
-
-  for (i = scheme_begin; uri_text[i] != 0; i++) {
-    if (uri_text[i] == ':') {
-      scheme_end = i;
-      break;
-    }
-    if (uri_text[i] >= 'a' && uri_text[i] <= 'z') continue;
-    if (uri_text[i] >= 'A' && uri_text[i] <= 'Z') continue;
-    if (i != scheme_begin) {
-      if (uri_text[i] >= '0' && uri_text[i] <= '9') continue;
-      if (uri_text[i] == '+') continue;
-      if (uri_text[i] == '-') continue;
-      if (uri_text[i] == '.') continue;
-    }
-    break;
-  }
-  if (scheme_end == NOT_SET) {
-    return bad_uri(uri_text, i, "scheme", suppress_errors);
-  }
-
-  if (uri_text[scheme_end + 1] == '/' && uri_text[scheme_end + 2] == '/') {
-    authority_begin = scheme_end + 3;
-    for (i = authority_begin; uri_text[i] != 0 && authority_end == NOT_SET;
-         i++) {
-      if (uri_text[i] == '/' || uri_text[i] == '?' || uri_text[i] == '#') {
-        authority_end = i;
-      }
-    }
-    if (authority_end == NOT_SET && uri_text[i] == 0) {
-      authority_end = i;
-    }
-    if (authority_end == NOT_SET) {
-      return bad_uri(uri_text, i, "authority", suppress_errors);
-    }
-    /* TODO(ctiller): parse the authority correctly */
-    path_begin = authority_end;
-  } else {
-    path_begin = scheme_end + 1;
-  }
-
-  for (i = path_begin; uri_text[i] != 0; i++) {
-    if (uri_text[i] == '?' || uri_text[i] == '#') {
-      path_end = i;
-      break;
-    }
-  }
-  if (path_end == NOT_SET && uri_text[i] == 0) {
-    path_end = i;
-  }
-  if (path_end == NOT_SET) {
-    return bad_uri(uri_text, i, "path", suppress_errors);
-  }
-
-  if (uri_text[i] == '?') {
-    query_begin = ++i;
-    if (!parse_fragment_or_query(uri_text, &i)) {
-      return bad_uri(uri_text, i, "query", suppress_errors);
-    } else if (uri_text[i] != 0 && uri_text[i] != '#') {
-      /* We must be at the end or at the beginning of a fragment */
-      return bad_uri(uri_text, i, "query", suppress_errors);
-    }
-    query_end = i;
-  }
-  if (uri_text[i] == '#') {
-    fragment_begin = ++i;
-    if (!parse_fragment_or_query(uri_text, &i)) {
-      return bad_uri(uri_text, i - fragment_end, "fragment", suppress_errors);
-    } else if (uri_text[i] != 0) {
-      /* We must be at the end */
-      return bad_uri(uri_text, i, "fragment", suppress_errors);
-    }
-    fragment_end = i;
-  }
-
-  uri = gpr_malloc(sizeof(*uri));
-  memset(uri, 0, sizeof(*uri));
-  uri->scheme = copy_component(uri_text, scheme_begin, scheme_end);
-  uri->authority = copy_component(uri_text, authority_begin, authority_end);
-  uri->path = copy_component(uri_text, path_begin, path_end);
-  uri->query = copy_component(uri_text, query_begin, query_end);
-  uri->fragment = copy_component(uri_text, fragment_begin, fragment_end);
-
-  return uri;
-}
-
-void grpc_uri_destroy(grpc_uri *uri) {
-  if (!uri) return;
-  gpr_free(uri->scheme);
-  gpr_free(uri->authority);
-  gpr_free(uri->path);
-  gpr_free(uri->query);
-  gpr_free(uri->fragment);
-  gpr_free(uri);
-}
diff --git a/src/core/client_config/uri_parser.h b/src/core/client_config/uri_parser.h
deleted file mode 100644
index af013d8..0000000
--- a/src/core/client_config/uri_parser.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_CLIENT_CONFIG_URI_PARSER_H
-#define GRPC_CORE_CLIENT_CONFIG_URI_PARSER_H
-
-typedef struct {
-  char *scheme;
-  char *authority;
-  char *path;
-  char *query;
-  char *fragment;
-} grpc_uri;
-
-/** parse a uri, return NULL on failure */
-grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors);
-
-/** destroy a uri */
-void grpc_uri_destroy(grpc_uri *uri);
-
-#endif /* GRPC_CORE_CLIENT_CONFIG_URI_PARSER_H */
diff --git a/src/core/compression/algorithm_metadata.h b/src/core/compression/algorithm_metadata.h
deleted file mode 100644
index 34abf1d..0000000
--- a/src/core/compression/algorithm_metadata.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_COMPRESSION_ALGORITHM_METADATA_H
-#define GRPC_CORE_COMPRESSION_ALGORITHM_METADATA_H
-
-#include <grpc/compression.h>
-#include "src/core/transport/metadata.h"
-
-/** Return compression algorithm based metadata value */
-grpc_mdstr *grpc_compression_algorithm_mdstr(
-    grpc_compression_algorithm algorithm);
-
-/** Return compression algorithm based metadata element (grpc-encoding: xxx) */
-grpc_mdelem *grpc_compression_encoding_mdelem(
-    grpc_compression_algorithm algorithm);
-
-/** Find compression algorithm based on passed in mdstr - returns
- * GRPC_COMPRESS_ALGORITHM_COUNT on failure */
-grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
-    grpc_mdstr *str);
-
-#endif /* GRPC_CORE_COMPRESSION_ALGORITHM_METADATA_H */
diff --git a/src/core/compression/compression_algorithm.c b/src/core/compression/compression_algorithm.c
deleted file mode 100644
index 2810a38..0000000
--- a/src/core/compression/compression_algorithm.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *
- * 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 <stdlib.h>
-#include <string.h>
-
-#include <grpc/compression.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/compression/algorithm_metadata.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/transport/static_metadata.h"
-
-int grpc_compression_algorithm_parse(const char *name, size_t name_length,
-                                     grpc_compression_algorithm *algorithm) {
-  /* we use strncmp not only because it's safer (even though in this case it
-   * doesn't matter, given that we are comparing against string literals, but
-   * because this way we needn't have "name" nil-terminated (useful for slice
-   * data, for example) */
-  GRPC_API_TRACE(
-      "grpc_compression_algorithm_parse("
-      "name=%*.*s, name_length=%lu, algorithm=%p)",
-      5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
-          algorithm));
-  if (name_length == 0) {
-    return 0;
-  }
-  if (strncmp(name, "identity", name_length) == 0) {
-    *algorithm = GRPC_COMPRESS_NONE;
-  } else if (strncmp(name, "gzip", name_length) == 0) {
-    *algorithm = GRPC_COMPRESS_GZIP;
-  } else if (strncmp(name, "deflate", name_length) == 0) {
-    *algorithm = GRPC_COMPRESS_DEFLATE;
-  } else {
-    return 0;
-  }
-  return 1;
-}
-
-int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
-                                    char **name) {
-  GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
-                 ((int)algorithm, name));
-  switch (algorithm) {
-    case GRPC_COMPRESS_NONE:
-      *name = "identity";
-      return 1;
-    case GRPC_COMPRESS_DEFLATE:
-      *name = "deflate";
-      return 1;
-    case GRPC_COMPRESS_GZIP:
-      *name = "gzip";
-      return 1;
-    case GRPC_COMPRESS_ALGORITHMS_COUNT:
-      return 0;
-  }
-  return 0;
-}
-
-grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
-    grpc_mdstr *str) {
-  if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
-  if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
-  if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
-  return GRPC_COMPRESS_ALGORITHMS_COUNT;
-}
-
-grpc_mdstr *grpc_compression_algorithm_mdstr(
-    grpc_compression_algorithm algorithm) {
-  switch (algorithm) {
-    case GRPC_COMPRESS_NONE:
-      return GRPC_MDSTR_IDENTITY;
-    case GRPC_COMPRESS_DEFLATE:
-      return GRPC_MDSTR_DEFLATE;
-    case GRPC_COMPRESS_GZIP:
-      return GRPC_MDSTR_GZIP;
-    case GRPC_COMPRESS_ALGORITHMS_COUNT:
-      return NULL;
-  }
-  return NULL;
-}
-
-grpc_mdelem *grpc_compression_encoding_mdelem(
-    grpc_compression_algorithm algorithm) {
-  switch (algorithm) {
-    case GRPC_COMPRESS_NONE:
-      return GRPC_MDELEM_GRPC_ENCODING_IDENTITY;
-    case GRPC_COMPRESS_DEFLATE:
-      return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
-    case GRPC_COMPRESS_GZIP:
-      return GRPC_MDELEM_GRPC_ENCODING_GZIP;
-    default:
-      break;
-  }
-  return NULL;
-}
-
-/* TODO(dgq): Add the ability to specify parameters to the individual
- * compression algorithms */
-grpc_compression_algorithm grpc_compression_algorithm_for_level(
-    grpc_compression_level level, uint32_t accepted_encodings) {
-  GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1,
-                 ((int)level));
-  if (level > GRPC_COMPRESS_LEVEL_HIGH) {
-    gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
-    abort();
-  }
-
-  const size_t num_supported =
-      GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */
-  if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) {
-    return GRPC_COMPRESS_NONE;
-  }
-
-  GPR_ASSERT(level > 0);
-
-  /* Establish a "ranking" or compression algorithms in increasing order of
-   * compression.
-   * This is simplistic and we will probably want to introduce other dimensions
-   * in the future (cpu/memory cost, etc). */
-  const grpc_compression_algorithm algos_ranking[] = {GRPC_COMPRESS_GZIP,
-                                                      GRPC_COMPRESS_DEFLATE};
-
-  /* intersect algos_ranking with the supported ones keeping the ranked order */
-  grpc_compression_algorithm
-      sorted_supported_algos[GRPC_COMPRESS_ALGORITHMS_COUNT];
-  size_t algos_supported_idx = 0;
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) {
-    const grpc_compression_algorithm alg = algos_ranking[i];
-    for (size_t j = 0; j < num_supported; j++) {
-      if (GPR_BITGET(accepted_encodings, alg) == 1) {
-        /* if \a alg in supported */
-        sorted_supported_algos[algos_supported_idx++] = alg;
-        break;
-      }
-    }
-    if (algos_supported_idx == num_supported) break;
-  }
-
-  switch (level) {
-    case GRPC_COMPRESS_LEVEL_NONE:
-      abort(); /* should have been handled already */
-    case GRPC_COMPRESS_LEVEL_LOW:
-      return sorted_supported_algos[0];
-    case GRPC_COMPRESS_LEVEL_MED:
-      return sorted_supported_algos[num_supported / 2];
-    case GRPC_COMPRESS_LEVEL_HIGH:
-      return sorted_supported_algos[num_supported - 1];
-    default:
-      abort();
-  };
-}
-
-void grpc_compression_options_init(grpc_compression_options *opts) {
-  opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
-  opts->default_compression_algorithm = GRPC_COMPRESS_NONE;
-}
-
-void grpc_compression_options_enable_algorithm(
-    grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
-  GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm);
-}
-
-void grpc_compression_options_disable_algorithm(
-    grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
-  GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm);
-}
-
-int grpc_compression_options_is_algorithm_enabled(
-    const grpc_compression_options *opts,
-    grpc_compression_algorithm algorithm) {
-  return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
-}
diff --git a/src/core/compression/message_compress.c b/src/core/compression/message_compress.c
deleted file mode 100644
index edc21a9..0000000
--- a/src/core/compression/message_compress.c
+++ /dev/null
@@ -1,198 +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/compression/message_compress.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include <zlib.h>
-
-#define OUTPUT_BLOCK_SIZE 1024
-
-static int zlib_body(z_stream* zs, gpr_slice_buffer* input,
-                     gpr_slice_buffer* output,
-                     int (*flate)(z_stream* zs, int flush)) {
-  int r;
-  int flush;
-  size_t i;
-  gpr_slice outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE);
-  const uInt uint_max = ~(uInt)0;
-
-  GPR_ASSERT(GPR_SLICE_LENGTH(outbuf) <= uint_max);
-  zs->avail_out = (uInt)GPR_SLICE_LENGTH(outbuf);
-  zs->next_out = GPR_SLICE_START_PTR(outbuf);
-  flush = Z_NO_FLUSH;
-  for (i = 0; i < input->count; i++) {
-    if (i == input->count - 1) flush = Z_FINISH;
-    GPR_ASSERT(GPR_SLICE_LENGTH(input->slices[i]) <= uint_max);
-    zs->avail_in = (uInt)GPR_SLICE_LENGTH(input->slices[i]);
-    zs->next_in = GPR_SLICE_START_PTR(input->slices[i]);
-    do {
-      if (zs->avail_out == 0) {
-        gpr_slice_buffer_add_indexed(output, outbuf);
-        outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE);
-        GPR_ASSERT(GPR_SLICE_LENGTH(outbuf) <= uint_max);
-        zs->avail_out = (uInt)GPR_SLICE_LENGTH(outbuf);
-        zs->next_out = GPR_SLICE_START_PTR(outbuf);
-      }
-      r = flate(zs, flush);
-      if (r < 0 && r != Z_BUF_ERROR /* not fatal */) {
-        gpr_log(GPR_INFO, "zlib error (%d)", r);
-        goto error;
-      }
-    } while (zs->avail_out == 0);
-    if (zs->avail_in) {
-      gpr_log(GPR_INFO, "zlib: not all input consumed");
-      goto error;
-    }
-  }
-
-  GPR_ASSERT(outbuf.refcount);
-  outbuf.data.refcounted.length -= zs->avail_out;
-  gpr_slice_buffer_add_indexed(output, outbuf);
-
-  return 1;
-
-error:
-  gpr_slice_unref(outbuf);
-  return 0;
-}
-
-static void* zalloc_gpr(void* opaque, unsigned int items, unsigned int size) {
-  return gpr_malloc(items * size);
-}
-
-static void zfree_gpr(void* opaque, void* address) { gpr_free(address); }
-
-static int zlib_compress(gpr_slice_buffer* input, gpr_slice_buffer* output,
-                         int gzip) {
-  z_stream zs;
-  int r;
-  size_t i;
-  size_t count_before = output->count;
-  size_t length_before = output->length;
-  memset(&zs, 0, sizeof(zs));
-  zs.zalloc = zalloc_gpr;
-  zs.zfree = zfree_gpr;
-  r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | (gzip ? 16 : 0),
-                   8, Z_DEFAULT_STRATEGY);
-  GPR_ASSERT(r == Z_OK);
-  r = zlib_body(&zs, input, output, deflate) && output->length < input->length;
-  if (!r) {
-    for (i = count_before; i < output->count; i++) {
-      gpr_slice_unref(output->slices[i]);
-    }
-    output->count = count_before;
-    output->length = length_before;
-  }
-  deflateEnd(&zs);
-  return r;
-}
-
-static int zlib_decompress(gpr_slice_buffer* input, gpr_slice_buffer* output,
-                           int gzip) {
-  z_stream zs;
-  int r;
-  size_t i;
-  size_t count_before = output->count;
-  size_t length_before = output->length;
-  memset(&zs, 0, sizeof(zs));
-  zs.zalloc = zalloc_gpr;
-  zs.zfree = zfree_gpr;
-  r = inflateInit2(&zs, 15 | (gzip ? 16 : 0));
-  GPR_ASSERT(r == Z_OK);
-  r = zlib_body(&zs, input, output, inflate);
-  if (!r) {
-    for (i = count_before; i < output->count; i++) {
-      gpr_slice_unref(output->slices[i]);
-    }
-    output->count = count_before;
-    output->length = length_before;
-  }
-  inflateEnd(&zs);
-  return r;
-}
-
-static int copy(gpr_slice_buffer* input, gpr_slice_buffer* output) {
-  size_t i;
-  for (i = 0; i < input->count; i++) {
-    gpr_slice_buffer_add(output, gpr_slice_ref(input->slices[i]));
-  }
-  return 1;
-}
-
-static int compress_inner(grpc_compression_algorithm algorithm,
-                          gpr_slice_buffer* input, gpr_slice_buffer* output) {
-  switch (algorithm) {
-    case GRPC_COMPRESS_NONE:
-      /* the fallback path always needs to be send uncompressed: we simply
-         rely on that here */
-      return 0;
-    case GRPC_COMPRESS_DEFLATE:
-      return zlib_compress(input, output, 0);
-    case GRPC_COMPRESS_GZIP:
-      return zlib_compress(input, output, 1);
-    case GRPC_COMPRESS_ALGORITHMS_COUNT:
-      break;
-  }
-  gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm);
-  return 0;
-}
-
-int grpc_msg_compress(grpc_compression_algorithm algorithm,
-                      gpr_slice_buffer* input, gpr_slice_buffer* output) {
-  if (!compress_inner(algorithm, input, output)) {
-    copy(input, output);
-    return 0;
-  }
-  return 1;
-}
-
-int grpc_msg_decompress(grpc_compression_algorithm algorithm,
-                        gpr_slice_buffer* input, gpr_slice_buffer* output) {
-  switch (algorithm) {
-    case GRPC_COMPRESS_NONE:
-      return copy(input, output);
-    case GRPC_COMPRESS_DEFLATE:
-      return zlib_decompress(input, output, 0);
-    case GRPC_COMPRESS_GZIP:
-      return zlib_decompress(input, output, 1);
-    case GRPC_COMPRESS_ALGORITHMS_COUNT:
-      break;
-  }
-  gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm);
-  return 0;
-}
diff --git a/src/core/compression/message_compress.h b/src/core/compression/message_compress.h
deleted file mode 100644
index 20b78c0..0000000
--- a/src/core/compression/message_compress.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_COMPRESSION_MESSAGE_COMPRESS_H
-#define GRPC_CORE_COMPRESSION_MESSAGE_COMPRESS_H
-
-#include <grpc/compression.h>
-#include <grpc/support/slice_buffer.h>
-
-/* compress 'input' to 'output' using 'algorithm'.
-   On success, appends compressed slices to output and returns 1.
-   On failure, appends uncompressed slices to output and returns 0. */
-int grpc_msg_compress(grpc_compression_algorithm algorithm,
-                      gpr_slice_buffer* input, gpr_slice_buffer* output);
-
-/* decompress 'input' to 'output' using 'algorithm'.
-   On success, appends slices to output and returns 1.
-   On failure, output is unchanged, and returns 0. */
-int grpc_msg_decompress(grpc_compression_algorithm algorithm,
-                        gpr_slice_buffer* input, gpr_slice_buffer* output);
-
-#endif /* GRPC_CORE_COMPRESSION_MESSAGE_COMPRESS_H */
diff --git a/src/core/debug/trace.c b/src/core/debug/trace.c
deleted file mode 100644
index 3b35d81..0000000
--- a/src/core/debug/trace.c
+++ /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.
- *
- */
-
-#include "src/core/debug/trace.h"
-
-#include <string.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include "src/core/support/env.h"
-
-typedef struct tracer {
-  const char *name;
-  int *flag;
-  struct tracer *next;
-} tracer;
-static tracer *tracers;
-
-void grpc_register_tracer(const char *name, int *flag) {
-  tracer *t = gpr_malloc(sizeof(*t));
-  t->name = name;
-  t->flag = flag;
-  t->next = tracers;
-  *flag = 0;
-  tracers = t;
-}
-
-static void add(const char *beg, const char *end, char ***ss, size_t *ns) {
-  size_t n = *ns;
-  size_t np = n + 1;
-  char *s;
-  size_t len;
-  GPR_ASSERT(end >= beg);
-  len = (size_t)(end - beg);
-  s = gpr_malloc(len + 1);
-  memcpy(s, beg, len);
-  s[len] = 0;
-  *ss = gpr_realloc(*ss, sizeof(char **) * np);
-  (*ss)[n] = s;
-  *ns = np;
-}
-
-static void split(const char *s, char ***ss, size_t *ns) {
-  const char *c = strchr(s, ',');
-  if (c == NULL) {
-    add(s, s + strlen(s), ss, ns);
-  } else {
-    add(s, c, ss, ns);
-    split(c + 1, ss, ns);
-  }
-}
-
-static void parse(const char *s) {
-  char **strings = NULL;
-  size_t nstrings = 0;
-  size_t i;
-  split(s, &strings, &nstrings);
-
-  for (i = 0; i < nstrings; i++) {
-    grpc_tracer_set_enabled(strings[i], 1);
-  }
-
-  for (i = 0; i < nstrings; i++) {
-    gpr_free(strings[i]);
-  }
-  gpr_free(strings);
-}
-
-void grpc_tracer_init(const char *env_var) {
-  char *e = gpr_getenv(env_var);
-  if (e != NULL) {
-    parse(e);
-    gpr_free(e);
-  }
-}
-
-void grpc_tracer_shutdown(void) {
-  while (tracers) {
-    tracer *t = tracers;
-    tracers = t->next;
-    gpr_free(t);
-  }
-}
-
-int grpc_tracer_set_enabled(const char *name, int enabled) {
-  tracer *t;
-  if (0 == strcmp(name, "all")) {
-    for (t = tracers; t; t = t->next) {
-      *t->flag = 1;
-    }
-  } else {
-    int found = 0;
-    for (t = tracers; t; t = t->next) {
-      if (0 == strcmp(name, t->name)) {
-        *t->flag = enabled;
-        found = 1;
-      }
-    }
-    if (!found) {
-      gpr_log(GPR_ERROR, "Unknown trace var: '%s'", name);
-      return 0; /* early return */
-    }
-  }
-  return 1;
-}
diff --git a/src/core/debug/trace.h b/src/core/debug/trace.h
deleted file mode 100644
index 91ec140..0000000
--- a/src/core/debug/trace.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_DEBUG_TRACE_H
-#define GRPC_CORE_DEBUG_TRACE_H
-
-#include <grpc/support/port_platform.h>
-
-void grpc_register_tracer(const char *name, int *flag);
-void grpc_tracer_init(const char *env_var_name);
-void grpc_tracer_shutdown(void);
-
-#endif /* GRPC_CORE_DEBUG_TRACE_H */
diff --git a/src/core/census/README.md b/src/core/ext/census/README.md
similarity index 100%
rename from src/core/census/README.md
rename to src/core/ext/census/README.md
diff --git a/src/core/ext/census/aggregation.h b/src/core/ext/census/aggregation.h
new file mode 100644
index 0000000..45f789c
--- /dev/null
+++ b/src/core/ext/census/aggregation.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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 <stddef.h>
+
+#ifndef GRPC_CORE_EXT_CENSUS_AGGREGATION_H
+#define GRPC_CORE_EXT_CENSUS_AGGREGATION_H
+
+/** Structure used to describe an aggregation type. */
+struct census_aggregation_ops {
+  /* Create a new aggregation. The pointer returned can be used in future calls
+     to clone(), free(), record(), data() and reset(). */
+  void *(*create)(const void *create_arg);
+  /* Make a copy of an aggregation created by create() */
+  void *(*clone)(const void *aggregation);
+  /* Destroy an aggregation created by create() */
+  void (*free)(void *aggregation);
+  /* Record a new value against aggregation. */
+  void (*record)(void *aggregation, double value);
+  /* Return current aggregation data. The caller must cast this object into
+     the correct type for the aggregation result. The object returned can be
+     freed by using free_data(). */
+  void *(*data)(const void *aggregation);
+  /* free data returned by data() */
+  void (*free_data)(void *data);
+  /* Reset an aggregation to default (zero) values. */
+  void (*reset)(void *aggregation);
+  /* Merge 'from' aggregation into 'to'. Both aggregations must be compatible */
+  void (*merge)(void *to, const void *from);
+  /* Fill buffer with printable string version of aggregation contents. For
+     debugging only. Returns the number of bytes added to buffer (a value == n
+     implies the buffer was of insufficient size). */
+  size_t (*print)(const void *aggregation, char *buffer, size_t n);
+};
+
+#endif /* GRPC_CORE_EXT_CENSUS_AGGREGATION_H */
diff --git a/src/core/ext/census/census_init.c b/src/core/ext/census/census_init.c
new file mode 100644
index 0000000..690b09e
--- /dev/null
+++ b/src/core/ext/census/census_init.c
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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/ext/census/census_interface.h"
+
+#include <grpc/support/log.h>
+#include "src/core/ext/census/census_rpc_stats.h"
+#include "src/core/ext/census/census_tracing.h"
+
+void census_init(void) {
+  census_tracing_init();
+  census_stats_store_init();
+}
+
+void census_shutdown(void) {
+  census_stats_store_shutdown();
+  census_tracing_shutdown();
+}
diff --git a/src/core/ext/census/census_interface.h b/src/core/ext/census/census_interface.h
new file mode 100644
index 0000000..57e75f5
--- /dev/null
+++ b/src/core/ext/census/census_interface.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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_EXT_CENSUS_CENSUS_INTERFACE_H
+#define GRPC_CORE_EXT_CENSUS_CENSUS_INTERFACE_H
+
+#include <grpc/support/port_platform.h>
+
+/* Maximum length of an individual census trace annotation. */
+#define CENSUS_MAX_ANNOTATION_LENGTH 200
+
+/* Structure of a census op id. Define as structure because 64bit integer is not
+   available on every platform for C89. */
+typedef struct census_op_id {
+  uint32_t upper;
+  uint32_t lower;
+} census_op_id;
+
+typedef struct census_rpc_stats census_rpc_stats;
+
+/* Initializes Census library. No-op if Census is already initialized. */
+void census_init(void);
+
+/* Shutdown Census Library. */
+void census_shutdown(void);
+
+/* Annotates grpc method name on a census_op_id. The method name has the format
+   of <full quantified rpc service name>/<rpc function name>. Returns 0 iff
+   op_id and method_name are all valid. op_id is valid after its creation and
+   before calling census_tracing_end_op().
+
+   TODO(hongyu): Figure out valid characters set for service name and command
+   name and document requirements here.*/
+int census_add_method_tag(census_op_id op_id, const char *method_name);
+
+/* Annotates tracing information to a specific op_id.
+   Up to CENSUS_MAX_ANNOTATION_LENGTH bytes are recorded. */
+void census_tracing_print(census_op_id op_id, const char *annotation);
+
+/* Starts tracing for an RPC. Returns a locally unique census_op_id */
+census_op_id census_tracing_start_op(void);
+
+/* Ends tracing. Calling this function will invalidate the input op_id. */
+void census_tracing_end_op(census_op_id op_id);
+
+#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_INTERFACE_H */
diff --git a/src/core/ext/census/census_log.c b/src/core/ext/census/census_log.c
new file mode 100644
index 0000000..9a7331a
--- /dev/null
+++ b/src/core/ext/census/census_log.c
@@ -0,0 +1,603 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Available log space is divided up in blocks of
+   CENSUS_LOG_2_MAX_RECORD_SIZE bytes. A block can be in one of the
+   following three data structures:
+   - Free blocks (free_block_list)
+   - Blocks with unread data (dirty_block_list)
+   - Blocks currently attached to cores (core_local_blocks[])
+
+   census_log_start_write() moves a block from core_local_blocks[] to the
+   end of dirty_block_list when block:
+   - is out-of-space OR
+   - has an incomplete record (an incomplete record occurs when a thread calls
+     census_log_start_write() and is context-switched before calling
+     census_log_end_write()
+   So, blocks in dirty_block_list are ordered, from oldest to newest, by time
+   when block is detached from the core.
+
+   census_log_read_next() first iterates over dirty_block_list and then
+   core_local_blocks[]. It moves completely read blocks from dirty_block_list
+   to free_block_list. Blocks in core_local_blocks[] are not freed, even when
+   completely read.
+
+   If log is configured to discard old records and free_block_list is empty,
+   census_log_start_write() iterates over dirty_block_list to allocate a
+   new block. It moves the oldest available block (no pending read/write) to
+   core_local_blocks[].
+
+   core_local_block_struct is used to implement a map from core id to the block
+   associated with that core. This mapping is advisory. It is possible that the
+   block returned by this mapping is no longer associated with that core. This
+   mapping is updated, lazily, by census_log_start_write().
+
+   Locking in block struct:
+
+   Exclusive g_log.lock must be held before calling any functions operatong on
+   block structs except census_log_start_write() and
+   census_log_end_write().
+
+   Writes to a block are serialized via writer_lock.
+   census_log_start_write() acquires this lock and
+   census_log_end_write() releases it. On failure to acquire the lock,
+   writer allocates a new block for the current core and updates
+   core_local_block accordingly.
+
+   Simultaneous read and write access is allowed. Reader can safely read up to
+   committed bytes (bytes_committed).
+
+   reader_lock protects the block, currently being read, from getting recycled.
+   start_read() acquires reader_lock and end_read() releases the lock.
+
+   Read/write access to a block is disabled via try_disable_access(). It returns
+   with both writer_lock and reader_lock held. These locks are subsequently
+   released by enable_access() to enable access to the block.
+
+   A note on naming: Most function/struct names are prepended by cl_
+   (shorthand for census_log). Further, functions that manipulate structures
+   include the name of the structure, which will be passed as the first
+   argument. E.g. cl_block_initialize() will initialize a cl_block.
+*/
+#include "src/core/ext/census/census_log.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/cpu.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
+#include <string.h>
+
+/* End of platform specific code */
+
+typedef struct census_log_block_list_struct {
+  struct census_log_block_list_struct *next;
+  struct census_log_block_list_struct *prev;
+  struct census_log_block *block;
+} cl_block_list_struct;
+
+typedef struct census_log_block {
+  /* Pointer to underlying buffer */
+  char *buffer;
+  gpr_atm writer_lock;
+  gpr_atm reader_lock;
+  /* Keeps completely written bytes. Declared atomic because accessed
+     simultaneously by reader and writer. */
+  gpr_atm bytes_committed;
+  /* Bytes already read */
+  int32_t bytes_read;
+  /* Links for list */
+  cl_block_list_struct link;
+/* We want this structure to be cacheline aligned. We assume the following
+   sizes for the various parts on 32/64bit systems:
+   type                 32b size    64b size
+   char*                   4           8
+   3x gpr_atm             12          24
+   int32_t               4           8 (assumes padding)
+   cl_block_list_struct   12          24
+   TOTAL                  32          64
+
+   Depending on the size of our cacheline and the architecture, we
+   selectively add char buffering to this structure. The size is checked
+   via assert in census_log_initialize(). */
+#if defined(GPR_ARCH_64)
+#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 64)
+#else
+#if defined(GPR_ARCH_32)
+#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 32)
+#else
+#error "Unknown architecture"
+#endif
+#endif
+#if CL_BLOCK_PAD_SIZE > 0
+  char padding[CL_BLOCK_PAD_SIZE];
+#endif
+} cl_block;
+
+/* A list of cl_blocks, doubly-linked through cl_block::link. */
+typedef struct census_log_block_list {
+  int32_t count;           /* Number of items in list. */
+  cl_block_list_struct ht; /* head/tail of linked list. */
+} cl_block_list;
+
+/* Cacheline aligned block pointers to avoid false sharing. Block pointer must
+   be initialized via set_block(), before calling other functions */
+typedef struct census_log_core_local_block {
+  gpr_atm block;
+/* Ensure cachline alignment: we assume sizeof(gpr_atm) == 4 or 8 */
+#if defined(GPR_ARCH_64)
+#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 8)
+#else
+#if defined(GPR_ARCH_32)
+#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 4)
+#else
+#error "Unknown architecture"
+#endif
+#endif
+#if CL_CORE_LOCAL_BLOCK_PAD_SIZE > 0
+  char padding[CL_CORE_LOCAL_BLOCK_PAD_SIZE];
+#endif
+} cl_core_local_block;
+
+struct census_log {
+  int discard_old_records;
+  /* Number of cores (aka hardware-contexts) */
+  unsigned num_cores;
+  /* number of CENSUS_LOG_2_MAX_RECORD_SIZE blocks in log */
+  int32_t num_blocks;
+  cl_block *blocks;                       /* Block metadata. */
+  cl_core_local_block *core_local_blocks; /* Keeps core to block mappings. */
+  gpr_mu lock;
+  int initialized; /* has log been initialized? */
+  /* Keeps the state of the reader iterator. A value of 0 indicates that
+     iterator has reached the end. census_log_init_reader() resets the
+     value to num_core to restart iteration. */
+  uint32_t read_iterator_state;
+  /* Points to the block being read. If non-NULL, the block is locked for
+     reading (block_being_read_->reader_lock is held). */
+  cl_block *block_being_read;
+  /* A non-zero value indicates that log is full. */
+  gpr_atm is_full;
+  char *buffer;
+  cl_block_list free_block_list;
+  cl_block_list dirty_block_list;
+  gpr_atm out_of_space_count;
+};
+
+/* Single internal log */
+static struct census_log g_log;
+
+/* Functions that operate on an atomic memory location used as a lock */
+
+/* Returns non-zero if lock is acquired */
+static int cl_try_lock(gpr_atm *lock) { return gpr_atm_acq_cas(lock, 0, 1); }
+
+static void cl_unlock(gpr_atm *lock) { gpr_atm_rel_store(lock, 0); }
+
+/* Functions that operate on cl_core_local_block's */
+
+static void cl_core_local_block_set_block(cl_core_local_block *clb,
+                                          cl_block *block) {
+  gpr_atm_rel_store(&clb->block, (gpr_atm)block);
+}
+
+static cl_block *cl_core_local_block_get_block(cl_core_local_block *clb) {
+  return (cl_block *)gpr_atm_acq_load(&clb->block);
+}
+
+/* Functions that operate on cl_block_list_struct's */
+
+static void cl_block_list_struct_initialize(cl_block_list_struct *bls,
+                                            cl_block *block) {
+  bls->next = bls->prev = bls;
+  bls->block = block;
+}
+
+/* Functions that operate on cl_block_list's */
+
+static void cl_block_list_initialize(cl_block_list *list) {
+  list->count = 0;
+  cl_block_list_struct_initialize(&list->ht, NULL);
+}
+
+/* Returns head of *this, or NULL if empty. */
+static cl_block *cl_block_list_head(cl_block_list *list) {
+  return list->ht.next->block;
+}
+
+/* Insert element *e after *pos. */
+static void cl_block_list_insert(cl_block_list *list, cl_block_list_struct *pos,
+                                 cl_block_list_struct *e) {
+  list->count++;
+  e->next = pos->next;
+  e->prev = pos;
+  e->next->prev = e;
+  e->prev->next = e;
+}
+
+/* Insert block at the head of the list */
+static void cl_block_list_insert_at_head(cl_block_list *list, cl_block *block) {
+  cl_block_list_insert(list, &list->ht, &block->link);
+}
+
+/* Insert block at the tail of the list */
+static void cl_block_list_insert_at_tail(cl_block_list *list, cl_block *block) {
+  cl_block_list_insert(list, list->ht.prev, &block->link);
+}
+
+/* Removes block *b. Requires *b be in the list. */
+static void cl_block_list_remove(cl_block_list *list, cl_block *b) {
+  list->count--;
+  b->link.next->prev = b->link.prev;
+  b->link.prev->next = b->link.next;
+}
+
+/* Functions that operate on cl_block's */
+
+static void cl_block_initialize(cl_block *block, char *buffer) {
+  block->buffer = buffer;
+  gpr_atm_rel_store(&block->writer_lock, 0);
+  gpr_atm_rel_store(&block->reader_lock, 0);
+  gpr_atm_rel_store(&block->bytes_committed, 0);
+  block->bytes_read = 0;
+  cl_block_list_struct_initialize(&block->link, block);
+}
+
+/* Guards against exposing partially written buffer to the reader. */
+static void cl_block_set_bytes_committed(cl_block *block,
+                                         int32_t bytes_committed) {
+  gpr_atm_rel_store(&block->bytes_committed, bytes_committed);
+}
+
+static int32_t cl_block_get_bytes_committed(cl_block *block) {
+  return gpr_atm_acq_load(&block->bytes_committed);
+}
+
+/* Tries to disable future read/write access to this block. Succeeds if:
+   - no in-progress write AND
+   - no in-progress read AND
+   - 'discard_data' set to true OR no unread data
+   On success, clears the block state and returns with writer_lock_ and
+   reader_lock_ held. These locks are released by a subsequent
+   cl_block_access_enable() call. */
+static int cl_block_try_disable_access(cl_block *block, int discard_data) {
+  if (!cl_try_lock(&block->writer_lock)) {
+    return 0;
+  }
+  if (!cl_try_lock(&block->reader_lock)) {
+    cl_unlock(&block->writer_lock);
+    return 0;
+  }
+  if (!discard_data &&
+      (block->bytes_read != cl_block_get_bytes_committed(block))) {
+    cl_unlock(&block->reader_lock);
+    cl_unlock(&block->writer_lock);
+    return 0;
+  }
+  cl_block_set_bytes_committed(block, 0);
+  block->bytes_read = 0;
+  return 1;
+}
+
+static void cl_block_enable_access(cl_block *block) {
+  cl_unlock(&block->reader_lock);
+  cl_unlock(&block->writer_lock);
+}
+
+/* Returns with writer_lock held. */
+static void *cl_block_start_write(cl_block *block, size_t size) {
+  int32_t bytes_committed;
+  if (!cl_try_lock(&block->writer_lock)) {
+    return NULL;
+  }
+  bytes_committed = cl_block_get_bytes_committed(block);
+  if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) {
+    cl_unlock(&block->writer_lock);
+    return NULL;
+  }
+  return block->buffer + bytes_committed;
+}
+
+/* Releases writer_lock and increments committed bytes by 'bytes_written'.
+  'bytes_written' must be <= 'size' specified in the corresponding
+  StartWrite() call. This function is thread-safe. */
+static void cl_block_end_write(cl_block *block, size_t bytes_written) {
+  cl_block_set_bytes_committed(
+      block, cl_block_get_bytes_committed(block) + bytes_written);
+  cl_unlock(&block->writer_lock);
+}
+
+/* Returns a pointer to the first unread byte in buffer. The number of bytes
+   available are returned in 'bytes_available'. Acquires reader lock that is
+   released by a subsequent cl_block_end_read() call. Returns NULL if:
+   - read in progress
+   - no data available */
+static void *cl_block_start_read(cl_block *block, size_t *bytes_available) {
+  void *record;
+  if (!cl_try_lock(&block->reader_lock)) {
+    return NULL;
+  }
+  /* bytes_committed may change from under us. Use bytes_available to update
+     bytes_read below. */
+  *bytes_available = cl_block_get_bytes_committed(block) - block->bytes_read;
+  if (*bytes_available == 0) {
+    cl_unlock(&block->reader_lock);
+    return NULL;
+  }
+  record = block->buffer + block->bytes_read;
+  block->bytes_read += *bytes_available;
+  return record;
+}
+
+static void cl_block_end_read(cl_block *block) {
+  cl_unlock(&block->reader_lock);
+}
+
+/* Internal functions operating on g_log */
+
+/* Allocates a new free block (or recycles an available dirty block if log is
+   configured to discard old records). Returns NULL if out-of-space. */
+static cl_block *cl_allocate_block(void) {
+  cl_block *block = cl_block_list_head(&g_log.free_block_list);
+  if (block != NULL) {
+    cl_block_list_remove(&g_log.free_block_list, block);
+    return block;
+  }
+  if (!g_log.discard_old_records) {
+    /* No free block and log is configured to keep old records. */
+    return NULL;
+  }
+  /* Recycle dirty block. Start from the oldest. */
+  for (block = cl_block_list_head(&g_log.dirty_block_list); block != NULL;
+       block = block->link.next->block) {
+    if (cl_block_try_disable_access(block, 1 /* discard data */)) {
+      cl_block_list_remove(&g_log.dirty_block_list, block);
+      return block;
+    }
+  }
+  return NULL;
+}
+
+/* Allocates a new block and updates core id => block mapping. 'old_block'
+   points to the block that the caller thinks is attached to
+   'core_id'. 'old_block' may be NULL. Returns non-zero if:
+   - allocated a new block OR
+   - 'core_id' => 'old_block' mapping changed (another thread allocated a
+     block before lock was acquired). */
+static int cl_allocate_core_local_block(int32_t core_id, cl_block *old_block) {
+  /* Now that we have the lock, check if core-local mapping has changed. */
+  cl_core_local_block *core_local_block = &g_log.core_local_blocks[core_id];
+  cl_block *block = cl_core_local_block_get_block(core_local_block);
+  if ((block != NULL) && (block != old_block)) {
+    return 1;
+  }
+  if (block != NULL) {
+    cl_core_local_block_set_block(core_local_block, NULL);
+    cl_block_list_insert_at_tail(&g_log.dirty_block_list, block);
+  }
+  block = cl_allocate_block();
+  if (block == NULL) {
+    gpr_atm_rel_store(&g_log.is_full, 1);
+    return 0;
+  }
+  cl_core_local_block_set_block(core_local_block, block);
+  cl_block_enable_access(block);
+  return 1;
+}
+
+static cl_block *cl_get_block(void *record) {
+  uintptr_t p = (uintptr_t)((char *)record - g_log.buffer);
+  uintptr_t index = p >> CENSUS_LOG_2_MAX_RECORD_SIZE;
+  return &g_log.blocks[index];
+}
+
+/* Gets the next block to read and tries to free 'prev' block (if not NULL).
+   Returns NULL if reached the end. */
+static cl_block *cl_next_block_to_read(cl_block *prev) {
+  cl_block *block = NULL;
+  if (g_log.read_iterator_state == g_log.num_cores) {
+    /* We are traversing dirty list; find the next dirty block. */
+    if (prev != NULL) {
+      /* Try to free the previous block if there is no unread data. This block
+         may have unread data if previously incomplete record completed between
+         read_next() calls. */
+      block = prev->link.next->block;
+      if (cl_block_try_disable_access(prev, 0 /* do not discard data */)) {
+        cl_block_list_remove(&g_log.dirty_block_list, prev);
+        cl_block_list_insert_at_head(&g_log.free_block_list, prev);
+        gpr_atm_rel_store(&g_log.is_full, 0);
+      }
+    } else {
+      block = cl_block_list_head(&g_log.dirty_block_list);
+    }
+    if (block != NULL) {
+      return block;
+    }
+    /* We are done with the dirty list; moving on to core-local blocks. */
+  }
+  while (g_log.read_iterator_state > 0) {
+    g_log.read_iterator_state--;
+    block = cl_core_local_block_get_block(
+        &g_log.core_local_blocks[g_log.read_iterator_state]);
+    if (block != NULL) {
+      return block;
+    }
+  }
+  return NULL;
+}
+
+/* External functions: primary stats_log interface */
+void census_log_initialize(size_t size_in_mb, int discard_old_records) {
+  int32_t ix;
+  /* Check cacheline alignment. */
+  GPR_ASSERT(sizeof(cl_block) % GPR_CACHELINE_SIZE == 0);
+  GPR_ASSERT(sizeof(cl_core_local_block) % GPR_CACHELINE_SIZE == 0);
+  GPR_ASSERT(!g_log.initialized);
+  g_log.discard_old_records = discard_old_records;
+  g_log.num_cores = gpr_cpu_num_cores();
+  /* Ensure at least as many blocks as there are cores. */
+  g_log.num_blocks = GPR_MAX(
+      g_log.num_cores, (size_in_mb << 20) >> CENSUS_LOG_2_MAX_RECORD_SIZE);
+  gpr_mu_init(&g_log.lock);
+  g_log.read_iterator_state = 0;
+  g_log.block_being_read = NULL;
+  gpr_atm_rel_store(&g_log.is_full, 0);
+  g_log.core_local_blocks = (cl_core_local_block *)gpr_malloc_aligned(
+      g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG);
+  memset(g_log.core_local_blocks, 0,
+         g_log.num_cores * sizeof(cl_core_local_block));
+  g_log.blocks = (cl_block *)gpr_malloc_aligned(
+      g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG);
+  memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block));
+  g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
+  memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
+  cl_block_list_initialize(&g_log.free_block_list);
+  cl_block_list_initialize(&g_log.dirty_block_list);
+  for (ix = 0; ix < g_log.num_blocks; ++ix) {
+    cl_block *block = g_log.blocks + ix;
+    cl_block_initialize(block,
+                        g_log.buffer + (CENSUS_LOG_MAX_RECORD_SIZE * ix));
+    cl_block_try_disable_access(block, 1 /* discard data */);
+    cl_block_list_insert_at_tail(&g_log.free_block_list, block);
+  }
+  gpr_atm_rel_store(&g_log.out_of_space_count, 0);
+  g_log.initialized = 1;
+}
+
+void census_log_shutdown(void) {
+  GPR_ASSERT(g_log.initialized);
+  gpr_mu_destroy(&g_log.lock);
+  gpr_free_aligned(g_log.core_local_blocks);
+  g_log.core_local_blocks = NULL;
+  gpr_free_aligned(g_log.blocks);
+  g_log.blocks = NULL;
+  gpr_free(g_log.buffer);
+  g_log.buffer = NULL;
+  g_log.initialized = 0;
+}
+
+void *census_log_start_write(size_t size) {
+  /* Used to bound number of times block allocation is attempted. */
+  int32_t attempts_remaining = g_log.num_blocks;
+  /* TODO(aveitch): move this inside the do loop when current_cpu is fixed */
+  int32_t core_id = gpr_cpu_current_cpu();
+  GPR_ASSERT(g_log.initialized);
+  if (size > CENSUS_LOG_MAX_RECORD_SIZE) {
+    return NULL;
+  }
+  do {
+    int allocated;
+    void *record = NULL;
+    cl_block *block =
+        cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]);
+    if (block && (record = cl_block_start_write(block, size))) {
+      return record;
+    }
+    /* Need to allocate a new block. We are here if:
+       - No block associated with the core OR
+       - Write in-progress on the block OR
+       - block is out of space */
+    if (gpr_atm_acq_load(&g_log.is_full)) {
+      gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
+      return NULL;
+    }
+    gpr_mu_lock(&g_log.lock);
+    allocated = cl_allocate_core_local_block(core_id, block);
+    gpr_mu_unlock(&g_log.lock);
+    if (!allocated) {
+      gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
+      return NULL;
+    }
+  } while (attempts_remaining--);
+  /* Give up. */
+  gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
+  return NULL;
+}
+
+void census_log_end_write(void *record, size_t bytes_written) {
+  GPR_ASSERT(g_log.initialized);
+  cl_block_end_write(cl_get_block(record), bytes_written);
+}
+
+void census_log_init_reader(void) {
+  GPR_ASSERT(g_log.initialized);
+  gpr_mu_lock(&g_log.lock);
+  /* If a block is locked for reading unlock it. */
+  if (g_log.block_being_read != NULL) {
+    cl_block_end_read(g_log.block_being_read);
+    g_log.block_being_read = NULL;
+  }
+  g_log.read_iterator_state = g_log.num_cores;
+  gpr_mu_unlock(&g_log.lock);
+}
+
+const void *census_log_read_next(size_t *bytes_available) {
+  GPR_ASSERT(g_log.initialized);
+  gpr_mu_lock(&g_log.lock);
+  if (g_log.block_being_read != NULL) {
+    cl_block_end_read(g_log.block_being_read);
+  }
+  do {
+    g_log.block_being_read = cl_next_block_to_read(g_log.block_being_read);
+    if (g_log.block_being_read != NULL) {
+      void *record =
+          cl_block_start_read(g_log.block_being_read, bytes_available);
+      if (record != NULL) {
+        gpr_mu_unlock(&g_log.lock);
+        return record;
+      }
+    }
+  } while (g_log.block_being_read != NULL);
+  gpr_mu_unlock(&g_log.lock);
+  return NULL;
+}
+
+size_t census_log_remaining_space(void) {
+  size_t space;
+  GPR_ASSERT(g_log.initialized);
+  gpr_mu_lock(&g_log.lock);
+  if (g_log.discard_old_records) {
+    /* Remaining space is not meaningful; just return the entire log space. */
+    space = g_log.num_blocks << CENSUS_LOG_2_MAX_RECORD_SIZE;
+  } else {
+    space = g_log.free_block_list.count * CENSUS_LOG_MAX_RECORD_SIZE;
+  }
+  gpr_mu_unlock(&g_log.lock);
+  return space;
+}
+
+int census_log_out_of_space_count(void) {
+  GPR_ASSERT(g_log.initialized);
+  return gpr_atm_acq_load(&g_log.out_of_space_count);
+}
diff --git a/src/core/ext/census/census_log.h b/src/core/ext/census/census_log.h
new file mode 100644
index 0000000..534ecc5
--- /dev/null
+++ b/src/core/ext/census/census_log.h
@@ -0,0 +1,91 @@
+/*
+ *
+ * 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_EXT_CENSUS_CENSUS_LOG_H
+#define GRPC_CORE_EXT_CENSUS_CENSUS_LOG_H
+
+#include <stddef.h>
+
+/* Maximum record size, in bytes. */
+#define CENSUS_LOG_2_MAX_RECORD_SIZE 14 /* 2^14 = 16KB */
+#define CENSUS_LOG_MAX_RECORD_SIZE (1 << CENSUS_LOG_2_MAX_RECORD_SIZE)
+
+/* Initialize the statistics logging subsystem with the given log size. A log
+   size of 0 will result in the smallest possible log for the platform
+   (approximately CENSUS_LOG_MAX_RECORD_SIZE * gpr_cpu_num_cores()). If
+   discard_old_records is non-zero, then new records will displace older ones
+   when the log is full. This function must be called before any other
+   census_log functions.
+*/
+void census_log_initialize(size_t size_in_mb, int discard_old_records);
+
+/* Shutdown the logging subsystem. Caller must ensure that:
+   - no in progress or future call to any census_log functions
+   - no incomplete records
+*/
+void census_log_shutdown(void);
+
+/* Allocates and returns a 'size' bytes record and marks it in use. A
+   subsequent census_log_end_write() marks the record complete. The
+   'bytes_written' census_log_end_write() argument must be <=
+   'size'. Returns NULL if out-of-space AND:
+       - log is configured to keep old records OR
+       - all blocks are pinned by incomplete records.
+*/
+void *census_log_start_write(size_t size);
+
+void census_log_end_write(void *record, size_t bytes_written);
+
+/* census_log_read_next() iterates over blocks with data and for each block
+   returns a pointer to the first unread byte. The number of bytes that can be
+   read are returned in 'bytes_available'. Reader is expected to read all
+   available data. Reading the data consumes it i.e. it cannot be read again.
+   census_log_read_next() returns NULL if the end is reached i.e last block
+   is read. census_log_init_reader() starts the iteration or aborts the
+   current iteration.
+*/
+void census_log_init_reader(void);
+const void *census_log_read_next(size_t *bytes_available);
+
+/* Returns estimated remaining space across all blocks, in bytes. If log is
+   configured to discard old records, returns total log space. Otherwise,
+   returns space available in empty blocks (partially filled blocks are
+   treated as full).
+*/
+size_t census_log_remaining_space(void);
+
+/* Returns the number of times gprc_stats_log_start_write() failed due to
+   out-of-space. */
+int census_log_out_of_space_count(void);
+
+#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_LOG_H */
diff --git a/src/core/ext/census/census_rpc_stats.c b/src/core/ext/census/census_rpc_stats.c
new file mode 100644
index 0000000..09ee12d
--- /dev/null
+++ b/src/core/ext/census/census_rpc_stats.c
@@ -0,0 +1,253 @@
+/*
+ *
+ * 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 <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include "src/core/ext/census/census_interface.h"
+#include "src/core/ext/census/census_rpc_stats.h"
+#include "src/core/ext/census/census_tracing.h"
+#include "src/core/ext/census/hash_table.h"
+#include "src/core/ext/census/window_stats.h"
+#include "src/core/lib/support/murmur_hash.h"
+#include "src/core/lib/support/string.h"
+
+#define NUM_INTERVALS 3
+#define MINUTE_INTERVAL 0
+#define HOUR_INTERVAL 1
+#define TOTAL_INTERVAL 2
+
+/* for easier typing */
+typedef census_per_method_rpc_stats per_method_stats;
+
+/* Ensure mu is only initialized once. */
+static gpr_once g_stats_store_mu_init = GPR_ONCE_INIT;
+/* Guards two stats stores. */
+static gpr_mu g_mu;
+static census_ht *g_client_stats_store = NULL;
+static census_ht *g_server_stats_store = NULL;
+
+static void init_mutex(void) { gpr_mu_init(&g_mu); }
+
+static void init_mutex_once(void) {
+  gpr_once_init(&g_stats_store_mu_init, init_mutex);
+}
+
+static int cmp_str_keys(const void *k1, const void *k2) {
+  return strcmp((const char *)k1, (const char *)k2);
+}
+
+/* TODO(hongyu): replace it with cityhash64 */
+static uint64_t simple_hash(const void *k) {
+  size_t len = strlen(k);
+  uint64_t higher = gpr_murmur_hash3((const char *)k, len / 2, 0);
+  return higher << 32 |
+         gpr_murmur_hash3((const char *)k + len / 2, len - len / 2, 0);
+}
+
+static void delete_stats(void *stats) {
+  census_window_stats_destroy((struct census_window_stats *)stats);
+}
+
+static void delete_key(void *key) { gpr_free(key); }
+
+static const census_ht_option ht_opt = {
+    CENSUS_HT_POINTER /* key type */, 1999 /* n_of_buckets */,
+    simple_hash /* hash function */,  cmp_str_keys /* key comparator */,
+    delete_stats /* data deleter */,  delete_key /* key deleter */
+};
+
+static void init_rpc_stats(void *stats) {
+  memset(stats, 0, sizeof(census_rpc_stats));
+}
+
+static void stat_add_proportion(double p, void *base, const void *addme) {
+  census_rpc_stats *b = (census_rpc_stats *)base;
+  census_rpc_stats *a = (census_rpc_stats *)addme;
+  b->cnt += p * a->cnt;
+  b->rpc_error_cnt += p * a->rpc_error_cnt;
+  b->app_error_cnt += p * a->app_error_cnt;
+  b->elapsed_time_ms += p * a->elapsed_time_ms;
+  b->api_request_bytes += p * a->api_request_bytes;
+  b->wire_request_bytes += p * a->wire_request_bytes;
+  b->api_response_bytes += p * a->api_response_bytes;
+  b->wire_response_bytes += p * a->wire_response_bytes;
+}
+
+static void stat_add(void *base, const void *addme) {
+  stat_add_proportion(1.0, base, addme);
+}
+
+static gpr_timespec min_hour_total_intervals[3] = {
+    {60, 0}, {3600, 0}, {36000000, 0}};
+
+static const census_window_stats_stat_info window_stats_settings = {
+    sizeof(census_rpc_stats), init_rpc_stats, stat_add, stat_add_proportion};
+
+census_rpc_stats *census_rpc_stats_create_empty(void) {
+  census_rpc_stats *ret =
+      (census_rpc_stats *)gpr_malloc(sizeof(census_rpc_stats));
+  memset(ret, 0, sizeof(census_rpc_stats));
+  return ret;
+}
+
+void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats *data) {
+  int i = 0;
+  for (i = 0; i < data->num_entries; i++) {
+    if (data->stats[i].method != NULL) {
+      gpr_free((void *)data->stats[i].method);
+    }
+  }
+  if (data->stats != NULL) {
+    gpr_free(data->stats);
+  }
+  data->num_entries = 0;
+  data->stats = NULL;
+}
+
+static void record_stats(census_ht *store, census_op_id op_id,
+                         const census_rpc_stats *stats) {
+  gpr_mu_lock(&g_mu);
+  if (store != NULL) {
+    census_trace_obj *trace = NULL;
+    census_internal_lock_trace_store();
+    trace = census_get_trace_obj_locked(op_id);
+    if (trace != NULL) {
+      const char *method_name = census_get_trace_method_name(trace);
+      struct census_window_stats *window_stats = NULL;
+      census_ht_key key;
+      key.ptr = (void *)method_name;
+      window_stats = census_ht_find(store, key);
+      census_internal_unlock_trace_store();
+      if (window_stats == NULL) {
+        window_stats = census_window_stats_create(3, min_hour_total_intervals,
+                                                  30, &window_stats_settings);
+        key.ptr = gpr_strdup(key.ptr);
+        census_ht_insert(store, key, (void *)window_stats);
+      }
+      census_window_stats_add(window_stats, gpr_now(GPR_CLOCK_REALTIME), stats);
+    } else {
+      census_internal_unlock_trace_store();
+    }
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+void census_record_rpc_client_stats(census_op_id op_id,
+                                    const census_rpc_stats *stats) {
+  record_stats(g_client_stats_store, op_id, stats);
+}
+
+void census_record_rpc_server_stats(census_op_id op_id,
+                                    const census_rpc_stats *stats) {
+  record_stats(g_server_stats_store, op_id, stats);
+}
+
+/* Get stats from input stats store */
+static void get_stats(census_ht *store, census_aggregated_rpc_stats *data) {
+  GPR_ASSERT(data != NULL);
+  if (data->num_entries != 0) {
+    census_aggregated_rpc_stats_set_empty(data);
+  }
+  gpr_mu_lock(&g_mu);
+  if (store != NULL) {
+    size_t n;
+    unsigned i, j;
+    gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
+    census_ht_kv *kv = census_ht_get_all_elements(store, &n);
+    if (kv != NULL) {
+      data->num_entries = n;
+      data->stats =
+          (per_method_stats *)gpr_malloc(sizeof(per_method_stats) * n);
+      for (i = 0; i < n; i++) {
+        census_window_stats_sums sums[NUM_INTERVALS];
+        for (j = 0; j < NUM_INTERVALS; j++) {
+          sums[j].statistic = (void *)census_rpc_stats_create_empty();
+        }
+        data->stats[i].method = gpr_strdup(kv[i].k.ptr);
+        census_window_stats_get_sums(kv[i].v, now, sums);
+        data->stats[i].minute_stats =
+            *(census_rpc_stats *)sums[MINUTE_INTERVAL].statistic;
+        data->stats[i].hour_stats =
+            *(census_rpc_stats *)sums[HOUR_INTERVAL].statistic;
+        data->stats[i].total_stats =
+            *(census_rpc_stats *)sums[TOTAL_INTERVAL].statistic;
+        for (j = 0; j < NUM_INTERVALS; j++) {
+          gpr_free(sums[j].statistic);
+        }
+      }
+      gpr_free(kv);
+    }
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+void census_get_client_stats(census_aggregated_rpc_stats *data) {
+  get_stats(g_client_stats_store, data);
+}
+
+void census_get_server_stats(census_aggregated_rpc_stats *data) {
+  get_stats(g_server_stats_store, data);
+}
+
+void census_stats_store_init(void) {
+  init_mutex_once();
+  gpr_mu_lock(&g_mu);
+  if (g_client_stats_store == NULL && g_server_stats_store == NULL) {
+    g_client_stats_store = census_ht_create(&ht_opt);
+    g_server_stats_store = census_ht_create(&ht_opt);
+  } else {
+    gpr_log(GPR_ERROR, "Census stats store already initialized.");
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+void census_stats_store_shutdown(void) {
+  init_mutex_once();
+  gpr_mu_lock(&g_mu);
+  if (g_client_stats_store != NULL) {
+    census_ht_destroy(g_client_stats_store);
+    g_client_stats_store = NULL;
+  } else {
+    gpr_log(GPR_ERROR, "Census server stats store not initialized.");
+  }
+  if (g_server_stats_store != NULL) {
+    census_ht_destroy(g_server_stats_store);
+    g_server_stats_store = NULL;
+  } else {
+    gpr_log(GPR_ERROR, "Census client stats store not initialized.");
+  }
+  gpr_mu_unlock(&g_mu);
+}
diff --git a/src/core/ext/census/census_rpc_stats.h b/src/core/ext/census/census_rpc_stats.h
new file mode 100644
index 0000000..7e4d8d1
--- /dev/null
+++ b/src/core/ext/census/census_rpc_stats.h
@@ -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.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_CENSUS_RPC_STATS_H
+#define GRPC_CORE_EXT_CENSUS_CENSUS_RPC_STATS_H
+
+#include <grpc/support/port_platform.h>
+#include "src/core/ext/census/census_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct census_rpc_stats {
+  uint64_t cnt;
+  uint64_t rpc_error_cnt;
+  uint64_t app_error_cnt;
+  double elapsed_time_ms;
+  double api_request_bytes;
+  double wire_request_bytes;
+  double api_response_bytes;
+  double wire_response_bytes;
+};
+
+/* Creates an empty rpc stats object on heap. */
+census_rpc_stats *census_rpc_stats_create_empty(void);
+
+typedef struct census_per_method_rpc_stats {
+  const char *method;
+  census_rpc_stats minute_stats; /* cumulative stats in the past minute */
+  census_rpc_stats hour_stats;   /* cumulative stats in the past hour */
+  census_rpc_stats total_stats;  /* cumulative stats from last gc */
+} census_per_method_rpc_stats;
+
+typedef struct census_aggregated_rpc_stats {
+  int num_entries;
+  census_per_method_rpc_stats *stats;
+} census_aggregated_rpc_stats;
+
+/* Initializes an aggregated rpc stats object to an empty state. */
+void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats *data);
+
+/* Records client side stats of a rpc. */
+void census_record_rpc_client_stats(census_op_id op_id,
+                                    const census_rpc_stats *stats);
+
+/* Records server side stats of a rpc. */
+void census_record_rpc_server_stats(census_op_id op_id,
+                                    const census_rpc_stats *stats);
+
+/* The following two functions are intended for inprocess query of
+   per-service per-method stats from grpc implementations. */
+
+/* Populates *data_map with server side aggregated per-service per-method
+   stats.
+   DO NOT CALL from outside of grpc code. */
+void census_get_server_stats(census_aggregated_rpc_stats *data_map);
+
+/* Populates *data_map with client side aggregated per-service per-method
+   stats.
+   DO NOT CALL from outside of grpc code. */
+void census_get_client_stats(census_aggregated_rpc_stats *data_map);
+
+void census_stats_store_init(void);
+void census_stats_store_shutdown(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_RPC_STATS_H */
diff --git a/src/core/ext/census/census_tracing.c b/src/core/ext/census/census_tracing.c
new file mode 100644
index 0000000..f893dc9
--- /dev/null
+++ b/src/core/ext/census/census_tracing.c
@@ -0,0 +1,241 @@
+/*
+ *
+ * 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/ext/census/census_tracing.h"
+#include "src/core/ext/census/census_interface.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/sync.h>
+#include "src/core/ext/census/hash_table.h"
+#include "src/core/lib/support/string.h"
+
+void census_trace_obj_destroy(census_trace_obj *obj) {
+  census_trace_annotation *p = obj->annotations;
+  while (p != NULL) {
+    census_trace_annotation *next = p->next;
+    gpr_free(p);
+    p = next;
+  }
+  gpr_free(obj->method);
+  gpr_free(obj);
+}
+
+static void delete_trace_obj(void *obj) {
+  census_trace_obj_destroy((census_trace_obj *)obj);
+}
+
+static const census_ht_option ht_opt = {
+    CENSUS_HT_UINT64 /* key type */,
+    571 /* n_of_buckets */,
+    NULL /* hash */,
+    NULL /* compare_keys */,
+    delete_trace_obj /* delete data */,
+    NULL /* delete key */
+};
+
+static gpr_once g_init_mutex_once = GPR_ONCE_INIT;
+static gpr_mu g_mu; /* Guards following two static variables. */
+static census_ht *g_trace_store = NULL;
+static uint64_t g_id = 0;
+
+static census_ht_key op_id_as_key(census_op_id *id) {
+  return *(census_ht_key *)id;
+}
+
+static uint64_t op_id_2_uint64(census_op_id *id) {
+  uint64_t ret;
+  memcpy(&ret, id, sizeof(census_op_id));
+  return ret;
+}
+
+static void init_mutex(void) { gpr_mu_init(&g_mu); }
+
+static void init_mutex_once(void) {
+  gpr_once_init(&g_init_mutex_once, init_mutex);
+}
+
+census_op_id census_tracing_start_op(void) {
+  gpr_mu_lock(&g_mu);
+  {
+    census_trace_obj *ret = gpr_malloc(sizeof(census_trace_obj));
+    memset(ret, 0, sizeof(census_trace_obj));
+    g_id++;
+    memcpy(&ret->id, &g_id, sizeof(census_op_id));
+    ret->rpc_stats.cnt = 1;
+    ret->ts = gpr_now(GPR_CLOCK_REALTIME);
+    census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void *)ret);
+    gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id);
+    gpr_mu_unlock(&g_mu);
+    return ret->id;
+  }
+}
+
+int census_add_method_tag(census_op_id op_id, const char *method) {
+  int ret = 0;
+  census_trace_obj *trace = NULL;
+  gpr_mu_lock(&g_mu);
+  trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
+  if (trace == NULL) {
+    ret = 1;
+  } else {
+    trace->method = gpr_strdup(method);
+  }
+  gpr_mu_unlock(&g_mu);
+  return ret;
+}
+
+void census_tracing_print(census_op_id op_id, const char *anno_txt) {
+  census_trace_obj *trace = NULL;
+  gpr_mu_lock(&g_mu);
+  trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
+  if (trace != NULL) {
+    census_trace_annotation *anno = gpr_malloc(sizeof(census_trace_annotation));
+    anno->ts = gpr_now(GPR_CLOCK_REALTIME);
+    {
+      char *d = anno->txt;
+      const char *s = anno_txt;
+      int n = 0;
+      for (; n < CENSUS_MAX_ANNOTATION_LENGTH && *s != '\0'; ++n) {
+        *d++ = *s++;
+      }
+      *d = '\0';
+    }
+    anno->next = trace->annotations;
+    trace->annotations = anno;
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+void census_tracing_end_op(census_op_id op_id) {
+  census_trace_obj *trace = NULL;
+  gpr_mu_lock(&g_mu);
+  trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
+  if (trace != NULL) {
+    trace->rpc_stats.elapsed_time_ms = gpr_timespec_to_micros(
+        gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), trace->ts));
+    gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us",
+            op_id_2_uint64(&op_id), trace->method,
+            trace->rpc_stats.elapsed_time_ms);
+    census_ht_erase(g_trace_store, op_id_as_key(&op_id));
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+void census_tracing_init(void) {
+  init_mutex_once();
+  gpr_mu_lock(&g_mu);
+  if (g_trace_store == NULL) {
+    g_id = 1;
+    g_trace_store = census_ht_create(&ht_opt);
+  } else {
+    gpr_log(GPR_ERROR, "Census trace store already initialized.");
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+void census_tracing_shutdown(void) {
+  gpr_mu_lock(&g_mu);
+  if (g_trace_store != NULL) {
+    census_ht_destroy(g_trace_store);
+    g_trace_store = NULL;
+  } else {
+    gpr_log(GPR_ERROR, "Census trace store is not initialized.");
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+void census_internal_lock_trace_store(void) { gpr_mu_lock(&g_mu); }
+
+void census_internal_unlock_trace_store(void) { gpr_mu_unlock(&g_mu); }
+
+census_trace_obj *census_get_trace_obj_locked(census_op_id op_id) {
+  if (g_trace_store == NULL) {
+    gpr_log(GPR_ERROR, "Census trace store is not initialized.");
+    return NULL;
+  }
+  return (census_trace_obj *)census_ht_find(g_trace_store,
+                                            op_id_as_key(&op_id));
+}
+
+const char *census_get_trace_method_name(const census_trace_obj *trace) {
+  return trace->method;
+}
+
+static census_trace_annotation *dup_annotation_chain(
+    census_trace_annotation *from) {
+  census_trace_annotation *ret = NULL;
+  census_trace_annotation **to = &ret;
+  for (; from != NULL; from = from->next) {
+    *to = gpr_malloc(sizeof(census_trace_annotation));
+    memcpy(*to, from, sizeof(census_trace_annotation));
+    to = &(*to)->next;
+  }
+  return ret;
+}
+
+static census_trace_obj *trace_obj_dup(census_trace_obj *from) {
+  census_trace_obj *to = NULL;
+  GPR_ASSERT(from != NULL);
+  to = gpr_malloc(sizeof(census_trace_obj));
+  to->id = from->id;
+  to->ts = from->ts;
+  to->rpc_stats = from->rpc_stats;
+  to->method = gpr_strdup(from->method);
+  to->annotations = dup_annotation_chain(from->annotations);
+  return to;
+}
+
+census_trace_obj **census_get_active_ops(int *num_active_ops) {
+  census_trace_obj **ret = NULL;
+  gpr_mu_lock(&g_mu);
+  if (g_trace_store != NULL) {
+    size_t n = 0;
+    census_ht_kv *all_kvs = census_ht_get_all_elements(g_trace_store, &n);
+    *num_active_ops = (int)n;
+    if (n != 0) {
+      size_t i = 0;
+      ret = gpr_malloc(sizeof(census_trace_obj *) * n);
+      for (i = 0; i < n; i++) {
+        ret[i] = trace_obj_dup((census_trace_obj *)all_kvs[i].v);
+      }
+    }
+    gpr_free(all_kvs);
+  }
+  gpr_mu_unlock(&g_mu);
+  return ret;
+}
diff --git a/src/core/ext/census/census_tracing.h b/src/core/ext/census/census_tracing.h
new file mode 100644
index 0000000..42a0d74
--- /dev/null
+++ b/src/core/ext/census/census_tracing.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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_EXT_CENSUS_CENSUS_TRACING_H
+#define GRPC_CORE_EXT_CENSUS_CENSUS_TRACING_H
+
+#include <grpc/support/time.h>
+#include "src/core/ext/census/census_rpc_stats.h"
+
+/* WARNING: The data structures and APIs provided by this file are for GRPC
+   library's internal use ONLY. They might be changed in backward-incompatible
+   ways and are not subject to any deprecation policy.
+   They are not recommended for external use.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Struct for a trace annotation. */
+typedef struct census_trace_annotation {
+  gpr_timespec ts;                            /* timestamp of the annotation */
+  char txt[CENSUS_MAX_ANNOTATION_LENGTH + 1]; /* actual txt annotation */
+  struct census_trace_annotation *next;
+} census_trace_annotation;
+
+typedef struct census_trace_obj {
+  census_op_id id;
+  gpr_timespec ts;
+  census_rpc_stats rpc_stats;
+  char *method;
+  census_trace_annotation *annotations;
+} census_trace_obj;
+
+/* Deletes trace object. */
+void census_trace_obj_destroy(census_trace_obj *obj);
+
+/* Initializes trace store. This function is thread safe. */
+void census_tracing_init(void);
+
+/* Shutsdown trace store. This function is thread safe. */
+void census_tracing_shutdown(void);
+
+/* Gets trace obj corresponding to the input op_id. Returns NULL if trace store
+   is not initialized or trace obj is not found. Requires trace store being
+   locked before calling this function. */
+census_trace_obj *census_get_trace_obj_locked(census_op_id op_id);
+
+/* The following two functions acquire and release the trace store global lock.
+   They are for census internal use only. */
+void census_internal_lock_trace_store(void);
+void census_internal_unlock_trace_store(void);
+
+/* Gets method name associated with the input trace object. */
+const char *census_get_trace_method_name(const census_trace_obj *trace);
+
+/* Returns an array of pointers to trace objects of currently active operations
+   and fills in number of active operations. Returns NULL if there are no active
+   operations.
+   Caller owns the returned objects. */
+census_trace_obj **census_get_active_ops(int *num_active_ops);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_TRACING_H */
diff --git a/src/core/ext/census/context.c b/src/core/ext/census/context.c
new file mode 100644
index 0000000..0dfc4ec
--- /dev/null
+++ b/src/core/ext/census/context.c
@@ -0,0 +1,509 @@
+/*
+ *
+ * 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/census.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
+#include <stdbool.h>
+#include <string.h>
+#include "src/core/lib/support/string.h"
+
+// Functions in this file support the public context API, including
+// encoding/decoding as part of context propagation across RPC's. The overall
+// requirements (in approximate priority order) for the
+// context representation:
+// 1. Efficient conversion to/from wire format
+// 2. Minimal bytes used on-wire
+// 3. Efficient context creation
+// 4. Efficient lookup of tag value for a key
+// 5. Efficient iteration over tags
+// 6. Minimal memory footprint
+//
+// Notes on tradeoffs/decisions:
+// * tag includes 1 byte length of key, as well as nil-terminating byte. These
+//   are to aid in efficient parsing and the ability to directly return key
+//   strings. This is more important than saving a single byte/tag on the wire.
+// * The wire encoding uses only single byte values. This eliminates the need
+//   to handle endian-ness conversions. It also means there is a hard upper
+//   limit of 255 for both CENSUS_MAX_TAG_KV_LEN and CENSUS_MAX_PROPAGATED_TAGS.
+// * Keep all tag information (keys/values/flags) in a single memory buffer,
+//   that can be directly copied to the wire.
+
+// min and max valid chars in tag keys and values. All printable ASCII is OK.
+#define MIN_VALID_TAG_CHAR 32   // ' '
+#define MAX_VALID_TAG_CHAR 126  // '~'
+
+// Structure representing a set of tags. Essentially a count of number of tags
+// present, and pointer to a chunk of memory that contains the per-tag details.
+struct tag_set {
+  int ntags;        // number of tags.
+  int ntags_alloc;  // ntags + number of deleted tags (total number of tags
+  // in all of kvm). This will always be == ntags, except during the process
+  // of building a new tag set.
+  size_t kvm_size;  // number of bytes allocated for key/value storage.
+  size_t kvm_used;  // number of bytes of used key/value memory
+  char *kvm;        // key/value memory. Consists of repeated entries of:
+  //   Offset  Size  Description
+  //     0      1    Key length, including trailing 0. (K)
+  //     1      1    Value length, including trailing 0 (V)
+  //     2      1    Flags
+  //     3      K    Key bytes
+  //     3 + K  V    Value bytes
+  //
+  // We refer to the first 3 entries as the 'tag header'. If extra values are
+  // introduced in the header, you will need to modify the TAG_HEADER_SIZE
+  // constant, the raw_tag structure (and everything that uses it) and the
+  // encode/decode functions appropriately.
+};
+
+// Number of bytes in tag header.
+#define TAG_HEADER_SIZE 3  // key length (1) + value length (1) + flags (1)
+// Offsets to tag header entries.
+#define KEY_LEN_OFFSET 0
+#define VALUE_LEN_OFFSET 1
+#define FLAG_OFFSET 2
+
+// raw_tag represents the raw-storage form of a tag in the kvm of a tag_set.
+struct raw_tag {
+  uint8_t key_len;
+  uint8_t value_len;
+  uint8_t flags;
+  char *key;
+  char *value;
+};
+
+// Use a reserved flag bit for indication of deleted tag.
+#define CENSUS_TAG_DELETED CENSUS_TAG_RESERVED
+#define CENSUS_TAG_IS_DELETED(flags) (flags & CENSUS_TAG_DELETED)
+
+// Primary representation of a context. Composed of 2 underlying tag_set
+// structs, one each for propagated and local (non-propagated) tags. This is
+// to efficiently support tag encoding/decoding.
+// TODO(aveitch): need to add tracing id's/structure.
+struct census_context {
+  struct tag_set tags[2];
+  census_context_status status;
+};
+
+// Indices into the tags member of census_context
+#define PROPAGATED_TAGS 0
+#define LOCAL_TAGS 1
+
+// Validate (check all characters are in range and size is less than limit) a
+// key or value string. Returns 0 if the string is invalid, or the length
+// (including terminator) if valid.
+static size_t validate_tag(const char *kv) {
+  size_t len = 1;
+  char ch;
+  while ((ch = *kv++) != 0) {
+    if (ch < MIN_VALID_TAG_CHAR || ch > MAX_VALID_TAG_CHAR) {
+      return 0;
+    }
+    len++;
+  }
+  if (len > CENSUS_MAX_TAG_KV_LEN) {
+    return 0;
+  }
+  return len;
+}
+
+// Extract a raw tag given a pointer (raw) to the tag header. Allow for some
+// extra bytes in the tag header (see encode/decode functions for usage: this
+// allows for future expansion of the tag header).
+static char *decode_tag(struct raw_tag *tag, char *header, int offset) {
+  tag->key_len = (uint8_t)(*header++);
+  tag->value_len = (uint8_t)(*header++);
+  tag->flags = (uint8_t)(*header++);
+  header += offset;
+  tag->key = header;
+  header += tag->key_len;
+  tag->value = header;
+  return header + tag->value_len;
+}
+
+// Make a copy (in 'to') of an existing tag_set.
+static void tag_set_copy(struct tag_set *to, const struct tag_set *from) {
+  memcpy(to, from, sizeof(struct tag_set));
+  to->kvm = gpr_malloc(to->kvm_size);
+  memcpy(to->kvm, from->kvm, from->kvm_used);
+}
+
+// Delete a tag from a tag_set, if it exists (returns true if it did).
+static bool tag_set_delete_tag(struct tag_set *tags, const char *key,
+                               size_t key_len) {
+  char *kvp = tags->kvm;
+  for (int i = 0; i < tags->ntags_alloc; i++) {
+    uint8_t *flags = (uint8_t *)(kvp + FLAG_OFFSET);
+    struct raw_tag tag;
+    kvp = decode_tag(&tag, kvp, 0);
+    if (CENSUS_TAG_IS_DELETED(tag.flags)) continue;
+    if ((key_len == tag.key_len) && (memcmp(key, tag.key, key_len) == 0)) {
+      *flags |= CENSUS_TAG_DELETED;
+      tags->ntags--;
+      return true;
+    }
+  }
+  return false;
+}
+
+// Delete a tag from a context, return true if it existed.
+static bool context_delete_tag(census_context *context, const census_tag *tag,
+                               size_t key_len) {
+  return (
+      tag_set_delete_tag(&context->tags[LOCAL_TAGS], tag->key, key_len) ||
+      tag_set_delete_tag(&context->tags[PROPAGATED_TAGS], tag->key, key_len));
+}
+
+// Add a tag to a tag_set. Return true on success, false if the tag could
+// not be added because of constraints on tag set size. This function should
+// not be called if the tag may already exist (in a non-deleted state) in
+// the tag_set, as that would result in two tags with the same key.
+static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
+                            size_t key_len, size_t value_len) {
+  if (tags->ntags == CENSUS_MAX_PROPAGATED_TAGS) {
+    return false;
+  }
+  const size_t tag_size = key_len + value_len + TAG_HEADER_SIZE;
+  if (tags->kvm_used + tag_size > tags->kvm_size) {
+    // allocate new memory if needed
+    tags->kvm_size += 2 * CENSUS_MAX_TAG_KV_LEN + TAG_HEADER_SIZE;
+    char *new_kvm = gpr_malloc(tags->kvm_size);
+    memcpy(new_kvm, tags->kvm, tags->kvm_used);
+    gpr_free(tags->kvm);
+    tags->kvm = new_kvm;
+  }
+  char *kvp = tags->kvm + tags->kvm_used;
+  *kvp++ = (char)key_len;
+  *kvp++ = (char)value_len;
+  // ensure reserved flags are not used.
+  *kvp++ = (char)(tag->flags & (CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS));
+  memcpy(kvp, tag->key, key_len);
+  kvp += key_len;
+  memcpy(kvp, tag->value, value_len);
+  tags->kvm_used += tag_size;
+  tags->ntags++;
+  tags->ntags_alloc++;
+  return true;
+}
+
+// Add/modify/delete a tag to/in a context. Caller must validate that tag key
+// etc. are valid.
+static void context_modify_tag(census_context *context, const census_tag *tag,
+                               size_t key_len, size_t value_len) {
+  // First delete the tag if it is already present.
+  bool deleted = context_delete_tag(context, tag, key_len);
+  bool added = false;
+  if (CENSUS_TAG_IS_PROPAGATED(tag->flags)) {
+    added = tag_set_add_tag(&context->tags[PROPAGATED_TAGS], tag, key_len,
+                            value_len);
+  } else {
+    added =
+        tag_set_add_tag(&context->tags[LOCAL_TAGS], tag, key_len, value_len);
+  }
+
+  if (deleted) {
+    context->status.n_modified_tags++;
+  } else {
+    if (added) {
+      context->status.n_added_tags++;
+    } else {
+      context->status.n_ignored_tags++;
+    }
+  }
+}
+
+// Remove memory used for deleted tags from a tag set. Basic algorithm:
+// 1) Walk through tag set to find first deleted tag. Record where it is.
+// 2) Find the next not-deleted tag. Copy all of kvm from there to the end
+//    "over" the deleted tags
+// 3) repeat #1 and #2 until we have seen all tags
+// 4) if we are still looking for a not-deleted tag, then all the end portion
+//    of the kvm is deleted. Just reduce the used amount of memory by the
+//    appropriate amount.
+static void tag_set_flatten(struct tag_set *tags) {
+  if (tags->ntags == tags->ntags_alloc) return;
+  bool found_deleted = false;  // found a deleted tag.
+  char *kvp = tags->kvm;
+  char *dbase = NULL;  // record location of deleted tag
+  for (int i = 0; i < tags->ntags_alloc; i++) {
+    struct raw_tag tag;
+    char *next_kvp = decode_tag(&tag, kvp, 0);
+    if (found_deleted) {
+      if (!CENSUS_TAG_IS_DELETED(tag.flags)) {
+        ptrdiff_t reduce = kvp - dbase;  // #bytes in deleted tags
+        GPR_ASSERT(reduce > 0);
+        ptrdiff_t copy_size = tags->kvm + tags->kvm_used - kvp;
+        GPR_ASSERT(copy_size > 0);
+        memmove(dbase, kvp, (size_t)copy_size);
+        tags->kvm_used -= (size_t)reduce;
+        next_kvp -= reduce;
+        found_deleted = false;
+      }
+    } else {
+      if (CENSUS_TAG_IS_DELETED(tag.flags)) {
+        dbase = kvp;
+        found_deleted = true;
+      }
+    }
+    kvp = next_kvp;
+  }
+  if (found_deleted) {
+    GPR_ASSERT(dbase > tags->kvm);
+    tags->kvm_used = (size_t)(dbase - tags->kvm);
+  }
+  tags->ntags_alloc = tags->ntags;
+}
+
+census_context *census_context_create(const census_context *base,
+                                      const census_tag *tags, int ntags,
+                                      census_context_status const **status) {
+  census_context *context = gpr_malloc(sizeof(census_context));
+  // If we are given a base, copy it into our new tag set. Otherwise set it
+  // to zero/NULL everything.
+  if (base == NULL) {
+    memset(context, 0, sizeof(census_context));
+  } else {
+    tag_set_copy(&context->tags[PROPAGATED_TAGS], &base->tags[PROPAGATED_TAGS]);
+    tag_set_copy(&context->tags[LOCAL_TAGS], &base->tags[LOCAL_TAGS]);
+    memset(&context->status, 0, sizeof(context->status));
+  }
+  // Walk over the additional tags and, for those that aren't invalid, modify
+  // the context to add/replace/delete as required.
+  for (int i = 0; i < ntags; i++) {
+    const census_tag *tag = &tags[i];
+    size_t key_len = validate_tag(tag->key);
+    // ignore the tag if it is invalid or too short.
+    if (key_len <= 1) {
+      context->status.n_invalid_tags++;
+    } else {
+      if (tag->value != NULL) {
+        size_t value_len = validate_tag(tag->value);
+        if (value_len != 0) {
+          context_modify_tag(context, tag, key_len, value_len);
+        } else {
+          context->status.n_invalid_tags++;
+        }
+      } else {
+        if (context_delete_tag(context, tag, key_len)) {
+          context->status.n_deleted_tags++;
+        }
+      }
+    }
+  }
+  // Remove any deleted tags, update status if needed, and return.
+  tag_set_flatten(&context->tags[PROPAGATED_TAGS]);
+  tag_set_flatten(&context->tags[LOCAL_TAGS]);
+  context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
+  context->status.n_local_tags = context->tags[LOCAL_TAGS].ntags;
+  if (status) {
+    *status = &context->status;
+  }
+  return context;
+}
+
+const census_context_status *census_context_get_status(
+    const census_context *context) {
+  return &context->status;
+}
+
+void census_context_destroy(census_context *context) {
+  gpr_free(context->tags[PROPAGATED_TAGS].kvm);
+  gpr_free(context->tags[LOCAL_TAGS].kvm);
+  gpr_free(context);
+}
+
+void census_context_initialize_iterator(const census_context *context,
+                                        census_context_iterator *iterator) {
+  iterator->context = context;
+  iterator->index = 0;
+  if (context->tags[PROPAGATED_TAGS].ntags != 0) {
+    iterator->base = PROPAGATED_TAGS;
+    iterator->kvm = context->tags[PROPAGATED_TAGS].kvm;
+  } else if (context->tags[LOCAL_TAGS].ntags != 0) {
+    iterator->base = LOCAL_TAGS;
+    iterator->kvm = context->tags[LOCAL_TAGS].kvm;
+  } else {
+    iterator->base = -1;
+  }
+}
+
+int census_context_next_tag(census_context_iterator *iterator,
+                            census_tag *tag) {
+  if (iterator->base < 0) {
+    return 0;
+  }
+  struct raw_tag raw;
+  iterator->kvm = decode_tag(&raw, iterator->kvm, 0);
+  tag->key = raw.key;
+  tag->value = raw.value;
+  tag->flags = raw.flags;
+  if (++iterator->index == iterator->context->tags[iterator->base].ntags) {
+    do {
+      if (iterator->base == LOCAL_TAGS) {
+        iterator->base = -1;
+        return 1;
+      }
+    } while (iterator->context->tags[++iterator->base].ntags == 0);
+    iterator->index = 0;
+    iterator->kvm = iterator->context->tags[iterator->base].kvm;
+  }
+  return 1;
+}
+
+// Find a tag in a tag_set by key. Return true if found, false otherwise.
+static bool tag_set_get_tag(const struct tag_set *tags, const char *key,
+                            size_t key_len, census_tag *tag) {
+  char *kvp = tags->kvm;
+  for (int i = 0; i < tags->ntags; i++) {
+    struct raw_tag raw;
+    kvp = decode_tag(&raw, kvp, 0);
+    if (key_len == raw.key_len && memcmp(raw.key, key, key_len) == 0) {
+      tag->key = raw.key;
+      tag->value = raw.value;
+      tag->flags = raw.flags;
+      return true;
+    }
+  }
+  return false;
+}
+
+int census_context_get_tag(const census_context *context, const char *key,
+                           census_tag *tag) {
+  size_t key_len = strlen(key) + 1;
+  if (key_len == 1) {
+    return 0;
+  }
+  if (tag_set_get_tag(&context->tags[PROPAGATED_TAGS], key, key_len, tag) ||
+      tag_set_get_tag(&context->tags[LOCAL_TAGS], key, key_len, tag)) {
+    return 1;
+  }
+  return 0;
+}
+
+// Context encoding and decoding functions.
+//
+// Wire format for tag_set's on the wire:
+//
+// First, a tag set header:
+//
+// offset   bytes  description
+//   0        1    version number
+//   1        1    number of bytes in this header. This allows for future
+//                 expansion.
+//   2        1    number of bytes in each tag header.
+//   3        1    ntags value from tag set.
+//
+//   This is followed by the key/value memory from struct tag_set.
+
+#define ENCODED_VERSION 0      // Version number
+#define ENCODED_HEADER_SIZE 4  // size of tag set header
+
+// Encode a tag set. Returns 0 if buffer is too small.
+static size_t tag_set_encode(const struct tag_set *tags, char *buffer,
+                             size_t buf_size) {
+  if (buf_size < ENCODED_HEADER_SIZE + tags->kvm_used) {
+    return 0;
+  }
+  buf_size -= ENCODED_HEADER_SIZE;
+  *buffer++ = (char)ENCODED_VERSION;
+  *buffer++ = (char)ENCODED_HEADER_SIZE;
+  *buffer++ = (char)TAG_HEADER_SIZE;
+  *buffer++ = (char)tags->ntags;
+  if (tags->ntags == 0) {
+    return ENCODED_HEADER_SIZE;
+  }
+  memcpy(buffer, tags->kvm, tags->kvm_used);
+  return ENCODED_HEADER_SIZE + tags->kvm_used;
+}
+
+size_t census_context_encode(const census_context *context, char *buffer,
+                             size_t buf_size) {
+  return tag_set_encode(&context->tags[PROPAGATED_TAGS], buffer, buf_size);
+}
+
+// Decode a tag set.
+static void tag_set_decode(struct tag_set *tags, const char *buffer,
+                           size_t size) {
+  uint8_t version = (uint8_t)(*buffer++);
+  uint8_t header_size = (uint8_t)(*buffer++);
+  uint8_t tag_header_size = (uint8_t)(*buffer++);
+  tags->ntags = tags->ntags_alloc = (int)(*buffer++);
+  if (tags->ntags == 0) {
+    tags->ntags_alloc = 0;
+    tags->kvm_size = 0;
+    tags->kvm_used = 0;
+    tags->kvm = NULL;
+    return;
+  }
+  if (header_size != ENCODED_HEADER_SIZE) {
+    GPR_ASSERT(version != ENCODED_VERSION);
+    GPR_ASSERT(ENCODED_HEADER_SIZE < header_size);
+    buffer += (header_size - ENCODED_HEADER_SIZE);
+  }
+  tags->kvm_used = size - header_size;
+  tags->kvm_size = tags->kvm_used + CENSUS_MAX_TAG_KV_LEN;
+  tags->kvm = gpr_malloc(tags->kvm_size);
+  if (tag_header_size != TAG_HEADER_SIZE) {
+    // something new in the tag information. I don't understand it, so
+    // don't copy it over.
+    GPR_ASSERT(version != ENCODED_VERSION);
+    GPR_ASSERT(tag_header_size > TAG_HEADER_SIZE);
+    char *kvp = tags->kvm;
+    for (int i = 0; i < tags->ntags; i++) {
+      memcpy(kvp, buffer, TAG_HEADER_SIZE);
+      kvp += header_size;
+      struct raw_tag raw;
+      buffer =
+          decode_tag(&raw, (char *)buffer, tag_header_size - TAG_HEADER_SIZE);
+      memcpy(kvp, raw.key, (size_t)raw.key_len + raw.value_len);
+      kvp += raw.key_len + raw.value_len;
+    }
+  } else {
+    memcpy(tags->kvm, buffer, tags->kvm_used);
+  }
+}
+
+census_context *census_context_decode(const char *buffer, size_t size) {
+  census_context *context = gpr_malloc(sizeof(census_context));
+  memset(&context->tags[LOCAL_TAGS], 0, sizeof(struct tag_set));
+  if (buffer == NULL) {
+    memset(&context->tags[PROPAGATED_TAGS], 0, sizeof(struct tag_set));
+  } else {
+    tag_set_decode(&context->tags[PROPAGATED_TAGS], buffer, size);
+  }
+  memset(&context->status, 0, sizeof(context->status));
+  context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
+  return context;
+}
diff --git a/src/core/ext/census/grpc_context.c b/src/core/ext/census/grpc_context.c
new file mode 100644
index 0000000..98285ab
--- /dev/null
+++ b/src/core/ext/census/grpc_context.c
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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/census.h>
+#include <grpc/grpc.h>
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+
+void grpc_census_call_set_context(grpc_call *call, census_context *context) {
+  GRPC_API_TRACE("grpc_census_call_set_context(call=%p, census_context=%p)", 2,
+                 (call, context));
+  if (census_enabled() == CENSUS_FEATURE_NONE) {
+    return;
+  }
+  if (context != NULL) {
+    grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context, NULL);
+  }
+}
+
+census_context *grpc_census_call_get_context(grpc_call *call) {
+  GRPC_API_TRACE("grpc_census_call_get_context(call=%p)", 1, (call));
+  return (census_context *)grpc_call_context_get(call, GRPC_CONTEXT_TRACING);
+}
diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c
new file mode 100644
index 0000000..abfb3bb
--- /dev/null
+++ b/src/core/ext/census/grpc_filter.c
@@ -0,0 +1,198 @@
+/*
+ *
+ * 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/ext/census/grpc_filter.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/census.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/time.h>
+
+#include "src/core/ext/census/census_interface.h"
+#include "src/core/ext/census/census_rpc_stats.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+typedef struct call_data {
+  census_op_id op_id;
+  census_context *ctxt;
+  gpr_timespec start_ts;
+  int error;
+
+  /* recv callback */
+  grpc_metadata_batch *recv_initial_metadata;
+  grpc_closure *on_done_recv;
+  grpc_closure finish_recv;
+} call_data;
+
+typedef struct channel_data { uint8_t unused; } channel_data;
+
+static void extract_and_annotate_method_tag(grpc_metadata_batch *md,
+                                            call_data *calld,
+                                            channel_data *chand) {
+  grpc_linked_mdelem *m;
+  for (m = md->list.head; m != NULL; m = m->next) {
+    if (m->md->key == GRPC_MDSTR_PATH) {
+      gpr_log(GPR_DEBUG, "%s",
+              (const char *)GPR_SLICE_START_PTR(m->md->value->slice));
+      /* Add method tag here */
+    }
+  }
+}
+
+static void client_mutate_op(grpc_call_element *elem,
+                             grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  if (op->send_initial_metadata) {
+    extract_and_annotate_method_tag(op->send_initial_metadata, calld, chand);
+  }
+}
+
+static void client_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                      grpc_call_element *elem,
+                                      grpc_transport_stream_op *op) {
+  client_mutate_op(elem, op);
+  grpc_call_next_op(exec_ctx, elem, op);
+}
+
+static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
+                                bool success) {
+  grpc_call_element *elem = ptr;
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  if (success) {
+    extract_and_annotate_method_tag(calld->recv_initial_metadata, calld, chand);
+  }
+  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+}
+
+static void server_mutate_op(grpc_call_element *elem,
+                             grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+  if (op->recv_initial_metadata) {
+    /* substitute our callback for the op callback */
+    calld->recv_initial_metadata = op->recv_initial_metadata;
+    calld->on_done_recv = op->recv_initial_metadata_ready;
+    op->recv_initial_metadata_ready = &calld->finish_recv;
+  }
+}
+
+static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                      grpc_call_element *elem,
+                                      grpc_transport_stream_op *op) {
+  /* TODO(ctiller): this code fails. I don't know why. I expect it's
+                    incomplete, and someone should look at it soon.
+
+  call_data *calld = elem->call_data;
+  GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); */
+  server_mutate_op(elem, op);
+  grpc_call_next_op(exec_ctx, elem, op);
+}
+
+static void client_init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
+  call_data *d = elem->call_data;
+  GPR_ASSERT(d != NULL);
+  memset(d, 0, sizeof(*d));
+  d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
+}
+
+static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_element *elem) {
+  call_data *d = elem->call_data;
+  GPR_ASSERT(d != NULL);
+  /* TODO(hongyu): record rpc client stats and census_rpc_end_op here */
+}
+
+static void server_init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
+  call_data *d = elem->call_data;
+  GPR_ASSERT(d != NULL);
+  memset(d, 0, sizeof(*d));
+  d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
+  /* TODO(hongyu): call census_tracing_start_op here. */
+  grpc_closure_init(&d->finish_recv, server_on_done_recv, elem);
+}
+
+static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_element *elem) {
+  call_data *d = elem->call_data;
+  GPR_ASSERT(d != NULL);
+  /* TODO(hongyu): record rpc server stats and census_tracing_end_op here */
+}
+
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  channel_data *chand = elem->channel_data;
+  GPR_ASSERT(chand != NULL);
+}
+
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {
+  channel_data *chand = elem->channel_data;
+  GPR_ASSERT(chand != NULL);
+}
+
+const grpc_channel_filter grpc_client_census_filter = {
+    client_start_transport_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    client_init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    client_destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "census-client"};
+
+const grpc_channel_filter grpc_server_census_filter = {
+    server_start_transport_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    server_init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    server_destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "census-server"};
diff --git a/src/core/ext/census/grpc_filter.h b/src/core/ext/census/grpc_filter.h
new file mode 100644
index 0000000..a39bd82
--- /dev/null
+++ b/src/core/ext/census/grpc_filter.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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_EXT_CENSUS_GRPC_FILTER_H
+#define GRPC_CORE_EXT_CENSUS_GRPC_FILTER_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+/* Census filters: provides tracing and stats collection functionalities. It
+   needs to reside right below the surface filter in the channel stack. */
+extern const grpc_channel_filter grpc_client_census_filter;
+extern const grpc_channel_filter grpc_server_census_filter;
+
+#endif /* GRPC_CORE_EXT_CENSUS_GRPC_FILTER_H */
diff --git a/src/core/ext/census/grpc_plugin.c b/src/core/ext/census/grpc_plugin.c
new file mode 100644
index 0000000..e43ceaf
--- /dev/null
+++ b/src/core/ext/census/grpc_plugin.c
@@ -0,0 +1,82 @@
+/*
+ *
+ * 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 <limits.h>
+#include <string.h>
+
+#include <grpc/census.h>
+
+#include "src/core/ext/census/grpc_filter.h"
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/surface/channel_init.h"
+
+static bool is_census_enabled(const grpc_channel_args *a) {
+  size_t i;
+  if (a == NULL) return 0;
+  for (i = 0; i < a->num_args; i++) {
+    if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_CENSUS)) {
+      return a->args[i].value.integer != 0 && census_enabled();
+    }
+  }
+  return census_enabled();
+}
+
+static bool maybe_add_census_filter(grpc_channel_stack_builder *builder,
+                                    void *arg) {
+  const grpc_channel_args *args =
+      grpc_channel_stack_builder_get_channel_arguments(builder);
+  if (is_census_enabled(args)) {
+    return grpc_channel_stack_builder_prepend_filter(
+        builder, (const grpc_channel_filter *)arg, NULL, NULL);
+  }
+  return true;
+}
+
+void census_grpc_plugin_init(void) {
+  /* Only initialize census if no one else has and some features are
+   * available. */
+  if (census_enabled() == CENSUS_FEATURE_NONE &&
+      census_supported() != CENSUS_FEATURE_NONE) {
+    if (census_initialize(census_supported())) { /* enable all features. */
+      gpr_log(GPR_ERROR, "Could not initialize census.");
+    }
+  }
+  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
+                                   maybe_add_census_filter,
+                                   (void *)&grpc_client_census_filter);
+  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
+                                   maybe_add_census_filter,
+                                   (void *)&grpc_server_census_filter);
+}
+
+void census_grpc_plugin_shutdown(void) { census_shutdown(); }
diff --git a/src/core/ext/census/hash_table.c b/src/core/ext/census/hash_table.c
new file mode 100644
index 0000000..ee6fdfc
--- /dev/null
+++ b/src/core/ext/census/hash_table.c
@@ -0,0 +1,303 @@
+/*
+ *
+ * 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/ext/census/hash_table.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+
+#define CENSUS_HT_NUM_BUCKETS 1999
+
+/* A single hash table data entry */
+typedef struct ht_entry {
+  census_ht_key key;
+  void *data;
+  struct ht_entry *next;
+} ht_entry;
+
+/* hash table bucket */
+typedef struct bucket {
+  /* NULL if bucket is empty */
+  ht_entry *next;
+  /* -1 if all buckets are empty. */
+  int32_t prev_non_empty_bucket;
+  /* -1 if all buckets are empty. */
+  int32_t next_non_empty_bucket;
+} bucket;
+
+struct unresizable_hash_table {
+  /* Number of entries in the table */
+  size_t size;
+  /* Number of buckets */
+  uint32_t num_buckets;
+  /* Array of buckets initialized at creation time. Memory consumption is
+     16 bytes per bucket on a 64-bit platform. */
+  bucket *buckets;
+  /* Index of the first non-empty bucket. -1 iff size == 0. */
+  int32_t first_non_empty_bucket;
+  /* Index of the last non_empty bucket. -1 iff size == 0. */
+  int32_t last_non_empty_bucket;
+  /* Immutable options of this hash table, initialized at creation time. */
+  census_ht_option options;
+};
+
+typedef struct entry_locator {
+  int32_t bucket_idx;
+  int is_first_in_chain;
+  int found;
+  ht_entry *prev_entry;
+} entry_locator;
+
+/* Asserts if option is not valid. */
+void check_options(const census_ht_option *option) {
+  GPR_ASSERT(option != NULL);
+  GPR_ASSERT(option->num_buckets > 0);
+  GPR_ASSERT(option->key_type == CENSUS_HT_UINT64 ||
+             option->key_type == CENSUS_HT_POINTER);
+  if (option->key_type == CENSUS_HT_UINT64) {
+    GPR_ASSERT(option->hash == NULL);
+  } else if (option->key_type == CENSUS_HT_POINTER) {
+    GPR_ASSERT(option->hash != NULL);
+    GPR_ASSERT(option->compare_keys != NULL);
+  }
+}
+
+#define REMOVE_NEXT(options, ptr) \
+  do {                            \
+    ht_entry *tmp = (ptr)->next;  \
+    (ptr)->next = tmp->next;      \
+    delete_entry(options, tmp);   \
+  } while (0)
+
+static void delete_entry(const census_ht_option *opt, ht_entry *p) {
+  if (opt->delete_data != NULL) {
+    opt->delete_data(p->data);
+  }
+  if (opt->delete_key != NULL) {
+    opt->delete_key(p->key.ptr);
+  }
+  gpr_free(p);
+}
+
+static uint64_t hash(const census_ht_option *opt, census_ht_key key) {
+  return opt->key_type == CENSUS_HT_UINT64 ? key.val : opt->hash(key.ptr);
+}
+
+census_ht *census_ht_create(const census_ht_option *option) {
+  int i;
+  census_ht *ret = NULL;
+  check_options(option);
+  ret = (census_ht *)gpr_malloc(sizeof(census_ht));
+  ret->size = 0;
+  ret->num_buckets = option->num_buckets;
+  ret->buckets = (bucket *)gpr_malloc(sizeof(bucket) * ret->num_buckets);
+  ret->options = *option;
+  /* initialize each bucket */
+  for (i = 0; i < ret->options.num_buckets; i++) {
+    ret->buckets[i].prev_non_empty_bucket = -1;
+    ret->buckets[i].next_non_empty_bucket = -1;
+    ret->buckets[i].next = NULL;
+  }
+  return ret;
+}
+
+static int32_t find_bucket_idx(const census_ht *ht, census_ht_key key) {
+  return hash(&ht->options, key) % ht->num_buckets;
+}
+
+static int keys_match(const census_ht_option *opt, const ht_entry *p,
+                      const census_ht_key key) {
+  GPR_ASSERT(opt->key_type == CENSUS_HT_UINT64 ||
+             opt->key_type == CENSUS_HT_POINTER);
+  if (opt->key_type == CENSUS_HT_UINT64) return p->key.val == key.val;
+  return !opt->compare_keys((p->key).ptr, key.ptr);
+}
+
+static entry_locator ht_find(const census_ht *ht, census_ht_key key) {
+  entry_locator loc = {0, 0, 0, NULL};
+  int32_t idx = 0;
+  ht_entry *ptr = NULL;
+  GPR_ASSERT(ht != NULL);
+  idx = find_bucket_idx(ht, key);
+  ptr = ht->buckets[idx].next;
+  if (ptr == NULL) {
+    /* bucket is empty */
+    return loc;
+  }
+  if (keys_match(&ht->options, ptr, key)) {
+    loc.bucket_idx = idx;
+    loc.is_first_in_chain = 1;
+    loc.found = 1;
+    return loc;
+  } else {
+    for (; ptr->next != NULL; ptr = ptr->next) {
+      if (keys_match(&ht->options, ptr->next, key)) {
+        loc.bucket_idx = idx;
+        loc.is_first_in_chain = 0;
+        loc.found = 1;
+        loc.prev_entry = ptr;
+        return loc;
+      }
+    }
+  }
+  /* Could not find the key */
+  return loc;
+}
+
+void *census_ht_find(const census_ht *ht, census_ht_key key) {
+  entry_locator loc = ht_find(ht, key);
+  if (loc.found == 0) {
+    return NULL;
+  }
+  return loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next->data
+                               : loc.prev_entry->next->data;
+}
+
+void census_ht_insert(census_ht *ht, census_ht_key key, void *data) {
+  int32_t idx = find_bucket_idx(ht, key);
+  ht_entry *ptr = NULL;
+  entry_locator loc = ht_find(ht, key);
+  if (loc.found) {
+    /* Replace old value with new value. */
+    ptr = loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next
+                                : loc.prev_entry->next;
+    if (ht->options.delete_data != NULL) {
+      ht->options.delete_data(ptr->data);
+    }
+    ptr->data = data;
+    return;
+  }
+
+  /* first entry in the table. */
+  if (ht->size == 0) {
+    ht->buckets[idx].next_non_empty_bucket = -1;
+    ht->buckets[idx].prev_non_empty_bucket = -1;
+    ht->first_non_empty_bucket = idx;
+    ht->last_non_empty_bucket = idx;
+  } else if (ht->buckets[idx].next == NULL) {
+    /* first entry in the bucket. */
+    ht->buckets[ht->last_non_empty_bucket].next_non_empty_bucket = idx;
+    ht->buckets[idx].prev_non_empty_bucket = ht->last_non_empty_bucket;
+    ht->buckets[idx].next_non_empty_bucket = -1;
+    ht->last_non_empty_bucket = idx;
+  }
+  ptr = (ht_entry *)gpr_malloc(sizeof(ht_entry));
+  ptr->key = key;
+  ptr->data = data;
+  ptr->next = ht->buckets[idx].next;
+  ht->buckets[idx].next = ptr;
+  ht->size++;
+}
+
+void census_ht_erase(census_ht *ht, census_ht_key key) {
+  entry_locator loc = ht_find(ht, key);
+  if (loc.found == 0) {
+    /* noop if not found */
+    return;
+  }
+  ht->size--;
+  if (loc.is_first_in_chain) {
+    bucket *b = &ht->buckets[loc.bucket_idx];
+    GPR_ASSERT(b->next != NULL);
+    /* The only entry in the bucket */
+    if (b->next->next == NULL) {
+      int prev = b->prev_non_empty_bucket;
+      int next = b->next_non_empty_bucket;
+      if (prev != -1) {
+        ht->buckets[prev].next_non_empty_bucket = next;
+      } else {
+        ht->first_non_empty_bucket = next;
+      }
+      if (next != -1) {
+        ht->buckets[next].prev_non_empty_bucket = prev;
+      } else {
+        ht->last_non_empty_bucket = prev;
+      }
+    }
+    REMOVE_NEXT(&ht->options, b);
+  } else {
+    GPR_ASSERT(loc.prev_entry->next != NULL);
+    REMOVE_NEXT(&ht->options, loc.prev_entry);
+  }
+}
+
+/* Returns NULL if input table is empty. */
+census_ht_kv *census_ht_get_all_elements(const census_ht *ht, size_t *num) {
+  census_ht_kv *ret = NULL;
+  int i = 0;
+  int32_t idx = -1;
+  GPR_ASSERT(ht != NULL && num != NULL);
+  *num = ht->size;
+  if (*num == 0) {
+    return NULL;
+  }
+
+  ret = (census_ht_kv *)gpr_malloc(sizeof(census_ht_kv) * ht->size);
+  idx = ht->first_non_empty_bucket;
+  while (idx >= 0) {
+    ht_entry *ptr = ht->buckets[idx].next;
+    for (; ptr != NULL; ptr = ptr->next) {
+      ret[i].k = ptr->key;
+      ret[i].v = ptr->data;
+      i++;
+    }
+    idx = ht->buckets[idx].next_non_empty_bucket;
+  }
+  return ret;
+}
+
+static void ht_delete_entry_chain(const census_ht_option *options,
+                                  ht_entry *first) {
+  if (first == NULL) {
+    return;
+  }
+  if (first->next != NULL) {
+    ht_delete_entry_chain(options, first->next);
+  }
+  delete_entry(options, first);
+}
+
+void census_ht_destroy(census_ht *ht) {
+  unsigned i;
+  for (i = 0; i < ht->num_buckets; ++i) {
+    ht_delete_entry_chain(&ht->options, ht->buckets[i].next);
+  }
+  gpr_free(ht->buckets);
+  gpr_free(ht);
+}
+
+size_t census_ht_get_size(const census_ht *ht) { return ht->size; }
diff --git a/src/core/ext/census/hash_table.h b/src/core/ext/census/hash_table.h
new file mode 100644
index 0000000..30ea426
--- /dev/null
+++ b/src/core/ext/census/hash_table.h
@@ -0,0 +1,131 @@
+/*
+ *
+ * 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_EXT_CENSUS_HASH_TABLE_H
+#define GRPC_CORE_EXT_CENSUS_HASH_TABLE_H
+
+#include <stddef.h>
+
+#include <grpc/support/port_platform.h>
+
+/* A chain based hash table with fixed number of buckets.
+   Your probably shouldn't use this code directly. It is implemented for the
+   use case in census trace store and stats store, where number of entries in
+   the table is in the scale of upto several thousands, entries are added and
+   removed from the table very frequently (~100k/s), the frequency of find()
+   operations is roughly several times of the frequency of insert() and erase()
+   Comparing to find(), the insert(), erase() and get_all_entries() operations
+   are much less freqent (<1/s).
+
+   Per bucket memory overhead is about (8 + sizeof(intptr_t) bytes.
+   Per entry memory overhead is about (8 + 2 * sizeof(intptr_t) bytes.
+
+   All functions are not thread-safe. Synchronization will be provided in the
+   upper layer (in trace store and stats store).
+*/
+
+/* Opaque hash table struct */
+typedef struct unresizable_hash_table census_ht;
+
+/* Currently, the hash_table can take two types of keys. (uint64 for trace
+   store and const char* for stats store). */
+typedef union {
+  uint64_t val;
+  void *ptr;
+} census_ht_key;
+
+typedef enum census_ht_key_type {
+  CENSUS_HT_UINT64 = 0,
+  CENSUS_HT_POINTER = 1
+} census_ht_key_type;
+
+typedef struct census_ht_option {
+  /* Type of hash key */
+  census_ht_key_type key_type;
+  /* Desired number of buckets, preferably a prime number */
+  int32_t num_buckets;
+  /* Fucntion to calculate uint64 hash value of the key. Only takes effect if
+     key_type is POINTER. */
+  uint64_t (*hash)(const void *);
+  /* Function to compare two keys, returns 0 iff equal. Only takes effect if
+     key_type is POINTER */
+  int (*compare_keys)(const void *k1, const void *k2);
+  /* Value deleter. NULL if no specialized delete function is needed. */
+  void (*delete_data)(void *);
+  /* Key deleter. NULL if table does not own the key. (e.g. key is part of the
+     value or key is not owned by the table.) */
+  void (*delete_key)(void *);
+} census_ht_option;
+
+/* Creates a hashtable with fixed number of buckets according to the settings
+   specified in 'options' arg. Function pointers "hash" and "compare_keys" must
+   be provided if key_type is POINTER. Asserts if fail to create. */
+census_ht *census_ht_create(const census_ht_option *options);
+
+/* Deletes hash table instance. Frees all dynamic memory owned by ht.*/
+void census_ht_destroy(census_ht *ht);
+
+/* Inserts the input key-val pair into hash_table. If an entry with the same key
+   exists in the table, the corresponding value will be overwritten by the input
+   val. */
+void census_ht_insert(census_ht *ht, census_ht_key key, void *val);
+
+/* Returns pointer to data, returns NULL if not found. */
+void *census_ht_find(const census_ht *ht, census_ht_key key);
+
+/* Erase hash table entry with input key. Noop if key is not found. */
+void census_ht_erase(census_ht *ht, census_ht_key key);
+
+typedef struct census_ht_kv {
+  census_ht_key k;
+  void *v;
+} census_ht_kv;
+
+/* Returns an array of pointers to all values in the hash table. Order of the
+   elements can be arbitrary. Sets 'num' to the size of returned array. Caller
+   owns returned array. */
+census_ht_kv *census_ht_get_all_elements(const census_ht *ht, size_t *num);
+
+/* Returns number of elements kept. */
+size_t census_ht_get_size(const census_ht *ht);
+
+/* Functor applied on each key-value pair while iterating through entries in the
+   table. The functor should not mutate data. */
+typedef void (*census_ht_itr_cb)(census_ht_key key, const void *val_ptr,
+                                 void *state);
+
+/* Iterates through all key-value pairs in the hash_table. The callback function
+   should not invalidate data entries. */
+uint64_t census_ht_for_all(const census_ht *ht, census_ht_itr_cb);
+
+#endif /* GRPC_CORE_EXT_CENSUS_HASH_TABLE_H */
diff --git a/src/core/ext/census/initialize.c b/src/core/ext/census/initialize.c
new file mode 100644
index 0000000..896276e
--- /dev/null
+++ b/src/core/ext/census/initialize.c
@@ -0,0 +1,54 @@
+/*
+ *
+ * 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/census.h>
+
+static int features_enabled = CENSUS_FEATURE_NONE;
+
+int census_initialize(int features) {
+  if (features_enabled != CENSUS_FEATURE_NONE) {
+    // Must have been a previous call to census_initialize; return error
+    return 1;
+  }
+  features_enabled = features;
+  return 0;
+}
+
+void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; }
+
+int census_supported(void) {
+  /* TODO(aveitch): improve this as we implement features... */
+  return CENSUS_FEATURE_NONE;
+}
+
+int census_enabled(void) { return features_enabled; }
diff --git a/src/core/ext/census/mlog.c b/src/core/ext/census/mlog.c
new file mode 100644
index 0000000..698b709
--- /dev/null
+++ b/src/core/ext/census/mlog.c
@@ -0,0 +1,600 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+// Implements an efficient in-memory log, optimized for multiple writers and
+// a single reader. Available log space is divided up in blocks of
+// CENSUS_LOG_2_MAX_RECORD_SIZE bytes. A block can be in one of the following
+// three data structures:
+// - Free blocks (free_block_list)
+// - Blocks with unread data (dirty_block_list)
+// - Blocks currently attached to cores (core_local_blocks[])
+//
+// census_log_start_write() moves a block from core_local_blocks[] to the end of
+// dirty_block_list when block:
+// - is out-of-space OR
+// - has an incomplete record (an incomplete record occurs when a thread calls
+//   census_log_start_write() and is context-switched before calling
+//   census_log_end_write()
+// So, blocks in dirty_block_list are ordered, from oldest to newest, by the
+// time when block is detached from the core.
+//
+// census_log_read_next() first iterates over dirty_block_list and then
+// core_local_blocks[]. It moves completely read blocks from dirty_block_list
+// to free_block_list. Blocks in core_local_blocks[] are not freed, even when
+// completely read.
+//
+// If the log is configured to discard old records and free_block_list is empty,
+// census_log_start_write() iterates over dirty_block_list to allocate a
+// new block. It moves the oldest available block (no pending read/write) to
+// core_local_blocks[].
+//
+// core_local_block_struct is used to implement a map from core id to the block
+// associated with that core. This mapping is advisory. It is possible that the
+// block returned by this mapping is no longer associated with that core. This
+// mapping is updated, lazily, by census_log_start_write().
+//
+// Locking in block struct:
+//
+// Exclusive g_log.lock must be held before calling any functions operating on
+// block structs except census_log_start_write() and census_log_end_write().
+//
+// Writes to a block are serialized via writer_lock. census_log_start_write()
+// acquires this lock and census_log_end_write() releases it. On failure to
+// acquire the lock, writer allocates a new block for the current core and
+// updates core_local_block accordingly.
+//
+// Simultaneous read and write access is allowed. Readers can safely read up to
+// committed bytes (bytes_committed).
+//
+// reader_lock protects the block, currently being read, from getting recycled.
+// start_read() acquires reader_lock and end_read() releases the lock.
+//
+// Read/write access to a block is disabled via try_disable_access(). It returns
+// with both writer_lock and reader_lock held. These locks are subsequently
+// released by enable_access() to enable access to the block.
+//
+// A note on naming: Most function/struct names are prepended by cl_
+// (shorthand for census_log). Further, functions that manipulate structures
+// include the name of the structure, which will be passed as the first
+// argument. E.g. cl_block_initialize() will initialize a cl_block.
+
+#include "src/core/ext/census/mlog.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/cpu.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
+#include <stdbool.h>
+#include <string.h>
+
+// End of platform specific code
+
+typedef struct census_log_block_list_struct {
+  struct census_log_block_list_struct* next;
+  struct census_log_block_list_struct* prev;
+  struct census_log_block* block;
+} cl_block_list_struct;
+
+typedef struct census_log_block {
+  // Pointer to underlying buffer.
+  char* buffer;
+  gpr_atm writer_lock;
+  gpr_atm reader_lock;
+  // Keeps completely written bytes. Declared atomic because accessed
+  // simultaneously by reader and writer.
+  gpr_atm bytes_committed;
+  // Bytes already read.
+  size_t bytes_read;
+  // Links for list.
+  cl_block_list_struct link;
+// We want this structure to be cacheline aligned. We assume the following
+// sizes for the various parts on 32/64bit systems:
+// type                 32b size    64b size
+// char*                   4           8
+// 3x gpr_atm             12          24
+// size_t                  4           8
+// cl_block_list_struct   12          24
+// TOTAL                  32          64
+//
+// Depending on the size of our cacheline and the architecture, we
+// selectively add char buffering to this structure. The size is checked
+// via assert in census_log_initialize().
+#if defined(GPR_ARCH_64)
+#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 64)
+#else
+#if defined(GPR_ARCH_32)
+#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 32)
+#else
+#error "Unknown architecture"
+#endif
+#endif
+#if CL_BLOCK_PAD_SIZE > 0
+  char padding[CL_BLOCK_PAD_SIZE];
+#endif
+} cl_block;
+
+// A list of cl_blocks, doubly-linked through cl_block::link.
+typedef struct census_log_block_list {
+  int32_t count;            // Number of items in list.
+  cl_block_list_struct ht;  // head/tail of linked list.
+} cl_block_list;
+
+// Cacheline aligned block pointers to avoid false sharing. Block pointer must
+// be initialized via set_block(), before calling other functions
+typedef struct census_log_core_local_block {
+  gpr_atm block;
+// Ensure cachline alignment: we assume sizeof(gpr_atm) == 4 or 8
+#if defined(GPR_ARCH_64)
+#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 8)
+#else
+#if defined(GPR_ARCH_32)
+#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 4)
+#else
+#error "Unknown architecture"
+#endif
+#endif
+#if CL_CORE_LOCAL_BLOCK_PAD_SIZE > 0
+  char padding[CL_CORE_LOCAL_BLOCK_PAD_SIZE];
+#endif
+} cl_core_local_block;
+
+struct census_log {
+  int discard_old_records;
+  // Number of cores (aka hardware-contexts)
+  unsigned num_cores;
+  // number of CENSUS_LOG_2_MAX_RECORD_SIZE blocks in log
+  uint32_t num_blocks;
+  cl_block* blocks;                        // Block metadata.
+  cl_core_local_block* core_local_blocks;  // Keeps core to block mappings.
+  gpr_mu lock;
+  int initialized;  // has log been initialized?
+  // Keeps the state of the reader iterator. A value of 0 indicates that
+  // iterator has reached the end. census_log_init_reader() resets the value
+  // to num_core to restart iteration.
+  uint32_t read_iterator_state;
+  // Points to the block being read. If non-NULL, the block is locked for
+  // reading(block_being_read_->reader_lock is held).
+  cl_block* block_being_read;
+  char* buffer;
+  cl_block_list free_block_list;
+  cl_block_list dirty_block_list;
+  gpr_atm out_of_space_count;
+};
+
+// Single internal log.
+static struct census_log g_log;
+
+// Functions that operate on an atomic memory location used as a lock.
+
+// Returns non-zero if lock is acquired.
+static int cl_try_lock(gpr_atm* lock) { return gpr_atm_acq_cas(lock, 0, 1); }
+
+static void cl_unlock(gpr_atm* lock) { gpr_atm_rel_store(lock, 0); }
+
+// Functions that operate on cl_core_local_block's.
+
+static void cl_core_local_block_set_block(cl_core_local_block* clb,
+                                          cl_block* block) {
+  gpr_atm_rel_store(&clb->block, (gpr_atm)block);
+}
+
+static cl_block* cl_core_local_block_get_block(cl_core_local_block* clb) {
+  return (cl_block*)gpr_atm_acq_load(&clb->block);
+}
+
+// Functions that operate on cl_block_list_struct's.
+
+static void cl_block_list_struct_initialize(cl_block_list_struct* bls,
+                                            cl_block* block) {
+  bls->next = bls->prev = bls;
+  bls->block = block;
+}
+
+// Functions that operate on cl_block_list's.
+
+static void cl_block_list_initialize(cl_block_list* list) {
+  list->count = 0;
+  cl_block_list_struct_initialize(&list->ht, NULL);
+}
+
+// Returns head of *this, or NULL if empty.
+static cl_block* cl_block_list_head(cl_block_list* list) {
+  return list->ht.next->block;
+}
+
+// Insert element *e after *pos.
+static void cl_block_list_insert(cl_block_list* list, cl_block_list_struct* pos,
+                                 cl_block_list_struct* e) {
+  list->count++;
+  e->next = pos->next;
+  e->prev = pos;
+  e->next->prev = e;
+  e->prev->next = e;
+}
+
+// Insert block at the head of the list
+static void cl_block_list_insert_at_head(cl_block_list* list, cl_block* block) {
+  cl_block_list_insert(list, &list->ht, &block->link);
+}
+
+// Insert block at the tail of the list.
+static void cl_block_list_insert_at_tail(cl_block_list* list, cl_block* block) {
+  cl_block_list_insert(list, list->ht.prev, &block->link);
+}
+
+// Removes block *b. Requires *b be in the list.
+static void cl_block_list_remove(cl_block_list* list, cl_block* b) {
+  list->count--;
+  b->link.next->prev = b->link.prev;
+  b->link.prev->next = b->link.next;
+}
+
+// Functions that operate on cl_block's
+
+static void cl_block_initialize(cl_block* block, char* buffer) {
+  block->buffer = buffer;
+  gpr_atm_rel_store(&block->writer_lock, 0);
+  gpr_atm_rel_store(&block->reader_lock, 0);
+  gpr_atm_rel_store(&block->bytes_committed, 0);
+  block->bytes_read = 0;
+  cl_block_list_struct_initialize(&block->link, block);
+}
+
+// Guards against exposing partially written buffer to the reader.
+static void cl_block_set_bytes_committed(cl_block* block,
+                                         size_t bytes_committed) {
+  gpr_atm_rel_store(&block->bytes_committed, (gpr_atm)bytes_committed);
+}
+
+static size_t cl_block_get_bytes_committed(cl_block* block) {
+  return (size_t)gpr_atm_acq_load(&block->bytes_committed);
+}
+
+// Tries to disable future read/write access to this block. Succeeds if:
+// - no in-progress write AND
+// - no in-progress read AND
+// - 'discard_data' set to true OR no unread data
+// On success, clears the block state and returns with writer_lock_ and
+// reader_lock_ held. These locks are released by a subsequent
+// cl_block_access_enable() call.
+static bool cl_block_try_disable_access(cl_block* block, int discard_data) {
+  if (!cl_try_lock(&block->writer_lock)) {
+    return false;
+  }
+  if (!cl_try_lock(&block->reader_lock)) {
+    cl_unlock(&block->writer_lock);
+    return false;
+  }
+  if (!discard_data &&
+      (block->bytes_read != cl_block_get_bytes_committed(block))) {
+    cl_unlock(&block->reader_lock);
+    cl_unlock(&block->writer_lock);
+    return false;
+  }
+  cl_block_set_bytes_committed(block, 0);
+  block->bytes_read = 0;
+  return true;
+}
+
+static void cl_block_enable_access(cl_block* block) {
+  cl_unlock(&block->reader_lock);
+  cl_unlock(&block->writer_lock);
+}
+
+// Returns with writer_lock held.
+static void* cl_block_start_write(cl_block* block, size_t size) {
+  if (!cl_try_lock(&block->writer_lock)) {
+    return NULL;
+  }
+  size_t bytes_committed = cl_block_get_bytes_committed(block);
+  if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) {
+    cl_unlock(&block->writer_lock);
+    return NULL;
+  }
+  return block->buffer + bytes_committed;
+}
+
+// Releases writer_lock and increments committed bytes by 'bytes_written'.
+// 'bytes_written' must be <= 'size' specified in the corresponding
+// StartWrite() call. This function is thread-safe.
+static void cl_block_end_write(cl_block* block, size_t bytes_written) {
+  cl_block_set_bytes_committed(
+      block, cl_block_get_bytes_committed(block) + bytes_written);
+  cl_unlock(&block->writer_lock);
+}
+
+// Returns a pointer to the first unread byte in buffer. The number of bytes
+// available are returned in 'bytes_available'. Acquires reader lock that is
+// released by a subsequent cl_block_end_read() call. Returns NULL if:
+// - read in progress
+// - no data available
+static void* cl_block_start_read(cl_block* block, size_t* bytes_available) {
+  if (!cl_try_lock(&block->reader_lock)) {
+    return NULL;
+  }
+  // bytes_committed may change from under us. Use bytes_available to update
+  // bytes_read below.
+  size_t bytes_committed = cl_block_get_bytes_committed(block);
+  GPR_ASSERT(bytes_committed >= block->bytes_read);
+  *bytes_available = bytes_committed - block->bytes_read;
+  if (*bytes_available == 0) {
+    cl_unlock(&block->reader_lock);
+    return NULL;
+  }
+  void* record = block->buffer + block->bytes_read;
+  block->bytes_read += *bytes_available;
+  return record;
+}
+
+static void cl_block_end_read(cl_block* block) {
+  cl_unlock(&block->reader_lock);
+}
+
+// Internal functions operating on g_log
+
+// Allocates a new free block (or recycles an available dirty block if log is
+// configured to discard old records). Returns NULL if out-of-space.
+static cl_block* cl_allocate_block(void) {
+  cl_block* block = cl_block_list_head(&g_log.free_block_list);
+  if (block != NULL) {
+    cl_block_list_remove(&g_log.free_block_list, block);
+    return block;
+  }
+  if (!g_log.discard_old_records) {
+    // No free block and log is configured to keep old records.
+    return NULL;
+  }
+  // Recycle dirty block. Start from the oldest.
+  for (block = cl_block_list_head(&g_log.dirty_block_list); block != NULL;
+       block = block->link.next->block) {
+    if (cl_block_try_disable_access(block, 1 /* discard data */)) {
+      cl_block_list_remove(&g_log.dirty_block_list, block);
+      return block;
+    }
+  }
+  return NULL;
+}
+
+// Allocates a new block and updates core id => block mapping. 'old_block'
+// points to the block that the caller thinks is attached to
+// 'core_id'. 'old_block' may be NULL. Returns true if:
+// - allocated a new block OR
+// - 'core_id' => 'old_block' mapping changed (another thread allocated a
+//   block before lock was acquired).
+static bool cl_allocate_core_local_block(uint32_t core_id,
+                                         cl_block* old_block) {
+  // Now that we have the lock, check if core-local mapping has changed.
+  cl_core_local_block* core_local_block = &g_log.core_local_blocks[core_id];
+  cl_block* block = cl_core_local_block_get_block(core_local_block);
+  if ((block != NULL) && (block != old_block)) {
+    return true;
+  }
+  if (block != NULL) {
+    cl_core_local_block_set_block(core_local_block, NULL);
+    cl_block_list_insert_at_tail(&g_log.dirty_block_list, block);
+  }
+  block = cl_allocate_block();
+  if (block == NULL) {
+    return false;
+  }
+  cl_core_local_block_set_block(core_local_block, block);
+  cl_block_enable_access(block);
+  return true;
+}
+
+static cl_block* cl_get_block(void* record) {
+  uintptr_t p = (uintptr_t)((char*)record - g_log.buffer);
+  uintptr_t index = p >> CENSUS_LOG_2_MAX_RECORD_SIZE;
+  return &g_log.blocks[index];
+}
+
+// Gets the next block to read and tries to free 'prev' block (if not NULL).
+// Returns NULL if reached the end.
+static cl_block* cl_next_block_to_read(cl_block* prev) {
+  cl_block* block = NULL;
+  if (g_log.read_iterator_state == g_log.num_cores) {
+    // We are traversing dirty list; find the next dirty block.
+    if (prev != NULL) {
+      // Try to free the previous block if there is no unread data. This
+      // block
+      // may have unread data if previously incomplete record completed
+      // between
+      // read_next() calls.
+      block = prev->link.next->block;
+      if (cl_block_try_disable_access(prev, 0 /* do not discard data */)) {
+        cl_block_list_remove(&g_log.dirty_block_list, prev);
+        cl_block_list_insert_at_head(&g_log.free_block_list, prev);
+      }
+    } else {
+      block = cl_block_list_head(&g_log.dirty_block_list);
+    }
+    if (block != NULL) {
+      return block;
+    }
+    // We are done with the dirty list; moving on to core-local blocks.
+  }
+  while (g_log.read_iterator_state > 0) {
+    g_log.read_iterator_state--;
+    block = cl_core_local_block_get_block(
+        &g_log.core_local_blocks[g_log.read_iterator_state]);
+    if (block != NULL) {
+      return block;
+    }
+  }
+  return NULL;
+}
+
+#define CL_LOG_2_MB 20  // 2^20 = 1MB
+
+// External functions: primary stats_log interface
+void census_log_initialize(size_t size_in_mb, int discard_old_records) {
+  // Check cacheline alignment.
+  GPR_ASSERT(sizeof(cl_block) % GPR_CACHELINE_SIZE == 0);
+  GPR_ASSERT(sizeof(cl_core_local_block) % GPR_CACHELINE_SIZE == 0);
+  GPR_ASSERT(!g_log.initialized);
+  g_log.discard_old_records = discard_old_records;
+  g_log.num_cores = gpr_cpu_num_cores();
+  // Ensure that we will not get any overflow in calaculating num_blocks
+  GPR_ASSERT(CL_LOG_2_MB >= CENSUS_LOG_2_MAX_RECORD_SIZE);
+  GPR_ASSERT(size_in_mb < 1000);
+  // Ensure at least 2x as many blocks as there are cores.
+  g_log.num_blocks =
+      (uint32_t)GPR_MAX(2 * g_log.num_cores, (size_in_mb << CL_LOG_2_MB) >>
+                                                 CENSUS_LOG_2_MAX_RECORD_SIZE);
+  gpr_mu_init(&g_log.lock);
+  g_log.read_iterator_state = 0;
+  g_log.block_being_read = NULL;
+  g_log.core_local_blocks = (cl_core_local_block*)gpr_malloc_aligned(
+      g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG);
+  memset(g_log.core_local_blocks, 0,
+         g_log.num_cores * sizeof(cl_core_local_block));
+  g_log.blocks = (cl_block*)gpr_malloc_aligned(
+      g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG);
+  memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block));
+  g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
+  memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
+  cl_block_list_initialize(&g_log.free_block_list);
+  cl_block_list_initialize(&g_log.dirty_block_list);
+  for (uint32_t i = 0; i < g_log.num_blocks; ++i) {
+    cl_block* block = g_log.blocks + i;
+    cl_block_initialize(block, g_log.buffer + (CENSUS_LOG_MAX_RECORD_SIZE * i));
+    cl_block_try_disable_access(block, 1 /* discard data */);
+    cl_block_list_insert_at_tail(&g_log.free_block_list, block);
+  }
+  gpr_atm_rel_store(&g_log.out_of_space_count, 0);
+  g_log.initialized = 1;
+}
+
+void census_log_shutdown(void) {
+  GPR_ASSERT(g_log.initialized);
+  gpr_mu_destroy(&g_log.lock);
+  gpr_free_aligned(g_log.core_local_blocks);
+  g_log.core_local_blocks = NULL;
+  gpr_free_aligned(g_log.blocks);
+  g_log.blocks = NULL;
+  gpr_free(g_log.buffer);
+  g_log.buffer = NULL;
+  g_log.initialized = 0;
+}
+
+void* census_log_start_write(size_t size) {
+  // Used to bound number of times block allocation is attempted.
+  GPR_ASSERT(size > 0);
+  GPR_ASSERT(g_log.initialized);
+  if (size > CENSUS_LOG_MAX_RECORD_SIZE) {
+    return NULL;
+  }
+  uint32_t attempts_remaining = g_log.num_blocks;
+  uint32_t core_id = gpr_cpu_current_cpu();
+  do {
+    void* record = NULL;
+    cl_block* block =
+        cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]);
+    if (block && (record = cl_block_start_write(block, size))) {
+      return record;
+    }
+    // Need to allocate a new block. We are here if:
+    // - No block associated with the core OR
+    // - Write in-progress on the block OR
+    // - block is out of space
+    gpr_mu_lock(&g_log.lock);
+    bool allocated = cl_allocate_core_local_block(core_id, block);
+    gpr_mu_unlock(&g_log.lock);
+    if (!allocated) {
+      gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
+      return NULL;
+    }
+  } while (attempts_remaining--);
+  // Give up.
+  gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
+  return NULL;
+}
+
+void census_log_end_write(void* record, size_t bytes_written) {
+  GPR_ASSERT(g_log.initialized);
+  cl_block_end_write(cl_get_block(record), bytes_written);
+}
+
+void census_log_init_reader(void) {
+  GPR_ASSERT(g_log.initialized);
+  gpr_mu_lock(&g_log.lock);
+  // If a block is locked for reading unlock it.
+  if (g_log.block_being_read != NULL) {
+    cl_block_end_read(g_log.block_being_read);
+    g_log.block_being_read = NULL;
+  }
+  g_log.read_iterator_state = g_log.num_cores;
+  gpr_mu_unlock(&g_log.lock);
+}
+
+const void* census_log_read_next(size_t* bytes_available) {
+  GPR_ASSERT(g_log.initialized);
+  gpr_mu_lock(&g_log.lock);
+  if (g_log.block_being_read != NULL) {
+    cl_block_end_read(g_log.block_being_read);
+  }
+  do {
+    g_log.block_being_read = cl_next_block_to_read(g_log.block_being_read);
+    if (g_log.block_being_read != NULL) {
+      void* record =
+          cl_block_start_read(g_log.block_being_read, bytes_available);
+      if (record != NULL) {
+        gpr_mu_unlock(&g_log.lock);
+        return record;
+      }
+    }
+  } while (g_log.block_being_read != NULL);
+  gpr_mu_unlock(&g_log.lock);
+  return NULL;
+}
+
+size_t census_log_remaining_space(void) {
+  GPR_ASSERT(g_log.initialized);
+  size_t space = 0;
+  gpr_mu_lock(&g_log.lock);
+  if (g_log.discard_old_records) {
+    // Remaining space is not meaningful; just return the entire log space.
+    space = g_log.num_blocks << CENSUS_LOG_2_MAX_RECORD_SIZE;
+  } else {
+    GPR_ASSERT(g_log.free_block_list.count >= 0);
+    space = (size_t)g_log.free_block_list.count * CENSUS_LOG_MAX_RECORD_SIZE;
+  }
+  gpr_mu_unlock(&g_log.lock);
+  return space;
+}
+
+int64_t census_log_out_of_space_count(void) {
+  GPR_ASSERT(g_log.initialized);
+  return gpr_atm_acq_load(&g_log.out_of_space_count);
+}
diff --git a/src/core/ext/census/mlog.h b/src/core/ext/census/mlog.h
new file mode 100644
index 0000000..a256426
--- /dev/null
+++ b/src/core/ext/census/mlog.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* A very fast in-memory log, optimized for multiple writers. */
+
+#ifndef GRPC_CORE_EXT_CENSUS_MLOG_H
+#define GRPC_CORE_EXT_CENSUS_MLOG_H
+
+#include <grpc/support/port_platform.h>
+#include <stddef.h>
+
+/* Maximum record size, in bytes. */
+#define CENSUS_LOG_2_MAX_RECORD_SIZE 14 /* 2^14 = 16KB */
+#define CENSUS_LOG_MAX_RECORD_SIZE (1 << CENSUS_LOG_2_MAX_RECORD_SIZE)
+
+/* Initialize the statistics logging subsystem with the given log size. A log
+   size of 0 will result in the smallest possible log for the platform
+   (approximately CENSUS_LOG_MAX_RECORD_SIZE * gpr_cpu_num_cores()). If
+   discard_old_records is non-zero, then new records will displace older ones
+   when the log is full. This function must be called before any other
+   census_log functions.
+*/
+void census_log_initialize(size_t size_in_mb, int discard_old_records);
+
+/* Shutdown the logging subsystem. Caller must ensure that:
+   - no in progress or future call to any census_log functions
+   - no incomplete records
+*/
+void census_log_shutdown(void);
+
+/* Allocates and returns a 'size' bytes record and marks it in use. A
+   subsequent census_log_end_write() marks the record complete. The
+   'bytes_written' census_log_end_write() argument must be <=
+   'size'. Returns NULL if out-of-space AND:
+       - log is configured to keep old records OR
+       - all blocks are pinned by incomplete records.
+*/
+void* census_log_start_write(size_t size);
+
+void census_log_end_write(void* record, size_t bytes_written);
+
+void census_log_init_reader(void);
+
+/* census_log_read_next() iterates over blocks with data and for each block
+   returns a pointer to the first unread byte. The number of bytes that can be
+   read are returned in 'bytes_available'. Reader is expected to read all
+   available data. Reading the data consumes it i.e. it cannot be read again.
+   census_log_read_next() returns NULL if the end is reached i.e last block
+   is read. census_log_init_reader() starts the iteration or aborts the
+   current iteration.
+*/
+const void* census_log_read_next(size_t* bytes_available);
+
+/* Returns estimated remaining space across all blocks, in bytes. If log is
+   configured to discard old records, returns total log space. Otherwise,
+   returns space available in empty blocks (partially filled blocks are
+   treated as full).
+*/
+size_t census_log_remaining_space(void);
+
+/* Returns the number of times gprc_stats_log_start_write() failed due to
+   out-of-space. */
+int64_t census_log_out_of_space_count(void);
+
+#endif /* GRPC_CORE_EXT_CENSUS_MLOG_H */
diff --git a/src/core/census/operation.c b/src/core/ext/census/operation.c
similarity index 100%
rename from src/core/census/operation.c
rename to src/core/ext/census/operation.c
diff --git a/src/core/census/placeholders.c b/src/core/ext/census/placeholders.c
similarity index 100%
rename from src/core/census/placeholders.c
rename to src/core/ext/census/placeholders.c
diff --git a/src/core/ext/census/rpc_metric_id.h b/src/core/ext/census/rpc_metric_id.h
new file mode 100644
index 0000000..888ec50
--- /dev/null
+++ b/src/core/ext/census/rpc_metric_id.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_EXT_CENSUS_RPC_METRIC_ID_H
+#define GRPC_CORE_EXT_CENSUS_RPC_METRIC_ID_H
+
+/* Metric ID's used for RPC measurements. */
+/* Count of client requests sent. */
+#define CENSUS_METRIC_RPC_CLIENT_REQUESTS ((uint32_t)0)
+/* Count of server requests sent. */
+#define CENSUS_METRIC_RPC_SERVER_REQUESTS ((uint32_t)1)
+/* Client error counts. */
+#define CENSUS_METRIC_RPC_CLIENT_ERRORS ((uint32_t)2)
+/* Server error counts. */
+#define CENSUS_METRIC_RPC_SERVER_ERRORS ((uint32_t)3)
+/* Client side request latency. */
+#define CENSUS_METRIC_RPC_CLIENT_LATENCY ((uint32_t)4)
+/* Server side request latency. */
+#define CENSUS_METRIC_RPC_SERVER_LATENCY ((uint32_t)5)
+
+#endif /* GRPC_CORE_EXT_CENSUS_RPC_METRIC_ID_H */
diff --git a/src/core/census/tracing.c b/src/core/ext/census/tracing.c
similarity index 100%
rename from src/core/census/tracing.c
rename to src/core/ext/census/tracing.c
diff --git a/src/core/ext/census/window_stats.c b/src/core/ext/census/window_stats.c
new file mode 100644
index 0000000..5f7bd99
--- /dev/null
+++ b/src/core/ext/census/window_stats.c
@@ -0,0 +1,316 @@
+/*
+ *
+ * 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/ext/census/window_stats.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include <math.h>
+#include <stddef.h>
+#include <string.h>
+
+/* typedefs make typing long names easier. Use cws (for census_window_stats) */
+typedef census_window_stats_stat_info cws_stat_info;
+typedef struct census_window_stats_sum cws_sum;
+
+/* Each interval is composed of a number of buckets, which hold a count of
+   entries and a single statistic */
+typedef struct census_window_stats_bucket {
+  int64_t count;
+  void *statistic;
+} cws_bucket;
+
+/* Each interval has a set of buckets, and the variables needed to keep
+   track of their current state */
+typedef struct census_window_stats_interval_stats {
+  /* The buckets. There will be 'granularity' + 1 of these. */
+  cws_bucket *buckets;
+  /* Index of the bucket containing the smallest time interval. */
+  int bottom_bucket;
+  /* The smallest time storable in the current window. */
+  int64_t bottom;
+  /* The largest time storable in the current window + 1ns */
+  int64_t top;
+  /* The width of each bucket in ns. */
+  int64_t width;
+} cws_interval_stats;
+
+typedef struct census_window_stats {
+  /* Number of intervals. */
+  int nintervals;
+  /* Number of buckets in each interval. 'granularity' + 1. */
+  int nbuckets;
+  /* Record of stat_info. */
+  cws_stat_info stat_info;
+  /* Stats for each interval. */
+  cws_interval_stats *interval_stats;
+  /* The time the newset stat was recorded. */
+  int64_t newest_time;
+} window_stats;
+
+/* Calculate an actual bucket index from a logical index 'IDX'. Other
+   parameters supply information on the interval struct and overall stats. */
+#define BUCKET_IDX(IS, IDX, WSTATS) \
+  ((IS->bottom_bucket + (IDX)) % WSTATS->nbuckets)
+
+/* The maximum seconds value we can have in a valid timespec. More than this
+   will result in overflow in timespec_to_ns(). This works out to ~292 years.
+   TODO: consider using doubles instead of int64. */
+static int64_t max_seconds = (GPR_INT64_MAX - GPR_NS_PER_SEC) / GPR_NS_PER_SEC;
+
+static int64_t timespec_to_ns(const gpr_timespec ts) {
+  if (ts.tv_sec > max_seconds) {
+    return GPR_INT64_MAX - 1;
+  }
+  return ts.tv_sec * GPR_NS_PER_SEC + ts.tv_nsec;
+}
+
+static void cws_initialize_statistic(void *statistic,
+                                     const cws_stat_info *stat_info) {
+  if (stat_info->stat_initialize == NULL) {
+    memset(statistic, 0, stat_info->stat_size);
+  } else {
+    stat_info->stat_initialize(statistic);
+  }
+}
+
+/* Create and initialize a statistic */
+static void *cws_create_statistic(const cws_stat_info *stat_info) {
+  void *stat = gpr_malloc(stat_info->stat_size);
+  cws_initialize_statistic(stat, stat_info);
+  return stat;
+}
+
+window_stats *census_window_stats_create(int nintervals,
+                                         const gpr_timespec intervals[],
+                                         int granularity,
+                                         const cws_stat_info *stat_info) {
+  window_stats *ret;
+  int i;
+  /* validate inputs */
+  GPR_ASSERT(nintervals > 0 && granularity > 2 && intervals != NULL &&
+             stat_info != NULL);
+  for (i = 0; i < nintervals; i++) {
+    int64_t ns = timespec_to_ns(intervals[i]);
+    GPR_ASSERT(intervals[i].tv_sec >= 0 && intervals[i].tv_nsec >= 0 &&
+               intervals[i].tv_nsec < GPR_NS_PER_SEC && ns >= 100 &&
+               granularity * 10 <= ns);
+  }
+  /* Allocate and initialize relevant data structures */
+  ret = (window_stats *)gpr_malloc(sizeof(window_stats));
+  ret->nintervals = nintervals;
+  ret->nbuckets = granularity + 1;
+  ret->stat_info = *stat_info;
+  ret->interval_stats =
+      (cws_interval_stats *)gpr_malloc(nintervals * sizeof(cws_interval_stats));
+  for (i = 0; i < nintervals; i++) {
+    int64_t size_ns = timespec_to_ns(intervals[i]);
+    cws_interval_stats *is = ret->interval_stats + i;
+    cws_bucket *buckets = is->buckets =
+        (cws_bucket *)gpr_malloc(ret->nbuckets * sizeof(cws_bucket));
+    int b;
+    for (b = 0; b < ret->nbuckets; b++) {
+      buckets[b].statistic = cws_create_statistic(stat_info);
+      buckets[b].count = 0;
+    }
+    is->bottom_bucket = 0;
+    is->bottom = 0;
+    is->width = size_ns / granularity;
+    /* Check for possible overflow issues, and maximize interval size if the
+       user requested something large enough. */
+    if ((GPR_INT64_MAX - is->width) > size_ns) {
+      is->top = size_ns + is->width;
+    } else {
+      is->top = GPR_INT64_MAX;
+      is->width = GPR_INT64_MAX / (granularity + 1);
+    }
+    /* If size doesn't divide evenly, we can have a width slightly too small;
+       better to have it slightly large. */
+    if ((size_ns - (granularity + 1) * is->width) > 0) {
+      is->width += 1;
+    }
+  }
+  ret->newest_time = 0;
+  return ret;
+}
+
+/* When we try adding a measurement above the current interval range, we
+   need to "shift" the buckets sufficiently to cover the new range. */
+static void cws_shift_buckets(const window_stats *wstats,
+                              cws_interval_stats *is, int64_t when_ns) {
+  int i;
+  /* number of bucket time widths to "shift" */
+  int shift;
+  /* number of buckets to clear */
+  int nclear;
+  GPR_ASSERT(when_ns >= is->top);
+  /* number of bucket time widths to "shift" */
+  shift = ((when_ns - is->top) / is->width) + 1;
+  /* number of buckets to clear - limited by actual number of buckets */
+  nclear = GPR_MIN(shift, wstats->nbuckets);
+  for (i = 0; i < nclear; i++) {
+    int b = BUCKET_IDX(is, i, wstats);
+    is->buckets[b].count = 0;
+    cws_initialize_statistic(is->buckets[b].statistic, &wstats->stat_info);
+  }
+  /* adjust top/bottom times and current bottom bucket */
+  is->bottom_bucket = BUCKET_IDX(is, shift, wstats);
+  is->top += shift * is->width;
+  is->bottom += shift * is->width;
+}
+
+void census_window_stats_add(window_stats *wstats, const gpr_timespec when,
+                             const void *stat_value) {
+  int i;
+  int64_t when_ns = timespec_to_ns(when);
+  GPR_ASSERT(wstats->interval_stats != NULL);
+  for (i = 0; i < wstats->nintervals; i++) {
+    cws_interval_stats *is = wstats->interval_stats + i;
+    cws_bucket *bucket;
+    if (when_ns < is->bottom) { /* Below smallest time in interval: drop */
+      continue;
+    }
+    if (when_ns >= is->top) { /* above limit: shift buckets */
+      cws_shift_buckets(wstats, is, when_ns);
+    }
+    /* Add the stat. */
+    GPR_ASSERT(is->bottom <= when_ns && when_ns < is->top);
+    bucket = is->buckets +
+             BUCKET_IDX(is, (when_ns - is->bottom) / is->width, wstats);
+    bucket->count++;
+    wstats->stat_info.stat_add(bucket->statistic, stat_value);
+  }
+  if (when_ns > wstats->newest_time) {
+    wstats->newest_time = when_ns;
+  }
+}
+
+/* Add a specific bucket contents to an accumulating total. */
+static void cws_add_bucket_to_sum(cws_sum *sum, const cws_bucket *bucket,
+                                  const cws_stat_info *stat_info) {
+  sum->count += bucket->count;
+  stat_info->stat_add(sum->statistic, bucket->statistic);
+}
+
+/* Add a proportion to an accumulating sum. */
+static void cws_add_proportion_to_sum(double p, cws_sum *sum,
+                                      const cws_bucket *bucket,
+                                      const cws_stat_info *stat_info) {
+  sum->count += p * bucket->count;
+  stat_info->stat_add_proportion(p, sum->statistic, bucket->statistic);
+}
+
+void census_window_stats_get_sums(const window_stats *wstats,
+                                  const gpr_timespec when, cws_sum sums[]) {
+  int i;
+  int64_t when_ns = timespec_to_ns(when);
+  GPR_ASSERT(wstats->interval_stats != NULL);
+  for (i = 0; i < wstats->nintervals; i++) {
+    int when_bucket;
+    int new_bucket;
+    double last_proportion = 1.0;
+    double bottom_proportion;
+    cws_interval_stats *is = wstats->interval_stats + i;
+    cws_sum *sum = sums + i;
+    sum->count = 0;
+    cws_initialize_statistic(sum->statistic, &wstats->stat_info);
+    if (when_ns < is->bottom) {
+      continue;
+    }
+    if (when_ns >= is->top) {
+      cws_shift_buckets(wstats, is, when_ns);
+    }
+    /* Calculating the appropriate amount of which buckets to use can get
+       complicated. Essentially there are two cases:
+       1) if the "top" bucket (new_bucket, where the newest additions to the
+       stats recorded are entered) corresponds to 'when', then we need
+       to take a proportion of it - (if when < newest_time) or the full
+       thing. We also (possibly) need to take a corresponding
+       proportion of the bottom bucket.
+       2) Other cases, we just take a straight proportion.
+     */
+    when_bucket = (when_ns - is->bottom) / is->width;
+    new_bucket = (wstats->newest_time - is->bottom) / is->width;
+    if (new_bucket == when_bucket) {
+      int64_t bottom_bucket_time = is->bottom + when_bucket * is->width;
+      if (when_ns < wstats->newest_time) {
+        last_proportion = (double)(when_ns - bottom_bucket_time) /
+                          (double)(wstats->newest_time - bottom_bucket_time);
+        bottom_proportion =
+            (double)(is->width - (when_ns - bottom_bucket_time)) / is->width;
+      } else {
+        bottom_proportion =
+            (double)(is->width - (wstats->newest_time - bottom_bucket_time)) /
+            is->width;
+      }
+    } else {
+      last_proportion =
+          (double)(when_ns + 1 - is->bottom - when_bucket * is->width) /
+          is->width;
+      bottom_proportion = 1.0 - last_proportion;
+    }
+    cws_add_proportion_to_sum(last_proportion, sum,
+                              is->buckets + BUCKET_IDX(is, when_bucket, wstats),
+                              &wstats->stat_info);
+    if (when_bucket != 0) { /* last bucket isn't also bottom bucket */
+      int b;
+      /* Add all of "bottom" bucket if we are looking at a subset of the
+         full interval, or a proportion if we are adding full interval. */
+      cws_add_proportion_to_sum(
+          (when_bucket == wstats->nbuckets - 1 ? bottom_proportion : 1.0), sum,
+          is->buckets + is->bottom_bucket, &wstats->stat_info);
+      /* Add all the remaining buckets (everything but top and bottom). */
+      for (b = 1; b < when_bucket; b++) {
+        cws_add_bucket_to_sum(sum, is->buckets + BUCKET_IDX(is, b, wstats),
+                              &wstats->stat_info);
+      }
+    }
+  }
+}
+
+void census_window_stats_destroy(window_stats *wstats) {
+  int i;
+  GPR_ASSERT(wstats->interval_stats != NULL);
+  for (i = 0; i < wstats->nintervals; i++) {
+    int b;
+    for (b = 0; b < wstats->nbuckets; b++) {
+      gpr_free(wstats->interval_stats[i].buckets[b].statistic);
+    }
+    gpr_free(wstats->interval_stats[i].buckets);
+  }
+  gpr_free(wstats->interval_stats);
+  /* Ensure any use-after free triggers assert. */
+  wstats->interval_stats = NULL;
+  gpr_free(wstats);
+}
diff --git a/src/core/ext/census/window_stats.h b/src/core/ext/census/window_stats.h
new file mode 100644
index 0000000..25658c9
--- /dev/null
+++ b/src/core/ext/census/window_stats.h
@@ -0,0 +1,173 @@
+/*
+ *
+ * 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_EXT_CENSUS_WINDOW_STATS_H
+#define GRPC_CORE_EXT_CENSUS_WINDOW_STATS_H
+
+#include <grpc/support/time.h>
+
+/* Keep rolling sums of a user-defined statistic (containing a number of
+   measurements) over a a number of time intervals ("windows"). For example,
+   you can use a window_stats object to answer questions such as
+   "Approximately how many RPCs/s did I receive over the past minute, and
+   approximately how many bytes did I send out over that period?".
+
+   The type of data to record, and the time intervals to keep are specified
+   when creating the object via a call to census_window_stats_create().
+
+   A window's interval is divided into one or more "buckets"; the interval
+   must be divisible by the number of buckets. Internally, these buckets
+   control the granularity of window_stats' measurements. Increasing the
+   number of buckets lets the object respond more quickly to changes in the
+   overall rate of data added into the object, at the cost of additional
+   memory usage.
+
+   Here's some code which keeps one minute/hour measurements for two values
+   (latency in seconds and bytes transferred), with each interval divided into
+   4 buckets.
+
+    typedef struct my_stat {
+      double latency;
+      int bytes;
+    } my_stat;
+
+    void add_my_stat(void* base, const void* addme) {
+      my_stat* b = (my_stat*)base;
+      const my_stat* a = (const my_stat*)addme;
+      b->latency += a->latency;
+      b->bytes += a->bytes;
+    }
+
+    void add_proportion_my_stat(double p, void* base, const void* addme) {
+      (my_stat*)result->latency += p * (const my_stat*)base->latency;
+      (my_stat*)result->bytes += p * (const my_stat*)base->bytes;
+    }
+
+    #define kNumIntervals 2
+    #define kMinInterval 0
+    #define kHourInterval 1
+    #define kNumBuckets 4
+
+    const struct census_window_stats_stat_info kMyStatInfo
+        = { sizeof(my_stat), NULL, add_my_stat, add_proportion_my_stat };
+    gpr_timespec intervals[kNumIntervals] = {{60, 0}, {3600, 0}};
+    my_stat stat;
+    my_stat sums[kNumIntervals];
+    census_window_stats_sums result[kNumIntervals];
+    struct census_window_stats* stats
+        = census_window_stats_create(kNumIntervals, intervals, kNumBuckets,
+                                     &kMyStatInfo);
+    // Record a new event, taking 15.3ms, transferring 1784 bytes.
+    stat.latency = 0.153;
+    stat.bytes = 1784;
+    census_window_stats_add(stats, gpr_now(GPR_CLOCK_REALTIME), &stat);
+    // Get sums and print them out
+    result[kMinInterval].statistic = &sums[kMinInterval];
+    result[kHourInterval].statistic = &sums[kHourInterval];
+    census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), result);
+    printf("%d events/min, average time %gs, average bytes %g\n",
+           result[kMinInterval].count,
+           (my_stat*)result[kMinInterval].statistic->latency /
+             result[kMinInterval].count,
+           (my_stat*)result[kMinInterval].statistic->bytes /
+             result[kMinInterval].count
+          );
+    printf("%d events/hr, average time %gs, average bytes %g\n",
+           result[kHourInterval].count,
+           (my_stat*)result[kHourInterval].statistic->latency /
+             result[kHourInterval].count,
+           (my_stat*)result[kHourInterval].statistic->bytes /
+             result[kHourInterval].count
+          );
+*/
+
+/* Opaque structure for representing window_stats object */
+struct census_window_stats;
+
+/* Information provided by API user on the information they want to record */
+typedef struct census_window_stats_stat_info {
+  /* Number of bytes in user-defined object. */
+  size_t stat_size;
+  /* Function to initialize a user-defined statistics object. If this is set
+   * to NULL, then the object will be zero-initialized. */
+  void (*stat_initialize)(void *stat);
+  /* Function to add one user-defined statistics object ('addme') to 'base' */
+  void (*stat_add)(void *base, const void *addme);
+  /* As for previous function, but only add a proportion 'p'. This API will
+     currently only use 'p' values in the range [0,1], but other values are
+     possible in the future, and should be supported. */
+  void (*stat_add_proportion)(double p, void *base, const void *addme);
+} census_window_stats_stat_info;
+
+/* Create a new window_stats object. 'nintervals' is the number of
+   'intervals', and must be >=1. 'granularity' is the number of buckets, with
+   a larger number using more memory, but providing greater accuracy of
+   results. 'granularity should be > 2. We also require that each interval be
+   at least 10 * 'granularity' nanoseconds in size. 'stat_info' contains
+   information about the statistic to be gathered. Intervals greater than ~192
+   years will be treated as essentially infinite in size. This function will
+   GPR_ASSERT() if the object cannot be created or any of the parameters have
+   invalid values. This function is thread-safe. */
+struct census_window_stats *census_window_stats_create(
+    int nintervals, const gpr_timespec intervals[], int granularity,
+    const census_window_stats_stat_info *stat_info);
+
+/* Add a new measurement (in 'stat_value'), as of a given time ('when').
+   This function is thread-compatible. */
+void census_window_stats_add(struct census_window_stats *wstats,
+                             const gpr_timespec when, const void *stat_value);
+
+/* Structure used to record a single intervals sum for a given statistic */
+typedef struct census_window_stats_sum {
+  /* Total count of samples. Note that because some internal interpolation
+     is performed, the count of samples returned for each interval may not be an
+     integral value. */
+  double count;
+  /* Sum for statistic */
+  void *statistic;
+} census_window_stats_sums;
+
+/* Retrieve a set of all values stored in a window_stats object 'wstats'. The
+   number of 'sums' MUST be the same as the number 'nintervals' used in
+   census_window_stats_create(). This function is thread-compatible. */
+void census_window_stats_get_sums(const struct census_window_stats *wstats,
+                                  const gpr_timespec when,
+                                  struct census_window_stats_sum sums[]);
+
+/* Destroy a window_stats object. Once this function has been called, the
+   object will no longer be usable from any of the above functions (and
+   calling them will most likely result in a NULL-pointer dereference or
+   assertion failure). This function is thread-compatible. */
+void census_window_stats_destroy(struct census_window_stats *wstats);
+
+#endif /* GRPC_CORE_EXT_CENSUS_WINDOW_STATS_H */
diff --git a/src/core/ext/client_config/README.md b/src/core/ext/client_config/README.md
new file mode 100644
index 0000000..7024fd5
--- /dev/null
+++ b/src/core/ext/client_config/README.md
@@ -0,0 +1,66 @@
+Client Configuration Support for GRPC
+=====================================
+
+This library provides high level configuration machinery to construct client
+channels and load balance between them.
+
+Each grpc_channel is created with a grpc_resolver. It is the resolver's duty
+to resolve a name into configuration data for the channel. Such configuration
+data might include:
+
+- a list of (ip, port) addresses to connect to
+- a load balancing policy to decide which server to send a request to
+- a set of filters to mutate outgoing requests (say, by adding metadata)
+
+The resolver provides this data as a stream of grpc_client_config objects to
+the channel. We represent configuration as a stream so that it can be changed
+by the resolver during execution, by reacting to external events (such as a
+new configuration file being pushed to some store).
+
+
+Load Balancing
+--------------
+
+Load balancing configuration is provided by a grpc_lb_policy object, stored as
+part of grpc_client_config.
+
+The primary job of the load balancing policies is to pick a target server given only the
+initial metadata for a request. It does this by providing a grpc_subchannel
+object to the owning channel.
+
+
+Sub-Channels
+------------
+
+A sub-channel provides a connection to a server for a client channel. It has a
+connectivity state like a regular channel, and so can be connected or
+disconnected. This connectivity state can be used to inform load balancing
+decisions (for example, by avoiding disconnected backends).
+
+Configured sub-channels are fully setup to participate in the grpc data plane.
+Their behavior is specified by a set of grpc channel filters defined at their
+construction. To customize this behavior, resolvers build
+grpc_client_channel_factory objects, which use the decorator pattern to customize
+construction arguments for concrete grpc_subchannel instances.
+
+
+Naming for GRPC
+===============
+
+Names in GRPC are represented by a URI (as defined in
+[RFC 3986](https://tools.ietf.org/html/rfc3986)).
+
+The following schemes are currently supported:
+
+dns:///host:port - dns schemes are currently supported so long as authority is
+                   empty (authority based dns resolution is expected in a future
+                   release)
+
+unix:path        - the unix scheme is used to create and connect to unix domain
+                   sockets - the authority must be empty, and the path
+                   represents the absolute or relative path to the desired
+                   socket
+
+ipv4:host:port   - a pre-resolved ipv4 dotted decimal address/port combination
+
+ipv6:[host]:port - a pre-resolved ipv6 address/port combination
diff --git a/src/core/ext/client_config/channel_connectivity.c b/src/core/ext/client_config/channel_connectivity.c
new file mode 100644
index 0000000..3ebc333
--- /dev/null
+++ b/src/core/ext/client_config/channel_connectivity.c
@@ -0,0 +1,207 @@
+/*
+ *
+ * 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/surface/channel.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/completion_queue.h"
+
+grpc_connectivity_state grpc_channel_check_connectivity_state(
+    grpc_channel *channel, int try_to_connect) {
+  /* forward through to the underlying client channel */
+  grpc_channel_element *client_channel_elem =
+      grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_connectivity_state state;
+  GRPC_API_TRACE(
+      "grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2,
+      (channel, try_to_connect));
+  if (client_channel_elem->filter == &grpc_client_channel_filter) {
+    state = grpc_client_channel_check_connectivity_state(
+        &exec_ctx, client_channel_elem, try_to_connect);
+    grpc_exec_ctx_finish(&exec_ctx);
+    return state;
+  }
+  gpr_log(GPR_ERROR,
+          "grpc_channel_check_connectivity_state called on something that is "
+          "not a (u)client channel, but '%s'",
+          client_channel_elem->filter->name);
+  grpc_exec_ctx_finish(&exec_ctx);
+  return GRPC_CHANNEL_FATAL_FAILURE;
+}
+
+typedef enum {
+  WAITING,
+  CALLING_BACK,
+  CALLING_BACK_AND_FINISHED,
+  CALLED_BACK
+} callback_phase;
+
+typedef struct {
+  gpr_mu mu;
+  callback_phase phase;
+  int success;
+  grpc_closure on_complete;
+  grpc_timer alarm;
+  grpc_connectivity_state state;
+  grpc_completion_queue *cq;
+  grpc_cq_completion completion_storage;
+  grpc_channel *channel;
+  void *tag;
+} state_watcher;
+
+static void delete_state_watcher(grpc_exec_ctx *exec_ctx, state_watcher *w) {
+  grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
+      grpc_channel_get_channel_stack(w->channel));
+  if (client_channel_elem->filter == &grpc_client_channel_filter) {
+    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->channel,
+                                "watch_channel_connectivity");
+  } else {
+    abort();
+  }
+  gpr_mu_destroy(&w->mu);
+  gpr_free(w);
+}
+
+static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
+                                grpc_cq_completion *ignored) {
+  int delete = 0;
+  state_watcher *w = pw;
+  gpr_mu_lock(&w->mu);
+  switch (w->phase) {
+    case WAITING:
+    case CALLED_BACK:
+      GPR_UNREACHABLE_CODE(return );
+    case CALLING_BACK:
+      w->phase = CALLED_BACK;
+      break;
+    case CALLING_BACK_AND_FINISHED:
+      delete = 1;
+      break;
+  }
+  gpr_mu_unlock(&w->mu);
+
+  if (delete) {
+    delete_state_watcher(exec_ctx, w);
+  }
+}
+
+static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
+                        int due_to_completion) {
+  int delete = 0;
+
+  if (due_to_completion) {
+    grpc_timer_cancel(exec_ctx, &w->alarm);
+  }
+
+  gpr_mu_lock(&w->mu);
+  if (due_to_completion) {
+    w->success = 1;
+  }
+  switch (w->phase) {
+    case WAITING:
+      w->phase = CALLING_BACK;
+      grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->success, finished_completion,
+                     w, &w->completion_storage);
+      break;
+    case CALLING_BACK:
+      w->phase = CALLING_BACK_AND_FINISHED;
+      break;
+    case CALLING_BACK_AND_FINISHED:
+      GPR_UNREACHABLE_CODE(return );
+    case CALLED_BACK:
+      delete = 1;
+      break;
+  }
+  gpr_mu_unlock(&w->mu);
+
+  if (delete) {
+    delete_state_watcher(exec_ctx, w);
+  }
+}
+
+static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
+  partly_done(exec_ctx, pw, 1);
+}
+
+static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
+  partly_done(exec_ctx, pw, 0);
+}
+
+void grpc_channel_watch_connectivity_state(
+    grpc_channel *channel, grpc_connectivity_state last_observed_state,
+    gpr_timespec deadline, grpc_completion_queue *cq, void *tag) {
+  grpc_channel_element *client_channel_elem =
+      grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  state_watcher *w = gpr_malloc(sizeof(*w));
+
+  GRPC_API_TRACE(
+      "grpc_channel_watch_connectivity_state("
+      "channel=%p, last_observed_state=%d, "
+      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
+      "cq=%p, tag=%p)",
+      7, (channel, (int)last_observed_state, (long long)deadline.tv_sec,
+          (int)deadline.tv_nsec, (int)deadline.clock_type, cq, tag));
+
+  grpc_cq_begin_op(cq, tag);
+
+  gpr_mu_init(&w->mu);
+  grpc_closure_init(&w->on_complete, watch_complete, w);
+  w->phase = WAITING;
+  w->state = last_observed_state;
+  w->success = 0;
+  w->cq = cq;
+  w->tag = tag;
+  w->channel = channel;
+
+  grpc_timer_init(&exec_ctx, &w->alarm,
+                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
+                  timeout_complete, w, gpr_now(GPR_CLOCK_MONOTONIC));
+
+  if (client_channel_elem->filter == &grpc_client_channel_filter) {
+    GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity");
+    grpc_client_channel_watch_connectivity_state(&exec_ctx, client_channel_elem,
+                                                 grpc_cq_pollset(cq), &w->state,
+                                                 &w->on_complete);
+  } else {
+    abort();
+  }
+
+  grpc_exec_ctx_finish(&exec_ctx);
+}
diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c
new file mode 100644
index 0000000..8a98a6b
--- /dev/null
+++ b/src/core/ext/client_config/client_channel.c
@@ -0,0 +1,562 @@
+/*
+ *
+ * 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/ext/client_config/client_channel.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/ext/client_config/subchannel_call_holder.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/transport/connectivity_state.h"
+
+/* Client channel implementation */
+
+typedef grpc_subchannel_call_holder call_data;
+
+typedef struct client_channel_channel_data {
+  /** resolver for this channel */
+  grpc_resolver *resolver;
+  /** have we started resolving this channel */
+  int started_resolving;
+
+  /** mutex protecting client configuration, including all
+      variables below in this data structure */
+  gpr_mu mu_config;
+  /** currently active load balancer - guarded by mu_config */
+  grpc_lb_policy *lb_policy;
+  /** incoming configuration - set by resolver.next
+      guarded by mu_config */
+  grpc_client_config *incoming_configuration;
+  /** a list of closures that are all waiting for config to come in */
+  grpc_closure_list waiting_for_config_closures;
+  /** resolver callback */
+  grpc_closure on_config_changed;
+  /** connectivity state being tracked */
+  grpc_connectivity_state_tracker state_tracker;
+  /** when an lb_policy arrives, should we try to exit idle */
+  int exit_idle_when_lb_policy_arrives;
+  /** owning stack */
+  grpc_channel_stack *owning_stack;
+  /** interested parties (owned) */
+  grpc_pollset_set *interested_parties;
+} channel_data;
+
+/** We create one watcher for each new lb_policy that is returned from a
+   resolver,
+    to watch for state changes from the lb_policy. When a state change is seen,
+   we
+    update the channel, and create a new watcher */
+typedef struct {
+  channel_data *chand;
+  grpc_closure on_changed;
+  grpc_connectivity_state state;
+  grpc_lb_policy *lb_policy;
+} lb_policy_connectivity_watcher;
+
+typedef struct {
+  grpc_closure closure;
+  grpc_call_element *elem;
+} waiting_call;
+
+static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+  return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
+}
+
+static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
+                                         grpc_call_element *elem,
+                                         grpc_transport_stream_op *op) {
+  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
+  grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
+}
+
+static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
+                            grpc_lb_policy *lb_policy,
+                            grpc_connectivity_state current_state);
+
+static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
+                                                  channel_data *chand,
+                                                  grpc_connectivity_state state,
+                                                  const char *reason) {
+  if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
+       state == GRPC_CHANNEL_FATAL_FAILURE) &&
+      chand->lb_policy != NULL) {
+    /* cancel fail-fast picks */
+    grpc_lb_policy_cancel_picks(
+        exec_ctx, chand->lb_policy,
+        /* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY,
+        /* check= */ 0);
+  }
+  grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, reason);
+}
+
+static void on_lb_policy_state_changed_locked(
+    grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
+  grpc_connectivity_state publish_state = w->state;
+  /* check if the notification is for a stale policy */
+  if (w->lb_policy != w->chand->lb_policy) return;
+
+  if (publish_state == GRPC_CHANNEL_FATAL_FAILURE &&
+      w->chand->resolver != NULL) {
+    publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
+    grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
+    GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
+    w->chand->lb_policy = NULL;
+  }
+  set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
+                                        "lb_changed");
+  if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
+    watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
+  }
+}
+
+static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
+                                       bool iomgr_success) {
+  lb_policy_connectivity_watcher *w = arg;
+
+  gpr_mu_lock(&w->chand->mu_config);
+  on_lb_policy_state_changed_locked(exec_ctx, w);
+  gpr_mu_unlock(&w->chand->mu_config);
+
+  GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
+  gpr_free(w);
+}
+
+static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
+                            grpc_lb_policy *lb_policy,
+                            grpc_connectivity_state current_state) {
+  lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
+  GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
+
+  w->chand = chand;
+  grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
+  w->state = current_state;
+  w->lb_policy = lb_policy;
+  grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
+                                        &w->on_changed);
+}
+
+static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
+                                 bool iomgr_success) {
+  channel_data *chand = arg;
+  grpc_lb_policy *lb_policy = NULL;
+  grpc_lb_policy *old_lb_policy;
+  grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
+  int exit_idle = 0;
+
+  if (chand->incoming_configuration != NULL) {
+    lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
+    if (lb_policy != NULL) {
+      GRPC_LB_POLICY_REF(lb_policy, "channel");
+      GRPC_LB_POLICY_REF(lb_policy, "config_change");
+      state = grpc_lb_policy_check_connectivity(exec_ctx, lb_policy);
+    }
+
+    grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
+  }
+
+  chand->incoming_configuration = NULL;
+
+  if (lb_policy != NULL) {
+    grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
+                                     chand->interested_parties);
+  }
+
+  gpr_mu_lock(&chand->mu_config);
+  old_lb_policy = chand->lb_policy;
+  chand->lb_policy = lb_policy;
+  if (lb_policy != NULL) {
+    grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
+                               NULL);
+  } else if (chand->resolver == NULL /* disconnected */) {
+    grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
+    grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
+                               NULL);
+  }
+  if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
+    GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
+    exit_idle = 1;
+    chand->exit_idle_when_lb_policy_arrives = 0;
+  }
+
+  if (iomgr_success && chand->resolver) {
+    set_channel_connectivity_state_locked(exec_ctx, chand, state,
+                                          "new_lb+resolver");
+    if (lb_policy != NULL) {
+      watch_lb_policy(exec_ctx, chand, lb_policy, state);
+    }
+    GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
+    grpc_resolver_next(exec_ctx, chand->resolver,
+                       &chand->incoming_configuration,
+                       &chand->on_config_changed);
+    gpr_mu_unlock(&chand->mu_config);
+  } else {
+    if (chand->resolver != NULL) {
+      grpc_resolver_shutdown(exec_ctx, chand->resolver);
+      GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+      chand->resolver = NULL;
+    }
+    set_channel_connectivity_state_locked(
+        exec_ctx, chand, GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
+    gpr_mu_unlock(&chand->mu_config);
+  }
+
+  if (exit_idle) {
+    grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
+    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
+  }
+
+  if (old_lb_policy != NULL) {
+    grpc_pollset_set_del_pollset_set(
+        exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
+    GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
+  }
+
+  if (lb_policy != NULL) {
+    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
+  }
+
+  GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
+}
+
+static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                  grpc_channel_element *elem,
+                                  grpc_transport_op *op) {
+  channel_data *chand = elem->channel_data;
+
+  grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
+
+  GPR_ASSERT(op->set_accept_stream == false);
+  if (op->bind_pollset != NULL) {
+    grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
+                                 op->bind_pollset);
+  }
+
+  gpr_mu_lock(&chand->mu_config);
+  if (op->on_connectivity_state_change != NULL) {
+    grpc_connectivity_state_notify_on_state_change(
+        exec_ctx, &chand->state_tracker, op->connectivity_state,
+        op->on_connectivity_state_change);
+    op->on_connectivity_state_change = NULL;
+    op->connectivity_state = NULL;
+  }
+
+  if (op->send_ping != NULL) {
+    if (chand->lb_policy == NULL) {
+      grpc_exec_ctx_enqueue(exec_ctx, op->send_ping, false, NULL);
+    } else {
+      grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
+      op->bind_pollset = NULL;
+    }
+    op->send_ping = NULL;
+  }
+
+  if (op->disconnect && chand->resolver != NULL) {
+    set_channel_connectivity_state_locked(
+        exec_ctx, chand, GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
+    grpc_resolver_shutdown(exec_ctx, chand->resolver);
+    GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+    chand->resolver = NULL;
+    if (!chand->started_resolving) {
+      grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
+      grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
+                                 NULL);
+    }
+    if (chand->lb_policy != NULL) {
+      grpc_pollset_set_del_pollset_set(exec_ctx,
+                                       chand->lb_policy->interested_parties,
+                                       chand->interested_parties);
+      GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
+      chand->lb_policy = NULL;
+    }
+  }
+  gpr_mu_unlock(&chand->mu_config);
+}
+
+typedef struct {
+  grpc_metadata_batch *initial_metadata;
+  uint32_t initial_metadata_flags;
+  grpc_connected_subchannel **connected_subchannel;
+  grpc_closure *on_ready;
+  grpc_call_element *elem;
+  grpc_closure closure;
+} continue_picking_args;
+
+static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
+                              grpc_metadata_batch *initial_metadata,
+                              uint32_t initial_metadata_flags,
+                              grpc_connected_subchannel **connected_subchannel,
+                              grpc_closure *on_ready);
+
+static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  continue_picking_args *cpa = arg;
+  if (cpa->connected_subchannel == NULL) {
+    /* cancelled, do nothing */
+  } else if (!success) {
+    grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
+  } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
+                                cpa->initial_metadata_flags,
+                                cpa->connected_subchannel, cpa->on_ready)) {
+    grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, true, NULL);
+  }
+  gpr_free(cpa);
+}
+
+static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
+                              grpc_metadata_batch *initial_metadata,
+                              uint32_t initial_metadata_flags,
+                              grpc_connected_subchannel **connected_subchannel,
+                              grpc_closure *on_ready) {
+  grpc_call_element *elem = elemp;
+  channel_data *chand = elem->channel_data;
+  call_data *calld = elem->call_data;
+  continue_picking_args *cpa;
+  grpc_closure *closure;
+
+  GPR_ASSERT(connected_subchannel);
+
+  gpr_mu_lock(&chand->mu_config);
+  if (initial_metadata == NULL) {
+    if (chand->lb_policy != NULL) {
+      grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
+                                 connected_subchannel);
+    }
+    for (closure = chand->waiting_for_config_closures.head; closure != NULL;
+         closure = grpc_closure_next(closure)) {
+      cpa = closure->cb_arg;
+      if (cpa->connected_subchannel == connected_subchannel) {
+        cpa->connected_subchannel = NULL;
+        grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
+      }
+    }
+    gpr_mu_unlock(&chand->mu_config);
+    return 1;
+  }
+  if (chand->lb_policy != NULL) {
+    grpc_lb_policy *lb_policy = chand->lb_policy;
+    int r;
+    GRPC_LB_POLICY_REF(lb_policy, "cc_pick_subchannel");
+    gpr_mu_unlock(&chand->mu_config);
+    r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollset,
+                            initial_metadata, initial_metadata_flags,
+                            connected_subchannel, on_ready);
+    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel");
+    return r;
+  }
+  if (chand->resolver != NULL && !chand->started_resolving) {
+    chand->started_resolving = 1;
+    GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
+    grpc_resolver_next(exec_ctx, chand->resolver,
+                       &chand->incoming_configuration,
+                       &chand->on_config_changed);
+  }
+  if (chand->resolver != NULL) {
+    cpa = gpr_malloc(sizeof(*cpa));
+    cpa->initial_metadata = initial_metadata;
+    cpa->initial_metadata_flags = initial_metadata_flags;
+    cpa->connected_subchannel = connected_subchannel;
+    cpa->on_ready = on_ready;
+    cpa->elem = elem;
+    grpc_closure_init(&cpa->closure, continue_picking, cpa);
+    grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure,
+                          1);
+  } else {
+    grpc_exec_ctx_enqueue(exec_ctx, on_ready, false, NULL);
+  }
+  gpr_mu_unlock(&chand->mu_config);
+  return 0;
+}
+
+/* Constructor for call_data */
+static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                           grpc_call_element_args *args) {
+  grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem,
+                                   args->call_stack);
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {
+  grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
+}
+
+/* Constructor for channel_data */
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  channel_data *chand = elem->channel_data;
+
+  memset(chand, 0, sizeof(*chand));
+
+  GPR_ASSERT(args->is_last);
+  GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
+
+  gpr_mu_init(&chand->mu_config);
+  grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
+  chand->owning_stack = args->channel_stack;
+
+  grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
+                               "client_channel");
+  chand->interested_parties = grpc_pollset_set_create();
+}
+
+/* Destructor for channel_data */
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {
+  channel_data *chand = elem->channel_data;
+
+  if (chand->resolver != NULL) {
+    grpc_resolver_shutdown(exec_ctx, chand->resolver);
+    GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+  }
+  if (chand->lb_policy != NULL) {
+    grpc_pollset_set_del_pollset_set(exec_ctx,
+                                     chand->lb_policy->interested_parties,
+                                     chand->interested_parties);
+    GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
+  }
+  grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
+  grpc_pollset_set_destroy(chand->interested_parties);
+  gpr_mu_destroy(&chand->mu_config);
+}
+
+static void cc_set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                           grpc_pollset *pollset) {
+  call_data *calld = elem->call_data;
+  calld->pollset = pollset;
+}
+
+const grpc_channel_filter grpc_client_channel_filter = {
+    cc_start_transport_stream_op,
+    cc_start_transport_op,
+    sizeof(call_data),
+    init_call_elem,
+    cc_set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    cc_get_peer,
+    "client-channel",
+};
+
+void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
+                                      grpc_channel_stack *channel_stack,
+                                      grpc_resolver *resolver) {
+  /* post construction initialization: set the transport setup pointer */
+  grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
+  channel_data *chand = elem->channel_data;
+  gpr_mu_lock(&chand->mu_config);
+  GPR_ASSERT(!chand->resolver);
+  chand->resolver = resolver;
+  GRPC_RESOLVER_REF(resolver, "channel");
+  if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
+      chand->exit_idle_when_lb_policy_arrives) {
+    chand->started_resolving = 1;
+    GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
+    grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
+                       &chand->on_config_changed);
+  }
+  gpr_mu_unlock(&chand->mu_config);
+}
+
+grpc_connectivity_state grpc_client_channel_check_connectivity_state(
+    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
+  channel_data *chand = elem->channel_data;
+  grpc_connectivity_state out;
+  gpr_mu_lock(&chand->mu_config);
+  out = grpc_connectivity_state_check(&chand->state_tracker);
+  if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
+    if (chand->lb_policy != NULL) {
+      grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
+    } else {
+      chand->exit_idle_when_lb_policy_arrives = 1;
+      if (!chand->started_resolving && chand->resolver != NULL) {
+        GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
+        chand->started_resolving = 1;
+        grpc_resolver_next(exec_ctx, chand->resolver,
+                           &chand->incoming_configuration,
+                           &chand->on_config_changed);
+      }
+    }
+  }
+  gpr_mu_unlock(&chand->mu_config);
+  return out;
+}
+
+typedef struct {
+  channel_data *chand;
+  grpc_pollset *pollset;
+  grpc_closure *on_complete;
+  grpc_closure my_closure;
+} external_connectivity_watcher;
+
+static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
+                                       bool iomgr_success) {
+  external_connectivity_watcher *w = arg;
+  grpc_closure *follow_up = w->on_complete;
+  grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
+                               w->pollset);
+  GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
+                           "external_connectivity_watcher");
+  gpr_free(w);
+  follow_up->cb(exec_ctx, follow_up->cb_arg, iomgr_success);
+}
+
+void grpc_client_channel_watch_connectivity_state(
+    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
+    grpc_connectivity_state *state, grpc_closure *on_complete) {
+  channel_data *chand = elem->channel_data;
+  external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
+  w->chand = chand;
+  w->pollset = pollset;
+  w->on_complete = on_complete;
+  grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
+  grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
+  GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
+                         "external_connectivity_watcher");
+  gpr_mu_lock(&chand->mu_config);
+  grpc_connectivity_state_notify_on_state_change(
+      exec_ctx, &chand->state_tracker, state, &w->my_closure);
+  gpr_mu_unlock(&chand->mu_config);
+}
diff --git a/src/core/ext/client_config/client_channel.h b/src/core/ext/client_config/client_channel.h
new file mode 100644
index 0000000..1e47ad3
--- /dev/null
+++ b/src/core/ext/client_config/client_channel.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_H
+
+#include "src/core/ext/client_config/resolver.h"
+#include "src/core/lib/channel/channel_stack.h"
+
+/* A client channel is a channel that begins disconnected, and can connect
+   to some endpoint on demand. If that endpoint disconnects, it will be
+   connected to again later.
+
+   Calls on a disconnected client channel are queued until a connection is
+   established. */
+
+extern const grpc_channel_filter grpc_client_channel_filter;
+
+/* post-construction initializer to let the client channel know which
+   transport setup it should cancel upon destruction, or initiate when it needs
+   a connection */
+void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
+                                      grpc_channel_stack *channel_stack,
+                                      grpc_resolver *resolver);
+
+grpc_connectivity_state grpc_client_channel_check_connectivity_state(
+    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
+
+void grpc_client_channel_watch_connectivity_state(
+    grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
+    grpc_connectivity_state *state, grpc_closure *on_complete);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_H */
diff --git a/src/core/ext/client_config/client_channel_factory.c b/src/core/ext/client_config/client_channel_factory.c
new file mode 100644
index 0000000..71c64c0
--- /dev/null
+++ b/src/core/ext/client_config/client_channel_factory.c
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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/ext/client_config/client_channel_factory.h"
+
+void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory) {
+  factory->vtable->ref(factory);
+}
+
+void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx,
+                                       grpc_client_channel_factory* factory) {
+  factory->vtable->unref(exec_ctx, factory);
+}
+
+grpc_subchannel* grpc_client_channel_factory_create_subchannel(
+    grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
+    grpc_subchannel_args* args) {
+  return factory->vtable->create_subchannel(exec_ctx, factory, args);
+}
+
+grpc_channel* grpc_client_channel_factory_create_channel(
+    grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
+    const char* target, grpc_client_channel_type type,
+    grpc_channel_args* args) {
+  return factory->vtable->create_client_channel(exec_ctx, factory, target, type,
+                                                args);
+}
diff --git a/src/core/ext/client_config/client_channel_factory.h b/src/core/ext/client_config/client_channel_factory.h
new file mode 100644
index 0000000..1241b9b
--- /dev/null
+++ b/src/core/ext/client_config/client_channel_factory.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+#include "src/core/ext/client_config/subchannel.h"
+#include "src/core/lib/channel/channel_stack.h"
+
+typedef struct grpc_client_channel_factory grpc_client_channel_factory;
+typedef struct grpc_client_channel_factory_vtable
+    grpc_client_channel_factory_vtable;
+
+typedef enum {
+  GRPC_CLIENT_CHANNEL_TYPE_REGULAR, /** for the user-level regular calls */
+  GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, /** for communication with a load
+                                              balancing service */
+} grpc_client_channel_type;
+
+/** Constructor for new configured channels.
+    Creating decorators around this type is encouraged to adapt behavior. */
+struct grpc_client_channel_factory {
+  const grpc_client_channel_factory_vtable *vtable;
+};
+
+struct grpc_client_channel_factory_vtable {
+  void (*ref)(grpc_client_channel_factory *factory);
+  void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory);
+  grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
+                                        grpc_client_channel_factory *factory,
+                                        grpc_subchannel_args *args);
+  grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx,
+                                         grpc_client_channel_factory *factory,
+                                         const char *target,
+                                         grpc_client_channel_type type,
+                                         grpc_channel_args *args);
+};
+
+void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory);
+void grpc_client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
+                                       grpc_client_channel_factory *factory);
+
+/** Create a new grpc_subchannel */
+grpc_subchannel *grpc_client_channel_factory_create_subchannel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
+    grpc_subchannel_args *args);
+
+/** Create a new grpc_channel */
+grpc_channel *grpc_client_channel_factory_create_channel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
+    const char *target, grpc_client_channel_type type, grpc_channel_args *args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H */
diff --git a/src/core/ext/client_config/client_config.c b/src/core/ext/client_config/client_config.c
new file mode 100644
index 0000000..f9b8e68
--- /dev/null
+++ b/src/core/ext/client_config/client_config.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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/ext/client_config/client_config.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+struct grpc_client_config {
+  gpr_refcount refs;
+  grpc_lb_policy *lb_policy;
+};
+
+grpc_client_config *grpc_client_config_create() {
+  grpc_client_config *c = gpr_malloc(sizeof(*c));
+  memset(c, 0, sizeof(*c));
+  gpr_ref_init(&c->refs, 1);
+  return c;
+}
+
+void grpc_client_config_ref(grpc_client_config *c) { gpr_ref(&c->refs); }
+
+void grpc_client_config_unref(grpc_exec_ctx *exec_ctx, grpc_client_config *c) {
+  if (gpr_unref(&c->refs)) {
+    if (c->lb_policy != NULL) {
+      GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
+    }
+    gpr_free(c);
+  }
+}
+
+void grpc_client_config_set_lb_policy(grpc_client_config *c,
+                                      grpc_lb_policy *lb_policy) {
+  GPR_ASSERT(c->lb_policy == NULL);
+  if (lb_policy) {
+    GRPC_LB_POLICY_REF(lb_policy, "client_config");
+  }
+  c->lb_policy = lb_policy;
+}
+
+grpc_lb_policy *grpc_client_config_get_lb_policy(grpc_client_config *c) {
+  return c->lb_policy;
+}
diff --git a/src/core/ext/client_config/client_config.h b/src/core/ext/client_config/client_config.h
new file mode 100644
index 0000000..a6290cb
--- /dev/null
+++ b/src/core/ext/client_config/client_config.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_CLIENT_CONFIG_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CONFIG_H
+
+#include "src/core/ext/client_config/lb_policy.h"
+
+/** Total configuration for a client. Provided, and updated, by
+    grpc_resolver */
+typedef struct grpc_client_config grpc_client_config;
+
+grpc_client_config *grpc_client_config_create();
+void grpc_client_config_ref(grpc_client_config *client_config);
+void grpc_client_config_unref(grpc_exec_ctx *exec_ctx,
+                              grpc_client_config *client_config);
+
+void grpc_client_config_set_lb_policy(grpc_client_config *client_config,
+                                      grpc_lb_policy *lb_policy);
+grpc_lb_policy *grpc_client_config_get_lb_policy(
+    grpc_client_config *client_config);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CONFIG_H */
diff --git a/src/core/ext/client_config/client_config_plugin.c b/src/core/ext/client_config/client_config_plugin.c
new file mode 100644
index 0000000..5e31613
--- /dev/null
+++ b/src/core/ext/client_config/client_config_plugin.c
@@ -0,0 +1,95 @@
+/*
+ *
+ * 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 <limits.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/ext/client_config/resolver_registry.h"
+#include "src/core/ext/client_config/subchannel_index.h"
+#include "src/core/lib/surface/channel_init.h"
+
+#ifndef GRPC_DEFAULT_NAME_PREFIX
+#define GRPC_DEFAULT_NAME_PREFIX "dns:///"
+#endif
+
+static bool append_filter(grpc_channel_stack_builder *builder, void *arg) {
+  return grpc_channel_stack_builder_append_filter(
+      builder, (const grpc_channel_filter *)arg, NULL, NULL);
+}
+
+static bool set_default_host_if_unset(grpc_channel_stack_builder *builder,
+                                      void *unused) {
+  const grpc_channel_args *args =
+      grpc_channel_stack_builder_get_channel_arguments(builder);
+  for (size_t i = 0; i < args->num_args; i++) {
+    if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY) ||
+        0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
+      return true;
+    }
+  }
+  char *default_authority = grpc_get_default_authority(
+      grpc_channel_stack_builder_get_target(builder));
+  if (default_authority != NULL) {
+    grpc_arg arg;
+    arg.type = GRPC_ARG_STRING;
+    arg.key = GRPC_ARG_DEFAULT_AUTHORITY;
+    arg.value.string = default_authority;
+    grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
+    grpc_channel_stack_builder_set_channel_arguments(builder, new_args);
+    gpr_free(default_authority);
+    grpc_channel_args_destroy(new_args);
+  }
+  return true;
+}
+
+void grpc_client_config_init(void) {
+  grpc_lb_policy_registry_init();
+  grpc_resolver_registry_init(GRPC_DEFAULT_NAME_PREFIX);
+  grpc_subchannel_index_init();
+  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
+                                   set_default_host_if_unset, NULL);
+  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, append_filter,
+                                   (void *)&grpc_client_channel_filter);
+}
+
+void grpc_client_config_shutdown(void) {
+  grpc_subchannel_index_shutdown();
+  grpc_channel_init_shutdown();
+  grpc_resolver_registry_shutdown();
+  grpc_lb_policy_registry_shutdown();
+}
diff --git a/src/core/ext/client_config/connector.c b/src/core/ext/client_config/connector.c
new file mode 100644
index 0000000..5b629ed
--- /dev/null
+++ b/src/core/ext/client_config/connector.c
@@ -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.
+ *
+ */
+
+#include "src/core/ext/client_config/connector.h"
+
+grpc_connector* grpc_connector_ref(grpc_connector* connector) {
+  connector->vtable->ref(connector);
+  return connector;
+}
+
+void grpc_connector_unref(grpc_exec_ctx* exec_ctx, grpc_connector* connector) {
+  connector->vtable->unref(exec_ctx, connector);
+}
+
+void grpc_connector_connect(grpc_exec_ctx* exec_ctx, grpc_connector* connector,
+                            const grpc_connect_in_args* in_args,
+                            grpc_connect_out_args* out_args,
+                            grpc_closure* notify) {
+  connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify);
+}
+
+void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx,
+                             grpc_connector* connector) {
+  connector->vtable->shutdown(exec_ctx, connector);
+}
diff --git a/src/core/ext/client_config/connector.h b/src/core/ext/client_config/connector.h
new file mode 100644
index 0000000..dd85dfc
--- /dev/null
+++ b/src/core/ext/client_config/connector.h
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_CONNECTOR_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_CONNECTOR_H
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/transport/transport.h"
+
+typedef struct grpc_connector grpc_connector;
+typedef struct grpc_connector_vtable grpc_connector_vtable;
+
+struct grpc_connector {
+  const grpc_connector_vtable *vtable;
+};
+
+typedef struct {
+  /** set of pollsets interested in this connection */
+  grpc_pollset_set *interested_parties;
+  /** address to connect to */
+  const struct sockaddr *addr;
+  size_t addr_len;
+  /** initial connect string to send */
+  gpr_slice initial_connect_string;
+  /** deadline for connection */
+  gpr_timespec deadline;
+  /** channel arguments (to be passed to transport) */
+  const grpc_channel_args *channel_args;
+} grpc_connect_in_args;
+
+typedef struct {
+  /** the connected transport */
+  grpc_transport *transport;
+
+  /** channel arguments (to be passed to the filters) */
+  const grpc_channel_args *channel_args;
+} grpc_connect_out_args;
+
+struct grpc_connector_vtable {
+  void (*ref)(grpc_connector *connector);
+  void (*unref)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
+  /** Implementation of grpc_connector_shutdown */
+  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
+  /** Implementation of grpc_connector_connect */
+  void (*connect)(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
+                  const grpc_connect_in_args *in_args,
+                  grpc_connect_out_args *out_args, grpc_closure *notify);
+};
+
+grpc_connector *grpc_connector_ref(grpc_connector *connector);
+void grpc_connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
+/** Connect using the connector: max one outstanding call at a time */
+void grpc_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
+                            const grpc_connect_in_args *in_args,
+                            grpc_connect_out_args *out_args,
+                            grpc_closure *notify);
+/** Cancel any pending connection */
+void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx,
+                             grpc_connector *connector);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_CONNECTOR_H */
diff --git a/src/core/ext/client_config/default_initial_connect_string.c b/src/core/ext/client_config/default_initial_connect_string.c
new file mode 100644
index 0000000..a70da4a
--- /dev/null
+++ b/src/core/ext/client_config/default_initial_connect_string.c
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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/slice.h>
+#include "src/core/lib/iomgr/sockaddr.h"
+
+void grpc_set_default_initial_connect_string(struct sockaddr **addr,
+                                             size_t *addr_len,
+                                             gpr_slice *initial_str) {}
diff --git a/src/core/ext/client_config/initial_connect_string.c b/src/core/ext/client_config/initial_connect_string.c
new file mode 100644
index 0000000..41580d2
--- /dev/null
+++ b/src/core/ext/client_config/initial_connect_string.c
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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/ext/client_config/initial_connect_string.h"
+
+#include <stddef.h>
+
+extern void grpc_set_default_initial_connect_string(struct sockaddr **addr,
+                                                    size_t *addr_len,
+                                                    gpr_slice *initial_str);
+
+static grpc_set_initial_connect_string_func g_set_initial_connect_string_func =
+    grpc_set_default_initial_connect_string;
+
+void grpc_test_set_initial_connect_string_function(
+    grpc_set_initial_connect_string_func func) {
+  g_set_initial_connect_string_func = func;
+}
+
+void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
+                                     gpr_slice *initial_str) {
+  g_set_initial_connect_string_func(addr, addr_len, initial_str);
+}
diff --git a/src/core/ext/client_config/initial_connect_string.h b/src/core/ext/client_config/initial_connect_string.h
new file mode 100644
index 0000000..06f0767
--- /dev/null
+++ b/src/core/ext/client_config/initial_connect_string.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H
+
+#include <grpc/support/slice.h>
+#include "src/core/lib/iomgr/sockaddr.h"
+
+typedef void (*grpc_set_initial_connect_string_func)(struct sockaddr **addr,
+                                                     size_t *addr_len,
+                                                     gpr_slice *initial_str);
+void grpc_test_set_initial_connect_string_function(
+    grpc_set_initial_connect_string_func func);
+
+/** Set a string to be sent once connected. Optionally reset addr. */
+void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
+                                     gpr_slice *connect_string);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H */
diff --git a/src/core/ext/client_config/lb_policy.c b/src/core/ext/client_config/lb_policy.c
new file mode 100644
index 0000000..a7ad984
--- /dev/null
+++ b/src/core/ext/client_config/lb_policy.c
@@ -0,0 +1,143 @@
+/*
+ *
+ * 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/ext/client_config/lb_policy.h"
+
+#define WEAK_REF_BITS 16
+
+void grpc_lb_policy_init(grpc_lb_policy *policy,
+                         const grpc_lb_policy_vtable *vtable) {
+  policy->vtable = vtable;
+  gpr_atm_no_barrier_store(&policy->ref_pair, 1 << WEAK_REF_BITS);
+  policy->interested_parties = grpc_pollset_set_create();
+}
+
+#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
+#define REF_FUNC_EXTRA_ARGS , const char *file, int line, const char *reason
+#define REF_MUTATE_EXTRA_ARGS REF_FUNC_EXTRA_ARGS, const char *purpose
+#define REF_FUNC_PASS_ARGS(new_reason) , file, line, new_reason
+#define REF_MUTATE_PASS_ARGS(purpose) , file, line, reason, purpose
+#else
+#define REF_FUNC_EXTRA_ARGS
+#define REF_MUTATE_EXTRA_ARGS
+#define REF_FUNC_PASS_ARGS(new_reason)
+#define REF_MUTATE_PASS_ARGS(x)
+#endif
+
+static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta,
+                          int barrier REF_MUTATE_EXTRA_ARGS) {
+  gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
+                            : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
+#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "LB_POLICY: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
+          old_val + delta, reason);
+#endif
+  return old_val;
+}
+
+void grpc_lb_policy_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
+  ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF"));
+}
+
+void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx,
+                          grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
+  gpr_atm old_val =
+      ref_mutate(policy, (gpr_atm)1 - (gpr_atm)(1 << WEAK_REF_BITS),
+                 1 REF_MUTATE_PASS_ARGS("STRONG_UNREF"));
+  gpr_atm mask = ~(gpr_atm)((1 << WEAK_REF_BITS) - 1);
+  gpr_atm check = 1 << WEAK_REF_BITS;
+  if ((old_val & mask) == check) {
+    policy->vtable->shutdown(exec_ctx, policy);
+  }
+  grpc_lb_policy_weak_unref(exec_ctx,
+                            policy REF_FUNC_PASS_ARGS("strong-unref"));
+}
+
+void grpc_lb_policy_weak_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
+  ref_mutate(policy, 1, 0 REF_MUTATE_PASS_ARGS("WEAK_REF"));
+}
+
+void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
+                               grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
+  gpr_atm old_val =
+      ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
+  if (old_val == 1) {
+    grpc_pollset_set_destroy(policy->interested_parties);
+    policy->vtable->destroy(exec_ctx, policy);
+  }
+}
+
+int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                        grpc_pollset *pollset,
+                        grpc_metadata_batch *initial_metadata,
+                        uint32_t initial_metadata_flags,
+                        grpc_connected_subchannel **target,
+                        grpc_closure *on_complete) {
+  return policy->vtable->pick(exec_ctx, policy, pollset, initial_metadata,
+                              initial_metadata_flags, target, on_complete);
+}
+
+void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                                grpc_connected_subchannel **target) {
+  policy->vtable->cancel_pick(exec_ctx, policy, target);
+}
+
+void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
+                                 grpc_lb_policy *policy,
+                                 uint32_t initial_metadata_flags_mask,
+                                 uint32_t initial_metadata_flags_eq) {
+  policy->vtable->cancel_picks(exec_ctx, policy, initial_metadata_flags_mask,
+                               initial_metadata_flags_eq);
+}
+
+void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
+  policy->vtable->exit_idle(exec_ctx, policy);
+}
+
+void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                             grpc_closure *closure) {
+  policy->vtable->ping_one(exec_ctx, policy, closure);
+}
+
+void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
+                                           grpc_lb_policy *policy,
+                                           grpc_connectivity_state *state,
+                                           grpc_closure *closure) {
+  policy->vtable->notify_on_state_change(exec_ctx, policy, state, closure);
+}
+
+grpc_connectivity_state grpc_lb_policy_check_connectivity(
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
+  return policy->vtable->check_connectivity(exec_ctx, policy);
+}
diff --git a/src/core/ext/client_config/lb_policy.h b/src/core/ext/client_config/lb_policy.h
new file mode 100644
index 0000000..0384e0b
--- /dev/null
+++ b/src/core/ext/client_config/lb_policy.h
@@ -0,0 +1,157 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_LB_POLICY_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_H
+
+#include "src/core/ext/client_config/subchannel.h"
+#include "src/core/lib/transport/connectivity_state.h"
+
+/** A load balancing policy: specified by a vtable and a struct (which
+    is expected to be extended to contain some parameters) */
+typedef struct grpc_lb_policy grpc_lb_policy;
+typedef struct grpc_lb_policy_vtable grpc_lb_policy_vtable;
+
+typedef void (*grpc_lb_completion)(void *cb_arg, grpc_subchannel *subchannel,
+                                   grpc_status_code status, const char *errmsg);
+
+struct grpc_lb_policy {
+  const grpc_lb_policy_vtable *vtable;
+  gpr_atm ref_pair;
+  /* owned pointer to interested parties in load balancing decisions */
+  grpc_pollset_set *interested_parties;
+};
+
+struct grpc_lb_policy_vtable {
+  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+
+  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+
+  /** implement grpc_lb_policy_pick */
+  int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+              grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
+              uint32_t initial_metadata_flags,
+              grpc_connected_subchannel **target, grpc_closure *on_complete);
+  void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                      grpc_connected_subchannel **target);
+  void (*cancel_picks)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                       uint32_t initial_metadata_flags_mask,
+                       uint32_t initial_metadata_flags_eq);
+
+  void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                   grpc_closure *closure);
+
+  /** try to enter a READY connectivity state */
+  void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+
+  /** check the current connectivity of the lb_policy */
+  grpc_connectivity_state (*check_connectivity)(grpc_exec_ctx *exec_ctx,
+                                                grpc_lb_policy *policy);
+
+  /** call notify when the connectivity state of a channel changes from *state.
+      Updates *state with the new state of the policy */
+  void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx,
+                                 grpc_lb_policy *policy,
+                                 grpc_connectivity_state *state,
+                                 grpc_closure *closure);
+};
+
+/*#define GRPC_LB_POLICY_REFCOUNT_DEBUG*/
+#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
+#define GRPC_LB_POLICY_REF(p, r) \
+  grpc_lb_policy_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_LB_POLICY_UNREF(exec_ctx, p, r) \
+  grpc_lb_policy_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
+#define GRPC_LB_POLICY_WEAK_REF(p, r) \
+  grpc_lb_policy_weak_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, p, r) \
+  grpc_lb_policy_weak_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
+void grpc_lb_policy_ref(grpc_lb_policy *policy, const char *file, int line,
+                        const char *reason);
+void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                          const char *file, int line, const char *reason);
+void grpc_lb_policy_weak_ref(grpc_lb_policy *policy, const char *file, int line,
+                             const char *reason);
+void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                               const char *file, int line, const char *reason);
+#else
+#define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p))
+#define GRPC_LB_POLICY_UNREF(cl, p, r) grpc_lb_policy_unref((cl), (p))
+#define GRPC_LB_POLICY_WEAK_REF(p, r) grpc_lb_policy_weak_ref((p))
+#define GRPC_LB_POLICY_WEAK_UNREF(cl, p, r) grpc_lb_policy_weak_unref((cl), (p))
+void grpc_lb_policy_ref(grpc_lb_policy *policy);
+void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+void grpc_lb_policy_weak_ref(grpc_lb_policy *policy);
+void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+#endif
+
+/** called by concrete implementations to initialize the base struct */
+void grpc_lb_policy_init(grpc_lb_policy *policy,
+                         const grpc_lb_policy_vtable *vtable);
+
+/** Given initial metadata in \a initial_metadata, find an appropriate
+    target for this rpc, and 'return' it by calling \a on_complete after setting
+    \a target.
+    Picking can be asynchronous. Any IO should be done under \a pollset. */
+int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                        grpc_pollset *pollset,
+                        grpc_metadata_batch *initial_metadata,
+                        uint32_t initial_metadata_flags,
+                        grpc_connected_subchannel **target,
+                        grpc_closure *on_complete);
+
+void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                             grpc_closure *closure);
+
+void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                                grpc_connected_subchannel **target);
+
+/** Cancel all pending picks which have:
+    (initial_metadata_flags & initial_metadata_flags_mask) ==
+         initial_metadata_flags_eq */
+void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
+                                 grpc_lb_policy *policy,
+                                 uint32_t initial_metadata_flags_mask,
+                                 uint32_t initial_metadata_flags_eq);
+
+void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+
+void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
+                                           grpc_lb_policy *policy,
+                                           grpc_connectivity_state *state,
+                                           grpc_closure *closure);
+
+grpc_connectivity_state grpc_lb_policy_check_connectivity(
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_H */
diff --git a/src/core/ext/client_config/lb_policy_factory.c b/src/core/ext/client_config/lb_policy_factory.c
new file mode 100644
index 0000000..70e46ef
--- /dev/null
+++ b/src/core/ext/client_config/lb_policy_factory.c
@@ -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.
+ *
+ */
+
+#include "src/core/ext/client_config/lb_policy_factory.h"
+
+void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
+  factory->vtable->ref(factory);
+}
+
+void grpc_lb_policy_factory_unref(grpc_lb_policy_factory* factory) {
+  factory->vtable->unref(factory);
+}
+
+grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy(
+    grpc_exec_ctx* exec_ctx, grpc_lb_policy_factory* factory,
+    grpc_lb_policy_args* args) {
+  if (factory == NULL) return NULL;
+  return factory->vtable->create_lb_policy(exec_ctx, factory, args);
+}
diff --git a/src/core/ext/client_config/lb_policy_factory.h b/src/core/ext/client_config/lb_policy_factory.h
new file mode 100644
index 0000000..1c89b28
--- /dev/null
+++ b/src/core/ext/client_config/lb_policy_factory.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_LB_POLICY_FACTORY_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_FACTORY_H
+
+#include "src/core/ext/client_config/client_channel_factory.h"
+#include "src/core/ext/client_config/lb_policy.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+typedef struct grpc_lb_policy_factory grpc_lb_policy_factory;
+typedef struct grpc_lb_policy_factory_vtable grpc_lb_policy_factory_vtable;
+
+/** grpc_lb_policy provides grpc_client_config objects to grpc_channel
+    objects */
+struct grpc_lb_policy_factory {
+  const grpc_lb_policy_factory_vtable *vtable;
+};
+
+typedef struct grpc_lb_policy_args {
+  grpc_resolved_addresses *addresses;
+  grpc_client_channel_factory *client_channel_factory;
+} grpc_lb_policy_args;
+
+struct grpc_lb_policy_factory_vtable {
+  void (*ref)(grpc_lb_policy_factory *factory);
+  void (*unref)(grpc_lb_policy_factory *factory);
+
+  /** Implementation of grpc_lb_policy_factory_create_lb_policy */
+  grpc_lb_policy *(*create_lb_policy)(grpc_exec_ctx *exec_ctx,
+                                      grpc_lb_policy_factory *factory,
+                                      grpc_lb_policy_args *args);
+
+  /** Name for the LB policy this factory implements */
+  const char *name;
+};
+
+void grpc_lb_policy_factory_ref(grpc_lb_policy_factory *factory);
+void grpc_lb_policy_factory_unref(grpc_lb_policy_factory *factory);
+
+/** Create a lb_policy instance. */
+grpc_lb_policy *grpc_lb_policy_factory_create_lb_policy(
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory,
+    grpc_lb_policy_args *args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_FACTORY_H */
diff --git a/src/core/ext/client_config/lb_policy_registry.c b/src/core/ext/client_config/lb_policy_registry.c
new file mode 100644
index 0000000..a23643e
--- /dev/null
+++ b/src/core/ext/client_config/lb_policy_registry.c
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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/ext/client_config/lb_policy_registry.h"
+
+#include <string.h>
+
+#define MAX_POLICIES 10
+
+static grpc_lb_policy_factory *g_all_of_the_lb_policies[MAX_POLICIES];
+static int g_number_of_lb_policies = 0;
+
+void grpc_lb_policy_registry_init(void) { g_number_of_lb_policies = 0; }
+
+void grpc_lb_policy_registry_shutdown(void) {
+  int i;
+  for (i = 0; i < g_number_of_lb_policies; i++) {
+    grpc_lb_policy_factory_unref(g_all_of_the_lb_policies[i]);
+  }
+}
+
+void grpc_register_lb_policy(grpc_lb_policy_factory *factory) {
+  int i;
+  for (i = 0; i < g_number_of_lb_policies; i++) {
+    GPR_ASSERT(0 != strcmp(factory->vtable->name,
+                           g_all_of_the_lb_policies[i]->vtable->name));
+  }
+  GPR_ASSERT(g_number_of_lb_policies != MAX_POLICIES);
+  grpc_lb_policy_factory_ref(factory);
+  g_all_of_the_lb_policies[g_number_of_lb_policies++] = factory;
+}
+
+static grpc_lb_policy_factory *lookup_factory(const char *name) {
+  int i;
+
+  if (name == NULL) return NULL;
+
+  for (i = 0; i < g_number_of_lb_policies; i++) {
+    if (0 == strcmp(name, g_all_of_the_lb_policies[i]->vtable->name)) {
+      return g_all_of_the_lb_policies[i];
+    }
+  }
+
+  return NULL;
+}
+
+grpc_lb_policy *grpc_lb_policy_create(grpc_exec_ctx *exec_ctx, const char *name,
+                                      grpc_lb_policy_args *args) {
+  grpc_lb_policy_factory *factory = lookup_factory(name);
+  grpc_lb_policy *lb_policy =
+      grpc_lb_policy_factory_create_lb_policy(exec_ctx, factory, args);
+  return lb_policy;
+}
diff --git a/src/core/ext/client_config/lb_policy_registry.h b/src/core/ext/client_config/lb_policy_registry.h
new file mode 100644
index 0000000..92f38d6
--- /dev/null
+++ b/src/core/ext/client_config/lb_policy_registry.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_EXT_CLIENT_CONFIG_LB_POLICY_REGISTRY_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_REGISTRY_H
+
+#include "src/core/ext/client_config/lb_policy_factory.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+/** Initialize the registry and set \a default_factory as the factory to be
+ * returned when no name is provided in a lookup */
+void grpc_lb_policy_registry_init(void);
+void grpc_lb_policy_registry_shutdown(void);
+
+/** Register a LB policy factory. */
+void grpc_register_lb_policy(grpc_lb_policy_factory *factory);
+
+/** Create a \a grpc_lb_policy instance.
+ *
+ * If \a name is NULL, the default factory from \a grpc_lb_policy_registry_init
+ * will be returned. */
+grpc_lb_policy *grpc_lb_policy_create(grpc_exec_ctx *exec_ctx, const char *name,
+                                      grpc_lb_policy_args *args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_REGISTRY_H */
diff --git a/src/core/ext/client_config/parse_address.c b/src/core/ext/client_config/parse_address.c
new file mode 100644
index 0000000..8b4abe2
--- /dev/null
+++ b/src/core/ext/client_config/parse_address.c
@@ -0,0 +1,137 @@
+/*
+ *
+ * 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/ext/client_config/parse_address.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef GPR_HAVE_UNIX_SOCKET
+#include <sys/un.h>
+#endif
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#ifdef GPR_HAVE_UNIX_SOCKET
+int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len) {
+  struct sockaddr_un *un = (struct sockaddr_un *)addr;
+
+  un->sun_family = AF_UNIX;
+  strcpy(un->sun_path, uri->path);
+  *len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
+
+  return 1;
+}
+#endif
+
+int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len) {
+  const char *host_port = uri->path;
+  char *host;
+  char *port;
+  int port_num;
+  int result = 0;
+  struct sockaddr_in *in = (struct sockaddr_in *)addr;
+
+  if (*host_port == '/') ++host_port;
+  if (!gpr_split_host_port(host_port, &host, &port)) {
+    return 0;
+  }
+
+  memset(in, 0, sizeof(*in));
+  *len = sizeof(*in);
+  in->sin_family = AF_INET;
+  if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
+    gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
+    goto done;
+  }
+
+  if (port != NULL) {
+    if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
+        port_num > 65535) {
+      gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
+      goto done;
+    }
+    in->sin_port = htons((uint16_t)port_num);
+  } else {
+    gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
+    goto done;
+  }
+
+  result = 1;
+done:
+  gpr_free(host);
+  gpr_free(port);
+  return result;
+}
+
+int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len) {
+  const char *host_port = uri->path;
+  char *host;
+  char *port;
+  int port_num;
+  int result = 0;
+  struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
+
+  if (*host_port == '/') ++host_port;
+  if (!gpr_split_host_port(host_port, &host, &port)) {
+    return 0;
+  }
+
+  memset(in6, 0, sizeof(*in6));
+  *len = sizeof(*in6);
+  in6->sin6_family = AF_INET6;
+  if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
+    gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
+    goto done;
+  }
+
+  if (port != NULL) {
+    if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
+        port_num > 65535) {
+      gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
+      goto done;
+    }
+    in6->sin6_port = htons((uint16_t)port_num);
+  } else {
+    gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
+    goto done;
+  }
+
+  result = 1;
+done:
+  gpr_free(host);
+  gpr_free(port);
+  return result;
+}
diff --git a/src/core/ext/client_config/parse_address.h b/src/core/ext/client_config/parse_address.h
new file mode 100644
index 0000000..74c86f4
--- /dev/null
+++ b/src/core/ext/client_config/parse_address.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_PARSE_ADDRESS_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_PARSE_ADDRESS_H
+
+#include <stddef.h>
+
+#include "src/core/ext/client_config/uri_parser.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
+#ifdef GPR_HAVE_UNIX_SOCKET
+/** Populate \a addr and \a len from \a uri, whose path is expected to contain a
+ * unix socket path. Returns true upon success. */
+int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len);
+#endif
+
+/** Populate /a addr and \a len from \a uri, whose path is expected to contain a
+ * host:port pair. Returns true upon success. */
+int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len);
+
+/** Populate /a addr and \a len from \a uri, whose path is expected to contain a
+ * host:port pair. Returns true upon success. */
+int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_PARSE_ADDRESS_H */
diff --git a/src/core/ext/client_config/resolver.c b/src/core/ext/client_config/resolver.c
new file mode 100644
index 0000000..eb00445
--- /dev/null
+++ b/src/core/ext/client_config/resolver.c
@@ -0,0 +1,82 @@
+/*
+ *
+ * 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/ext/client_config/resolver.h"
+
+void grpc_resolver_init(grpc_resolver *resolver,
+                        const grpc_resolver_vtable *vtable) {
+  resolver->vtable = vtable;
+  gpr_ref_init(&resolver->refs, 1);
+}
+
+#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
+void grpc_resolver_ref(grpc_resolver *resolver, grpc_closure_list *closure_list,
+                       const char *file, int line, const char *reason) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p   ref %d -> %d %s",
+          resolver, (int)resolver->refs.count, (int)resolver->refs.count + 1,
+          reason);
+#else
+void grpc_resolver_ref(grpc_resolver *resolver) {
+#endif
+  gpr_ref(&resolver->refs);
+}
+
+#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
+void grpc_resolver_unref(grpc_resolver *resolver,
+                         grpc_closure_list *closure_list, const char *file,
+                         int line, const char *reason) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p unref %d -> %d %s",
+          resolver, (int)resolver->refs.count, (int)resolver->refs.count - 1,
+          reason);
+#else
+void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
+#endif
+  if (gpr_unref(&resolver->refs)) {
+    resolver->vtable->destroy(exec_ctx, resolver);
+  }
+}
+
+void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
+  resolver->vtable->shutdown(exec_ctx, resolver);
+}
+
+void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
+                                     grpc_resolver *resolver) {
+  resolver->vtable->channel_saw_error(exec_ctx, resolver);
+}
+
+void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                        grpc_client_config **target_config,
+                        grpc_closure *on_complete) {
+  resolver->vtable->next(exec_ctx, resolver, target_config, on_complete);
+}
diff --git a/src/core/ext/client_config/resolver.h b/src/core/ext/client_config/resolver.h
new file mode 100644
index 0000000..6ecb5d2
--- /dev/null
+++ b/src/core/ext/client_config/resolver.h
@@ -0,0 +1,94 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_RESOLVER_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_H
+
+#include "src/core/ext/client_config/client_config.h"
+#include "src/core/ext/client_config/subchannel.h"
+#include "src/core/lib/iomgr/iomgr.h"
+
+typedef struct grpc_resolver grpc_resolver;
+typedef struct grpc_resolver_vtable grpc_resolver_vtable;
+
+/** grpc_resolver provides grpc_client_config objects to grpc_channel
+    objects */
+struct grpc_resolver {
+  const grpc_resolver_vtable *vtable;
+  gpr_refcount refs;
+};
+
+struct grpc_resolver_vtable {
+  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+  void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+  void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+               grpc_client_config **target_config, grpc_closure *on_complete);
+};
+
+#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
+#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_RESOLVER_UNREF(cl, p, r) \
+  grpc_resolver_unref((cl), (p), __FILE__, __LINE__, (r))
+void grpc_resolver_ref(grpc_resolver *policy, const char *file, int line,
+                       const char *reason);
+void grpc_resolver_unref(grpc_resolver *policy, grpc_closure_list *closure_list,
+                         const char *file, int line, const char *reason);
+#else
+#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p))
+#define GRPC_RESOLVER_UNREF(cl, p, r) grpc_resolver_unref((cl), (p))
+void grpc_resolver_ref(grpc_resolver *policy);
+void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy);
+#endif
+
+void grpc_resolver_init(grpc_resolver *resolver,
+                        const grpc_resolver_vtable *vtable);
+
+void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+
+/** Notification that the channel has seen an error on some address.
+    Can be used as a hint that re-resolution is desirable soon. */
+void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
+                                     grpc_resolver *resolver);
+
+/** Get the next client config. Called by the channel to fetch a new
+    configuration. Expected to set *target_config with a new configuration,
+    and then schedule on_complete for execution.
+
+    If resolution is fatally broken, set *target_config to NULL and
+    schedule on_complete. */
+void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                        grpc_client_config **target_config,
+                        grpc_closure *on_complete);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_H */
diff --git a/src/core/ext/client_config/resolver_factory.c b/src/core/ext/client_config/resolver_factory.c
new file mode 100644
index 0000000..67832dc
--- /dev/null
+++ b/src/core/ext/client_config/resolver_factory.c
@@ -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.
+ *
+ */
+
+#include "src/core/ext/client_config/resolver_factory.h"
+
+void grpc_resolver_factory_ref(grpc_resolver_factory* factory) {
+  factory->vtable->ref(factory);
+}
+
+void grpc_resolver_factory_unref(grpc_resolver_factory* factory) {
+  factory->vtable->unref(factory);
+}
+
+/** Create a resolver instance for a name */
+grpc_resolver* grpc_resolver_factory_create_resolver(
+    grpc_resolver_factory* factory, grpc_resolver_args* args) {
+  if (factory == NULL) return NULL;
+  return factory->vtable->create_resolver(factory, args);
+}
+
+char* grpc_resolver_factory_get_default_authority(
+    grpc_resolver_factory* factory, grpc_uri* uri) {
+  if (factory == NULL) return NULL;
+  return factory->vtable->get_default_authority(factory, uri);
+}
diff --git a/src/core/ext/client_config/resolver_factory.h b/src/core/ext/client_config/resolver_factory.h
new file mode 100644
index 0000000..4eb6979
--- /dev/null
+++ b/src/core/ext/client_config/resolver_factory.h
@@ -0,0 +1,82 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_RESOLVER_FACTORY_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_FACTORY_H
+
+#include "src/core/ext/client_config/client_channel_factory.h"
+#include "src/core/ext/client_config/resolver.h"
+#include "src/core/ext/client_config/uri_parser.h"
+
+typedef struct grpc_resolver_factory grpc_resolver_factory;
+typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable;
+
+/** grpc_resolver provides grpc_client_config objects to grpc_channel
+    objects */
+struct grpc_resolver_factory {
+  const grpc_resolver_factory_vtable *vtable;
+};
+
+typedef struct grpc_resolver_args {
+  grpc_uri *uri;
+  grpc_client_channel_factory *client_channel_factory;
+} grpc_resolver_args;
+
+struct grpc_resolver_factory_vtable {
+  void (*ref)(grpc_resolver_factory *factory);
+  void (*unref)(grpc_resolver_factory *factory);
+
+  /** Implementation of grpc_resolver_factory_create_resolver */
+  grpc_resolver *(*create_resolver)(grpc_resolver_factory *factory,
+                                    grpc_resolver_args *args);
+
+  /** Implementation of grpc_resolver_factory_get_default_authority */
+  char *(*get_default_authority)(grpc_resolver_factory *factory, grpc_uri *uri);
+
+  /** URI scheme that this factory implements */
+  const char *scheme;
+};
+
+void grpc_resolver_factory_ref(grpc_resolver_factory *resolver);
+void grpc_resolver_factory_unref(grpc_resolver_factory *resolver);
+
+/** Create a resolver instance for a name */
+grpc_resolver *grpc_resolver_factory_create_resolver(
+    grpc_resolver_factory *factory, grpc_resolver_args *args);
+
+/** Return a (freshly allocated with gpr_malloc) string representing
+    the default authority to use for this scheme. */
+char *grpc_resolver_factory_get_default_authority(
+    grpc_resolver_factory *factory, grpc_uri *uri);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_FACTORY_H */
diff --git a/src/core/ext/client_config/resolver_registry.c b/src/core/ext/client_config/resolver_registry.c
new file mode 100644
index 0000000..07f29bc
--- /dev/null
+++ b/src/core/ext/client_config/resolver_registry.c
@@ -0,0 +1,145 @@
+/*
+ *
+ * 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/ext/client_config/resolver_registry.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#define MAX_RESOLVERS 10
+
+static grpc_resolver_factory *g_all_of_the_resolvers[MAX_RESOLVERS];
+static int g_number_of_resolvers = 0;
+
+static char *g_default_resolver_prefix;
+
+void grpc_resolver_registry_init(const char *default_resolver_prefix) {
+  g_number_of_resolvers = 0;
+  g_default_resolver_prefix = gpr_strdup(default_resolver_prefix);
+}
+
+void grpc_resolver_registry_shutdown(void) {
+  int i;
+  for (i = 0; i < g_number_of_resolvers; i++) {
+    grpc_resolver_factory_unref(g_all_of_the_resolvers[i]);
+  }
+  gpr_free(g_default_resolver_prefix);
+}
+
+void grpc_register_resolver_type(grpc_resolver_factory *factory) {
+  int i;
+  for (i = 0; i < g_number_of_resolvers; i++) {
+    GPR_ASSERT(0 != strcmp(factory->vtable->scheme,
+                           g_all_of_the_resolvers[i]->vtable->scheme));
+  }
+  GPR_ASSERT(g_number_of_resolvers != MAX_RESOLVERS);
+  grpc_resolver_factory_ref(factory);
+  g_all_of_the_resolvers[g_number_of_resolvers++] = factory;
+}
+
+static grpc_resolver_factory *lookup_factory(const char *name) {
+  int i;
+
+  for (i = 0; i < g_number_of_resolvers; i++) {
+    if (0 == strcmp(name, g_all_of_the_resolvers[i]->vtable->scheme)) {
+      return g_all_of_the_resolvers[i];
+    }
+  }
+
+  return NULL;
+}
+
+grpc_resolver_factory *grpc_resolver_factory_lookup(const char *name) {
+  grpc_resolver_factory *f = lookup_factory(name);
+  if (f) grpc_resolver_factory_ref(f);
+  return f;
+}
+
+static grpc_resolver_factory *lookup_factory_by_uri(grpc_uri *uri) {
+  if (!uri) return NULL;
+  return lookup_factory(uri->scheme);
+}
+
+static grpc_resolver_factory *resolve_factory(const char *target,
+                                              grpc_uri **uri) {
+  char *tmp;
+  grpc_resolver_factory *factory = NULL;
+
+  GPR_ASSERT(uri != NULL);
+  *uri = grpc_uri_parse(target, 1);
+  factory = lookup_factory_by_uri(*uri);
+  if (factory == NULL) {
+    if (g_default_resolver_prefix != NULL) {
+      grpc_uri_destroy(*uri);
+      gpr_asprintf(&tmp, "%s%s", g_default_resolver_prefix, target);
+      *uri = grpc_uri_parse(tmp, 1);
+      factory = lookup_factory_by_uri(*uri);
+      if (factory == NULL) {
+        grpc_uri_destroy(grpc_uri_parse(target, 0));
+        grpc_uri_destroy(grpc_uri_parse(tmp, 0));
+        gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target,
+                tmp);
+      }
+      gpr_free(tmp);
+    } else {
+      grpc_uri_destroy(grpc_uri_parse(target, 0));
+      gpr_log(GPR_ERROR, "don't know how to resolve '%s'", target);
+    }
+  }
+  return factory;
+}
+
+grpc_resolver *grpc_resolver_create(
+    const char *target, grpc_client_channel_factory *client_channel_factory) {
+  grpc_uri *uri = NULL;
+  grpc_resolver_factory *factory = resolve_factory(target, &uri);
+  grpc_resolver *resolver;
+  grpc_resolver_args args;
+  memset(&args, 0, sizeof(args));
+  args.uri = uri;
+  args.client_channel_factory = client_channel_factory;
+  resolver = grpc_resolver_factory_create_resolver(factory, &args);
+  grpc_uri_destroy(uri);
+  return resolver;
+}
+
+char *grpc_get_default_authority(const char *target) {
+  grpc_uri *uri = NULL;
+  grpc_resolver_factory *factory = resolve_factory(target, &uri);
+  char *authority = grpc_resolver_factory_get_default_authority(factory, uri);
+  grpc_uri_destroy(uri);
+  return authority;
+}
diff --git a/src/core/ext/client_config/resolver_registry.h b/src/core/ext/client_config/resolver_registry.h
new file mode 100644
index 0000000..5ef1383
--- /dev/null
+++ b/src/core/ext/client_config/resolver_registry.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_RESOLVER_REGISTRY_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_REGISTRY_H
+
+#include "src/core/ext/client_config/resolver_factory.h"
+
+void grpc_resolver_registry_init(const char *default_prefix);
+void grpc_resolver_registry_shutdown(void);
+
+/** Register a resolver type.
+    URI's of \a scheme will be resolved with the given resolver.
+    If \a priority is greater than zero, then the resolver will be eligible
+    to resolve names that are passed in with no scheme. Higher priority
+    resolvers will be tried before lower priority schemes. */
+void grpc_register_resolver_type(grpc_resolver_factory *factory);
+
+/** Create a resolver given \a target.
+    First tries to parse \a target as a URI. If this succeeds, tries
+    to locate a registered resolver factory based on the URI scheme.
+    If parsing or location fails, prefixes default_prefix from
+    grpc_resolver_registry_init to target, and tries again (if default_prefix
+    was not NULL).
+    If a resolver factory was found, use it to instantiate a resolver and
+    return it.
+    If a resolver factory was not found, return NULL. */
+grpc_resolver *grpc_resolver_create(
+    const char *target, grpc_client_channel_factory *client_channel_factory);
+
+/** Find a resolver factory given a name and return an (owned-by-the-caller)
+ *  reference to it */
+grpc_resolver_factory *grpc_resolver_factory_lookup(const char *name);
+
+/** Given a target, return a (freshly allocated with gpr_malloc) string
+    representing the default authority to pass from a client. */
+char *grpc_get_default_authority(const char *target);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_REGISTRY_H */
diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c
new file mode 100644
index 0000000..c925c28
--- /dev/null
+++ b/src/core/ext/client_config/subchannel.c
@@ -0,0 +1,702 @@
+/*
+ *
+ * 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/ext/client_config/subchannel.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/avl.h>
+
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/client_config/initial_connect_string.h"
+#include "src/core/ext/client_config/subchannel_index.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/backoff.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/transport/connectivity_state.h"
+
+#define INTERNAL_REF_BITS 16
+#define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
+
+#define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20
+#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 2
+#define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
+#define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
+#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
+
+#define GET_CONNECTED_SUBCHANNEL(subchannel, barrier)      \
+  ((grpc_connected_subchannel *)(gpr_atm_##barrier##_load( \
+      &(subchannel)->connected_subchannel)))
+
+typedef struct {
+  grpc_closure closure;
+  grpc_subchannel *subchannel;
+  grpc_connectivity_state connectivity_state;
+} state_watcher;
+
+typedef struct external_state_watcher {
+  grpc_subchannel *subchannel;
+  grpc_pollset_set *pollset_set;
+  grpc_closure *notify;
+  grpc_closure closure;
+  struct external_state_watcher *next;
+  struct external_state_watcher *prev;
+} external_state_watcher;
+
+struct grpc_subchannel {
+  grpc_connector *connector;
+
+  /** refcount
+      - lower INTERNAL_REF_BITS bits are for internal references:
+        these do not keep the subchannel open.
+      - upper remaining bits are for public references: these do
+        keep the subchannel open */
+  gpr_atm ref_pair;
+
+  /** non-transport related channel filters */
+  const grpc_channel_filter **filters;
+  size_t num_filters;
+  /** channel arguments */
+  grpc_channel_args *args;
+  /** address to connect to */
+  struct sockaddr *addr;
+  size_t addr_len;
+
+  grpc_subchannel_key *key;
+
+  /** initial string to send to peer */
+  gpr_slice initial_connect_string;
+
+  /** set during connection */
+  grpc_connect_out_args connecting_result;
+
+  /** callback for connection finishing */
+  grpc_closure connected;
+
+  /** pollset_set tracking who's interested in a connection
+      being setup */
+  grpc_pollset_set *pollset_set;
+
+  /** active connection, or null; of type grpc_connected_subchannel */
+  gpr_atm connected_subchannel;
+
+  /** mutex protecting remaining elements */
+  gpr_mu mu;
+
+  /** have we seen a disconnection? */
+  int disconnected;
+  /** are we connecting */
+  int connecting;
+  /** connectivity state tracking */
+  grpc_connectivity_state_tracker state_tracker;
+
+  external_state_watcher root_external_state_watcher;
+
+  /** next connect attempt time */
+  gpr_timespec next_attempt;
+  /** backoff state */
+  gpr_backoff backoff_state;
+  /** do we have an active alarm? */
+  int have_alarm;
+  /** our alarm */
+  grpc_timer alarm;
+};
+
+struct grpc_subchannel_call {
+  grpc_connected_subchannel *connection;
+};
+
+#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
+#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)(con))
+#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
+  (((grpc_subchannel_call *)(callstack)) - 1)
+
+static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
+                                 bool iomgr_success);
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+#define REF_REASON reason
+#define REF_LOG(name, p)                                                  \
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p   ref %d -> %d %s", \
+          (name), (p), (p)->refs.count, (p)->refs.count + 1, reason)
+#define UNREF_LOG(name, p)                                                \
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p unref %d -> %d %s", \
+          (name), (p), (p)->refs.count, (p)->refs.count - 1, reason)
+#define REF_MUTATE_EXTRA_ARGS \
+  GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char *purpose
+#define REF_MUTATE_PURPOSE(x) , file, line, reason, x
+#else
+#define REF_REASON ""
+#define REF_LOG(name, p) \
+  do {                   \
+  } while (0)
+#define UNREF_LOG(name, p) \
+  do {                     \
+  } while (0)
+#define REF_MUTATE_EXTRA_ARGS
+#define REF_MUTATE_PURPOSE(x)
+#endif
+
+/*
+ * connection implementation
+ */
+
+static void connection_destroy(grpc_exec_ctx *exec_ctx, void *arg,
+                               bool success) {
+  grpc_connected_subchannel *c = arg;
+  grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c));
+  gpr_free(c);
+}
+
+void grpc_connected_subchannel_ref(
+    grpc_connected_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON);
+}
+
+void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
+                                     grpc_connected_subchannel *c
+                                         GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c),
+                           REF_REASON);
+}
+
+/*
+ * grpc_subchannel implementation
+ */
+
+static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
+                               bool success) {
+  grpc_subchannel *c = arg;
+  gpr_free((void *)c->filters);
+  grpc_channel_args_destroy(c->args);
+  gpr_free(c->addr);
+  gpr_slice_unref(c->initial_connect_string);
+  grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
+  grpc_connector_unref(exec_ctx, c->connector);
+  grpc_pollset_set_destroy(c->pollset_set);
+  grpc_subchannel_key_destroy(exec_ctx, c->key);
+  gpr_free(c);
+}
+
+static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta,
+                          int barrier REF_MUTATE_EXTRA_ARGS) {
+  gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
+                            : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "SUBCHANNEL: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
+          old_val + delta, reason);
+#endif
+  return old_val;
+}
+
+grpc_subchannel *grpc_subchannel_ref(
+    grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  gpr_atm old_refs;
+  old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS),
+                        0 REF_MUTATE_PURPOSE("STRONG_REF"));
+  GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
+  return c;
+}
+
+grpc_subchannel *grpc_subchannel_weak_ref(
+    grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  gpr_atm old_refs;
+  old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF"));
+  GPR_ASSERT(old_refs != 0);
+  return c;
+}
+
+grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
+    grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  if (!c) return NULL;
+  for (;;) {
+    gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair);
+    if (old_refs >= (1 << INTERNAL_REF_BITS)) {
+      gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
+      if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) {
+        return c;
+      }
+    } else {
+      return NULL;
+    }
+  }
+}
+
+static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
+  grpc_connected_subchannel *con;
+  grpc_subchannel_index_unregister(exec_ctx, c->key, c);
+  gpr_mu_lock(&c->mu);
+  GPR_ASSERT(!c->disconnected);
+  c->disconnected = 1;
+  grpc_connector_shutdown(exec_ctx, c->connector);
+  con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
+  if (con != NULL) {
+    GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection");
+    gpr_atm_no_barrier_store(&c->connected_subchannel, 0xdeadbeef);
+  }
+  gpr_mu_unlock(&c->mu);
+}
+
+void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
+                           grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  gpr_atm old_refs;
+  old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS),
+                        1 REF_MUTATE_PURPOSE("STRONG_UNREF"));
+  if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
+    disconnect(exec_ctx, c);
+  }
+  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "strong-unref");
+}
+
+void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
+                                grpc_subchannel *c
+                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  gpr_atm old_refs;
+  old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
+  if (old_refs == 1) {
+    grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(subchannel_destroy, c),
+                          true, NULL);
+  }
+}
+
+grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
+                                        grpc_connector *connector,
+                                        grpc_subchannel_args *args) {
+  grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
+  grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
+  if (c) {
+    grpc_subchannel_key_destroy(exec_ctx, key);
+    return c;
+  }
+
+  c = gpr_malloc(sizeof(*c));
+  memset(c, 0, sizeof(*c));
+  c->key = key;
+  gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
+  c->connector = connector;
+  grpc_connector_ref(c->connector);
+  c->num_filters = args->filter_count;
+  if (c->num_filters > 0) {
+    c->filters = gpr_malloc(sizeof(grpc_channel_filter *) * c->num_filters);
+    memcpy((void *)c->filters, args->filters,
+           sizeof(grpc_channel_filter *) * c->num_filters);
+  } else {
+    c->filters = NULL;
+  }
+  c->addr = gpr_malloc(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,
+                                  &c->initial_connect_string);
+  c->args = grpc_channel_args_copy(args->args);
+  c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
+      &c->root_external_state_watcher;
+  grpc_closure_init(&c->connected, subchannel_connected, c);
+  grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
+                               "subchannel");
+  gpr_backoff_init(&c->backoff_state,
+                   GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
+                   GRPC_SUBCHANNEL_RECONNECT_JITTER,
+                   GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
+                   GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
+  if (c->args) {
+    for (size_t i = 0; i < c->args->num_args; i++) {
+      if (0 == strcmp(c->args->args[i].key,
+                      "grpc.testing.fixed_reconnect_backoff")) {
+        GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
+        gpr_backoff_init(&c->backoff_state, 1.0, 0.0,
+                         c->args->args[i].value.integer,
+                         c->args->args[i].value.integer);
+      }
+      if (0 ==
+          strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) {
+        if (c->args->args[i].type == GRPC_ARG_INTEGER) {
+          if (c->args->args[i].value.integer >= 0) {
+            gpr_backoff_init(
+                &c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
+                GRPC_SUBCHANNEL_RECONNECT_JITTER,
+                GPR_MIN(c->args->args[i].value.integer,
+                        GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000),
+                c->args->args[i].value.integer);
+          } else {
+            gpr_log(GPR_ERROR, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS
+                    " : must be non-negative");
+          }
+        } else {
+          gpr_log(GPR_ERROR,
+                  GRPC_ARG_MAX_RECONNECT_BACKOFF_MS " : must be an integer");
+        }
+      }
+    }
+  }
+  gpr_mu_init(&c->mu);
+
+  return grpc_subchannel_index_register(exec_ctx, key, c);
+}
+
+static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
+  grpc_connect_in_args args;
+
+  args.interested_parties = c->pollset_set;
+  args.addr = c->addr;
+  args.addr_len = c->addr_len;
+  args.deadline = c->next_attempt;
+  args.channel_args = c->args;
+  args.initial_connect_string = c->initial_connect_string;
+
+  grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
+                              GRPC_CHANNEL_CONNECTING, "state_change");
+  grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
+                         &c->connected);
+}
+
+static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
+  c->next_attempt =
+      gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
+  continue_connect(exec_ctx, c);
+}
+
+grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c) {
+  grpc_connectivity_state state;
+  gpr_mu_lock(&c->mu);
+  state = grpc_connectivity_state_check(&c->state_tracker);
+  gpr_mu_unlock(&c->mu);
+  return state;
+}
+
+static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
+                                           bool success) {
+  external_state_watcher *w = arg;
+  grpc_closure *follow_up = w->notify;
+  if (w->pollset_set != NULL) {
+    grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set,
+                                     w->pollset_set);
+  }
+  gpr_mu_lock(&w->subchannel->mu);
+  w->next->prev = w->prev;
+  w->prev->next = w->next;
+  gpr_mu_unlock(&w->subchannel->mu);
+  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
+  gpr_free(w);
+  follow_up->cb(exec_ctx, follow_up->cb_arg, success);
+}
+
+void grpc_subchannel_notify_on_state_change(
+    grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
+    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
+    grpc_closure *notify) {
+  external_state_watcher *w;
+
+  if (state == NULL) {
+    gpr_mu_lock(&c->mu);
+    for (w = c->root_external_state_watcher.next;
+         w != &c->root_external_state_watcher; w = w->next) {
+      if (w->notify == notify) {
+        grpc_connectivity_state_notify_on_state_change(
+            exec_ctx, &c->state_tracker, NULL, &w->closure);
+      }
+    }
+    gpr_mu_unlock(&c->mu);
+  } else {
+    w = gpr_malloc(sizeof(*w));
+    w->subchannel = c;
+    w->pollset_set = interested_parties;
+    w->notify = notify;
+    grpc_closure_init(&w->closure, on_external_state_watcher_done, w);
+    if (interested_parties != NULL) {
+      grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set,
+                                       interested_parties);
+    }
+    GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
+    gpr_mu_lock(&c->mu);
+    w->next = &c->root_external_state_watcher;
+    w->prev = w->next->prev;
+    w->next->prev = w->prev->next = w;
+    if (grpc_connectivity_state_notify_on_state_change(
+            exec_ctx, &c->state_tracker, state, &w->closure)) {
+      c->connecting = 1;
+      /* released by connection */
+      GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
+      start_connect(exec_ctx, c);
+    }
+    gpr_mu_unlock(&c->mu);
+  }
+}
+
+void grpc_connected_subchannel_process_transport_op(
+    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
+    grpc_transport_op *op) {
+  grpc_channel_stack *channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
+  grpc_channel_element *top_elem = grpc_channel_stack_element(channel_stack, 0);
+  top_elem->filter->start_transport_op(exec_ctx, top_elem, op);
+}
+
+static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
+                                              bool iomgr_success) {
+  state_watcher *sw = p;
+  grpc_subchannel *c = sw->subchannel;
+  gpr_mu *mu = &c->mu;
+
+  gpr_mu_lock(mu);
+
+  /* if we failed just leave this closure */
+  if (iomgr_success) {
+    if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+      /* any errors on a subchannel ==> we're done, create a new one */
+      sw->connectivity_state = GRPC_CHANNEL_FATAL_FAILURE;
+    }
+    grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
+                                sw->connectivity_state, "reflect_child");
+    if (sw->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
+      grpc_connected_subchannel_notify_on_state_change(
+          exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
+          &sw->connectivity_state, &sw->closure);
+      GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
+      sw = NULL;
+    }
+  }
+
+  gpr_mu_unlock(mu);
+  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "state_watcher");
+  gpr_free(sw);
+}
+
+static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx,
+                                          grpc_connected_subchannel *con,
+                                          grpc_pollset_set *interested_parties,
+                                          grpc_connectivity_state *state,
+                                          grpc_closure *closure) {
+  grpc_transport_op op;
+  grpc_channel_element *elem;
+  memset(&op, 0, sizeof(op));
+  op.connectivity_state = state;
+  op.on_connectivity_state_change = closure;
+  op.bind_pollset_set = interested_parties;
+  elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
+  elem->filter->start_transport_op(exec_ctx, elem, &op);
+}
+
+void grpc_connected_subchannel_notify_on_state_change(
+    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
+    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
+    grpc_closure *closure) {
+  connected_subchannel_state_op(exec_ctx, con, interested_parties, state,
+                                closure);
+}
+
+void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
+                                    grpc_connected_subchannel *con,
+                                    grpc_closure *closure) {
+  grpc_transport_op op;
+  grpc_channel_element *elem;
+  memset(&op, 0, sizeof(op));
+  op.send_ping = closure;
+  elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
+  elem->filter->start_transport_op(exec_ctx, elem, &op);
+}
+
+static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
+                                     grpc_subchannel *c) {
+  grpc_connected_subchannel *con;
+  grpc_channel_stack *stk;
+  state_watcher *sw_subchannel;
+
+  /* construct channel stack */
+  grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create();
+  grpc_channel_stack_builder_set_channel_arguments(
+      builder, c->connecting_result.channel_args);
+  grpc_channel_stack_builder_set_transport(builder,
+                                           c->connecting_result.transport);
+
+  if (grpc_channel_init_create_stack(exec_ctx, builder,
+                                     GRPC_CLIENT_SUBCHANNEL)) {
+    con = grpc_channel_stack_builder_finish(exec_ctx, builder, 0, 1,
+                                            connection_destroy, NULL);
+  } else {
+    grpc_channel_stack_builder_destroy(builder);
+    abort(); /* TODO(ctiller): what to do here (previously we just crashed) */
+  }
+  stk = CHANNEL_STACK_FROM_CONNECTION(con);
+  memset(&c->connecting_result, 0, sizeof(c->connecting_result));
+
+  /* initialize state watcher */
+  sw_subchannel = gpr_malloc(sizeof(*sw_subchannel));
+  sw_subchannel->subchannel = c;
+  sw_subchannel->connectivity_state = GRPC_CHANNEL_READY;
+  grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
+                    sw_subchannel);
+
+  if (c->disconnected) {
+    gpr_free(sw_subchannel);
+    grpc_channel_stack_destroy(exec_ctx, stk);
+    gpr_free(con);
+    GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
+    return;
+  }
+
+  /* publish */
+  /* TODO(ctiller): this full barrier seems to clear up a TSAN failure.
+                    I'd have expected the rel_cas below to be enough, but
+                    seemingly it's not.
+                    Re-evaluate if we really need this. */
+  gpr_atm_full_barrier();
+  GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
+  c->connecting = 0;
+
+  /* setup subchannel watching connected subchannel for changes; subchannel
+     ref
+     for connecting is donated
+     to the state watcher */
+  GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
+  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
+  grpc_connected_subchannel_notify_on_state_change(
+      exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state,
+      &sw_subchannel->closure);
+
+  /* signal completion */
+  grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
+                              "connected");
+}
+
+static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
+  grpc_subchannel *c = arg;
+  gpr_mu_lock(&c->mu);
+  c->have_alarm = 0;
+  if (c->disconnected) {
+    iomgr_success = 0;
+  }
+  if (iomgr_success) {
+    c->next_attempt =
+        gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
+    continue_connect(exec_ctx, c);
+    gpr_mu_unlock(&c->mu);
+  } else {
+    gpr_mu_unlock(&c->mu);
+    GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
+  }
+}
+
+static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
+                                 bool iomgr_success) {
+  grpc_subchannel *c = arg;
+
+  GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
+  gpr_mu_lock(&c->mu);
+  if (c->connecting_result.transport != NULL) {
+    publish_transport_locked(exec_ctx, c);
+  } else if (c->disconnected) {
+    GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
+  } else {
+    gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+    GPR_ASSERT(!c->have_alarm);
+    c->have_alarm = 1;
+    grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
+                                GRPC_CHANNEL_TRANSIENT_FAILURE,
+                                "connect_failed");
+    grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
+  }
+  gpr_mu_unlock(&c->mu);
+  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
+}
+
+/*
+ * grpc_subchannel_call implementation
+ */
+
+static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
+                                    bool success) {
+  grpc_subchannel_call *c = call;
+  GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
+  grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c));
+  GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, c->connection, "subchannel_call");
+  gpr_free(c);
+  GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
+}
+
+void grpc_subchannel_call_ref(
+    grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
+}
+
+void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
+                                grpc_subchannel_call *c
+                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  GRPC_CALL_STACK_UNREF(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
+}
+
+char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
+                                    grpc_subchannel_call *call) {
+  grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
+  grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
+  return top_elem->filter->get_peer(exec_ctx, top_elem);
+}
+
+void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
+                                     grpc_subchannel_call *call,
+                                     grpc_transport_stream_op *op) {
+  grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
+  grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
+  top_elem->filter->start_transport_stream_op(exec_ctx, top_elem, op);
+}
+
+grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
+    grpc_subchannel *c) {
+  return GET_CONNECTED_SUBCHANNEL(c, acq);
+}
+
+grpc_subchannel_call *grpc_connected_subchannel_create_call(
+    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
+    grpc_pollset *pollset) {
+  grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
+  grpc_subchannel_call *call =
+      gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
+  grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
+  call->connection = con;
+  GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
+  grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call,
+                       NULL, NULL, callstk);
+  grpc_call_stack_set_pollset(exec_ctx, callstk, pollset);
+  return call;
+}
+
+grpc_call_stack *grpc_subchannel_call_get_call_stack(
+    grpc_subchannel_call *subchannel_call) {
+  return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
+}
diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h
new file mode 100644
index 0000000..0765a54
--- /dev/null
+++ b/src/core/ext/client_config/subchannel.h
@@ -0,0 +1,174 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_SUBCHANNEL_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_H
+
+#include "src/core/ext/client_config/connector.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/transport/connectivity_state.h"
+
+/** A (sub-)channel that knows how to connect to exactly one target
+    address. Provides a target for load balancing. */
+typedef struct grpc_subchannel grpc_subchannel;
+typedef struct grpc_connected_subchannel grpc_connected_subchannel;
+typedef struct grpc_subchannel_call grpc_subchannel_call;
+typedef struct grpc_subchannel_args grpc_subchannel_args;
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+#define GRPC_SUBCHANNEL_REF(p, r) \
+  grpc_subchannel_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
+  grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_SUBCHANNEL_UNREF(cl, p, r) \
+  grpc_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
+#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \
+  grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \
+  grpc_subchannel_weak_unref((cl), (p), __FILE__, __LINE__, (r))
+#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) \
+  grpc_connected_subchannel_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \
+  grpc_connected_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
+#define GRPC_SUBCHANNEL_CALL_REF(p, r) \
+  grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
+  grpc_subchannel_call_unref((cl), (p), __FILE__, __LINE__, (r))
+#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \
+  , const char *file, int line, const char *reason
+#else
+#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p))
+#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
+  grpc_subchannel_ref_from_weak_ref((p))
+#define GRPC_SUBCHANNEL_UNREF(cl, p, r) grpc_subchannel_unref((cl), (p))
+#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p))
+#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \
+  grpc_subchannel_weak_unref((cl), (p))
+#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) grpc_connected_subchannel_ref((p))
+#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \
+  grpc_connected_subchannel_unref((cl), (p))
+#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p))
+#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
+  grpc_subchannel_call_unref((cl), (p))
+#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS
+#endif
+
+grpc_subchannel *grpc_subchannel_ref(
+    grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
+    grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
+                           grpc_subchannel *channel
+                               GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+grpc_subchannel *grpc_subchannel_weak_ref(
+    grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
+                                grpc_subchannel *channel
+                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+void grpc_connected_subchannel_ref(
+    grpc_connected_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
+                                     grpc_connected_subchannel *channel
+                                         GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+void grpc_subchannel_call_ref(
+    grpc_subchannel_call *call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
+                                grpc_subchannel_call *call
+                                    GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+
+/** construct a subchannel call */
+grpc_subchannel_call *grpc_connected_subchannel_create_call(
+    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
+    grpc_pollset *pollset);
+
+/** process a transport level op */
+void grpc_connected_subchannel_process_transport_op(
+    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *subchannel,
+    grpc_transport_op *op);
+
+/** poll the current connectivity state of a channel */
+grpc_connectivity_state grpc_subchannel_check_connectivity(
+    grpc_subchannel *channel);
+
+/** call notify when the connectivity state of a channel changes from *state.
+    Updates *state with the new state of the channel */
+void grpc_subchannel_notify_on_state_change(
+    grpc_exec_ctx *exec_ctx, grpc_subchannel *channel,
+    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
+    grpc_closure *notify);
+void grpc_connected_subchannel_notify_on_state_change(
+    grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *channel,
+    grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
+    grpc_closure *notify);
+void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
+                                    grpc_connected_subchannel *channel,
+                                    grpc_closure *notify);
+
+/** retrieve the grpc_connected_subchannel - or NULL if called before
+    the subchannel becomes connected */
+grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
+    grpc_subchannel *subchannel);
+
+/** continue processing a transport op */
+void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
+                                     grpc_subchannel_call *subchannel_call,
+                                     grpc_transport_stream_op *op);
+
+/** continue querying for peer */
+char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
+                                    grpc_subchannel_call *subchannel_call);
+
+grpc_call_stack *grpc_subchannel_call_get_call_stack(
+    grpc_subchannel_call *subchannel_call);
+
+struct grpc_subchannel_args {
+  /* When updating this struct, also update subchannel_index.c */
+
+  /** Channel filters for this channel - wrapped factories will likely
+      want to mutate this */
+  const grpc_channel_filter **filters;
+  /** The number of filters in the above array */
+  size_t filter_count;
+  /** Channel arguments to be supplied to the newly created channel */
+  const grpc_channel_args *args;
+  /** Address to connect to */
+  struct sockaddr *addr;
+  size_t addr_len;
+};
+
+/** create a subchannel given a connector */
+grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
+                                        grpc_connector *connector,
+                                        grpc_subchannel_args *args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_H */
diff --git a/src/core/ext/client_config/subchannel_call_holder.c b/src/core/ext/client_config/subchannel_call_holder.c
new file mode 100644
index 0000000..9918fbd
--- /dev/null
+++ b/src/core/ext/client_config/subchannel_call_holder.c
@@ -0,0 +1,260 @@
+/*
+ *
+ * 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/ext/client_config/subchannel_call_holder.h"
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/lib/profiling/timers.h"
+
+#define GET_CALL(holder) \
+  ((grpc_subchannel_call *)(gpr_atm_acq_load(&(holder)->subchannel_call)))
+
+#define CANCELLED_CALL ((grpc_subchannel_call *)1)
+
+static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *holder,
+                             bool success);
+static void retry_ops(grpc_exec_ctx *exec_ctx, void *retry_ops_args,
+                      bool success);
+
+static void add_waiting_locked(grpc_subchannel_call_holder *holder,
+                               grpc_transport_stream_op *op);
+static void fail_locked(grpc_exec_ctx *exec_ctx,
+                        grpc_subchannel_call_holder *holder);
+static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
+                                 grpc_subchannel_call_holder *holder);
+
+void grpc_subchannel_call_holder_init(
+    grpc_subchannel_call_holder *holder,
+    grpc_subchannel_call_holder_pick_subchannel pick_subchannel,
+    void *pick_subchannel_arg, grpc_call_stack *owning_call) {
+  gpr_atm_rel_store(&holder->subchannel_call, 0);
+  holder->pick_subchannel = pick_subchannel;
+  holder->pick_subchannel_arg = pick_subchannel_arg;
+  gpr_mu_init(&holder->mu);
+  holder->connected_subchannel = NULL;
+  holder->waiting_ops = NULL;
+  holder->waiting_ops_count = 0;
+  holder->waiting_ops_capacity = 0;
+  holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
+  holder->owning_call = owning_call;
+}
+
+void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
+                                         grpc_subchannel_call_holder *holder) {
+  grpc_subchannel_call *call = GET_CALL(holder);
+  if (call != NULL && call != CANCELLED_CALL) {
+    GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "holder");
+  }
+  GPR_ASSERT(holder->creation_phase ==
+             GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
+  gpr_mu_destroy(&holder->mu);
+  GPR_ASSERT(holder->waiting_ops_count == 0);
+  gpr_free(holder->waiting_ops);
+}
+
+void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
+                                            grpc_subchannel_call_holder *holder,
+                                            grpc_transport_stream_op *op) {
+  /* try to (atomically) get the call */
+  grpc_subchannel_call *call = GET_CALL(holder);
+  GPR_TIMER_BEGIN("grpc_subchannel_call_holder_perform_op", 0);
+  if (call == CANCELLED_CALL) {
+    grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
+    return;
+  }
+  if (call != NULL) {
+    grpc_subchannel_call_process_op(exec_ctx, call, op);
+    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
+    return;
+  }
+  /* we failed; lock and figure out what to do */
+  gpr_mu_lock(&holder->mu);
+retry:
+  /* need to recheck that another thread hasn't set the call */
+  call = GET_CALL(holder);
+  if (call == CANCELLED_CALL) {
+    gpr_mu_unlock(&holder->mu);
+    grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
+    return;
+  }
+  if (call != NULL) {
+    gpr_mu_unlock(&holder->mu);
+    grpc_subchannel_call_process_op(exec_ctx, call, op);
+    GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
+    return;
+  }
+  /* if this is a cancellation, then we can raise our cancelled flag */
+  if (op->cancel_with_status != GRPC_STATUS_OK) {
+    if (!gpr_atm_rel_cas(&holder->subchannel_call, 0, 1)) {
+      goto retry;
+    } else {
+      switch (holder->creation_phase) {
+        case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
+          fail_locked(exec_ctx, holder);
+          break;
+        case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
+          holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL,
+                                  0, &holder->connected_subchannel, NULL);
+          break;
+      }
+      gpr_mu_unlock(&holder->mu);
+      grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+      GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
+      return;
+    }
+  }
+  /* if we don't have a subchannel, try to get one */
+  if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
+      holder->connected_subchannel == NULL &&
+      op->send_initial_metadata != NULL) {
+    holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
+    grpc_closure_init(&holder->next_step, subchannel_ready, holder);
+    GRPC_CALL_STACK_REF(holder->owning_call, "pick_subchannel");
+    if (holder->pick_subchannel(
+            exec_ctx, holder->pick_subchannel_arg, op->send_initial_metadata,
+            op->send_initial_metadata_flags, &holder->connected_subchannel,
+            &holder->next_step)) {
+      holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
+      GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
+    }
+  }
+  /* if we've got a subchannel, then let's ask it to create a call */
+  if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
+      holder->connected_subchannel != NULL) {
+    gpr_atm_rel_store(
+        &holder->subchannel_call,
+        (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
+            exec_ctx, holder->connected_subchannel, holder->pollset));
+    retry_waiting_locked(exec_ctx, holder);
+    goto retry;
+  }
+  /* nothing to be done but wait */
+  add_waiting_locked(holder, op);
+  gpr_mu_unlock(&holder->mu);
+  GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
+}
+
+static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  grpc_subchannel_call_holder *holder = arg;
+  gpr_mu_lock(&holder->mu);
+  GPR_ASSERT(holder->creation_phase ==
+             GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
+  holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
+  if (holder->connected_subchannel == NULL) {
+    fail_locked(exec_ctx, holder);
+  } else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
+    /* already cancelled before subchannel became ready */
+    fail_locked(exec_ctx, holder);
+  } else {
+    gpr_atm_rel_store(
+        &holder->subchannel_call,
+        (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
+            exec_ctx, holder->connected_subchannel, holder->pollset));
+    retry_waiting_locked(exec_ctx, holder);
+  }
+  gpr_mu_unlock(&holder->mu);
+  GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
+}
+
+typedef struct {
+  grpc_transport_stream_op *ops;
+  size_t nops;
+  grpc_subchannel_call *call;
+} retry_ops_args;
+
+static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
+                                 grpc_subchannel_call_holder *holder) {
+  retry_ops_args *a = gpr_malloc(sizeof(*a));
+  a->ops = holder->waiting_ops;
+  a->nops = holder->waiting_ops_count;
+  a->call = GET_CALL(holder);
+  if (a->call == CANCELLED_CALL) {
+    gpr_free(a);
+    fail_locked(exec_ctx, holder);
+    return;
+  }
+  holder->waiting_ops = NULL;
+  holder->waiting_ops_count = 0;
+  holder->waiting_ops_capacity = 0;
+  GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
+  grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(retry_ops, a), true,
+                        NULL);
+}
+
+static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, bool success) {
+  retry_ops_args *a = args;
+  size_t i;
+  for (i = 0; i < a->nops; i++) {
+    grpc_subchannel_call_process_op(exec_ctx, a->call, &a->ops[i]);
+  }
+  GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
+  gpr_free(a->ops);
+  gpr_free(a);
+}
+
+static void add_waiting_locked(grpc_subchannel_call_holder *holder,
+                               grpc_transport_stream_op *op) {
+  GPR_TIMER_BEGIN("add_waiting_locked", 0);
+  if (holder->waiting_ops_count == holder->waiting_ops_capacity) {
+    holder->waiting_ops_capacity = GPR_MAX(3, 2 * holder->waiting_ops_capacity);
+    holder->waiting_ops =
+        gpr_realloc(holder->waiting_ops, holder->waiting_ops_capacity *
+                                             sizeof(*holder->waiting_ops));
+  }
+  holder->waiting_ops[holder->waiting_ops_count++] = *op;
+  GPR_TIMER_END("add_waiting_locked", 0);
+}
+
+static void fail_locked(grpc_exec_ctx *exec_ctx,
+                        grpc_subchannel_call_holder *holder) {
+  size_t i;
+  for (i = 0; i < holder->waiting_ops_count; i++) {
+    grpc_transport_stream_op_finish_with_failure(exec_ctx,
+                                                 &holder->waiting_ops[i]);
+  }
+  holder->waiting_ops_count = 0;
+}
+
+char *grpc_subchannel_call_holder_get_peer(
+    grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder) {
+  grpc_subchannel_call *subchannel_call = GET_CALL(holder);
+
+  if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
+    return NULL;
+  } else {
+    return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
+  }
+}
diff --git a/src/core/ext/client_config/subchannel_call_holder.h b/src/core/ext/client_config/subchannel_call_holder.h
new file mode 100644
index 0000000..9299908
--- /dev/null
+++ b/src/core/ext/client_config/subchannel_call_holder.h
@@ -0,0 +1,98 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_SUBCHANNEL_CALL_HOLDER_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_CALL_HOLDER_H
+
+#include "src/core/ext/client_config/subchannel.h"
+
+/** Pick a subchannel for grpc_subchannel_call_holder;
+    Return 1 if subchannel is available immediately (in which case on_ready
+    should not be called), or 0 otherwise (in which case on_ready should be
+    called when the subchannel is available) */
+typedef int (*grpc_subchannel_call_holder_pick_subchannel)(
+    grpc_exec_ctx *exec_ctx, void *arg, grpc_metadata_batch *initial_metadata,
+    uint32_t initial_metadata_flags,
+    grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready);
+
+typedef enum {
+  GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
+  GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
+} grpc_subchannel_call_holder_creation_phase;
+
+/** Wrapper for holding a pointer to grpc_subchannel_call, and the
+    associated machinery to create such a pointer.
+    Handles queueing of stream ops until a call object is ready, waiting
+    for initial metadata before trying to create a call object,
+    and handling cancellation gracefully.
+
+    The channel filter uses this as their call_data. */
+typedef struct grpc_subchannel_call_holder {
+  /** either 0 for no call, 1 for cancelled, or a pointer to a
+      grpc_subchannel_call */
+  gpr_atm subchannel_call;
+  /** Helper function to choose the subchannel on which to create
+      the call object. Channel filter delegates to the load
+      balancing policy (once it's ready). */
+  grpc_subchannel_call_holder_pick_subchannel pick_subchannel;
+  void *pick_subchannel_arg;
+
+  gpr_mu mu;
+
+  grpc_subchannel_call_holder_creation_phase creation_phase;
+  grpc_connected_subchannel *connected_subchannel;
+  grpc_pollset *pollset;
+
+  grpc_transport_stream_op *waiting_ops;
+  size_t waiting_ops_count;
+  size_t waiting_ops_capacity;
+
+  grpc_closure next_step;
+
+  grpc_call_stack *owning_call;
+} grpc_subchannel_call_holder;
+
+void grpc_subchannel_call_holder_init(
+    grpc_subchannel_call_holder *holder,
+    grpc_subchannel_call_holder_pick_subchannel pick_subchannel,
+    void *pick_subchannel_arg, grpc_call_stack *owning_call);
+void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
+                                         grpc_subchannel_call_holder *holder);
+
+void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
+                                            grpc_subchannel_call_holder *holder,
+                                            grpc_transport_stream_op *op);
+char *grpc_subchannel_call_holder_get_peer(grpc_exec_ctx *exec_ctx,
+                                           grpc_subchannel_call_holder *holder);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_CALL_HOLDER_H */
diff --git a/src/core/ext/client_config/subchannel_factory.c b/src/core/ext/client_config/subchannel_factory.c
new file mode 100644
index 0000000..d1e4d75
--- /dev/null
+++ b/src/core/ext/client_config/subchannel_factory.c
@@ -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.
+ *
+ */
+
+#include "src/core/ext/client_config/subchannel_factory.h"
+
+void grpc_subchannel_factory_ref(grpc_subchannel_factory* factory) {
+  factory->vtable->ref(factory);
+}
+
+void grpc_subchannel_factory_unref(grpc_exec_ctx* exec_ctx,
+                                   grpc_subchannel_factory* factory) {
+  factory->vtable->unref(exec_ctx, factory);
+}
+
+grpc_subchannel* grpc_subchannel_factory_create_subchannel(
+    grpc_exec_ctx* exec_ctx, grpc_subchannel_factory* factory,
+    grpc_subchannel_args* args) {
+  return factory->vtable->create_subchannel(exec_ctx, factory, args);
+}
diff --git a/src/core/ext/client_config/subchannel_factory.h b/src/core/ext/client_config/subchannel_factory.h
new file mode 100644
index 0000000..0fb806d
--- /dev/null
+++ b/src/core/ext/client_config/subchannel_factory.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H
+
+#include "src/core/ext/client_config/subchannel.h"
+#include "src/core/lib/channel/channel_stack.h"
+
+typedef struct grpc_subchannel_factory grpc_subchannel_factory;
+typedef struct grpc_subchannel_factory_vtable grpc_subchannel_factory_vtable;
+
+/** Constructor for new configured channels.
+    Creating decorators around this type is encouraged to adapt behavior. */
+struct grpc_subchannel_factory {
+  const grpc_subchannel_factory_vtable *vtable;
+};
+
+struct grpc_subchannel_factory_vtable {
+  void (*ref)(grpc_subchannel_factory *factory);
+  void (*unref)(grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory);
+  grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
+                                        grpc_subchannel_factory *factory,
+                                        grpc_subchannel_args *args);
+};
+
+void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory);
+void grpc_subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
+                                   grpc_subchannel_factory *factory);
+
+/** Create a new grpc_subchannel */
+grpc_subchannel *grpc_subchannel_factory_create_subchannel(
+    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
+    grpc_subchannel_args *args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H */
diff --git a/src/core/ext/client_config/subchannel_index.c b/src/core/ext/client_config/subchannel_index.c
new file mode 100644
index 0000000..ab8d9bd
--- /dev/null
+++ b/src/core/ext/client_config/subchannel_index.c
@@ -0,0 +1,262 @@
+//
+//
+// 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/ext/client_config/subchannel_index.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/avl.h>
+#include <grpc/support/tls.h>
+
+#include "src/core/lib/channel/channel_args.h"
+
+// a map of subchannel_key --> subchannel, used for detecting connections
+// to the same destination in order to share them
+static gpr_avl g_subchannel_index;
+
+static gpr_mu g_mu;
+
+struct grpc_subchannel_key {
+  grpc_connector *connector;
+  grpc_subchannel_args args;
+};
+
+GPR_TLS_DECL(subchannel_index_exec_ctx);
+
+static void enter_ctx(grpc_exec_ctx *exec_ctx) {
+  GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == 0);
+  gpr_tls_set(&subchannel_index_exec_ctx, (intptr_t)exec_ctx);
+}
+
+static void leave_ctx(grpc_exec_ctx *exec_ctx) {
+  GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == (intptr_t)exec_ctx);
+  gpr_tls_set(&subchannel_index_exec_ctx, 0);
+}
+
+static grpc_exec_ctx *current_ctx() {
+  grpc_exec_ctx *c = (grpc_exec_ctx *)gpr_tls_get(&subchannel_index_exec_ctx);
+  GPR_ASSERT(c != NULL);
+  return c;
+}
+
+static grpc_subchannel_key *create_key(
+    grpc_connector *connector, grpc_subchannel_args *args,
+    grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) {
+  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);
+  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);
+  k->args.args = copy_channel_args(args->args);
+  return k;
+}
+
+grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector,
+                                                grpc_subchannel_args *args) {
+  return create_key(connector, args, grpc_channel_args_normalize);
+}
+
+static grpc_subchannel_key *subchannel_key_copy(grpc_subchannel_key *k) {
+  return create_key(k->connector, &k->args, grpc_channel_args_copy);
+}
+
+static int subchannel_key_compare(grpc_subchannel_key *a,
+                                  grpc_subchannel_key *b) {
+  int c = GPR_ICMP(a->connector, b->connector);
+  if (c != 0) return c;
+  c = GPR_ICMP(a->args.addr_len, b->args.addr_len);
+  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;
+  return grpc_channel_args_compare(a->args.args, b->args.args);
+}
+
+void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
+                                 grpc_subchannel_key *k) {
+  grpc_connector_unref(exec_ctx, k->connector);
+  gpr_free(k->args.addr);
+  gpr_free((grpc_channel_args *)k->args.filters);
+  grpc_channel_args_destroy((grpc_channel_args *)k->args.args);
+  gpr_free(k);
+}
+
+static void sck_avl_destroy(void *p) {
+  grpc_subchannel_key_destroy(current_ctx(), p);
+}
+
+static void *sck_avl_copy(void *p) { return subchannel_key_copy(p); }
+
+static long sck_avl_compare(void *a, void *b) {
+  return subchannel_key_compare(a, b);
+}
+
+static void scv_avl_destroy(void *p) {
+  GRPC_SUBCHANNEL_WEAK_UNREF(current_ctx(), p, "subchannel_index");
+}
+
+static void *scv_avl_copy(void *p) {
+  GRPC_SUBCHANNEL_WEAK_REF(p, "subchannel_index");
+  return p;
+}
+
+static const gpr_avl_vtable subchannel_avl_vtable = {
+    .destroy_key = sck_avl_destroy,
+    .copy_key = sck_avl_copy,
+    .compare_keys = sck_avl_compare,
+    .destroy_value = scv_avl_destroy,
+    .copy_value = scv_avl_copy};
+
+void grpc_subchannel_index_init(void) {
+  g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable);
+  gpr_mu_init(&g_mu);
+  gpr_tls_init(&subchannel_index_exec_ctx);
+}
+
+void grpc_subchannel_index_shutdown(void) {
+  gpr_mu_destroy(&g_mu);
+  gpr_avl_unref(g_subchannel_index);
+  gpr_tls_destroy(&subchannel_index_exec_ctx);
+}
+
+grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
+                                            grpc_subchannel_key *key) {
+  enter_ctx(exec_ctx);
+
+  // Lock, and take a reference to the subchannel index.
+  // We don't need to do the search under a lock as avl's are immutable.
+  gpr_mu_lock(&g_mu);
+  gpr_avl index = gpr_avl_ref(g_subchannel_index);
+  gpr_mu_unlock(&g_mu);
+
+  grpc_subchannel *c =
+      GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(gpr_avl_get(index, key), "index_find");
+  gpr_avl_unref(index);
+
+  leave_ctx(exec_ctx);
+  return c;
+}
+
+grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
+                                                grpc_subchannel_key *key,
+                                                grpc_subchannel *constructed) {
+  enter_ctx(exec_ctx);
+
+  grpc_subchannel *c = NULL;
+
+  while (c == NULL) {
+    // Compare and swap loop:
+    // - take a reference to the current index
+    gpr_mu_lock(&g_mu);
+    gpr_avl index = gpr_avl_ref(g_subchannel_index);
+    gpr_mu_unlock(&g_mu);
+
+    // - Check to see if a subchannel already exists
+    c = gpr_avl_get(index, key);
+    if (c != NULL) {
+      // yes -> we're done
+      GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register");
+    } else {
+      // no -> update the avl and compare/swap
+      gpr_avl updated =
+          gpr_avl_add(gpr_avl_ref(index), subchannel_key_copy(key),
+                      GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"));
+
+      // it may happen (but it's expected to be unlikely)
+      // that some other thread has changed the index:
+      // compare/swap here to check that, and retry as necessary
+      gpr_mu_lock(&g_mu);
+      if (index.root == g_subchannel_index.root) {
+        GPR_SWAP(gpr_avl, updated, g_subchannel_index);
+        c = constructed;
+      }
+      gpr_mu_unlock(&g_mu);
+
+      gpr_avl_unref(updated);
+    }
+    gpr_avl_unref(index);
+  }
+
+  leave_ctx(exec_ctx);
+
+  return c;
+}
+
+void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx,
+                                      grpc_subchannel_key *key,
+                                      grpc_subchannel *constructed) {
+  enter_ctx(exec_ctx);
+
+  bool done = false;
+  while (!done) {
+    // Compare and swap loop:
+    // - take a reference to the current index
+    gpr_mu_lock(&g_mu);
+    gpr_avl index = gpr_avl_ref(g_subchannel_index);
+    gpr_mu_unlock(&g_mu);
+
+    // Check to see if this key still refers to the previously
+    // registered subchannel
+    grpc_subchannel *c = gpr_avl_get(index, key);
+    if (c != constructed) {
+      gpr_avl_unref(index);
+      break;
+    }
+
+    // compare and swap the update (some other thread may have
+    // mutated the index behind us)
+    gpr_avl updated = gpr_avl_remove(gpr_avl_ref(index), key);
+
+    gpr_mu_lock(&g_mu);
+    if (index.root == g_subchannel_index.root) {
+      GPR_SWAP(gpr_avl, updated, g_subchannel_index);
+      done = true;
+    }
+    gpr_mu_unlock(&g_mu);
+
+    gpr_avl_unref(updated);
+    gpr_avl_unref(index);
+  }
+
+  leave_ctx(exec_ctx);
+}
diff --git a/src/core/ext/client_config/subchannel_index.h b/src/core/ext/client_config/subchannel_index.h
new file mode 100644
index 0000000..6b8d063
--- /dev/null
+++ b/src/core/ext/client_config/subchannel_index.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_SUBCHANNEL_INDEX_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_INDEX_H
+
+#include "src/core/ext/client_config/connector.h"
+#include "src/core/ext/client_config/subchannel.h"
+
+/** \file Provides an index of active subchannels so that they can be
+    shared amongst channels */
+
+typedef struct grpc_subchannel_key grpc_subchannel_key;
+
+/** Create a key that can be used to uniquely identify a subchannel */
+grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *con,
+                                                grpc_subchannel_args *args);
+
+/** Destroy a subchannel key */
+void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
+                                 grpc_subchannel_key *key);
+
+/** Given a subchannel key, find the subchannel registered for it.
+    Returns NULL if no such channel exists.
+    Thread-safe. */
+grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
+                                            grpc_subchannel_key *key);
+
+/** Register a subchannel against a key.
+    Takes ownership of \a constructed.
+    Returns the registered subchannel. This may be different from
+    \a constructed in the case of a registration race. */
+grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
+                                                grpc_subchannel_key *key,
+                                                grpc_subchannel *constructed);
+
+/** Remove \a constructed as the registered subchannel for \a key. */
+void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx,
+                                      grpc_subchannel_key *key,
+                                      grpc_subchannel *constructed);
+
+/** Initialize the subchannel index (global) */
+void grpc_subchannel_index_init(void);
+/** Shutdown the subchannel index (global) */
+void grpc_subchannel_index_shutdown(void);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_SUBCHANNEL_INDEX_H */
diff --git a/src/core/ext/client_config/uri_parser.c b/src/core/ext/client_config/uri_parser.c
new file mode 100644
index 0000000..3ca1a58
--- /dev/null
+++ b/src/core/ext/client_config/uri_parser.c
@@ -0,0 +1,310 @@
+/*
+ *
+ * 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/ext/client_config/uri_parser.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/support/string.h"
+
+/** a size_t default value... maps to all 1's */
+#define NOT_SET (~(size_t)0)
+
+static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section,
+                         int suppress_errors) {
+  char *line_prefix;
+  size_t pfx_len;
+
+  if (!suppress_errors) {
+    gpr_asprintf(&line_prefix, "bad uri.%s: '", section);
+    pfx_len = strlen(line_prefix) + pos;
+    gpr_log(GPR_ERROR, "%s%s'", line_prefix, uri_text);
+    gpr_free(line_prefix);
+
+    line_prefix = gpr_malloc(pfx_len + 1);
+    memset(line_prefix, ' ', pfx_len);
+    line_prefix[pfx_len] = 0;
+    gpr_log(GPR_ERROR, "%s^ here", line_prefix);
+    gpr_free(line_prefix);
+  }
+
+  return NULL;
+}
+
+/** Returns a copy of \a src[begin, end) */
+static char *copy_component(const char *src, size_t begin, size_t end) {
+  char *out = gpr_malloc(end - begin + 1);
+  memcpy(out, src + begin, end - begin);
+  out[end - begin] = 0;
+  return out;
+}
+
+/** Returns how many chars to advance if \a uri_text[i] begins a valid \a pchar
+ * production. If \a uri_text[i] introduces an invalid \a pchar (such as percent
+ * sign not followed by two hex digits), NOT_SET is returned. */
+static size_t parse_pchar(const char *uri_text, size_t i) {
+  /* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+   * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+   * pct-encoded = "%" HEXDIG HEXDIG
+   * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+   / "*" / "+" / "," / ";" / "=" */
+  char c = uri_text[i];
+  if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||
+      ((c >= '0') && (c <= '9')) ||
+      (c == '-' || c == '.' || c == '_' || c == '~') || /* unreserved */
+      (c == '!' || c == '$' || c == '&' || c == '\'' || c == '$' || c == '&' ||
+       c == '(' || c == ')' || c == '*' || c == '+' || c == ',' || c == ';' ||
+       c == '=') /* sub-delims */) {
+    return 1;
+  }
+  if (c == '%') { /* pct-encoded */
+    size_t j;
+    if (uri_text[i + 1] == 0 || uri_text[i + 2] == 0) {
+      return NOT_SET;
+    }
+    for (j = i + 1; j < 2; j++) {
+      c = uri_text[j];
+      if (!(((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) ||
+            ((c >= 'A') && (c <= 'F')))) {
+        return NOT_SET;
+      }
+    }
+    return 2;
+  }
+  return 0;
+}
+
+/* *( pchar / "?" / "/" ) */
+static int parse_fragment_or_query(const char *uri_text, size_t *i) {
+  char c;
+  while ((c = uri_text[*i]) != 0) {
+    const size_t advance = parse_pchar(uri_text, *i); /* pchar */
+    switch (advance) {
+      case 0: /* uri_text[i] isn't in pchar */
+        /* maybe it's ? or / */
+        if (uri_text[*i] == '?' || uri_text[*i] == '/') {
+          (*i)++;
+          break;
+        } else {
+          return 1;
+        }
+        GPR_UNREACHABLE_CODE(return 0);
+      default:
+        (*i) += advance;
+        break;
+      case NOT_SET: /* uri_text[i] introduces an invalid URI */
+        return 0;
+    }
+  }
+  /* *i is the first uri_text position past the \a query production, maybe \0 */
+  return 1;
+}
+
+static void do_nothing(void *ignored) {}
+static void parse_query_parts(grpc_uri *uri) {
+  static const char *QUERY_PARTS_SEPARATOR = "&";
+  static const char *QUERY_PARTS_VALUE_SEPARATOR = "=";
+  GPR_ASSERT(uri->query != NULL);
+  if (uri->query[0] == '\0') {
+    uri->query_parts = NULL;
+    uri->query_parts_values = NULL;
+    uri->num_query_parts = 0;
+    return;
+  }
+  gpr_slice query_slice =
+      gpr_slice_new(uri->query, strlen(uri->query), do_nothing);
+  gpr_slice_buffer query_parts; /* the &-separated elements of the query */
+  gpr_slice_buffer query_param_parts; /* the =-separated subelements */
+
+  gpr_slice_buffer_init(&query_parts);
+  gpr_slice_buffer_init(&query_param_parts);
+
+  gpr_slice_split(query_slice, QUERY_PARTS_SEPARATOR, &query_parts);
+  uri->query_parts = gpr_malloc(query_parts.count * sizeof(char *));
+  uri->query_parts_values = gpr_malloc(query_parts.count * sizeof(char *));
+  uri->num_query_parts = query_parts.count;
+  for (size_t i = 0; i < query_parts.count; i++) {
+    gpr_slice_split(query_parts.slices[i], QUERY_PARTS_VALUE_SEPARATOR,
+                    &query_param_parts);
+    GPR_ASSERT(query_param_parts.count > 0);
+    uri->query_parts[i] =
+        gpr_dump_slice(query_param_parts.slices[0], GPR_DUMP_ASCII);
+    if (query_param_parts.count > 1) {
+      /* TODO(dgq): only the first value after the separator is considered.
+       * Perhaps all chars after the first separator for the query part should
+       * be included, even if they include the separator. */
+      uri->query_parts_values[i] =
+          gpr_dump_slice(query_param_parts.slices[1], GPR_DUMP_ASCII);
+    } else {
+      uri->query_parts_values[i] = NULL;
+    }
+    gpr_slice_buffer_reset_and_unref(&query_param_parts);
+  }
+  gpr_slice_buffer_destroy(&query_parts);
+  gpr_slice_buffer_destroy(&query_param_parts);
+  gpr_slice_unref(query_slice);
+}
+
+grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
+  grpc_uri *uri;
+  size_t scheme_begin = 0;
+  size_t scheme_end = NOT_SET;
+  size_t authority_begin = NOT_SET;
+  size_t authority_end = NOT_SET;
+  size_t path_begin = NOT_SET;
+  size_t path_end = NOT_SET;
+  size_t query_begin = NOT_SET;
+  size_t query_end = NOT_SET;
+  size_t fragment_begin = NOT_SET;
+  size_t fragment_end = NOT_SET;
+  size_t i;
+
+  for (i = scheme_begin; uri_text[i] != 0; i++) {
+    if (uri_text[i] == ':') {
+      scheme_end = i;
+      break;
+    }
+    if (uri_text[i] >= 'a' && uri_text[i] <= 'z') continue;
+    if (uri_text[i] >= 'A' && uri_text[i] <= 'Z') continue;
+    if (i != scheme_begin) {
+      if (uri_text[i] >= '0' && uri_text[i] <= '9') continue;
+      if (uri_text[i] == '+') continue;
+      if (uri_text[i] == '-') continue;
+      if (uri_text[i] == '.') continue;
+    }
+    break;
+  }
+  if (scheme_end == NOT_SET) {
+    return bad_uri(uri_text, i, "scheme", suppress_errors);
+  }
+
+  if (uri_text[scheme_end + 1] == '/' && uri_text[scheme_end + 2] == '/') {
+    authority_begin = scheme_end + 3;
+    for (i = authority_begin; uri_text[i] != 0 && authority_end == NOT_SET;
+         i++) {
+      if (uri_text[i] == '/' || uri_text[i] == '?' || uri_text[i] == '#') {
+        authority_end = i;
+      }
+    }
+    if (authority_end == NOT_SET && uri_text[i] == 0) {
+      authority_end = i;
+    }
+    if (authority_end == NOT_SET) {
+      return bad_uri(uri_text, i, "authority", suppress_errors);
+    }
+    /* TODO(ctiller): parse the authority correctly */
+    path_begin = authority_end;
+  } else {
+    path_begin = scheme_end + 1;
+  }
+
+  for (i = path_begin; uri_text[i] != 0; i++) {
+    if (uri_text[i] == '?' || uri_text[i] == '#') {
+      path_end = i;
+      break;
+    }
+  }
+  if (path_end == NOT_SET && uri_text[i] == 0) {
+    path_end = i;
+  }
+  if (path_end == NOT_SET) {
+    return bad_uri(uri_text, i, "path", suppress_errors);
+  }
+
+  if (uri_text[i] == '?') {
+    query_begin = ++i;
+    if (!parse_fragment_or_query(uri_text, &i)) {
+      return bad_uri(uri_text, i, "query", suppress_errors);
+    } else if (uri_text[i] != 0 && uri_text[i] != '#') {
+      /* We must be at the end or at the beginning of a fragment */
+      return bad_uri(uri_text, i, "query", suppress_errors);
+    }
+    query_end = i;
+  }
+  if (uri_text[i] == '#') {
+    fragment_begin = ++i;
+    if (!parse_fragment_or_query(uri_text, &i)) {
+      return bad_uri(uri_text, i - fragment_end, "fragment", suppress_errors);
+    } else if (uri_text[i] != 0) {
+      /* We must be at the end */
+      return bad_uri(uri_text, i, "fragment", suppress_errors);
+    }
+    fragment_end = i;
+  }
+
+  uri = gpr_malloc(sizeof(*uri));
+  memset(uri, 0, sizeof(*uri));
+  uri->scheme = copy_component(uri_text, scheme_begin, scheme_end);
+  uri->authority = copy_component(uri_text, authority_begin, authority_end);
+  uri->path = copy_component(uri_text, path_begin, path_end);
+  uri->query = copy_component(uri_text, query_begin, query_end);
+  uri->fragment = copy_component(uri_text, fragment_begin, fragment_end);
+  parse_query_parts(uri);
+
+  return uri;
+}
+
+const char *grpc_uri_get_query_arg(const grpc_uri *uri, const char *key) {
+  GPR_ASSERT(key != NULL);
+  if (key[0] == '\0') return NULL;
+
+  for (size_t i = 0; i < uri->num_query_parts; ++i) {
+    if (0 == strcmp(key, uri->query_parts[i])) {
+      return uri->query_parts_values[i];
+    }
+  }
+  return NULL;
+}
+
+void grpc_uri_destroy(grpc_uri *uri) {
+  if (!uri) return;
+  gpr_free(uri->scheme);
+  gpr_free(uri->authority);
+  gpr_free(uri->path);
+  gpr_free(uri->query);
+  for (size_t i = 0; i < uri->num_query_parts; ++i) {
+    gpr_free(uri->query_parts[i]);
+    gpr_free(uri->query_parts_values[i]);
+  }
+  gpr_free(uri->query_parts);
+  gpr_free(uri->query_parts_values);
+  gpr_free(uri->fragment);
+  gpr_free(uri);
+}
diff --git a/src/core/ext/client_config/uri_parser.h b/src/core/ext/client_config/uri_parser.h
new file mode 100644
index 0000000..875a7cb
--- /dev/null
+++ b/src/core/ext/client_config/uri_parser.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * 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_EXT_CLIENT_CONFIG_URI_PARSER_H
+#define GRPC_CORE_EXT_CLIENT_CONFIG_URI_PARSER_H
+
+#include <stddef.h>
+
+typedef struct {
+  char *scheme;
+  char *authority;
+  char *path;
+  char *query;
+  /** Query substrings separated by '&' */
+  char **query_parts;
+  /** Number of elements in \a query_parts and \a query_parts_values */
+  size_t num_query_parts;
+  /** Split each query part by '='. NULL if not present. */
+  char **query_parts_values;
+  char *fragment;
+} grpc_uri;
+
+/** parse a uri, return NULL on failure */
+grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors);
+
+/** return the part of a query string after the '=' in "?key=xxx&...", or NULL
+ * if key is not present */
+const char *grpc_uri_get_query_arg(const grpc_uri *uri, const char *key);
+
+/** destroy a uri */
+void grpc_uri_destroy(grpc_uri *uri);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_URI_PARSER_H */
diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
new file mode 100644
index 0000000..459d6d9
--- /dev/null
+++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
@@ -0,0 +1,172 @@
+/*
+ *
+ * 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/ext/lb_policy/grpclb/load_balancer_api.h"
+#include "third_party/nanopb/pb_decode.h"
+#include "third_party/nanopb/pb_encode.h"
+
+#include <grpc/support/alloc.h>
+
+typedef struct decode_serverlist_arg {
+  int first_pass;
+  int i;
+  size_t num_servers;
+  grpc_grpclb_server **servers;
+} decode_serverlist_arg;
+
+/* invoked once for every Server in ServerList */
+static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
+                              void **arg) {
+  decode_serverlist_arg *dec_arg = *arg;
+  if (dec_arg->first_pass != 0) { /* first pass */
+    grpc_grpclb_server server;
+    if (!pb_decode(stream, grpc_lb_v0_Server_fields, &server)) {
+      return false;
+    }
+    dec_arg->num_servers++;
+  } else { /* second pass */
+    grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
+    GPR_ASSERT(dec_arg->num_servers > 0);
+    if (dec_arg->i == 0) { /* first iteration of second pass */
+      dec_arg->servers =
+          gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers);
+    }
+    if (!pb_decode(stream, grpc_lb_v0_Server_fields, server)) {
+      return false;
+    }
+    dec_arg->servers[dec_arg->i++] = server;
+  }
+
+  return true;
+}
+
+grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name) {
+  grpc_grpclb_request *req = gpr_malloc(sizeof(grpc_grpclb_request));
+
+  req->has_client_stats = 0; /* TODO(dgq): add support for stats once defined */
+  req->has_initial_request = 1;
+  req->initial_request.has_name = 1;
+  strncpy(req->initial_request.name, lb_service_name,
+          GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH);
+  return req;
+}
+
+gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) {
+  size_t encoded_length;
+  pb_ostream_t sizestream;
+  pb_ostream_t outputstream;
+  gpr_slice slice;
+  memset(&sizestream, 0, sizeof(pb_ostream_t));
+  pb_encode(&sizestream, grpc_lb_v0_LoadBalanceRequest_fields, request);
+  encoded_length = sizestream.bytes_written;
+
+  slice = gpr_slice_malloc(encoded_length);
+  outputstream =
+      pb_ostream_from_buffer(GPR_SLICE_START_PTR(slice), encoded_length);
+  GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v0_LoadBalanceRequest_fields,
+                       request) != 0);
+  return slice;
+}
+
+void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
+  gpr_free(request);
+}
+
+grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) {
+  bool status;
+  pb_istream_t stream =
+      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
+                             GPR_SLICE_LENGTH(encoded_response));
+  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
+  memset(res, 0, sizeof(*res));
+  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  if (!status) {
+    grpc_grpclb_response_destroy(res);
+    return NULL;
+  }
+  return res;
+}
+
+grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
+    gpr_slice encoded_response) {
+  bool status;
+  decode_serverlist_arg arg;
+  pb_istream_t stream =
+      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
+                             GPR_SLICE_LENGTH(encoded_response));
+  pb_istream_t stream_at_start = stream;
+  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
+  memset(res, 0, sizeof(*res));
+  memset(&arg, 0, sizeof(decode_serverlist_arg));
+
+  res->server_list.servers.funcs.decode = decode_serverlist;
+  res->server_list.servers.arg = &arg;
+  arg.first_pass = 1;
+  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  if (!status) {
+    grpc_grpclb_response_destroy(res);
+    return NULL;
+  }
+
+  arg.first_pass = 0;
+  status =
+      pb_decode(&stream_at_start, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  if (!status) {
+    grpc_grpclb_response_destroy(res);
+    return NULL;
+  }
+
+  grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
+  sl->num_servers = arg.num_servers;
+  sl->servers = arg.servers;
+  if (res->server_list.has_expiration_interval) {
+    sl->expiration_interval = res->server_list.expiration_interval;
+  }
+  grpc_grpclb_response_destroy(res);
+  return sl;
+}
+
+void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) {
+  if (serverlist == NULL) {
+    return;
+  }
+  for (size_t i = 0; i < serverlist->num_servers; i++) {
+    gpr_free(serverlist->servers[i]);
+  }
+  gpr_free(serverlist->servers);
+  gpr_free(serverlist);
+}
+
+void grpc_grpclb_response_destroy(grpc_grpclb_response *response) {
+  gpr_free(response);
+}
diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/lb_policy/grpclb/load_balancer_api.h
new file mode 100644
index 0000000..968f7d2
--- /dev/null
+++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.h
@@ -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.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_LB_POLICY_GRPCLB_LOAD_BALANCER_API_H
+#define GRPC_CORE_EXT_LB_POLICY_GRPCLB_LOAD_BALANCER_API_H
+
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/ext/client_config/lb_policy_factory.h"
+#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128
+
+typedef grpc_lb_v0_LoadBalanceRequest grpc_grpclb_request;
+typedef grpc_lb_v0_LoadBalanceResponse grpc_grpclb_response;
+typedef grpc_lb_v0_Server grpc_grpclb_server;
+typedef grpc_lb_v0_Duration grpc_grpclb_duration;
+typedef struct grpc_grpclb_serverlist {
+  grpc_grpclb_server **servers;
+  size_t num_servers;
+  grpc_grpclb_duration expiration_interval;
+} grpc_grpclb_serverlist;
+
+/** Create a request for a gRPC LB service under \a lb_service_name */
+grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name);
+
+/** Protocol Buffers v3-encode \a request */
+gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request);
+
+/** Destroy \a request */
+void grpc_grpclb_request_destroy(grpc_grpclb_request *request);
+
+/** Parse (ie, decode) the bytes in \a encoded_response as a \a
+ * grpc_grpclb_response */
+grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response);
+
+/** Destroy \a serverlist */
+void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist);
+
+/** Parse the list of servers from an encoded \a grpc_grpclb_response */
+grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
+    gpr_slice encoded_response);
+
+/** Destroy \a response */
+void grpc_grpclb_response_destroy(grpc_grpclb_response *response);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_EXT_LB_POLICY_GRPCLB_LOAD_BALANCER_API_H */
diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c
new file mode 100644
index 0000000..9719673
--- /dev/null
+++ b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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.
+ *
+ */
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.3.5-dev */
+
+#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h"
+
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+
+const pb_field_t grpc_lb_v0_Duration_fields[3] = {
+    PB_FIELD(  1, INT64   , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_Duration, seconds, seconds, 0),
+    PB_FIELD(  2, INT32   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Duration, nanos, seconds, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3] = {
+    PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v0_InitialLoadBalanceRequest_fields),
+    PB_FIELD(  2, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v0_ClientStats_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_InitialLoadBalanceRequest, name, name, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_ClientStats_fields[4] = {
+    PB_FIELD(  1, INT64   , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_ClientStats, total_requests, total_requests, 0),
+    PB_FIELD(  2, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ClientStats, client_rpc_errors, total_requests, 0),
+    PB_FIELD(  3, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ClientStats, dropped_requests, client_rpc_errors, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3] = {
+    PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v0_InitialLoadBalanceResponse_fields),
+    PB_FIELD(  2, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v0_ServerList_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_InitialLoadBalanceResponse, client_config, client_config, 0),
+    PB_FIELD(  2, STRING  , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, load_balancer_delegate, client_config, 0),
+    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v0_Duration_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_ServerList_fields[3] = {
+    PB_FIELD(  1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v0_ServerList, servers, servers, &grpc_lb_v0_Server_fields),
+    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ServerList, expiration_interval, servers, &grpc_lb_v0_Duration_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_Server_fields[5] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_Server, ip_address, ip_address, 0),
+    PB_FIELD(  2, INT32   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, port, ip_address, 0),
+    PB_FIELD(  3, BYTES   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, load_balance_token, port, 0),
+    PB_FIELD(  4, BOOL    , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, drop_request, load_balance_token, 0),
+    PB_LAST_FIELD
+};
+
+
+/* Check that field information fits in pb_field_t */
+#if !defined(PB_FIELD_32BIT)
+/* If you get an error here, it means that you need to define PB_FIELD_32BIT
+ * compile-time option. You can do that in pb.h or on compiler command line.
+ * 
+ * The reason you need to do this is that some of your messages contain tag
+ * numbers or field sizes that are larger than what can fit in 8 or 16 bit
+ * field descriptors.
+ */
+PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v0_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
+#endif
+
+#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
+/* If you get an error here, it means that you need to define PB_FIELD_16BIT
+ * compile-time option. You can do that in pb.h or on compiler command line.
+ * 
+ * The reason you need to do this is that some of your messages contain tag
+ * numbers or field sizes that are larger than what can fit in the default
+ * 8 bit descriptors.
+ */
+PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v0_ServerList, servers) < 256 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
+#endif
+
+
diff --git a/src/core/proto/grpc/lb/v0/load_balancer.pb.h b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h
similarity index 100%
rename from src/core/proto/grpc/lb/v0/load_balancer.pb.h
rename to src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
new file mode 100644
index 0000000..0d215cd
--- /dev/null
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -0,0 +1,478 @@
+/*
+ *
+ * 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 <grpc/support/alloc.h>
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/lib/transport/connectivity_state.h"
+
+typedef struct pending_pick {
+  struct pending_pick *next;
+  grpc_pollset *pollset;
+  uint32_t initial_metadata_flags;
+  grpc_connected_subchannel **target;
+  grpc_closure *on_complete;
+} pending_pick;
+
+typedef struct {
+  /** base policy: must be first */
+  grpc_lb_policy base;
+  /** all our subchannels */
+  grpc_subchannel **subchannels;
+  size_t num_subchannels;
+
+  grpc_closure connectivity_changed;
+
+  /** the selected channel (a grpc_connected_subchannel) */
+  gpr_atm selected;
+
+  /** mutex protecting remaining members */
+  gpr_mu mu;
+  /** have we started picking? */
+  int started_picking;
+  /** are we shut down? */
+  int shutdown;
+  /** which subchannel are we watching? */
+  size_t checking_subchannel;
+  /** what is the connectivity of that channel? */
+  grpc_connectivity_state checking_connectivity;
+  /** list of picks that are waiting on connectivity */
+  pending_pick *pending_picks;
+
+  /** our connectivity state tracker */
+  grpc_connectivity_state_tracker state_tracker;
+} pick_first_lb_policy;
+
+#define GET_SELECTED(p) \
+  ((grpc_connected_subchannel *)gpr_atm_acq_load(&(p)->selected))
+
+static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  grpc_connected_subchannel *selected = GET_SELECTED(p);
+  size_t i;
+  GPR_ASSERT(p->pending_picks == NULL);
+  for (i = 0; i < p->num_subchannels; i++) {
+    GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
+  }
+  if (selected != NULL) {
+    GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, selected, "picked_first");
+  }
+  grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
+  gpr_free(p->subchannels);
+  gpr_mu_destroy(&p->mu);
+  gpr_free(p);
+}
+
+static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  pending_pick *pp;
+  grpc_connected_subchannel *selected;
+  gpr_mu_lock(&p->mu);
+  selected = GET_SELECTED(p);
+  p->shutdown = 1;
+  pp = p->pending_picks;
+  p->pending_picks = NULL;
+  grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                              GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
+  /* cancel subscription */
+  if (selected != NULL) {
+    grpc_connected_subchannel_notify_on_state_change(
+        exec_ctx, selected, NULL, NULL, &p->connectivity_changed);
+  } else if (p->num_subchannels > 0) {
+    grpc_subchannel_notify_on_state_change(
+        exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
+        &p->connectivity_changed);
+  }
+  gpr_mu_unlock(&p->mu);
+  while (pp != NULL) {
+    pending_pick *next = pp->next;
+    *pp->target = NULL;
+    grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
+                                 pp->pollset);
+    grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+    gpr_free(pp);
+    pp = next;
+  }
+}
+
+static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                           grpc_connected_subchannel **target) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  pending_pick *pp;
+  gpr_mu_lock(&p->mu);
+  pp = p->pending_picks;
+  p->pending_picks = NULL;
+  while (pp != NULL) {
+    pending_pick *next = pp->next;
+    if (pp->target == target) {
+      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
+                                   pp->pollset);
+      *target = NULL;
+      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      gpr_free(pp);
+    } else {
+      pp->next = p->pending_picks;
+      p->pending_picks = pp;
+    }
+    pp = next;
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
+static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                            uint32_t initial_metadata_flags_mask,
+                            uint32_t initial_metadata_flags_eq) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  pending_pick *pp;
+  gpr_mu_lock(&p->mu);
+  pp = p->pending_picks;
+  p->pending_picks = NULL;
+  while (pp != NULL) {
+    pending_pick *next = pp->next;
+    if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
+        initial_metadata_flags_eq) {
+      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
+                                   pp->pollset);
+      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      gpr_free(pp);
+    } else {
+      pp->next = p->pending_picks;
+      p->pending_picks = pp;
+    }
+    pp = next;
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
+static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
+  p->started_picking = 1;
+  p->checking_subchannel = 0;
+  p->checking_connectivity = GRPC_CHANNEL_IDLE;
+  GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
+  grpc_subchannel_notify_on_state_change(
+      exec_ctx, p->subchannels[p->checking_subchannel],
+      p->base.interested_parties, &p->checking_connectivity,
+      &p->connectivity_changed);
+}
+
+static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  gpr_mu_lock(&p->mu);
+  if (!p->started_picking) {
+    start_picking(exec_ctx, p);
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
+static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                   grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
+                   uint32_t initial_metadata_flags,
+                   grpc_connected_subchannel **target,
+                   grpc_closure *on_complete) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  pending_pick *pp;
+
+  /* Check atomically for a selected channel */
+  grpc_connected_subchannel *selected = GET_SELECTED(p);
+  if (selected != NULL) {
+    *target = selected;
+    return 1;
+  }
+
+  /* No subchannel selected yet, so acquire lock and then attempt again */
+  gpr_mu_lock(&p->mu);
+  selected = GET_SELECTED(p);
+  if (selected) {
+    gpr_mu_unlock(&p->mu);
+    *target = selected;
+    return 1;
+  } else {
+    if (!p->started_picking) {
+      start_picking(exec_ctx, p);
+    }
+    grpc_pollset_set_add_pollset(exec_ctx, p->base.interested_parties, pollset);
+    pp = gpr_malloc(sizeof(*pp));
+    pp->next = p->pending_picks;
+    pp->pollset = pollset;
+    pp->target = target;
+    pp->initial_metadata_flags = initial_metadata_flags;
+    pp->on_complete = on_complete;
+    p->pending_picks = pp;
+    gpr_mu_unlock(&p->mu);
+    return 0;
+  }
+}
+
+static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
+                                bool iomgr_success) {
+  pick_first_lb_policy *p = arg;
+  size_t i;
+  size_t num_subchannels = p->num_subchannels;
+  grpc_subchannel **subchannels;
+
+  gpr_mu_lock(&p->mu);
+  subchannels = p->subchannels;
+  p->num_subchannels = 0;
+  p->subchannels = NULL;
+  gpr_mu_unlock(&p->mu);
+  GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
+
+  for (i = 0; i < num_subchannels; i++) {
+    GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
+  }
+
+  gpr_free(subchannels);
+}
+
+static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
+                                    bool iomgr_success) {
+  pick_first_lb_policy *p = arg;
+  grpc_subchannel *selected_subchannel;
+  pending_pick *pp;
+  grpc_connected_subchannel *selected;
+
+  gpr_mu_lock(&p->mu);
+
+  selected = GET_SELECTED(p);
+
+  if (p->shutdown) {
+    gpr_mu_unlock(&p->mu);
+    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
+    return;
+  } else if (selected != NULL) {
+    if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+      /* if the selected channel goes bad, we're done */
+      p->checking_connectivity = GRPC_CHANNEL_FATAL_FAILURE;
+    }
+    grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                p->checking_connectivity, "selected_changed");
+    if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
+      grpc_connected_subchannel_notify_on_state_change(
+          exec_ctx, selected, p->base.interested_parties,
+          &p->checking_connectivity, &p->connectivity_changed);
+    } else {
+      GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
+    }
+  } else {
+  loop:
+    switch (p->checking_connectivity) {
+      case GRPC_CHANNEL_READY:
+        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                    GRPC_CHANNEL_READY, "connecting_ready");
+        selected_subchannel = p->subchannels[p->checking_subchannel];
+        selected =
+            grpc_subchannel_get_connected_subchannel(selected_subchannel);
+        GPR_ASSERT(selected != NULL);
+        GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked_first");
+        /* drop the pick list: we are connected now */
+        GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
+        gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
+        grpc_exec_ctx_enqueue(
+            exec_ctx, grpc_closure_create(destroy_subchannels, p), true, NULL);
+        /* update any calls that were waiting for a pick */
+        while ((pp = p->pending_picks)) {
+          p->pending_picks = pp->next;
+          *pp->target = selected;
+          grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
+                                       pp->pollset);
+          grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+          gpr_free(pp);
+        }
+        grpc_connected_subchannel_notify_on_state_change(
+            exec_ctx, selected, p->base.interested_parties,
+            &p->checking_connectivity, &p->connectivity_changed);
+        break;
+      case GRPC_CHANNEL_TRANSIENT_FAILURE:
+        p->checking_subchannel =
+            (p->checking_subchannel + 1) % p->num_subchannels;
+        if (p->checking_subchannel == 0) {
+          /* only trigger transient failure when we've tried all alternatives */
+          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
+                                      "connecting_transient_failure");
+        }
+        p->checking_connectivity = grpc_subchannel_check_connectivity(
+            p->subchannels[p->checking_subchannel]);
+        if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+          grpc_subchannel_notify_on_state_change(
+              exec_ctx, p->subchannels[p->checking_subchannel],
+              p->base.interested_parties, &p->checking_connectivity,
+              &p->connectivity_changed);
+        } else {
+          goto loop;
+        }
+        break;
+      case GRPC_CHANNEL_CONNECTING:
+      case GRPC_CHANNEL_IDLE:
+        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                    GRPC_CHANNEL_CONNECTING,
+                                    "connecting_changed");
+        grpc_subchannel_notify_on_state_change(
+            exec_ctx, p->subchannels[p->checking_subchannel],
+            p->base.interested_parties, &p->checking_connectivity,
+            &p->connectivity_changed);
+        break;
+      case GRPC_CHANNEL_FATAL_FAILURE:
+        p->num_subchannels--;
+        GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
+                 p->subchannels[p->num_subchannels]);
+        GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
+                              "pick_first");
+        if (p->num_subchannels == 0) {
+          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                      GRPC_CHANNEL_FATAL_FAILURE,
+                                      "no_more_channels");
+          while ((pp = p->pending_picks)) {
+            p->pending_picks = pp->next;
+            *pp->target = NULL;
+            grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+            gpr_free(pp);
+          }
+          GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
+                                    "pick_first_connectivity");
+        } else {
+          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
+                                      "subchannel_failed");
+          p->checking_subchannel %= p->num_subchannels;
+          p->checking_connectivity = grpc_subchannel_check_connectivity(
+              p->subchannels[p->checking_subchannel]);
+          goto loop;
+        }
+    }
+  }
+
+  gpr_mu_unlock(&p->mu);
+}
+
+static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
+                                                     grpc_lb_policy *pol) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  grpc_connectivity_state st;
+  gpr_mu_lock(&p->mu);
+  st = grpc_connectivity_state_check(&p->state_tracker);
+  gpr_mu_unlock(&p->mu);
+  return st;
+}
+
+static void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx,
+                                      grpc_lb_policy *pol,
+                                      grpc_connectivity_state *current,
+                                      grpc_closure *notify) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  gpr_mu_lock(&p->mu);
+  grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
+                                                 current, notify);
+  gpr_mu_unlock(&p->mu);
+}
+
+static void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                        grpc_closure *closure) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  grpc_connected_subchannel *selected = GET_SELECTED(p);
+  if (selected) {
+    grpc_connected_subchannel_ping(exec_ctx, selected, closure);
+  } else {
+    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+  }
+}
+
+static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
+    pf_destroy,     pf_shutdown,           pf_pick,
+    pf_cancel_pick, pf_cancel_picks,       pf_ping_one,
+    pf_exit_idle,   pf_check_connectivity, pf_notify_on_state_change};
+
+static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
+
+static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
+
+static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
+                                         grpc_lb_policy_factory *factory,
+                                         grpc_lb_policy_args *args) {
+  GPR_ASSERT(args->addresses != NULL);
+  GPR_ASSERT(args->client_channel_factory != NULL);
+
+  if (args->addresses->naddrs == 0) return NULL;
+
+  pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
+  memset(p, 0, sizeof(*p));
+
+  p->subchannels =
+      gpr_malloc(sizeof(grpc_subchannel *) * args->addresses->naddrs);
+  memset(p->subchannels, 0, sizeof(*p->subchannels) * args->addresses->naddrs);
+  grpc_subchannel_args sc_args;
+  size_t subchannel_idx = 0;
+  for (size_t i = 0; i < args->addresses->naddrs; i++) {
+    memset(&sc_args, 0, sizeof(grpc_subchannel_args));
+    sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr);
+    sc_args.addr_len = (size_t)args->addresses->addrs[i].len;
+
+    grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
+        exec_ctx, args->client_channel_factory, &sc_args);
+
+    if (subchannel != NULL) {
+      p->subchannels[subchannel_idx++] = subchannel;
+    }
+  }
+  if (subchannel_idx == 0) {
+    gpr_free(p->subchannels);
+    gpr_free(p);
+    return NULL;
+  }
+  p->num_subchannels = subchannel_idx;
+
+  grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
+  grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);
+  gpr_mu_init(&p->mu);
+  return &p->base;
+}
+
+static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = {
+    pick_first_factory_ref, pick_first_factory_unref, create_pick_first,
+    "pick_first"};
+
+static grpc_lb_policy_factory pick_first_lb_policy_factory = {
+    &pick_first_factory_vtable};
+
+static grpc_lb_policy_factory *pick_first_lb_factory_create() {
+  return &pick_first_lb_policy_factory;
+}
+
+/* Plugin registration */
+
+void grpc_lb_policy_pick_first_init() {
+  grpc_register_lb_policy(pick_first_lb_factory_create());
+}
+
+void grpc_lb_policy_pick_first_shutdown() {}
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
new file mode 100644
index 0000000..3f6051b
--- /dev/null
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -0,0 +1,598 @@
+/*
+ *
+ * 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 <grpc/support/alloc.h>
+
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/transport/connectivity_state.h"
+
+typedef struct round_robin_lb_policy round_robin_lb_policy;
+
+int grpc_lb_round_robin_trace = 0;
+
+/** List of entities waiting for a pick.
+ *
+ * Once a pick is available, \a target is updated and \a on_complete called. */
+typedef struct pending_pick {
+  struct pending_pick *next;
+  grpc_pollset *pollset;
+  uint32_t initial_metadata_flags;
+  grpc_connected_subchannel **target;
+  grpc_closure *on_complete;
+} pending_pick;
+
+/** List of subchannels in a connectivity READY state */
+typedef struct ready_list {
+  grpc_subchannel *subchannel;
+  struct ready_list *next;
+  struct ready_list *prev;
+} ready_list;
+
+typedef struct {
+  /** index within policy->subchannels */
+  size_t index;
+  /** backpointer to owning policy */
+  round_robin_lb_policy *policy;
+  /** subchannel itself */
+  grpc_subchannel *subchannel;
+  /** notification that connectivity has changed on subchannel */
+  grpc_closure connectivity_changed_closure;
+  /** this subchannels current position in subchannel->ready_list */
+  ready_list *ready_list_node;
+  /** last observed connectivity */
+  grpc_connectivity_state connectivity_state;
+} subchannel_data;
+
+struct round_robin_lb_policy {
+  /** base policy: must be first */
+  grpc_lb_policy base;
+
+  /** all our subchannels */
+  size_t num_subchannels;
+  subchannel_data **subchannels;
+
+  /** mutex protecting remaining members */
+  gpr_mu mu;
+  /** have we started picking? */
+  int started_picking;
+  /** are we shutting down? */
+  int shutdown;
+  /** List of picks that are waiting on connectivity */
+  pending_pick *pending_picks;
+
+  /** our connectivity state tracker */
+  grpc_connectivity_state_tracker state_tracker;
+
+  /** (Dummy) root of the doubly linked list containing READY subchannels */
+  ready_list ready_list;
+  /** Last pick from the ready list. */
+  ready_list *ready_list_last_pick;
+};
+
+/** Returns the next subchannel from the connected list or NULL if the list is
+ * empty.
+ *
+ * Note that this function does *not* advance p->ready_list_last_pick. Use \a
+ * advance_last_picked_locked() for that. */
+static ready_list *peek_next_connected_locked(const round_robin_lb_policy *p) {
+  ready_list *selected;
+  selected = p->ready_list_last_pick->next;
+
+  while (selected != NULL) {
+    if (selected == &p->ready_list) {
+      GPR_ASSERT(selected->subchannel == NULL);
+      /* skip dummy root */
+      selected = selected->next;
+    } else {
+      GPR_ASSERT(selected->subchannel != NULL);
+      return selected;
+    }
+  }
+  return NULL;
+}
+
+/** Advance the \a ready_list picking head. */
+static void advance_last_picked_locked(round_robin_lb_policy *p) {
+  if (p->ready_list_last_pick->next != NULL) { /* non-empty list */
+    p->ready_list_last_pick = p->ready_list_last_pick->next;
+    if (p->ready_list_last_pick == &p->ready_list) {
+      /* skip dummy root */
+      p->ready_list_last_pick = p->ready_list_last_pick->next;
+    }
+  } else { /* should be an empty list */
+    GPR_ASSERT(p->ready_list_last_pick == &p->ready_list);
+  }
+
+  if (grpc_lb_round_robin_trace) {
+    gpr_log(GPR_DEBUG, "[READYLIST] ADVANCED LAST PICK. NOW AT NODE %p (SC %p)",
+            p->ready_list_last_pick, p->ready_list_last_pick->subchannel);
+  }
+}
+
+/** Prepends (relative to the root at p->ready_list) the connected subchannel \a
+ * csc to the list of ready subchannels. */
+static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
+                                           grpc_subchannel *sc) {
+  ready_list *new_elem = gpr_malloc(sizeof(ready_list));
+  new_elem->subchannel = sc;
+  if (p->ready_list.prev == NULL) {
+    /* first element */
+    new_elem->next = &p->ready_list;
+    new_elem->prev = &p->ready_list;
+    p->ready_list.next = new_elem;
+    p->ready_list.prev = new_elem;
+  } else {
+    new_elem->next = &p->ready_list;
+    new_elem->prev = p->ready_list.prev;
+    p->ready_list.prev->next = new_elem;
+    p->ready_list.prev = new_elem;
+  }
+  if (grpc_lb_round_robin_trace) {
+    gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (SC %p)", new_elem, sc);
+  }
+  return new_elem;
+}
+
+/** Removes \a node from the list of connected subchannels */
+static void remove_disconnected_sc_locked(round_robin_lb_policy *p,
+                                          ready_list *node) {
+  if (node == NULL) {
+    return;
+  }
+  if (node == p->ready_list_last_pick) {
+    /* If removing the lastly picked node, reset the last pick pointer to the
+     * dummy root of the list */
+    p->ready_list_last_pick = &p->ready_list;
+  }
+
+  /* removing last item */
+  if (node->next == &p->ready_list && node->prev == &p->ready_list) {
+    GPR_ASSERT(p->ready_list.next == node);
+    GPR_ASSERT(p->ready_list.prev == node);
+    p->ready_list.next = NULL;
+    p->ready_list.prev = NULL;
+  } else {
+    node->prev->next = node->next;
+    node->next->prev = node->prev;
+  }
+
+  if (grpc_lb_round_robin_trace) {
+    gpr_log(GPR_DEBUG, "[READYLIST] REMOVED NODE %p (SC %p)", node,
+            node->subchannel);
+  }
+
+  node->next = NULL;
+  node->prev = NULL;
+  node->subchannel = NULL;
+
+  gpr_free(node);
+}
+
+static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  size_t i;
+  ready_list *elem;
+  for (i = 0; i < p->num_subchannels; i++) {
+    subchannel_data *sd = p->subchannels[i];
+    GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "round_robin");
+    gpr_free(sd);
+  }
+
+  grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
+  gpr_free(p->subchannels);
+  gpr_mu_destroy(&p->mu);
+
+  elem = p->ready_list.next;
+  while (elem != NULL && elem != &p->ready_list) {
+    ready_list *tmp;
+    tmp = elem->next;
+    elem->next = NULL;
+    elem->prev = NULL;
+    elem->subchannel = NULL;
+    gpr_free(elem);
+    elem = tmp;
+  }
+  gpr_free(p);
+}
+
+static void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  pending_pick *pp;
+  size_t i;
+
+  gpr_mu_lock(&p->mu);
+
+  p->shutdown = 1;
+  while ((pp = p->pending_picks)) {
+    p->pending_picks = pp->next;
+    *pp->target = NULL;
+    grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+    gpr_free(pp);
+  }
+  grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                              GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
+  for (i = 0; i < p->num_subchannels; i++) {
+    subchannel_data *sd = p->subchannels[i];
+    grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL,
+                                           &sd->connectivity_changed_closure);
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
+static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                           grpc_connected_subchannel **target) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  pending_pick *pp;
+  gpr_mu_lock(&p->mu);
+  pp = p->pending_picks;
+  p->pending_picks = NULL;
+  while (pp != NULL) {
+    pending_pick *next = pp->next;
+    if (pp->target == target) {
+      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
+                                   pp->pollset);
+      *target = NULL;
+      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      gpr_free(pp);
+    } else {
+      pp->next = p->pending_picks;
+      p->pending_picks = pp;
+    }
+    pp = next;
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
+static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                            uint32_t initial_metadata_flags_mask,
+                            uint32_t initial_metadata_flags_eq) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  pending_pick *pp;
+  gpr_mu_lock(&p->mu);
+  pp = p->pending_picks;
+  p->pending_picks = NULL;
+  while (pp != NULL) {
+    pending_pick *next = pp->next;
+    if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
+        initial_metadata_flags_eq) {
+      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
+                                   pp->pollset);
+      *pp->target = NULL;
+      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      gpr_free(pp);
+    } else {
+      pp->next = p->pending_picks;
+      p->pending_picks = pp;
+    }
+    pp = next;
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
+static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
+  size_t i;
+  p->started_picking = 1;
+
+  gpr_log(GPR_DEBUG, "LB_POLICY: p=%p num_subchannels=%d", p,
+          p->num_subchannels);
+
+  for (i = 0; i < p->num_subchannels; i++) {
+    subchannel_data *sd = p->subchannels[i];
+    sd->connectivity_state = GRPC_CHANNEL_IDLE;
+    grpc_subchannel_notify_on_state_change(
+        exec_ctx, sd->subchannel, p->base.interested_parties,
+        &sd->connectivity_state, &sd->connectivity_changed_closure);
+    GRPC_LB_POLICY_WEAK_REF(&p->base, "round_robin_connectivity");
+  }
+}
+
+static void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  gpr_mu_lock(&p->mu);
+  if (!p->started_picking) {
+    start_picking(exec_ctx, p);
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
+static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                   grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
+                   uint32_t initial_metadata_flags,
+                   grpc_connected_subchannel **target,
+                   grpc_closure *on_complete) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  pending_pick *pp;
+  ready_list *selected;
+  gpr_mu_lock(&p->mu);
+  if ((selected = peek_next_connected_locked(p))) {
+    gpr_mu_unlock(&p->mu);
+    *target = grpc_subchannel_get_connected_subchannel(selected->subchannel);
+    if (grpc_lb_round_robin_trace) {
+      gpr_log(GPR_DEBUG,
+              "[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (NODE %p)",
+              selected->subchannel, selected);
+    }
+    /* only advance the last picked pointer if the selection was used */
+    advance_last_picked_locked(p);
+    return 1;
+  } else {
+    if (!p->started_picking) {
+      start_picking(exec_ctx, p);
+    }
+    grpc_pollset_set_add_pollset(exec_ctx, p->base.interested_parties, pollset);
+    pp = gpr_malloc(sizeof(*pp));
+    pp->next = p->pending_picks;
+    pp->pollset = pollset;
+    pp->target = target;
+    pp->on_complete = on_complete;
+    pp->initial_metadata_flags = initial_metadata_flags;
+    p->pending_picks = pp;
+    gpr_mu_unlock(&p->mu);
+    return 0;
+  }
+}
+
+static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
+                                    bool iomgr_success) {
+  subchannel_data *sd = arg;
+  round_robin_lb_policy *p = sd->policy;
+  pending_pick *pp;
+  ready_list *selected;
+
+  int unref = 0;
+
+  gpr_mu_lock(&p->mu);
+
+  if (p->shutdown) {
+    unref = 1;
+  } else {
+    switch (sd->connectivity_state) {
+      case GRPC_CHANNEL_READY:
+        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                    GRPC_CHANNEL_READY, "connecting_ready");
+        /* add the newly connected subchannel to the list of connected ones.
+         * Note that it goes to the "end of the line". */
+        sd->ready_list_node = add_connected_sc_locked(p, sd->subchannel);
+        /* at this point we know there's at least one suitable subchannel. Go
+         * ahead and pick one and notify the pending suitors in
+         * p->pending_picks. This preemtively replicates rr_pick()'s actions. */
+        selected = peek_next_connected_locked(p);
+        if (p->pending_picks != NULL) {
+          /* if the selected subchannel is going to be used for the pending
+           * picks, update the last picked pointer */
+          advance_last_picked_locked(p);
+        }
+        while ((pp = p->pending_picks)) {
+          p->pending_picks = pp->next;
+          *pp->target =
+              grpc_subchannel_get_connected_subchannel(selected->subchannel);
+          if (grpc_lb_round_robin_trace) {
+            gpr_log(GPR_DEBUG,
+                    "[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)",
+                    selected->subchannel, selected);
+          }
+          grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
+                                       pp->pollset);
+          grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+          gpr_free(pp);
+        }
+        grpc_subchannel_notify_on_state_change(
+            exec_ctx, sd->subchannel, p->base.interested_parties,
+            &sd->connectivity_state, &sd->connectivity_changed_closure);
+        break;
+      case GRPC_CHANNEL_CONNECTING:
+      case GRPC_CHANNEL_IDLE:
+        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                    sd->connectivity_state,
+                                    "connecting_changed");
+        grpc_subchannel_notify_on_state_change(
+            exec_ctx, sd->subchannel, p->base.interested_parties,
+            &sd->connectivity_state, &sd->connectivity_changed_closure);
+        break;
+      case GRPC_CHANNEL_TRANSIENT_FAILURE:
+        /* renew state notification */
+        grpc_subchannel_notify_on_state_change(
+            exec_ctx, sd->subchannel, p->base.interested_parties,
+            &sd->connectivity_state, &sd->connectivity_changed_closure);
+
+        /* remove from ready list if still present */
+        if (sd->ready_list_node != NULL) {
+          remove_disconnected_sc_locked(p, sd->ready_list_node);
+          sd->ready_list_node = NULL;
+        }
+        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                    GRPC_CHANNEL_TRANSIENT_FAILURE,
+                                    "connecting_transient_failure");
+        break;
+      case GRPC_CHANNEL_FATAL_FAILURE:
+        if (sd->ready_list_node != NULL) {
+          remove_disconnected_sc_locked(p, sd->ready_list_node);
+          sd->ready_list_node = NULL;
+        }
+
+        p->num_subchannels--;
+        GPR_SWAP(subchannel_data *, p->subchannels[sd->index],
+                 p->subchannels[p->num_subchannels]);
+        GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "round_robin");
+        p->subchannels[sd->index]->index = sd->index;
+        gpr_free(sd);
+
+        unref = 1;
+        if (p->num_subchannels == 0) {
+          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                      GRPC_CHANNEL_FATAL_FAILURE,
+                                      "no_more_channels");
+          while ((pp = p->pending_picks)) {
+            p->pending_picks = pp->next;
+            *pp->target = NULL;
+            grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+            gpr_free(pp);
+          }
+        } else {
+          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
+                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
+                                      "subchannel_failed");
+        }
+    } /* switch */
+  }   /* !unref */
+
+  gpr_mu_unlock(&p->mu);
+
+  if (unref) {
+    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "round_robin_connectivity");
+  }
+}
+
+static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
+                                                     grpc_lb_policy *pol) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  grpc_connectivity_state st;
+  gpr_mu_lock(&p->mu);
+  st = grpc_connectivity_state_check(&p->state_tracker);
+  gpr_mu_unlock(&p->mu);
+  return st;
+}
+
+static void rr_notify_on_state_change(grpc_exec_ctx *exec_ctx,
+                                      grpc_lb_policy *pol,
+                                      grpc_connectivity_state *current,
+                                      grpc_closure *notify) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  gpr_mu_lock(&p->mu);
+  grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
+                                                 current, notify);
+  gpr_mu_unlock(&p->mu);
+}
+
+static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                        grpc_closure *closure) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  ready_list *selected;
+  grpc_connected_subchannel *target;
+  gpr_mu_lock(&p->mu);
+  if ((selected = peek_next_connected_locked(p))) {
+    gpr_mu_unlock(&p->mu);
+    target = grpc_subchannel_get_connected_subchannel(selected->subchannel);
+    grpc_connected_subchannel_ping(exec_ctx, target, closure);
+  } else {
+    gpr_mu_unlock(&p->mu);
+    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+  }
+}
+
+static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
+    rr_destroy,     rr_shutdown,           rr_pick,
+    rr_cancel_pick, rr_cancel_picks,       rr_ping_one,
+    rr_exit_idle,   rr_check_connectivity, rr_notify_on_state_change};
+
+static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}
+
+static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {}
+
+static grpc_lb_policy *create_round_robin(grpc_exec_ctx *exec_ctx,
+                                          grpc_lb_policy_factory *factory,
+                                          grpc_lb_policy_args *args) {
+  GPR_ASSERT(args->addresses != NULL);
+  GPR_ASSERT(args->client_channel_factory != NULL);
+
+  round_robin_lb_policy *p = gpr_malloc(sizeof(*p));
+  memset(p, 0, sizeof(*p));
+
+  p->subchannels =
+      gpr_malloc(sizeof(*p->subchannels) * args->addresses->naddrs);
+  memset(p->subchannels, 0, sizeof(*p->subchannels) * args->addresses->naddrs);
+
+  grpc_subchannel_args sc_args;
+  size_t subchannel_idx = 0;
+  for (size_t i = 0; i < args->addresses->naddrs; i++) {
+    memset(&sc_args, 0, sizeof(grpc_subchannel_args));
+    sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr);
+    sc_args.addr_len = (size_t)args->addresses->addrs[i].len;
+
+    grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
+        exec_ctx, args->client_channel_factory, &sc_args);
+
+    if (subchannel != NULL) {
+      subchannel_data *sd = gpr_malloc(sizeof(*sd));
+      memset(sd, 0, sizeof(*sd));
+      p->subchannels[subchannel_idx] = sd;
+      sd->policy = p;
+      sd->index = subchannel_idx;
+      sd->subchannel = subchannel;
+      ++subchannel_idx;
+      grpc_closure_init(&sd->connectivity_changed_closure,
+                        rr_connectivity_changed, sd);
+    }
+  }
+  if (subchannel_idx == 0) {
+    gpr_free(p->subchannels);
+    gpr_free(p);
+    return NULL;
+  }
+  p->num_subchannels = subchannel_idx;
+
+  /* The (dummy node) root of the ready list */
+  p->ready_list.subchannel = NULL;
+  p->ready_list.prev = NULL;
+  p->ready_list.next = NULL;
+  p->ready_list_last_pick = &p->ready_list;
+
+  grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable);
+  grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
+                               "round_robin");
+  gpr_mu_init(&p->mu);
+  return &p->base;
+}
+
+static const grpc_lb_policy_factory_vtable round_robin_factory_vtable = {
+    round_robin_factory_ref, round_robin_factory_unref, create_round_robin,
+    "round_robin"};
+
+static grpc_lb_policy_factory round_robin_lb_policy_factory = {
+    &round_robin_factory_vtable};
+
+static grpc_lb_policy_factory *round_robin_lb_factory_create() {
+  return &round_robin_lb_policy_factory;
+}
+
+/* Plugin registration */
+
+void grpc_lb_policy_round_robin_init() {
+  grpc_register_lb_policy(round_robin_lb_factory_create());
+  grpc_register_tracer("round_robin", &grpc_lb_round_robin_trace);
+}
+
+void grpc_lb_policy_round_robin_shutdown() {}
diff --git a/src/core/ext/resolver/dns/native/README.md b/src/core/ext/resolver/dns/native/README.md
new file mode 100644
index 0000000..695de47
--- /dev/null
+++ b/src/core/ext/resolver/dns/native/README.md
@@ -0,0 +1,2 @@
+dns: scheme name resolution, using getaddrbyname
+(or other OS specific implementation)
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
new file mode 100644
index 0000000..620ba4e
--- /dev/null
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -0,0 +1,301 @@
+/*
+ *
+ * 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 <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/ext/client_config/resolver_registry.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/support/backoff.h"
+#include "src/core/lib/support/string.h"
+
+#define BACKOFF_MULTIPLIER 1.6
+#define BACKOFF_JITTER 0.2
+#define BACKOFF_MIN_SECONDS 1
+#define BACKOFF_MAX_SECONDS 120
+
+typedef struct {
+  /** base class: must be first */
+  grpc_resolver base;
+  /** refcount */
+  gpr_refcount refs;
+  /** name to resolve */
+  char *name;
+  /** default port to use */
+  char *default_port;
+  /** subchannel factory */
+  grpc_client_channel_factory *client_channel_factory;
+  /** load balancing policy name */
+  char *lb_policy_name;
+
+  /** mutex guarding the rest of the state */
+  gpr_mu mu;
+  /** are we currently resolving? */
+  int resolving;
+  /** which version of resolved_config have we published? */
+  int published_version;
+  /** which version of resolved_config is current? */
+  int resolved_version;
+  /** pending next completion, or NULL */
+  grpc_closure *next_completion;
+  /** target config address for next completion */
+  grpc_client_config **target_config;
+  /** current (fully resolved) config */
+  grpc_client_config *resolved_config;
+  /** retry timer */
+  bool have_retry_timer;
+  grpc_timer retry_timer;
+  /** retry backoff state */
+  gpr_backoff backoff_state;
+} dns_resolver;
+
+static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+
+static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
+                                       dns_resolver *r);
+static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
+                                         dns_resolver *r);
+
+static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+                     grpc_client_config **target_config,
+                     grpc_closure *on_complete);
+
+static const grpc_resolver_vtable dns_resolver_vtable = {
+    dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
+
+static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
+  dns_resolver *r = (dns_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  if (r->have_retry_timer) {
+    grpc_timer_cancel(exec_ctx, &r->retry_timer);
+  }
+  if (r->next_completion != NULL) {
+    *r->target_config = NULL;
+    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    r->next_completion = NULL;
+  }
+  gpr_mu_unlock(&r->mu);
+}
+
+static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
+                                  grpc_resolver *resolver) {
+  dns_resolver *r = (dns_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  if (!r->resolving) {
+    gpr_backoff_reset(&r->backoff_state);
+    dns_start_resolving_locked(exec_ctx, r);
+  }
+  gpr_mu_unlock(&r->mu);
+}
+
+static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                     grpc_client_config **target_config,
+                     grpc_closure *on_complete) {
+  dns_resolver *r = (dns_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  GPR_ASSERT(!r->next_completion);
+  r->next_completion = on_complete;
+  r->target_config = target_config;
+  if (r->resolved_version == 0 && !r->resolving) {
+    gpr_backoff_reset(&r->backoff_state);
+    dns_start_resolving_locked(exec_ctx, r);
+  } else {
+    dns_maybe_finish_next_locked(exec_ctx, r);
+  }
+  gpr_mu_unlock(&r->mu);
+}
+
+static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
+                               bool success) {
+  dns_resolver *r = arg;
+
+  gpr_mu_lock(&r->mu);
+  r->have_retry_timer = false;
+  if (success) {
+    if (!r->resolving) {
+      dns_start_resolving_locked(exec_ctx, r);
+    }
+  }
+  gpr_mu_unlock(&r->mu);
+
+  GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
+}
+
+static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
+                            grpc_resolved_addresses *addresses) {
+  dns_resolver *r = arg;
+  grpc_client_config *config = NULL;
+  grpc_lb_policy *lb_policy;
+  gpr_mu_lock(&r->mu);
+  GPR_ASSERT(r->resolving);
+  r->resolving = 0;
+  if (addresses != NULL) {
+    grpc_lb_policy_args lb_policy_args;
+    config = grpc_client_config_create();
+    memset(&lb_policy_args, 0, sizeof(lb_policy_args));
+    lb_policy_args.addresses = addresses;
+    lb_policy_args.client_channel_factory = r->client_channel_factory;
+    lb_policy =
+        grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
+    if (lb_policy != NULL) {
+      grpc_client_config_set_lb_policy(config, lb_policy);
+      GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
+    }
+    grpc_resolved_addresses_destroy(addresses);
+  } else {
+    gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+    gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
+    gpr_timespec timeout = gpr_time_sub(next_try, now);
+    gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d.%09d seconds",
+            timeout.tv_sec, timeout.tv_nsec);
+    GPR_ASSERT(!r->have_retry_timer);
+    r->have_retry_timer = true;
+    GRPC_RESOLVER_REF(&r->base, "retry-timer");
+    grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
+                    now);
+  }
+  if (r->resolved_config) {
+    grpc_client_config_unref(exec_ctx, r->resolved_config);
+  }
+  r->resolved_config = config;
+  r->resolved_version++;
+  dns_maybe_finish_next_locked(exec_ctx, r);
+  gpr_mu_unlock(&r->mu);
+
+  GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
+}
+
+static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
+                                       dns_resolver *r) {
+  GRPC_RESOLVER_REF(&r->base, "dns-resolving");
+  GPR_ASSERT(!r->resolving);
+  r->resolving = 1;
+  grpc_resolve_address(exec_ctx, r->name, r->default_port, dns_on_resolved, r);
+}
+
+static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
+                                         dns_resolver *r) {
+  if (r->next_completion != NULL &&
+      r->resolved_version != r->published_version) {
+    *r->target_config = r->resolved_config;
+    if (r->resolved_config) {
+      grpc_client_config_ref(r->resolved_config);
+    }
+    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    r->next_completion = NULL;
+    r->published_version = r->resolved_version;
+  }
+}
+
+static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
+  dns_resolver *r = (dns_resolver *)gr;
+  gpr_mu_destroy(&r->mu);
+  if (r->resolved_config) {
+    grpc_client_config_unref(exec_ctx, r->resolved_config);
+  }
+  grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
+  gpr_free(r->name);
+  gpr_free(r->default_port);
+  gpr_free(r->lb_policy_name);
+  gpr_free(r);
+}
+
+static grpc_resolver *dns_create(grpc_resolver_args *args,
+                                 const char *default_port,
+                                 const char *lb_policy_name) {
+  dns_resolver *r;
+  const char *path = args->uri->path;
+
+  if (0 != strcmp(args->uri->authority, "")) {
+    gpr_log(GPR_ERROR, "authority based dns uri's not supported");
+    return NULL;
+  }
+
+  if (path[0] == '/') ++path;
+
+  r = gpr_malloc(sizeof(dns_resolver));
+  memset(r, 0, sizeof(*r));
+  gpr_ref_init(&r->refs, 1);
+  gpr_mu_init(&r->mu);
+  grpc_resolver_init(&r->base, &dns_resolver_vtable);
+  r->name = gpr_strdup(path);
+  r->default_port = gpr_strdup(default_port);
+  r->client_channel_factory = args->client_channel_factory;
+  gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
+                   BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
+  grpc_client_channel_factory_ref(r->client_channel_factory);
+  r->lb_policy_name = gpr_strdup(lb_policy_name);
+  return &r->base;
+}
+
+/*
+ * FACTORY
+ */
+
+static void dns_factory_ref(grpc_resolver_factory *factory) {}
+
+static void dns_factory_unref(grpc_resolver_factory *factory) {}
+
+static grpc_resolver *dns_factory_create_resolver(
+    grpc_resolver_factory *factory, grpc_resolver_args *args) {
+  return dns_create(args, "https", "pick_first");
+}
+
+static char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
+                                               grpc_uri *uri) {
+  const char *path = uri->path;
+  if (path[0] == '/') ++path;
+  return gpr_strdup(path);
+}
+
+static const grpc_resolver_factory_vtable dns_factory_vtable = {
+    dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
+    dns_factory_get_default_host_name, "dns"};
+static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
+
+static grpc_resolver_factory *dns_resolver_factory_create() {
+  return &dns_resolver_factory;
+}
+
+void grpc_resolver_dns_native_init(void) {
+  grpc_register_resolver_type(dns_resolver_factory_create());
+}
+
+void grpc_resolver_dns_native_shutdown(void) {}
diff --git a/src/core/ext/resolver/sockaddr/README.md b/src/core/ext/resolver/sockaddr/README.md
new file mode 100644
index 0000000..e307ba8
--- /dev/null
+++ b/src/core/ext/resolver/sockaddr/README.md
@@ -0,0 +1 @@
+Support for resolving ipv4:, ipv6:, unix: schemes
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
new file mode 100644
index 0000000..a4fa9ac
--- /dev/null
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -0,0 +1,288 @@
+/*
+ *
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/ext/client_config/parse_address.h"
+#include "src/core/ext/client_config/resolver_registry.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/support/string.h"
+
+typedef struct {
+  /** base class: must be first */
+  grpc_resolver base;
+  /** refcount */
+  gpr_refcount refs;
+  /** subchannel factory */
+  grpc_client_channel_factory *client_channel_factory;
+  /** load balancing policy name */
+  char *lb_policy_name;
+
+  /** the addresses that we've 'resolved' */
+  grpc_resolved_addresses *addresses;
+
+  /** mutex guarding the rest of the state */
+  gpr_mu mu;
+  /** have we published? */
+  int published;
+  /** pending next completion, or NULL */
+  grpc_closure *next_completion;
+  /** target config address for next completion */
+  grpc_client_config **target_config;
+} sockaddr_resolver;
+
+static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+
+static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
+                                              sockaddr_resolver *r);
+
+static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
+                                       grpc_resolver *r);
+static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+                          grpc_client_config **target_config,
+                          grpc_closure *on_complete);
+
+static const grpc_resolver_vtable sockaddr_resolver_vtable = {
+    sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
+    sockaddr_next};
+
+static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
+                              grpc_resolver *resolver) {
+  sockaddr_resolver *r = (sockaddr_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  if (r->next_completion != NULL) {
+    *r->target_config = NULL;
+    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    r->next_completion = NULL;
+  }
+  gpr_mu_unlock(&r->mu);
+}
+
+static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
+                                       grpc_resolver *resolver) {
+  sockaddr_resolver *r = (sockaddr_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  r->published = 0;
+  sockaddr_maybe_finish_next_locked(exec_ctx, r);
+  gpr_mu_unlock(&r->mu);
+}
+
+static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                          grpc_client_config **target_config,
+                          grpc_closure *on_complete) {
+  sockaddr_resolver *r = (sockaddr_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  GPR_ASSERT(!r->next_completion);
+  r->next_completion = on_complete;
+  r->target_config = target_config;
+  sockaddr_maybe_finish_next_locked(exec_ctx, r);
+  gpr_mu_unlock(&r->mu);
+}
+
+static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
+                                              sockaddr_resolver *r) {
+  if (r->next_completion != NULL && !r->published) {
+    grpc_client_config *cfg = grpc_client_config_create();
+    grpc_lb_policy_args lb_policy_args;
+    memset(&lb_policy_args, 0, sizeof(lb_policy_args));
+    lb_policy_args.addresses = r->addresses;
+    lb_policy_args.client_channel_factory = r->client_channel_factory;
+    grpc_lb_policy *lb_policy =
+        grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
+    grpc_client_config_set_lb_policy(cfg, lb_policy);
+    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
+    r->published = 1;
+    *r->target_config = cfg;
+    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    r->next_completion = NULL;
+  }
+}
+
+static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
+  sockaddr_resolver *r = (sockaddr_resolver *)gr;
+  gpr_mu_destroy(&r->mu);
+  grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
+  grpc_resolved_addresses_destroy(r->addresses);
+  gpr_free(r->lb_policy_name);
+  gpr_free(r);
+}
+
+static char *ip_get_default_authority(grpc_uri *uri) {
+  const char *path = uri->path;
+  if (path[0] == '/') ++path;
+  return gpr_strdup(path);
+}
+
+static char *ipv4_get_default_authority(grpc_resolver_factory *factory,
+                                        grpc_uri *uri) {
+  return ip_get_default_authority(uri);
+}
+
+static char *ipv6_get_default_authority(grpc_resolver_factory *factory,
+                                        grpc_uri *uri) {
+  return ip_get_default_authority(uri);
+}
+
+#ifdef GPR_HAVE_UNIX_SOCKET
+char *unix_get_default_authority(grpc_resolver_factory *factory,
+                                 grpc_uri *uri) {
+  return gpr_strdup("localhost");
+}
+#endif
+
+static void do_nothing(void *ignored) {}
+
+static grpc_resolver *sockaddr_create(
+    grpc_resolver_args *args, const char *default_lb_policy_name,
+    int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) {
+  int errors_found = 0; /* GPR_FALSE */
+  sockaddr_resolver *r;
+  gpr_slice path_slice;
+  gpr_slice_buffer path_parts;
+
+  if (0 != strcmp(args->uri->authority, "")) {
+    gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme",
+            args->uri->scheme);
+    return NULL;
+  }
+
+  r = gpr_malloc(sizeof(sockaddr_resolver));
+  memset(r, 0, sizeof(*r));
+
+  r->lb_policy_name =
+      gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy"));
+  const char *lb_enabled_qpart =
+      grpc_uri_get_query_arg(args->uri, "lb_enabled");
+  /* anything other than "0" is interpreted as true */
+  const bool lb_enabled =
+      (lb_enabled_qpart != NULL && (strcmp("0", lb_enabled_qpart) != 0));
+
+  if (r->lb_policy_name != NULL && strcmp("grpclb", r->lb_policy_name) == 0 &&
+      !lb_enabled) {
+    /* we want grpclb but the "resolved" addresses aren't LB enabled. Bail
+     * out, as this is meant mostly for tests. */
+    gpr_log(GPR_ERROR,
+            "Requested 'grpclb' LB policy but resolved addresses don't "
+            "support load balancing.");
+    abort();
+  }
+
+  if (r->lb_policy_name == NULL) {
+    r->lb_policy_name = gpr_strdup(default_lb_policy_name);
+  }
+
+  path_slice =
+      gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing);
+  gpr_slice_buffer_init(&path_parts);
+
+  gpr_slice_split(path_slice, ",", &path_parts);
+  r->addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
+  r->addresses->naddrs = path_parts.count;
+  r->addresses->addrs =
+      gpr_malloc(sizeof(grpc_resolved_address) * r->addresses->naddrs);
+
+  for (size_t i = 0; i < r->addresses->naddrs; i++) {
+    grpc_uri ith_uri = *args->uri;
+    char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
+    ith_uri.path = part_str;
+    if (!parse(&ith_uri,
+               (struct sockaddr_storage *)(&r->addresses->addrs[i].addr),
+               &r->addresses->addrs[i].len)) {
+      errors_found = 1; /* GPR_TRUE */
+    }
+    gpr_free(part_str);
+    if (errors_found) break;
+  }
+
+  gpr_slice_buffer_destroy(&path_parts);
+  gpr_slice_unref(path_slice);
+  if (errors_found) {
+    gpr_free(r->lb_policy_name);
+    grpc_resolved_addresses_destroy(r->addresses);
+    gpr_free(r);
+    return NULL;
+  }
+
+  gpr_ref_init(&r->refs, 1);
+  gpr_mu_init(&r->mu);
+  grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
+  r->client_channel_factory = args->client_channel_factory;
+  grpc_client_channel_factory_ref(r->client_channel_factory);
+
+  return &r->base;
+}
+
+/*
+ * FACTORY
+ */
+
+static void sockaddr_factory_ref(grpc_resolver_factory *factory) {}
+
+static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
+
+#define DECL_FACTORY(name)                                                  \
+  static grpc_resolver *name##_factory_create_resolver(                     \
+      grpc_resolver_factory *factory, grpc_resolver_args *args) {           \
+    return sockaddr_create(args, "pick_first", parse_##name);               \
+  }                                                                         \
+  static const grpc_resolver_factory_vtable name##_factory_vtable = {       \
+      sockaddr_factory_ref, sockaddr_factory_unref,                         \
+      name##_factory_create_resolver, name##_get_default_authority, #name}; \
+  static grpc_resolver_factory name##_resolver_factory = {                  \
+      &name##_factory_vtable}
+
+#ifdef GPR_HAVE_UNIX_SOCKET
+DECL_FACTORY(unix);
+#endif
+DECL_FACTORY(ipv4);
+DECL_FACTORY(ipv6);
+
+void grpc_resolver_sockaddr_init(void) {
+  grpc_register_resolver_type(&ipv4_resolver_factory);
+  grpc_register_resolver_type(&ipv6_resolver_factory);
+#ifdef GPR_HAVE_UNIX_SOCKET
+  grpc_register_resolver_type(&unix_resolver_factory);
+#endif
+}
+
+void grpc_resolver_sockaddr_shutdown(void) {}
diff --git a/src/core/ext/resolver/zookeeper/README.md b/src/core/ext/resolver/zookeeper/README.md
new file mode 100644
index 0000000..ce6f396
--- /dev/null
+++ b/src/core/ext/resolver/zookeeper/README.md
@@ -0,0 +1 @@
+Zookeeper based name resolver: WIP
diff --git a/src/core/ext/resolver/zookeeper/zookeeper_resolver.c b/src/core/ext/resolver/zookeeper/zookeeper_resolver.c
new file mode 100644
index 0000000..deb4b9b
--- /dev/null
+++ b/src/core/ext/resolver/zookeeper/zookeeper_resolver.c
@@ -0,0 +1,513 @@
+/*
+ *
+ * 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 <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+#include <grpc/grpc_zookeeper.h>
+#include <zookeeper/zookeeper.h>
+
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/ext/client_config/resolver_registry.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+
+/** Zookeeper session expiration time in milliseconds */
+#define GRPC_ZOOKEEPER_SESSION_TIMEOUT 15000
+
+typedef struct {
+  /** base class: must be first */
+  grpc_resolver base;
+  /** refcount */
+  gpr_refcount refs;
+  /** name to resolve */
+  char *name;
+  /** subchannel factory */
+  grpc_client_channel_factory *client_channel_factory;
+  /** load balancing policy name */
+  char *lb_policy_name;
+
+  /** mutex guarding the rest of the state */
+  gpr_mu mu;
+  /** are we currently resolving? */
+  int resolving;
+  /** which version of resolved_config have we published? */
+  int published_version;
+  /** which version of resolved_config is current? */
+  int resolved_version;
+  /** pending next completion, or NULL */
+  grpc_closure *next_completion;
+  /** target config address for next completion */
+  grpc_client_config **target_config;
+  /** current (fully resolved) config */
+  grpc_client_config *resolved_config;
+
+  /** zookeeper handle */
+  zhandle_t *zookeeper_handle;
+  /** zookeeper resolved addresses */
+  grpc_resolved_addresses *resolved_addrs;
+  /** total number of addresses to be resolved */
+  int resolved_total;
+  /** number of addresses resolved */
+  int resolved_num;
+} zookeeper_resolver;
+
+static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+
+static void zookeeper_start_resolving_locked(zookeeper_resolver *r);
+static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
+                                               zookeeper_resolver *r);
+
+static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
+                                        grpc_resolver *r);
+static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+                           grpc_client_config **target_config,
+                           grpc_closure *on_complete);
+
+static const grpc_resolver_vtable zookeeper_resolver_vtable = {
+    zookeeper_destroy, zookeeper_shutdown, zookeeper_channel_saw_error,
+    zookeeper_next};
+
+static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx,
+                               grpc_resolver *resolver) {
+  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
+  grpc_closure *call = NULL;
+  gpr_mu_lock(&r->mu);
+  if (r->next_completion != NULL) {
+    *r->target_config = NULL;
+    call = r->next_completion;
+    r->next_completion = NULL;
+  }
+  zookeeper_close(r->zookeeper_handle);
+  gpr_mu_unlock(&r->mu);
+  if (call != NULL) {
+    call->cb(exec_ctx, call->cb_arg, 1);
+  }
+}
+
+static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
+                                        grpc_resolver *resolver) {
+  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  if (r->resolving == 0) {
+    zookeeper_start_resolving_locked(r);
+  }
+  gpr_mu_unlock(&r->mu);
+}
+
+static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                           grpc_client_config **target_config,
+                           grpc_closure *on_complete) {
+  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
+  gpr_mu_lock(&r->mu);
+  GPR_ASSERT(r->next_completion == NULL);
+  r->next_completion = on_complete;
+  r->target_config = target_config;
+  if (r->resolved_version == 0 && r->resolving == 0) {
+    zookeeper_start_resolving_locked(r);
+  } else {
+    zookeeper_maybe_finish_next_locked(exec_ctx, r);
+  }
+  gpr_mu_unlock(&r->mu);
+}
+
+/** Zookeeper global watcher for connection management
+    TODO: better connection management besides logs */
+static void zookeeper_global_watcher(zhandle_t *zookeeper_handle, int type,
+                                     int state, const char *path,
+                                     void *watcher_ctx) {
+  if (type == ZOO_SESSION_EVENT) {
+    if (state == ZOO_EXPIRED_SESSION_STATE) {
+      gpr_log(GPR_ERROR, "Zookeeper session expired");
+    } else if (state == ZOO_AUTH_FAILED_STATE) {
+      gpr_log(GPR_ERROR, "Zookeeper authentication failed");
+    }
+  }
+}
+
+/** Zookeeper watcher triggered by changes to watched nodes
+    Once triggered, it tries to resolve again to get updated addresses */
+static void zookeeper_watcher(zhandle_t *zookeeper_handle, int type, int state,
+                              const char *path, void *watcher_ctx) {
+  if (watcher_ctx != NULL) {
+    zookeeper_resolver *r = (zookeeper_resolver *)watcher_ctx;
+    if (state == ZOO_CONNECTED_STATE) {
+      gpr_mu_lock(&r->mu);
+      if (r->resolving == 0) {
+        zookeeper_start_resolving_locked(r);
+      }
+      gpr_mu_unlock(&r->mu);
+    }
+  }
+}
+
+/** Callback function after getting all resolved addresses
+    Creates a subchannel for each address */
+static void zookeeper_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
+                                  grpc_resolved_addresses *addresses) {
+  zookeeper_resolver *r = arg;
+  grpc_client_config *config = NULL;
+  grpc_lb_policy *lb_policy;
+
+  if (addresses != NULL) {
+    grpc_lb_policy_args lb_policy_args;
+    config = grpc_client_config_create();
+    lb_policy_args.addresses = addresses;
+    lb_policy_args.client_channel_factory = r->client_channel_factory;
+    lb_policy =
+        grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
+
+    if (lb_policy != NULL) {
+      grpc_client_config_set_lb_policy(config, lb_policy);
+      GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
+    }
+    grpc_resolved_addresses_destroy(addresses);
+  }
+  gpr_mu_lock(&r->mu);
+  GPR_ASSERT(r->resolving == 1);
+  r->resolving = 0;
+  if (r->resolved_config != NULL) {
+    grpc_client_config_unref(exec_ctx, r->resolved_config);
+  }
+  r->resolved_config = config;
+  r->resolved_version++;
+  zookeeper_maybe_finish_next_locked(exec_ctx, r);
+  gpr_mu_unlock(&r->mu);
+
+  GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "zookeeper-resolving");
+}
+
+/** Callback function for each DNS resolved address */
+static void zookeeper_dns_resolved(grpc_exec_ctx *exec_ctx, void *arg,
+                                   grpc_resolved_addresses *addresses) {
+  size_t i;
+  zookeeper_resolver *r = arg;
+  int resolve_done = 0;
+
+  gpr_mu_lock(&r->mu);
+  r->resolved_num++;
+  r->resolved_addrs->addrs =
+      gpr_realloc(r->resolved_addrs->addrs,
+                  sizeof(grpc_resolved_address) *
+                      (r->resolved_addrs->naddrs + addresses->naddrs));
+  for (i = 0; i < addresses->naddrs; i++) {
+    memcpy(r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].addr,
+           addresses->addrs[i].addr, addresses->addrs[i].len);
+    r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].len =
+        addresses->addrs[i].len;
+  }
+
+  r->resolved_addrs->naddrs += addresses->naddrs;
+  grpc_resolved_addresses_destroy(addresses);
+
+  /** Wait for all addresses to be resolved */
+  resolve_done = (r->resolved_num == r->resolved_total);
+  gpr_mu_unlock(&r->mu);
+  if (resolve_done) {
+    zookeeper_on_resolved(exec_ctx, r, r->resolved_addrs);
+  }
+}
+
+/** Parses JSON format address of a zookeeper node */
+static char *zookeeper_parse_address(const char *value, size_t value_len) {
+  grpc_json *json;
+  grpc_json *cur;
+  const char *host;
+  const char *port;
+  char *buffer;
+  char *address = NULL;
+
+  buffer = gpr_malloc(value_len);
+  memcpy(buffer, value, value_len);
+  json = grpc_json_parse_string_with_len(buffer, value_len);
+  if (json != NULL) {
+    host = NULL;
+    port = NULL;
+    for (cur = json->child; cur != NULL; cur = cur->next) {
+      if (!strcmp(cur->key, "host")) {
+        host = cur->value;
+        if (port != NULL) {
+          break;
+        }
+      } else if (!strcmp(cur->key, "port")) {
+        port = cur->value;
+        if (host != NULL) {
+          break;
+        }
+      }
+    }
+    if (host != NULL && port != NULL) {
+      gpr_asprintf(&address, "%s:%s", host, port);
+    }
+    grpc_json_destroy(json);
+  }
+  gpr_free(buffer);
+
+  return address;
+}
+
+static void zookeeper_get_children_node_completion(int rc, const char *value,
+                                                   int value_len,
+                                                   const struct Stat *stat,
+                                                   const void *arg) {
+  char *address = NULL;
+  zookeeper_resolver *r = (zookeeper_resolver *)arg;
+  int resolve_done = 0;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  if (rc != 0) {
+    gpr_log(GPR_ERROR, "Error in getting a child node of %s", r->name);
+    grpc_exec_ctx_finish(&exec_ctx);
+    return;
+  }
+
+  address = zookeeper_parse_address(value, (size_t)value_len);
+  if (address != NULL) {
+    /** Further resolves address by DNS */
+    grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
+    gpr_free(address);
+  } else {
+    gpr_log(GPR_ERROR, "Error in resolving a child node of %s", r->name);
+    gpr_mu_lock(&r->mu);
+    r->resolved_total--;
+    resolve_done = (r->resolved_num == r->resolved_total);
+    gpr_mu_unlock(&r->mu);
+    if (resolve_done) {
+      zookeeper_on_resolved(&exec_ctx, r, r->resolved_addrs);
+    }
+  }
+
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void zookeeper_get_children_completion(
+    int rc, const struct String_vector *children, const void *arg) {
+  char *path;
+  int status;
+  int i;
+  zookeeper_resolver *r = (zookeeper_resolver *)arg;
+
+  if (rc != 0) {
+    gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
+    return;
+  }
+
+  if (children->count == 0) {
+    gpr_log(GPR_ERROR, "Error in resolving zookeeper address %s", r->name);
+    return;
+  }
+
+  r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
+  r->resolved_addrs->addrs = NULL;
+  r->resolved_addrs->naddrs = 0;
+  r->resolved_total = children->count;
+
+  /** TODO: Replace expensive heap allocation with stack
+      if we can get maximum length of zookeeper path */
+  for (i = 0; i < children->count; i++) {
+    gpr_asprintf(&path, "%s/%s", r->name, children->data[i]);
+    status = zoo_awget(r->zookeeper_handle, path, zookeeper_watcher, r,
+                       zookeeper_get_children_node_completion, r);
+    gpr_free(path);
+    if (status != 0) {
+      gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", path);
+    }
+  }
+}
+
+static void zookeeper_get_node_completion(int rc, const char *value,
+                                          int value_len,
+                                          const struct Stat *stat,
+                                          const void *arg) {
+  int status;
+  char *address = NULL;
+  zookeeper_resolver *r = (zookeeper_resolver *)arg;
+  r->resolved_addrs = NULL;
+  r->resolved_total = 0;
+  r->resolved_num = 0;
+
+  if (rc != 0) {
+    gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
+    return;
+  }
+
+  /** If zookeeper node of path r->name does not have address
+      (i.e. service node), get its children */
+  address = zookeeper_parse_address(value, (size_t)value_len);
+  if (address != NULL) {
+    r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
+    r->resolved_addrs->addrs = NULL;
+    r->resolved_addrs->naddrs = 0;
+    r->resolved_total = 1;
+    /** Further resolves address by DNS */
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
+    gpr_free(address);
+    grpc_exec_ctx_finish(&exec_ctx);
+    return;
+  }
+
+  status = zoo_awget_children(r->zookeeper_handle, r->name, zookeeper_watcher,
+                              r, zookeeper_get_children_completion, r);
+  if (status != 0) {
+    gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
+  }
+}
+
+static void zookeeper_resolve_address(zookeeper_resolver *r) {
+  int status;
+  status = zoo_awget(r->zookeeper_handle, r->name, zookeeper_watcher, r,
+                     zookeeper_get_node_completion, r);
+  if (status != 0) {
+    gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
+  }
+}
+
+static void zookeeper_start_resolving_locked(zookeeper_resolver *r) {
+  GRPC_RESOLVER_REF(&r->base, "zookeeper-resolving");
+  GPR_ASSERT(r->resolving == 0);
+  r->resolving = 1;
+  zookeeper_resolve_address(r);
+}
+
+static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
+                                               zookeeper_resolver *r) {
+  if (r->next_completion != NULL &&
+      r->resolved_version != r->published_version) {
+    *r->target_config = r->resolved_config;
+    if (r->resolved_config != NULL) {
+      grpc_client_config_ref(r->resolved_config);
+    }
+    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    r->next_completion = NULL;
+    r->published_version = r->resolved_version;
+  }
+}
+
+static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
+  zookeeper_resolver *r = (zookeeper_resolver *)gr;
+  gpr_mu_destroy(&r->mu);
+  if (r->resolved_config != NULL) {
+    grpc_client_config_unref(exec_ctx, r->resolved_config);
+  }
+  grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
+  gpr_free(r->name);
+  gpr_free(r->lb_policy_name);
+  gpr_free(r);
+}
+
+static grpc_resolver *zookeeper_create(grpc_resolver_args *args,
+                                       const char *lb_policy_name) {
+  zookeeper_resolver *r;
+  size_t length;
+  char *path = args->uri->path;
+
+  if (0 == strcmp(args->uri->authority, "")) {
+    gpr_log(GPR_ERROR, "No authority specified in zookeeper uri");
+    return NULL;
+  }
+
+  /** Removes the trailing slash if exists */
+  length = strlen(path);
+  if (length > 1 && path[length - 1] == '/') {
+    path[length - 1] = 0;
+  }
+
+  r = gpr_malloc(sizeof(zookeeper_resolver));
+  memset(r, 0, sizeof(*r));
+  gpr_ref_init(&r->refs, 1);
+  gpr_mu_init(&r->mu);
+  grpc_resolver_init(&r->base, &zookeeper_resolver_vtable);
+  r->name = gpr_strdup(path);
+
+  r->client_channel_factory = args->client_channel_factory;
+  grpc_client_channel_factory_ref(r->client_channel_factory);
+
+  r->lb_policy_name = gpr_strdup(lb_policy_name);
+
+  /** Initializes zookeeper client */
+  zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
+  r->zookeeper_handle =
+      zookeeper_init(args->uri->authority, zookeeper_global_watcher,
+                     GRPC_ZOOKEEPER_SESSION_TIMEOUT, 0, 0, 0);
+  if (r->zookeeper_handle == NULL) {
+    gpr_log(GPR_ERROR, "Unable to connect to zookeeper server");
+    return NULL;
+  }
+
+  return &r->base;
+}
+
+/*
+ * FACTORY
+ */
+
+static void zookeeper_factory_ref(grpc_resolver_factory *factory) {}
+
+static void zookeeper_factory_unref(grpc_resolver_factory *factory) {}
+
+static char *zookeeper_factory_get_default_hostname(
+    grpc_resolver_factory *factory, grpc_uri *uri) {
+  return NULL;
+}
+
+static grpc_resolver *zookeeper_factory_create_resolver(
+    grpc_resolver_factory *factory, grpc_resolver_args *args) {
+  return zookeeper_create(args, "pick_first");
+}
+
+static const grpc_resolver_factory_vtable zookeeper_factory_vtable = {
+    zookeeper_factory_ref, zookeeper_factory_unref,
+    zookeeper_factory_create_resolver, zookeeper_factory_get_default_hostname,
+    "zookeeper"};
+
+static grpc_resolver_factory zookeeper_resolver_factory = {
+    &zookeeper_factory_vtable};
+
+static grpc_resolver_factory *zookeeper_resolver_factory_create() {
+  return &zookeeper_resolver_factory;
+}
+
+static void zookeeper_plugin_init() {
+  grpc_register_resolver_type(zookeeper_resolver_factory_create());
+}
+
+void grpc_zookeeper_register() {
+  GRPC_API_TRACE("grpc_zookeeper_register(void)", 0, ());
+  grpc_register_plugin(zookeeper_plugin_init, NULL);
+}
diff --git a/src/core/ext/transport/chttp2/alpn/alpn.c b/src/core/ext/transport/chttp2/alpn/alpn.c
new file mode 100644
index 0000000..48b0217
--- /dev/null
+++ b/src/core/ext/transport/chttp2/alpn/alpn.c
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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/ext/transport/chttp2/alpn/alpn.h"
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+/* in order of preference */
+static const char *const supported_versions[] = {"h2"};
+
+int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size) {
+  size_t i;
+  for (i = 0; i < GPR_ARRAY_SIZE(supported_versions); i++) {
+    if (!strncmp(version, supported_versions[i], size)) return 1;
+  }
+  return 0;
+}
+
+size_t grpc_chttp2_num_alpn_versions(void) {
+  return GPR_ARRAY_SIZE(supported_versions);
+}
+
+const char *grpc_chttp2_get_alpn_version_index(size_t i) {
+  GPR_ASSERT(i < GPR_ARRAY_SIZE(supported_versions));
+  return supported_versions[i];
+}
diff --git a/src/core/ext/transport/chttp2/alpn/alpn.h b/src/core/ext/transport/chttp2/alpn/alpn.h
new file mode 100644
index 0000000..1316770
--- /dev/null
+++ b/src/core/ext/transport/chttp2/alpn/alpn.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_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H
+
+#include <string.h>
+
+/* Retuns 1 if the version is supported, 0 otherwise. */
+int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size);
+
+/* Returns the number of protocol versions to advertise */
+size_t grpc_chttp2_num_alpn_versions(void);
+
+/* Returns the protocol version at index i (0 <= i <
+ * grpc_chttp2_num_alpn_versions()) */
+const char *grpc_chttp2_get_alpn_version_index(size_t i);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H */
diff --git a/src/core/ext/transport/chttp2/client/insecure/README.md b/src/core/ext/transport/chttp2/client/insecure/README.md
new file mode 100644
index 0000000..fa11463
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/insecure/README.md
@@ -0,0 +1 @@
+Plugin for creating insecure channels using chttp2
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
new file mode 100644
index 0000000..c5d3d8d
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -0,0 +1,241 @@
+/*
+ *
+ * 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/grpc.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/client_config/resolver_registry.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/iomgr/tcp_client.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/channel.h"
+
+typedef struct {
+  grpc_connector base;
+  gpr_refcount refs;
+
+  grpc_closure *notify;
+  grpc_connect_in_args args;
+  grpc_connect_out_args *result;
+  grpc_closure initial_string_sent;
+  gpr_slice_buffer initial_string_buffer;
+
+  grpc_endpoint *tcp;
+
+  grpc_closure connected;
+} connector;
+
+static void connector_ref(grpc_connector *con) {
+  connector *c = (connector *)con;
+  gpr_ref(&c->refs);
+}
+
+static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
+  connector *c = (connector *)con;
+  if (gpr_unref(&c->refs)) {
+    /* c->initial_string_buffer does not need to be destroyed */
+    gpr_free(c);
+  }
+}
+
+static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
+                                           bool success) {
+  connector_unref(exec_ctx, arg);
+}
+
+static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  connector *c = arg;
+  grpc_closure *notify;
+  grpc_endpoint *tcp = c->tcp;
+  if (tcp != NULL) {
+    if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
+      grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
+                        c);
+      gpr_slice_buffer_init(&c->initial_string_buffer);
+      gpr_slice_buffer_add(&c->initial_string_buffer,
+                           c->args.initial_connect_string);
+      connector_ref(arg);
+      grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
+                          &c->initial_string_sent);
+    }
+    c->result->transport =
+        grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1);
+    grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
+                                        0);
+    GPR_ASSERT(c->result->transport);
+    c->result->channel_args = c->args.channel_args;
+  } else {
+    memset(c->result, 0, sizeof(*c->result));
+  }
+  notify = c->notify;
+  c->notify = NULL;
+  notify->cb(exec_ctx, notify->cb_arg, 1);
+}
+
+static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}
+
+static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
+                              const grpc_connect_in_args *args,
+                              grpc_connect_out_args *result,
+                              grpc_closure *notify) {
+  connector *c = (connector *)con;
+  GPR_ASSERT(c->notify == NULL);
+  GPR_ASSERT(notify->cb);
+  c->notify = notify;
+  c->args = *args;
+  c->result = result;
+  c->tcp = NULL;
+  grpc_closure_init(&c->connected, connected, c);
+  grpc_tcp_client_connect(exec_ctx, &c->connected, &c->tcp,
+                          args->interested_parties, args->addr, args->addr_len,
+                          args->deadline);
+}
+
+static const grpc_connector_vtable connector_vtable = {
+    connector_ref, connector_unref, connector_shutdown, connector_connect};
+
+typedef struct {
+  grpc_client_channel_factory base;
+  gpr_refcount refs;
+  grpc_channel_args *merge_args;
+  grpc_channel *master;
+} client_channel_factory;
+
+static void client_channel_factory_ref(
+    grpc_client_channel_factory *cc_factory) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+  gpr_ref(&f->refs);
+}
+
+static void client_channel_factory_unref(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+  if (gpr_unref(&f->refs)) {
+    if (f->master != NULL) {
+      GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master,
+                                  "client_channel_factory");
+    }
+    grpc_channel_args_destroy(f->merge_args);
+    gpr_free(f);
+  }
+}
+
+static grpc_subchannel *client_channel_factory_create_subchannel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
+    grpc_subchannel_args *args) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+  connector *c = gpr_malloc(sizeof(*c));
+  grpc_channel_args *final_args =
+      grpc_channel_args_merge(args->args, f->merge_args);
+  grpc_subchannel *s;
+  memset(c, 0, sizeof(*c));
+  c->base.vtable = &connector_vtable;
+  gpr_ref_init(&c->refs, 1);
+  args->args = final_args;
+  s = grpc_subchannel_create(exec_ctx, &c->base, args);
+  grpc_connector_unref(exec_ctx, &c->base);
+  grpc_channel_args_destroy(final_args);
+  return s;
+}
+
+static grpc_channel *client_channel_factory_create_channel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
+    const char *target, grpc_client_channel_type type,
+    grpc_channel_args *args) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+  grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
+  grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
+                                              GRPC_CLIENT_CHANNEL, NULL);
+  grpc_channel_args_destroy(final_args);
+  grpc_resolver *resolver = grpc_resolver_create(target, &f->base);
+  if (!resolver) {
+    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
+                                "client_channel_factory_create_channel");
+    return NULL;
+  }
+
+  grpc_client_channel_set_resolver(
+      exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
+  GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel");
+
+  return channel;
+}
+
+static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
+    {client_channel_factory_ref, client_channel_factory_unref,
+     client_channel_factory_create_subchannel,
+     client_channel_factory_create_channel};
+
+/* Create a client channel:
+   Asynchronously: - resolve target
+                   - connect to it (trying alternatives as presented)
+                   - perform handshakes */
+grpc_channel *grpc_insecure_channel_create(const char *target,
+                                           const grpc_channel_args *args,
+                                           void *reserved) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GRPC_API_TRACE(
+      "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3,
+      (target, args, reserved));
+  GPR_ASSERT(!reserved);
+
+  client_channel_factory *f = gpr_malloc(sizeof(*f));
+  memset(f, 0, sizeof(*f));
+  f->base.vtable = &client_channel_factory_vtable;
+  gpr_ref_init(&f->refs, 1);
+  f->merge_args = grpc_channel_args_copy(args);
+
+  grpc_channel *channel = client_channel_factory_create_channel(
+      &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
+  if (channel != NULL) {
+    f->master = channel;
+    GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_insecure_channel_create");
+  }
+  grpc_client_channel_factory_unref(&exec_ctx, &f->base);
+
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  return channel != NULL ? channel : grpc_lame_client_channel_create(
+                                         target, GRPC_STATUS_INTERNAL,
+                                         "Failed to create client channel");
+}
diff --git a/src/core/ext/transport/chttp2/client/secure/README.md b/src/core/ext/transport/chttp2/client/secure/README.md
new file mode 100644
index 0000000..405a86e
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/secure/README.md
@@ -0,0 +1 @@
+Plugin for creating secure channels using chttp2
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
new file mode 100644
index 0000000..58af6f9
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.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 <grpc/grpc.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/client_config/resolver_registry.h"
+#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/surface/api_trace.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/tsi/transport_security_interface.h"
+
+typedef struct {
+  grpc_connector base;
+  gpr_refcount refs;
+
+  grpc_channel_security_connector *security_connector;
+
+  grpc_closure *notify;
+  grpc_connect_in_args args;
+  grpc_connect_out_args *result;
+  grpc_closure initial_string_sent;
+  gpr_slice_buffer initial_string_buffer;
+
+  gpr_mu mu;
+  grpc_endpoint *connecting_endpoint;
+  grpc_endpoint *newly_connecting_endpoint;
+
+  grpc_closure connected_closure;
+} connector;
+
+static void connector_ref(grpc_connector *con) {
+  connector *c = (connector *)con;
+  gpr_ref(&c->refs);
+}
+
+static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
+  connector *c = (connector *)con;
+  if (gpr_unref(&c->refs)) {
+    /* c->initial_string_buffer does not need to be destroyed */
+    gpr_free(c);
+  }
+}
+
+static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
+                                     grpc_security_status status,
+                                     grpc_endpoint *secure_endpoint,
+                                     grpc_auth_context *auth_context) {
+  connector *c = arg;
+  grpc_closure *notify;
+  grpc_channel_args *args_copy = NULL;
+  gpr_mu_lock(&c->mu);
+  if (c->connecting_endpoint == NULL) {
+    memset(c->result, 0, sizeof(*c->result));
+    gpr_mu_unlock(&c->mu);
+  } else if (status != GRPC_SECURITY_OK) {
+    gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status);
+    memset(c->result, 0, sizeof(*c->result));
+    c->connecting_endpoint = NULL;
+    gpr_mu_unlock(&c->mu);
+  } else {
+    grpc_arg auth_context_arg;
+    c->connecting_endpoint = NULL;
+    gpr_mu_unlock(&c->mu);
+    c->result->transport = grpc_create_chttp2_transport(
+        exec_ctx, c->args.channel_args, secure_endpoint, 1);
+    grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
+                                        0);
+    auth_context_arg = grpc_auth_context_to_arg(auth_context);
+    args_copy = grpc_channel_args_copy_and_add(c->args.channel_args,
+                                               &auth_context_arg, 1);
+    c->result->channel_args = args_copy;
+  }
+  notify = c->notify;
+  c->notify = NULL;
+  /* look at c->args which are connector args. */
+  notify->cb(exec_ctx, notify->cb_arg, 1);
+  if (args_copy != NULL) grpc_channel_args_destroy(args_copy);
+}
+
+static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
+                                           bool success) {
+  connector *c = arg;
+  grpc_channel_security_connector_do_handshake(exec_ctx, c->security_connector,
+                                               c->connecting_endpoint,
+                                               on_secure_handshake_done, c);
+}
+
+static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  connector *c = arg;
+  grpc_closure *notify;
+  grpc_endpoint *tcp = c->newly_connecting_endpoint;
+  if (tcp != NULL) {
+    gpr_mu_lock(&c->mu);
+    GPR_ASSERT(c->connecting_endpoint == NULL);
+    c->connecting_endpoint = tcp;
+    gpr_mu_unlock(&c->mu);
+    if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
+      grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
+                        c);
+      gpr_slice_buffer_init(&c->initial_string_buffer);
+      gpr_slice_buffer_add(&c->initial_string_buffer,
+                           c->args.initial_connect_string);
+      grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
+                          &c->initial_string_sent);
+    } else {
+      grpc_channel_security_connector_do_handshake(
+          exec_ctx, c->security_connector, tcp, on_secure_handshake_done, c);
+    }
+  } else {
+    memset(c->result, 0, sizeof(*c->result));
+    notify = c->notify;
+    c->notify = NULL;
+    notify->cb(exec_ctx, notify->cb_arg, 1);
+  }
+}
+
+static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
+  connector *c = (connector *)con;
+  grpc_endpoint *ep;
+  gpr_mu_lock(&c->mu);
+  ep = c->connecting_endpoint;
+  c->connecting_endpoint = NULL;
+  gpr_mu_unlock(&c->mu);
+  if (ep) {
+    grpc_endpoint_shutdown(exec_ctx, ep);
+  }
+}
+
+static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
+                              const grpc_connect_in_args *args,
+                              grpc_connect_out_args *result,
+                              grpc_closure *notify) {
+  connector *c = (connector *)con;
+  GPR_ASSERT(c->notify == NULL);
+  GPR_ASSERT(notify->cb);
+  c->notify = notify;
+  c->args = *args;
+  c->result = result;
+  gpr_mu_lock(&c->mu);
+  GPR_ASSERT(c->connecting_endpoint == NULL);
+  gpr_mu_unlock(&c->mu);
+  grpc_closure_init(&c->connected_closure, connected, c);
+  grpc_tcp_client_connect(
+      exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint,
+      args->interested_parties, args->addr, args->addr_len, args->deadline);
+}
+
+static const grpc_connector_vtable connector_vtable = {
+    connector_ref, connector_unref, connector_shutdown, connector_connect};
+
+typedef struct {
+  grpc_client_channel_factory base;
+  gpr_refcount refs;
+  grpc_channel_args *merge_args;
+  grpc_channel_security_connector *security_connector;
+  grpc_channel *master;
+} client_channel_factory;
+
+static void client_channel_factory_ref(
+    grpc_client_channel_factory *cc_factory) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+  gpr_ref(&f->refs);
+}
+
+static void client_channel_factory_unref(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+  if (gpr_unref(&f->refs)) {
+    GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
+                                  "client_channel_factory");
+    if (f->master != NULL) {
+      GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master,
+                                  "client_channel_factory");
+    }
+    grpc_channel_args_destroy(f->merge_args);
+    gpr_free(f);
+  }
+}
+
+static grpc_subchannel *client_channel_factory_create_subchannel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
+    grpc_subchannel_args *args) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+  connector *c = gpr_malloc(sizeof(*c));
+  grpc_channel_args *final_args =
+      grpc_channel_args_merge(args->args, f->merge_args);
+  grpc_subchannel *s;
+  memset(c, 0, sizeof(*c));
+  c->base.vtable = &connector_vtable;
+  c->security_connector = f->security_connector;
+  gpr_mu_init(&c->mu);
+  gpr_ref_init(&c->refs, 1);
+  args->args = final_args;
+  s = grpc_subchannel_create(exec_ctx, &c->base, args);
+  grpc_connector_unref(exec_ctx, &c->base);
+  grpc_channel_args_destroy(final_args);
+  return s;
+}
+
+static grpc_channel *client_channel_factory_create_channel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
+    const char *target, grpc_client_channel_type type,
+    grpc_channel_args *args) {
+  client_channel_factory *f = (client_channel_factory *)cc_factory;
+
+  grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
+  grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
+                                              GRPC_CLIENT_CHANNEL, NULL);
+  grpc_channel_args_destroy(final_args);
+
+  grpc_resolver *resolver = grpc_resolver_create(target, &f->base);
+  if (resolver != NULL) {
+    grpc_client_channel_set_resolver(
+        exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
+    GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create");
+  } else {
+    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
+                                "client_channel_factory_create_channel");
+    channel = NULL;
+  }
+
+  GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
+                                "client_channel_factory_create_channel");
+  return channel;
+}
+
+static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
+    {client_channel_factory_ref, client_channel_factory_unref,
+     client_channel_factory_create_subchannel,
+     client_channel_factory_create_channel};
+
+/* Create a secure client channel:
+   Asynchronously: - resolve target
+                   - connect to it (trying alternatives as presented)
+                   - perform handshakes */
+grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
+                                         const char *target,
+                                         const grpc_channel_args *args,
+                                         void *reserved) {
+  grpc_arg connector_arg;
+  grpc_channel_args *args_copy;
+  grpc_channel_args *new_args_from_connector;
+  grpc_channel_security_connector *security_connector;
+  client_channel_factory *f;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_API_TRACE(
+      "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
+      "reserved=%p)",
+      4, (creds, target, args, reserved));
+  GPR_ASSERT(reserved == NULL);
+
+  if (grpc_find_security_connector_in_args(args) != NULL) {
+    gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
+    grpc_exec_ctx_finish(&exec_ctx);
+    return grpc_lame_client_channel_create(
+        target, GRPC_STATUS_INTERNAL,
+        "Security connector exists in channel args.");
+  }
+
+  if (grpc_channel_credentials_create_security_connector(
+          creds, target, args, &security_connector, &new_args_from_connector) !=
+      GRPC_SECURITY_OK) {
+    grpc_exec_ctx_finish(&exec_ctx);
+    return grpc_lame_client_channel_create(
+        target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
+  }
+
+  connector_arg = grpc_security_connector_to_arg(&security_connector->base);
+  args_copy = grpc_channel_args_copy_and_add(
+      new_args_from_connector != NULL ? new_args_from_connector : args,
+      &connector_arg, 1);
+
+  f = gpr_malloc(sizeof(*f));
+  memset(f, 0, sizeof(*f));
+  f->base.vtable = &client_channel_factory_vtable;
+  gpr_ref_init(&f->refs, 1);
+
+  f->merge_args = grpc_channel_args_copy(args_copy);
+  grpc_channel_args_destroy(args_copy);
+  if (new_args_from_connector != NULL) {
+    grpc_channel_args_destroy(new_args_from_connector);
+  }
+
+  GRPC_SECURITY_CONNECTOR_REF(&security_connector->base,
+                              "grpc_secure_channel_create");
+  f->security_connector = security_connector;
+
+  grpc_channel *channel = client_channel_factory_create_channel(
+      &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
+  if (channel != NULL) {
+    f->master = channel;
+    GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_secure_channel_create");
+  }
+
+  grpc_client_channel_factory_unref(&exec_ctx, &f->base);
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  return channel; /* may be NULL */
+}
diff --git a/src/core/ext/transport/chttp2/server/insecure/README.md b/src/core/ext/transport/chttp2/server/insecure/README.md
new file mode 100644
index 0000000..fc0bc14
--- /dev/null
+++ b/src/core/ext/transport/chttp2/server/insecure/README.md
@@ -0,0 +1 @@
+Plugin for creating insecure servers using chttp2
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
new file mode 100644
index 0000000..e21fa2a
--- /dev/null
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
@@ -0,0 +1,146 @@
+/*
+ *
+ * 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/grpc.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/tcp_server.h"
+#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_tcp_server_acceptor *acceptor) {
+  /*
+   * Beware that the call to grpc_create_chttp2_transport() has to happen before
+   * grpc_tcp_server_destroy(). This is fine here, but similar code
+   * asynchronously doing a handshake instead of calling grpc_tcp_server_start()
+   * (as in server_secure_chttp2.c) needs to add synchronization to avoid this
+   * case.
+   */
+  grpc_transport *transport = grpc_create_chttp2_transport(
+      exec_ctx, grpc_server_get_channel_args(server), tcp, 0);
+  setup_transport(exec_ctx, server, transport);
+  grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
+}
+
+/* Server callback: start listening on our ports */
+static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
+                  grpc_pollset **pollsets, size_t pollset_count) {
+  grpc_tcp_server *tcp = tcpp;
+  grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, new_transport,
+                        server);
+}
+
+/* Server callback: destroy the tcp listener (so we don't generate further
+   callbacks) */
+static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
+                    grpc_closure *destroy_done) {
+  grpc_tcp_server *tcp = tcpp;
+  grpc_tcp_server_unref(exec_ctx, tcp);
+  grpc_exec_ctx_enqueue(exec_ctx, destroy_done, true, NULL);
+}
+
+int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
+  grpc_resolved_addresses *resolved = NULL;
+  grpc_tcp_server *tcp = NULL;
+  size_t i;
+  unsigned count = 0;
+  int port_num = -1;
+  int port_temp;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2,
+                 (server, addr));
+
+  resolved = grpc_blocking_resolve_address(addr, "http");
+  if (!resolved) {
+    goto error;
+  }
+
+  tcp = grpc_tcp_server_create(NULL);
+  GPR_ASSERT(tcp);
+
+  for (i = 0; i < resolved->naddrs; i++) {
+    port_temp = grpc_tcp_server_add_port(
+        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
+        resolved->addrs[i].len);
+    if (port_temp > 0) {
+      if (port_num == -1) {
+        port_num = port_temp;
+      } else {
+        GPR_ASSERT(port_num == port_temp);
+      }
+      count++;
+    }
+  }
+  if (count == 0) {
+    gpr_log(GPR_ERROR, "No address added out of total %d resolved",
+            resolved->naddrs);
+    goto error;
+  }
+  if (count != resolved->naddrs) {
+    gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved",
+            count, resolved->naddrs);
+  }
+  grpc_resolved_addresses_destroy(resolved);
+
+  /* Register with the server only upon success */
+  grpc_server_add_listener(&exec_ctx, server, tcp, start, destroy);
+  goto done;
+
+/* Error path: cleanup and return */
+error:
+  if (resolved) {
+    grpc_resolved_addresses_destroy(resolved);
+  }
+  if (tcp) {
+    grpc_tcp_server_unref(&exec_ctx, tcp);
+  }
+  port_num = 0;
+
+done:
+  grpc_exec_ctx_finish(&exec_ctx);
+  return port_num;
+}
diff --git a/src/core/ext/transport/chttp2/server/secure/README.md b/src/core/ext/transport/chttp2/server/secure/README.md
new file mode 100644
index 0000000..6bda696
--- /dev/null
+++ b/src/core/ext/transport/chttp2/server/secure/README.md
@@ -0,0 +1 @@
+Plugin for creating secure servers using chttp2
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
new file mode 100644
index 0000000..698b2be
--- /dev/null
+++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
@@ -0,0 +1,264 @@
+/*
+ *
+ * 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/grpc.h>
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#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/surface/api_trace.h"
+#include "src/core/lib/surface/server.h"
+
+typedef struct grpc_server_secure_state {
+  grpc_server *server;
+  grpc_tcp_server *tcp;
+  grpc_server_security_connector *sc;
+  grpc_server_credentials *creds;
+  int is_shutdown;
+  gpr_mu mu;
+  gpr_refcount refcount;
+  grpc_closure destroy_closure;
+  grpc_closure *destroy_callback;
+} grpc_server_secure_state;
+
+static void state_ref(grpc_server_secure_state *state) {
+  gpr_ref(&state->refcount);
+}
+
+static void state_unref(grpc_server_secure_state *state) {
+  if (gpr_unref(&state->refcount)) {
+    /* ensure all threads have unlocked */
+    gpr_mu_lock(&state->mu);
+    gpr_mu_unlock(&state->mu);
+    /* clean up */
+    GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server");
+    grpc_server_credentials_unref(state->creds);
+    gpr_free(state);
+  }
+}
+
+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;
+  grpc_transport *transport;
+  if (status == GRPC_SECURITY_OK) {
+    if (secure_endpoint) {
+      gpr_mu_lock(&state->mu);
+      if (!state->is_shutdown) {
+        transport = grpc_create_chttp2_transport(
+            exec_ctx, grpc_server_get_channel_args(state->server),
+            secure_endpoint, 0);
+        setup_transport(exec_ctx, state, transport, auth_context);
+        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);
+    }
+  } else {
+    gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
+  }
+  state_unref(state);
+}
+
+static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
+                      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 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;
+  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;
+  if (state->destroy_callback != NULL) {
+    state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
+                                success);
+  }
+  grpc_server_security_connector_shutdown(exec_ctx, state->sc);
+  state_unref(state);
+}
+
+/* Server callback: destroy the tcp listener (so we don't generate further
+   callbacks) */
+static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
+                    grpc_closure *callback) {
+  grpc_server_secure_state *state = statep;
+  grpc_tcp_server *tcp;
+  gpr_mu_lock(&state->mu);
+  state->is_shutdown = 1;
+  state->destroy_callback = callback;
+  tcp = state->tcp;
+  gpr_mu_unlock(&state->mu);
+  grpc_tcp_server_unref(exec_ctx, tcp);
+}
+
+int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
+                                      grpc_server_credentials *creds) {
+  grpc_resolved_addresses *resolved = NULL;
+  grpc_tcp_server *tcp = NULL;
+  grpc_server_secure_state *state = NULL;
+  size_t i;
+  unsigned count = 0;
+  int port_num = -1;
+  int port_temp;
+  grpc_security_status status = GRPC_SECURITY_ERROR;
+  grpc_server_security_connector *sc = NULL;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_API_TRACE(
+      "grpc_server_add_secure_http2_port("
+      "server=%p, addr=%s, creds=%p)",
+      3, (server, addr, creds));
+
+  /* create security context */
+  if (creds == NULL) goto error;
+  status = grpc_server_credentials_create_security_connector(creds, &sc);
+  if (status != GRPC_SECURITY_OK) {
+    gpr_log(GPR_ERROR,
+            "Unable to create secure server with credentials of type %s.",
+            creds->type);
+    goto error;
+  }
+  sc->channel_args = grpc_server_get_channel_args(server);
+
+  /* resolve address */
+  resolved = grpc_blocking_resolve_address(addr, "https");
+  if (!resolved) {
+    goto error;
+  }
+  state = gpr_malloc(sizeof(*state));
+  memset(state, 0, sizeof(*state));
+  grpc_closure_init(&state->destroy_closure, destroy_done, state);
+  tcp = grpc_tcp_server_create(&state->destroy_closure);
+  if (!tcp) {
+    goto error;
+  }
+
+  state->server = server;
+  state->tcp = tcp;
+  state->sc = sc;
+  state->creds = grpc_server_credentials_ref(creds);
+  state->is_shutdown = 0;
+  gpr_mu_init(&state->mu);
+  gpr_ref_init(&state->refcount, 1);
+
+  for (i = 0; i < resolved->naddrs; i++) {
+    port_temp = grpc_tcp_server_add_port(
+        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
+        resolved->addrs[i].len);
+    if (port_temp > 0) {
+      if (port_num == -1) {
+        port_num = port_temp;
+      } else {
+        GPR_ASSERT(port_num == port_temp);
+      }
+      count++;
+    }
+  }
+  if (count == 0) {
+    gpr_log(GPR_ERROR, "No address added out of total %d resolved",
+            resolved->naddrs);
+    goto error;
+  }
+  if (count != resolved->naddrs) {
+    gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved",
+            count, resolved->naddrs);
+    /* if it's an error, don't we want to goto error; here ? */
+  }
+  grpc_resolved_addresses_destroy(resolved);
+
+  /* Register with the server only upon success */
+  grpc_server_add_listener(&exec_ctx, server, state, start, destroy);
+
+  grpc_exec_ctx_finish(&exec_ctx);
+  return port_num;
+
+/* Error path: cleanup and return */
+error:
+  if (resolved) {
+    grpc_resolved_addresses_destroy(resolved);
+  }
+  if (tcp) {
+    grpc_tcp_server_unref(&exec_ctx, tcp);
+  } else {
+    if (sc) {
+      GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server");
+    }
+    if (state) {
+      gpr_free(state);
+    }
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  return 0;
+}
diff --git a/src/core/ext/transport/chttp2/transport/README.md b/src/core/ext/transport/chttp2/transport/README.md
new file mode 100644
index 0000000..4684e58
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/README.md
@@ -0,0 +1,4 @@
+chttp2 transport plugin - implements grpc over http2
+
+Used by chttp2/{client,server}/{insecure,secure} plugins to implement most of
+their functionality
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.c b/src/core/ext/transport/chttp2/transport/bin_encoder.c
new file mode 100644
index 0000000..1b43c28
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.c
@@ -0,0 +1,239 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/bin_encoder.h"
+
+#include <string.h>
+
+#include <grpc/support/log.h>
+#include "src/core/ext/transport/chttp2/transport/huffsyms.h"
+
+static const char alphabet[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+typedef struct {
+  uint16_t bits;
+  uint8_t length;
+} b64_huff_sym;
+
+static const b64_huff_sym huff_alphabet[64] = {
+    {0x21, 6}, {0x5d, 7}, {0x5e, 7},   {0x5f, 7}, {0x60, 7}, {0x61, 7},
+    {0x62, 7}, {0x63, 7}, {0x64, 7},   {0x65, 7}, {0x66, 7}, {0x67, 7},
+    {0x68, 7}, {0x69, 7}, {0x6a, 7},   {0x6b, 7}, {0x6c, 7}, {0x6d, 7},
+    {0x6e, 7}, {0x6f, 7}, {0x70, 7},   {0x71, 7}, {0x72, 7}, {0xfc, 8},
+    {0x73, 7}, {0xfd, 8}, {0x3, 5},    {0x23, 6}, {0x4, 5},  {0x24, 6},
+    {0x5, 5},  {0x25, 6}, {0x26, 6},   {0x27, 6}, {0x6, 5},  {0x74, 7},
+    {0x75, 7}, {0x28, 6}, {0x29, 6},   {0x2a, 6}, {0x7, 5},  {0x2b, 6},
+    {0x76, 7}, {0x2c, 6}, {0x8, 5},    {0x9, 5},  {0x2d, 6}, {0x77, 7},
+    {0x78, 7}, {0x79, 7}, {0x7a, 7},   {0x7b, 7}, {0x0, 5},  {0x1, 5},
+    {0x2, 5},  {0x19, 6}, {0x1a, 6},   {0x1b, 6}, {0x1c, 6}, {0x1d, 6},
+    {0x1e, 6}, {0x1f, 6}, {0x7fb, 11}, {0x18, 6}};
+
+static const uint8_t tail_xtra[3] = {0, 2, 3};
+
+gpr_slice grpc_chttp2_base64_encode(gpr_slice input) {
+  size_t input_length = GPR_SLICE_LENGTH(input);
+  size_t input_triplets = input_length / 3;
+  size_t tail_case = input_length % 3;
+  size_t output_length = input_triplets * 4 + tail_xtra[tail_case];
+  gpr_slice output = gpr_slice_malloc(output_length);
+  uint8_t *in = GPR_SLICE_START_PTR(input);
+  char *out = (char *)GPR_SLICE_START_PTR(output);
+  size_t i;
+
+  /* encode full triplets */
+  for (i = 0; i < input_triplets; i++) {
+    out[0] = alphabet[in[0] >> 2];
+    out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
+    out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)];
+    out[3] = alphabet[in[2] & 0x3f];
+    out += 4;
+    in += 3;
+  }
+
+  /* encode the remaining bytes */
+  switch (tail_case) {
+    case 0:
+      break;
+    case 1:
+      out[0] = alphabet[in[0] >> 2];
+      out[1] = alphabet[(in[0] & 0x3) << 4];
+      out += 2;
+      in += 1;
+      break;
+    case 2:
+      out[0] = alphabet[in[0] >> 2];
+      out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
+      out[2] = alphabet[(in[1] & 0xf) << 2];
+      out += 3;
+      in += 2;
+      break;
+  }
+
+  GPR_ASSERT(out == (char *)GPR_SLICE_END_PTR(output));
+  GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
+  return output;
+}
+
+gpr_slice grpc_chttp2_huffman_compress(gpr_slice input) {
+  size_t nbits;
+  uint8_t *in;
+  uint8_t *out;
+  gpr_slice output;
+  uint32_t temp = 0;
+  uint32_t temp_length = 0;
+
+  nbits = 0;
+  for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
+    nbits += grpc_chttp2_huffsyms[*in].length;
+  }
+
+  output = gpr_slice_malloc(nbits / 8 + (nbits % 8 != 0));
+  out = GPR_SLICE_START_PTR(output);
+  for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
+    int sym = *in;
+    temp <<= grpc_chttp2_huffsyms[sym].length;
+    temp |= grpc_chttp2_huffsyms[sym].bits;
+    temp_length += grpc_chttp2_huffsyms[sym].length;
+
+    while (temp_length > 8) {
+      temp_length -= 8;
+      *out++ = (uint8_t)(temp >> temp_length);
+    }
+  }
+
+  if (temp_length) {
+    /* NB: the following integer arithmetic operation needs to be in its
+     * expanded form due to the "integral promotion" performed (see section
+     * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
+     * is then required to avoid the compiler warning */
+    *out++ = (uint8_t)((uint8_t)(temp << (8u - temp_length)) |
+                       (uint8_t)(0xffu >> temp_length));
+  }
+
+  GPR_ASSERT(out == GPR_SLICE_END_PTR(output));
+
+  return output;
+}
+
+typedef struct {
+  uint32_t temp;
+  uint32_t temp_length;
+  uint8_t *out;
+} huff_out;
+
+static void enc_flush_some(huff_out *out) {
+  while (out->temp_length > 8) {
+    out->temp_length -= 8;
+    *out->out++ = (uint8_t)(out->temp >> out->temp_length);
+  }
+}
+
+static void enc_add2(huff_out *out, uint8_t a, uint8_t b) {
+  b64_huff_sym sa = huff_alphabet[a];
+  b64_huff_sym sb = huff_alphabet[b];
+  out->temp = (out->temp << (sa.length + sb.length)) |
+              ((uint32_t)sa.bits << sb.length) | sb.bits;
+  out->temp_length += (uint32_t)sa.length + (uint32_t)sb.length;
+  enc_flush_some(out);
+}
+
+static void enc_add1(huff_out *out, uint8_t a) {
+  b64_huff_sym sa = huff_alphabet[a];
+  out->temp = (out->temp << sa.length) | sa.bits;
+  out->temp_length += sa.length;
+  enc_flush_some(out);
+}
+
+gpr_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(gpr_slice input) {
+  size_t input_length = GPR_SLICE_LENGTH(input);
+  size_t input_triplets = input_length / 3;
+  size_t tail_case = input_length % 3;
+  size_t output_syms = input_triplets * 4 + tail_xtra[tail_case];
+  size_t max_output_bits = 11 * output_syms;
+  size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0);
+  gpr_slice output = gpr_slice_malloc(max_output_length);
+  uint8_t *in = GPR_SLICE_START_PTR(input);
+  uint8_t *start_out = GPR_SLICE_START_PTR(output);
+  huff_out out;
+  size_t i;
+
+  out.temp = 0;
+  out.temp_length = 0;
+  out.out = start_out;
+
+  /* encode full triplets */
+  for (i = 0; i < input_triplets; i++) {
+    const uint8_t low_to_high = (uint8_t)((in[0] & 0x3) << 4);
+    const uint8_t high_to_low = in[1] >> 4;
+    enc_add2(&out, in[0] >> 2, low_to_high | high_to_low);
+
+    const uint8_t a = (uint8_t)((in[1] & 0xf) << 2);
+    const uint8_t b = (in[2] >> 6);
+    enc_add2(&out, a | b, in[2] & 0x3f);
+    in += 3;
+  }
+
+  /* encode the remaining bytes */
+  switch (tail_case) {
+    case 0:
+      break;
+    case 1:
+      enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4));
+      in += 1;
+      break;
+    case 2: {
+      const uint8_t low_to_high = (uint8_t)((in[0] & 0x3) << 4);
+      const uint8_t high_to_low = in[1] >> 4;
+      enc_add2(&out, in[0] >> 2, low_to_high | high_to_low);
+      enc_add1(&out, (uint8_t)((in[1] & 0xf) << 2));
+      in += 2;
+      break;
+    }
+  }
+
+  if (out.temp_length) {
+    /* NB: the following integer arithmetic operation needs to be in its
+     * expanded form due to the "integral promotion" performed (see section
+     * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
+     * is then required to avoid the compiler warning */
+    *out.out++ = (uint8_t)((uint8_t)(out.temp << (8u - out.temp_length)) |
+                           (uint8_t)(0xffu >> out.temp_length));
+  }
+
+  GPR_ASSERT(out.out <= GPR_SLICE_END_PTR(output));
+  GPR_SLICE_SET_LENGTH(output, out.out - start_out);
+
+  GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
+  return output;
+}
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.h b/src/core/ext/transport/chttp2/transport/bin_encoder.h
new file mode 100644
index 0000000..61ebbaf
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H
+
+#include <grpc/support/slice.h>
+
+/* base64 encode a slice. Returns a new slice, does not take ownership of the
+   input */
+gpr_slice grpc_chttp2_base64_encode(gpr_slice input);
+
+/* Compress a slice with the static huffman encoder detailed in the hpack
+   standard. Returns a new slice, does not take ownership of the input */
+gpr_slice grpc_chttp2_huffman_compress(gpr_slice input);
+
+/* equivalent to:
+   gpr_slice x = grpc_chttp2_base64_encode(input);
+   gpr_slice y = grpc_chttp2_huffman_compress(x);
+   gpr_slice_unref(x);
+   return y; */
+gpr_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(gpr_slice input);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
new file mode 100644
index 0000000..bd87253
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/bin_encoder.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/transport/metadata.h"
+
+void grpc_chttp2_plugin_init(void) {
+  grpc_chttp2_base64_encode_and_huffman_compress =
+      grpc_chttp2_base64_encode_and_huffman_compress_impl;
+  grpc_register_tracer("http", &grpc_http_trace);
+  grpc_register_tracer("flowctl", &grpc_flowctl_trace);
+}
+
+void grpc_chttp2_plugin_shutdown(void) {}
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
new file mode 100644
index 0000000..01507f5
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -0,0 +1,1816 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/chttp2_transport.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
+#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/transport_impl.h"
+
+#define DEFAULT_WINDOW 65535
+#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
+#define MAX_WINDOW 0x7fffffffu
+
+#define MAX_CLIENT_STREAM_ID 0x7fffffffu
+
+int grpc_http_trace = 0;
+int grpc_flowctl_trace = 0;
+
+#define TRANSPORT_FROM_WRITING(tw)                                        \
+  ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
+                                                   writing)))
+
+#define TRANSPORT_FROM_PARSING(tw)                                        \
+  ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
+                                                   parsing)))
+
+#define TRANSPORT_FROM_GLOBAL(tg)                                         \
+  ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
+                                                   global)))
+
+#define STREAM_FROM_GLOBAL(sg) \
+  ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
+
+#define STREAM_FROM_PARSING(sg) \
+  ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, parsing)))
+
+static const grpc_transport_vtable vtable;
+
+static void lock(grpc_chttp2_transport *t);
+static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
+
+/* forward declarations of various callbacks that we'll build closures around */
+static void writing_action(grpc_exec_ctx *exec_ctx, void *t,
+                           bool iomgr_success_ignored);
+
+/** Set a transport level setting, and push it to our peer */
+static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
+                         uint32_t value);
+
+/** Endpoint callback to process incoming data */
+static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success);
+
+/** Start disconnection chain */
+static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
+
+/** Perform a transport_op */
+static void perform_stream_op_locked(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op);
+
+/** Cancel a stream: coming from the transport API */
+static void cancel_from_api(grpc_exec_ctx *exec_ctx,
+                            grpc_chttp2_transport_global *transport_global,
+                            grpc_chttp2_stream_global *stream_global,
+                            grpc_status_code status);
+
+static void close_from_api(grpc_exec_ctx *exec_ctx,
+                           grpc_chttp2_transport_global *transport_global,
+                           grpc_chttp2_stream_global *stream_global,
+                           grpc_status_code status,
+                           gpr_slice *optional_message);
+
+/** Add endpoint from this transport to pollset */
+static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
+                                  grpc_chttp2_transport *t,
+                                  grpc_pollset *pollset);
+static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
+                                      grpc_chttp2_transport *t,
+                                      grpc_pollset_set *pollset_set);
+
+/** Start new streams that have been created if we can */
+static void maybe_start_some_streams(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global);
+
+static void connectivity_state_set(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_connectivity_state state, const char *reason);
+
+static void check_read_ops(grpc_exec_ctx *exec_ctx,
+                           grpc_chttp2_transport_global *transport_global);
+
+static void incoming_byte_stream_update_flow_control(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
+    size_t have_already);
+
+static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
+                                grpc_chttp2_stream_global *stream_global);
+
+/*******************************************************************************
+ * CONSTRUCTION/DESTRUCTION/REFCOUNTING
+ */
+
+static void destruct_transport(grpc_exec_ctx *exec_ctx,
+                               grpc_chttp2_transport *t) {
+  size_t i;
+
+  gpr_mu_lock(&t->mu);
+
+  GPR_ASSERT(t->ep == NULL);
+
+  gpr_slice_buffer_destroy(&t->global.qbuf);
+
+  gpr_slice_buffer_destroy(&t->writing.outbuf);
+  grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor);
+
+  gpr_slice_buffer_destroy(&t->parsing.qbuf);
+  gpr_slice_buffer_destroy(&t->read_buffer);
+  grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser);
+  grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser);
+
+  for (i = 0; i < STREAM_LIST_COUNT; i++) {
+    GPR_ASSERT(t->lists[i].head == NULL);
+    GPR_ASSERT(t->lists[i].tail == NULL);
+  }
+
+  GPR_ASSERT(grpc_chttp2_stream_map_size(&t->parsing_stream_map) == 0);
+  GPR_ASSERT(grpc_chttp2_stream_map_size(&t->new_stream_map) == 0);
+
+  grpc_chttp2_stream_map_destroy(&t->parsing_stream_map);
+  grpc_chttp2_stream_map_destroy(&t->new_stream_map);
+  grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
+
+  gpr_mu_unlock(&t->mu);
+  gpr_mu_destroy(&t->mu);
+
+  /* callback remaining pings: they're not allowed to call into the transpot,
+     and maybe they hold resources that need to be freed */
+  while (t->global.pings.next != &t->global.pings) {
+    grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
+    grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, false, NULL);
+    ping->next->prev = ping->prev;
+    ping->prev->next = ping->next;
+    gpr_free(ping);
+  }
+
+  gpr_free(t->peer_string);
+  gpr_free(t);
+}
+
+#ifdef REFCOUNTING_DEBUG
+#define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__)
+#define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t, r, __FILE__, __LINE__)
+static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                            const char *reason, const char *file, int line) {
+  gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count,
+          t->refs.count - 1, reason, file, line);
+  if (!gpr_unref(&t->refs)) return;
+  destruct_transport(exec_ctx, t);
+}
+
+static void ref_transport(grpc_chttp2_transport *t, const char *reason,
+                          const char *file, int line) {
+  gpr_log(GPR_DEBUG, "chttp2:  ref:%p %d->%d %s [%s:%d]", t, t->refs.count,
+          t->refs.count + 1, reason, file, line);
+  gpr_ref(&t->refs);
+}
+#else
+#define REF_TRANSPORT(t, r) ref_transport(t)
+#define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t)
+static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
+  if (!gpr_unref(&t->refs)) return;
+  destruct_transport(exec_ctx, t);
+}
+
+static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
+#endif
+
+static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                           const grpc_channel_args *channel_args,
+                           grpc_endpoint *ep, uint8_t is_client) {
+  size_t i;
+  int j;
+
+  GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
+             GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
+
+  memset(t, 0, sizeof(*t));
+
+  t->base.vtable = &vtable;
+  t->ep = ep;
+  /* one ref is for destroy, the other for when ep becomes NULL */
+  gpr_ref_init(&t->refs, 2);
+  /* ref is dropped at transport close() */
+  gpr_ref_init(&t->shutdown_ep_refs, 1);
+  gpr_mu_init(&t->mu);
+  t->peer_string = grpc_endpoint_get_peer(ep);
+  t->endpoint_reading = 1;
+  t->global.next_stream_id = is_client ? 1 : 2;
+  t->global.is_client = is_client;
+  t->writing.outgoing_window = DEFAULT_WINDOW;
+  t->parsing.incoming_window = DEFAULT_WINDOW;
+  t->global.stream_lookahead = DEFAULT_WINDOW;
+  t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
+  t->global.ping_counter = 1;
+  t->global.pings.next = t->global.pings.prev = &t->global.pings;
+  t->parsing.is_client = is_client;
+  t->parsing.deframe_state =
+      is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
+  t->writing.is_client = is_client;
+  grpc_connectivity_state_init(
+      &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
+      is_client ? "client_transport" : "server_transport");
+
+  gpr_slice_buffer_init(&t->global.qbuf);
+
+  gpr_slice_buffer_init(&t->writing.outbuf);
+  grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor);
+  grpc_closure_init(&t->writing_action, writing_action, t);
+
+  gpr_slice_buffer_init(&t->parsing.qbuf);
+  grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser);
+  grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser);
+
+  grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing,
+                    &t->writing);
+  grpc_closure_init(&t->recv_data, recv_data, t);
+  gpr_slice_buffer_init(&t->read_buffer);
+
+  if (is_client) {
+    gpr_slice_buffer_add(
+        &t->global.qbuf,
+        gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
+  }
+  /* 8 is a random stab in the dark as to a good initial size: it's small enough
+     that it shouldn't waste memory for infrequently used connections, yet
+     large enough that the exponential growth should happen nicely when it's
+     needed.
+     TODO(ctiller): tune this */
+  grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8);
+  grpc_chttp2_stream_map_init(&t->new_stream_map, 8);
+
+  /* copy in initial settings to all setting sets */
+  for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) {
+    t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value;
+    for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) {
+      t->global.settings[j][i] =
+          grpc_chttp2_settings_parameters[i].default_value;
+    }
+  }
+  t->global.dirtied_local_settings = 1;
+  /* Hack: it's common for implementations to assume 65536 bytes initial send
+     window -- this should by rights be 0 */
+  t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
+  t->global.sent_local_settings = 0;
+
+  /* configure http2 the way we like it */
+  if (is_client) {
+    push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
+    push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
+  }
+  push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW);
+
+  if (channel_args) {
+    for (i = 0; i < channel_args->num_args; i++) {
+      if (0 ==
+          strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) {
+        if (is_client) {
+          gpr_log(GPR_ERROR, "%s: is ignored on the client",
+                  GRPC_ARG_MAX_CONCURRENT_STREAMS);
+        } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s: must be an integer",
+                  GRPC_ARG_MAX_CONCURRENT_STREAMS);
+        } else {
+          push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
+                       (uint32_t)channel_args->args[i].value.integer);
+        }
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
+        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s: must be an integer",
+                  GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER);
+        } else if ((t->global.next_stream_id & 1) !=
+                   (channel_args->args[i].value.integer & 1)) {
+          gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
+                  GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER,
+                  t->global.next_stream_id & 1,
+                  is_client ? "client" : "server");
+        } else {
+          t->global.next_stream_id =
+              (uint32_t)channel_args->args[i].value.integer;
+        }
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
+        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s: must be an integer",
+                  GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
+        } else if (channel_args->args[i].value.integer <= 5) {
+          gpr_log(GPR_ERROR, "%s: must be at least 5",
+                  GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
+        } else {
+          t->global.stream_lookahead =
+              (uint32_t)channel_args->args[i].value.integer;
+        }
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) {
+        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s: must be an integer",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
+        } else if (channel_args->args[i].value.integer < 0) {
+          gpr_log(GPR_ERROR, "%s: must be non-negative",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
+        } else {
+          push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
+                       (uint32_t)channel_args->args[i].value.integer);
+        }
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
+        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s: must be an integer",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
+        } else if (channel_args->args[i].value.integer < 0) {
+          gpr_log(GPR_ERROR, "%s: must be non-negative",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
+        } else {
+          grpc_chttp2_hpack_compressor_set_max_usable_size(
+              &t->writing.hpack_compressor,
+              (uint32_t)channel_args->args[i].value.integer);
+        }
+      }
+    }
+  }
+}
+
+static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+
+  lock(t);
+  t->destroying = 1;
+  drop_connection(exec_ctx, t);
+  unlock(exec_ctx, t);
+
+  UNREF_TRANSPORT(exec_ctx, t, "destroy");
+}
+
+/** block grpc_endpoint_shutdown being called until a paired
+    allow_endpoint_shutdown is made */
+static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) {
+  GPR_ASSERT(t->ep);
+  gpr_ref(&t->shutdown_ep_refs);
+}
+
+static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx,
+                                           grpc_chttp2_transport *t) {
+  if (gpr_unref(&t->shutdown_ep_refs)) {
+    if (t->ep) {
+      grpc_endpoint_shutdown(exec_ctx, t->ep);
+    }
+  }
+}
+
+static void allow_endpoint_shutdown_unlocked(grpc_exec_ctx *exec_ctx,
+                                             grpc_chttp2_transport *t) {
+  if (gpr_unref(&t->shutdown_ep_refs)) {
+    gpr_mu_lock(&t->mu);
+    if (t->ep) {
+      grpc_endpoint_shutdown(exec_ctx, t->ep);
+    }
+    gpr_mu_unlock(&t->mu);
+  }
+}
+
+static void destroy_endpoint(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport *t) {
+  grpc_endpoint_destroy(exec_ctx, t->ep);
+  t->ep = NULL;
+  /* safe because we'll still have the ref for write */
+  UNREF_TRANSPORT(exec_ctx, t, "disconnect");
+}
+
+static void close_transport_locked(grpc_exec_ctx *exec_ctx,
+                                   grpc_chttp2_transport *t) {
+  if (!t->closed) {
+    t->closed = 1;
+    connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_FATAL_FAILURE,
+                           "close_transport");
+    if (t->ep) {
+      allow_endpoint_shutdown_locked(exec_ctx, t);
+    }
+
+    /* flush writable stream list to avoid dangling references */
+    grpc_chttp2_stream_global *stream_global;
+    grpc_chttp2_stream_writing *stream_writing;
+    while (grpc_chttp2_list_pop_writable_stream(
+        &t->global, &t->writing, &stream_global, &stream_writing)) {
+      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
+    }
+  }
+}
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global,
+                            const char *reason) {
+  grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount, reason);
+}
+void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_stream_global *stream_global,
+                              const char *reason) {
+  grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount,
+                    reason);
+}
+#else
+void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global) {
+  grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount);
+}
+void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_stream_global *stream_global) {
+  grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount);
+}
+#endif
+
+static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                       grpc_stream *gs, grpc_stream_refcount *refcount,
+                       const void *server_data) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
+
+  memset(s, 0, sizeof(*s));
+
+  s->refcount = refcount;
+  GRPC_CHTTP2_STREAM_REF(&s->global, "chttp2");
+
+  grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[0]);
+  grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[1]);
+  grpc_chttp2_incoming_metadata_buffer_init(
+      &s->global.received_initial_metadata);
+  grpc_chttp2_incoming_metadata_buffer_init(
+      &s->global.received_trailing_metadata);
+  grpc_chttp2_data_parser_init(&s->parsing.data_parser);
+  gpr_slice_buffer_init(&s->writing.flow_controlled_buffer);
+
+  REF_TRANSPORT(t, "stream");
+
+  lock(t);
+  grpc_chttp2_register_stream(t, s);
+  if (server_data) {
+    GPR_ASSERT(t->parsing_active);
+    s->global.id = (uint32_t)(uintptr_t)server_data;
+    s->parsing.id = s->global.id;
+    s->global.outgoing_window =
+        t->global.settings[GRPC_PEER_SETTINGS]
+                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+    s->parsing.incoming_window = s->global.max_recv_bytes =
+        t->global.settings[GRPC_SENT_SETTINGS]
+                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+    *t->accepting_stream = s;
+    grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s);
+    s->global.in_stream_map = 1;
+  }
+  unlock(exec_ctx, t);
+
+  return 0;
+}
+
+static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                           grpc_stream *gs) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
+  int i;
+  grpc_byte_stream *bs;
+
+  GPR_TIMER_BEGIN("destroy_stream", 0);
+
+  gpr_mu_lock(&t->mu);
+
+  GPR_ASSERT((s->global.write_closed && s->global.read_closed) ||
+             s->global.id == 0);
+  GPR_ASSERT(!s->global.in_stream_map);
+  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
+    close_transport_locked(exec_ctx, t);
+  }
+  if (!t->parsing_active && s->global.id) {
+    GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
+                                           s->global.id) == NULL);
+  }
+
+  grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global,
+                                                                &s->global);
+  grpc_chttp2_list_remove_stalled_by_transport(&t->global, &s->global);
+
+  gpr_mu_unlock(&t->mu);
+
+  for (i = 0; i < STREAM_LIST_COUNT; i++) {
+    if (s->included[i]) {
+      gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
+              t->global.is_client ? "client" : "server", s->global.id, i);
+      abort();
+    }
+  }
+
+  while (
+      (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) {
+    grpc_byte_stream_destroy(exec_ctx, bs);
+  }
+
+  GPR_ASSERT(s->global.send_initial_metadata_finished == NULL);
+  GPR_ASSERT(s->global.send_message_finished == NULL);
+  GPR_ASSERT(s->global.send_trailing_metadata_finished == NULL);
+  GPR_ASSERT(s->global.recv_initial_metadata_ready == NULL);
+  GPR_ASSERT(s->global.recv_message_ready == NULL);
+  GPR_ASSERT(s->global.recv_trailing_metadata_finished == NULL);
+  grpc_chttp2_data_parser_destroy(exec_ctx, &s->parsing.data_parser);
+  grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[0]);
+  grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[1]);
+  grpc_chttp2_incoming_metadata_buffer_destroy(
+      &s->global.received_initial_metadata);
+  grpc_chttp2_incoming_metadata_buffer_destroy(
+      &s->global.received_trailing_metadata);
+  gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer);
+
+  UNREF_TRANSPORT(exec_ctx, t, "stream");
+
+  GPR_TIMER_END("destroy_stream", 0);
+}
+
+grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
+    grpc_chttp2_transport_parsing *transport_parsing, uint32_t id) {
+  grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
+  grpc_chttp2_stream *s =
+      grpc_chttp2_stream_map_find(&t->parsing_stream_map, id);
+  return s ? &s->parsing : NULL;
+}
+
+grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    uint32_t id) {
+  grpc_chttp2_stream *accepting;
+  grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
+  GPR_ASSERT(t->accepting_stream == NULL);
+  t->accepting_stream = &accepting;
+  t->channel_callback.accept_stream(exec_ctx,
+                                    t->channel_callback.accept_stream_user_data,
+                                    &t->base, (void *)(uintptr_t)id);
+  t->accepting_stream = NULL;
+  return &accepting->parsing;
+}
+
+/*******************************************************************************
+ * LOCK MANAGEMENT
+ */
+
+/* We take a grpc_chttp2_transport-global lock in response to calls coming in
+   from above,
+   and in response to data being received from below. New data to be written
+   is always queued, as are callbacks to process data. During unlock() we
+   check our todo lists and initiate callbacks and flush writes. */
+
+static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
+
+static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
+  GPR_TIMER_BEGIN("unlock", 0);
+  if (!t->writing_active && !t->closed &&
+      grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing,
+                                         t->parsing_active)) {
+    t->writing_active = 1;
+    REF_TRANSPORT(t, "writing");
+    grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, true, NULL);
+    prevent_endpoint_shutdown(t);
+  }
+  check_read_ops(exec_ctx, &t->global);
+
+  gpr_mu_unlock(&t->mu);
+  GPR_TIMER_END("unlock", 0);
+}
+
+/*******************************************************************************
+ * OUTPUT PROCESSING
+ */
+
+void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
+                                 grpc_chttp2_stream_global *stream_global) {
+  if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed &&
+      grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) {
+    GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
+  }
+}
+
+static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
+                         uint32_t value) {
+  const grpc_chttp2_setting_parameters *sp =
+      &grpc_chttp2_settings_parameters[id];
+  uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
+  if (use_value != value) {
+    gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
+            value, use_value);
+  }
+  if (use_value != t->global.settings[GRPC_LOCAL_SETTINGS][id]) {
+    t->global.settings[GRPC_LOCAL_SETTINGS][id] = use_value;
+    t->global.dirtied_local_settings = 1;
+  }
+}
+
+void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
+                                   void *transport_writing_ptr, bool success) {
+  grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr;
+  grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
+  grpc_chttp2_stream_global *stream_global;
+
+  GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0);
+
+  lock(t);
+
+  allow_endpoint_shutdown_locked(exec_ctx, t);
+
+  if (!success) {
+    drop_connection(exec_ctx, t);
+  }
+
+  grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
+
+  while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
+                                                         &stream_global)) {
+    fail_pending_writes(exec_ctx, stream_global);
+    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
+  }
+
+  /* leave the writing flag up on shutdown to prevent further writes in unlock()
+     from starting */
+  t->writing_active = 0;
+  if (t->ep && !t->endpoint_reading) {
+    destroy_endpoint(exec_ctx, t);
+  }
+
+  unlock(exec_ctx, t);
+
+  UNREF_TRANSPORT(exec_ctx, t, "writing");
+
+  GPR_TIMER_END("grpc_chttp2_terminate_writing", 0);
+}
+
+static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
+                           bool iomgr_success_ignored) {
+  grpc_chttp2_transport *t = gt;
+  GPR_TIMER_BEGIN("writing_action", 0);
+  grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
+  GPR_TIMER_END("writing_action", 0);
+}
+
+void grpc_chttp2_add_incoming_goaway(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    uint32_t goaway_error, gpr_slice goaway_text) {
+  char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+  gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg);
+  gpr_free(msg);
+  gpr_slice_unref(goaway_text);
+  transport_global->seen_goaway = 1;
+  connectivity_state_set(exec_ctx, transport_global, GRPC_CHANNEL_FATAL_FAILURE,
+                         "got_goaway");
+}
+
+static void maybe_start_some_streams(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) {
+  grpc_chttp2_stream_global *stream_global;
+  uint32_t stream_incoming_window;
+  /* start streams where we have free grpc_chttp2_stream ids and free
+   * concurrency */
+  while (transport_global->next_stream_id <= MAX_CLIENT_STREAM_ID &&
+         transport_global->concurrent_stream_count <
+             transport_global
+                 ->settings[GRPC_PEER_SETTINGS]
+                           [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] &&
+         grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
+                                                      &stream_global)) {
+    /* safe since we can't (legally) be parsing this stream yet */
+    grpc_chttp2_stream_parsing *stream_parsing =
+        &STREAM_FROM_GLOBAL(stream_global)->parsing;
+    GRPC_CHTTP2_IF_TRACING(gpr_log(
+        GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
+        transport_global->is_client ? "CLI" : "SVR", stream_global,
+        transport_global->next_stream_id));
+
+    GPR_ASSERT(stream_global->id == 0);
+    stream_global->id = stream_parsing->id = transport_global->next_stream_id;
+    transport_global->next_stream_id += 2;
+
+    if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
+      connectivity_state_set(exec_ctx, transport_global,
+                             GRPC_CHANNEL_TRANSIENT_FAILURE,
+                             "no_more_stream_ids");
+    }
+
+    stream_global->outgoing_window =
+        transport_global->settings[GRPC_PEER_SETTINGS]
+                                  [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+    stream_parsing->incoming_window = stream_incoming_window =
+        transport_global->settings[GRPC_SENT_SETTINGS]
+                                  [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+    stream_global->max_recv_bytes =
+        GPR_MAX(stream_incoming_window, stream_global->max_recv_bytes);
+    grpc_chttp2_stream_map_add(
+        &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map,
+        stream_global->id, STREAM_FROM_GLOBAL(stream_global));
+    stream_global->in_stream_map = 1;
+    transport_global->concurrent_stream_count++;
+    grpc_chttp2_become_writable(transport_global, stream_global);
+  }
+  /* cancel out streams that will never be started */
+  while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
+         grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
+                                                      &stream_global)) {
+    cancel_from_api(exec_ctx, transport_global, stream_global,
+                    GRPC_STATUS_UNAVAILABLE);
+  }
+}
+
+#define CLOSURE_BARRIER_STATS_BIT (1 << 0)
+#define CLOSURE_BARRIER_FAILURE_BIT (1 << 1)
+#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
+
+static grpc_closure *add_closure_barrier(grpc_closure *closure) {
+  closure->final_data += CLOSURE_BARRIER_FIRST_REF_BIT;
+  return closure;
+}
+
+void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
+                                       grpc_chttp2_stream_global *stream_global,
+                                       grpc_closure **pclosure, int success) {
+  grpc_closure *closure = *pclosure;
+  if (closure == NULL) {
+    return;
+  }
+  closure->final_data -= CLOSURE_BARRIER_FIRST_REF_BIT;
+  if (!success) {
+    closure->final_data |= CLOSURE_BARRIER_FAILURE_BIT;
+  }
+  if (closure->final_data < CLOSURE_BARRIER_FIRST_REF_BIT) {
+    if (closure->final_data & CLOSURE_BARRIER_STATS_BIT) {
+      grpc_transport_move_stats(&stream_global->stats,
+                                stream_global->collecting_stats);
+      stream_global->collecting_stats = NULL;
+    }
+    grpc_exec_ctx_enqueue(
+        exec_ctx, closure,
+        (closure->final_data & CLOSURE_BARRIER_FAILURE_BIT) == 0, NULL);
+  }
+  *pclosure = NULL;
+}
+
+static int contains_non_ok_status(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_metadata_batch *batch) {
+  grpc_linked_mdelem *l;
+  for (l = batch->list.head; l; l = l->next) {
+    if (l->md->key == GRPC_MDSTR_GRPC_STATUS &&
+        l->md != GRPC_MDELEM_GRPC_STATUS_0) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool success) {}
+
+static void perform_stream_op_locked(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) {
+  grpc_closure *on_complete;
+
+  GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
+
+  on_complete = op->on_complete;
+  if (on_complete == NULL) {
+    on_complete = grpc_closure_create(do_nothing, NULL);
+  }
+  /* use final_data as a barrier until enqueue time; the inital counter is
+     dropped at the end of this function */
+  on_complete->final_data = CLOSURE_BARRIER_FIRST_REF_BIT;
+
+  if (op->collect_stats != NULL) {
+    GPR_ASSERT(stream_global->collecting_stats == NULL);
+    stream_global->collecting_stats = op->collect_stats;
+    on_complete->final_data |= CLOSURE_BARRIER_STATS_BIT;
+  }
+
+  if (op->cancel_with_status != GRPC_STATUS_OK) {
+    cancel_from_api(exec_ctx, transport_global, stream_global,
+                    op->cancel_with_status);
+  }
+
+  if (op->close_with_status != GRPC_STATUS_OK) {
+    close_from_api(exec_ctx, transport_global, stream_global,
+                   op->close_with_status, op->optional_close_message);
+  }
+
+  if (op->send_initial_metadata != NULL) {
+    GPR_ASSERT(stream_global->send_initial_metadata_finished == NULL);
+    stream_global->send_initial_metadata_finished =
+        add_closure_barrier(on_complete);
+    stream_global->send_initial_metadata = op->send_initial_metadata;
+    if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
+      stream_global->seen_error = 1;
+      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+    }
+    if (!stream_global->write_closed) {
+      if (transport_global->is_client) {
+        GPR_ASSERT(stream_global->id == 0);
+        grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
+                                                     stream_global);
+        maybe_start_some_streams(exec_ctx, transport_global);
+      } else {
+        GPR_ASSERT(stream_global->id != 0);
+        grpc_chttp2_become_writable(transport_global, stream_global);
+      }
+    } else {
+      grpc_chttp2_complete_closure_step(
+          exec_ctx, stream_global,
+          &stream_global->send_initial_metadata_finished, 0);
+    }
+  }
+
+  if (op->send_message != NULL) {
+    GPR_ASSERT(stream_global->send_message_finished == NULL);
+    GPR_ASSERT(stream_global->send_message == NULL);
+    stream_global->send_message_finished = add_closure_barrier(on_complete);
+    if (stream_global->write_closed) {
+      grpc_chttp2_complete_closure_step(
+          exec_ctx, stream_global, &stream_global->send_message_finished, 0);
+    } else {
+      stream_global->send_message = op->send_message;
+      if (stream_global->id != 0) {
+        grpc_chttp2_become_writable(transport_global, stream_global);
+      }
+    }
+  }
+
+  if (op->send_trailing_metadata != NULL) {
+    GPR_ASSERT(stream_global->send_trailing_metadata_finished == NULL);
+    stream_global->send_trailing_metadata_finished =
+        add_closure_barrier(on_complete);
+    stream_global->send_trailing_metadata = op->send_trailing_metadata;
+    if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) {
+      stream_global->seen_error = 1;
+      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+    }
+    if (stream_global->write_closed) {
+      grpc_chttp2_complete_closure_step(
+          exec_ctx, stream_global,
+          &stream_global->send_trailing_metadata_finished,
+          grpc_metadata_batch_is_empty(op->send_trailing_metadata));
+    } else if (stream_global->id != 0) {
+      /* TODO(ctiller): check if there's flow control for any outstanding
+         bytes before going writable */
+      grpc_chttp2_become_writable(transport_global, stream_global);
+    }
+  }
+
+  if (op->recv_initial_metadata != NULL) {
+    GPR_ASSERT(stream_global->recv_initial_metadata_ready == NULL);
+    stream_global->recv_initial_metadata_ready =
+        op->recv_initial_metadata_ready;
+    stream_global->recv_initial_metadata = op->recv_initial_metadata;
+    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+  }
+
+  if (op->recv_message != NULL) {
+    GPR_ASSERT(stream_global->recv_message_ready == NULL);
+    stream_global->recv_message_ready = op->recv_message_ready;
+    stream_global->recv_message = op->recv_message;
+    if (stream_global->id != 0 &&
+        (stream_global->incoming_frames.head == NULL ||
+         stream_global->incoming_frames.head->is_tail)) {
+      incoming_byte_stream_update_flow_control(
+          transport_global, stream_global, transport_global->stream_lookahead,
+          0);
+    }
+    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+  }
+
+  if (op->recv_trailing_metadata != NULL) {
+    GPR_ASSERT(stream_global->recv_trailing_metadata_finished == NULL);
+    stream_global->recv_trailing_metadata_finished =
+        add_closure_barrier(on_complete);
+    stream_global->recv_trailing_metadata = op->recv_trailing_metadata;
+    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+  }
+
+  grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &on_complete, 1);
+
+  GPR_TIMER_END("perform_stream_op_locked", 0);
+}
+
+static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                              grpc_stream *gs, grpc_transport_stream_op *op) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
+
+  lock(t);
+  perform_stream_op_locked(exec_ctx, &t->global, &s->global, op);
+  unlock(exec_ctx, t);
+}
+
+static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) {
+  grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
+  p->next = &t->global.pings;
+  p->prev = p->next->prev;
+  p->prev->next = p->next->prev = p;
+  p->id[0] = (uint8_t)((t->global.ping_counter >> 56) & 0xff);
+  p->id[1] = (uint8_t)((t->global.ping_counter >> 48) & 0xff);
+  p->id[2] = (uint8_t)((t->global.ping_counter >> 40) & 0xff);
+  p->id[3] = (uint8_t)((t->global.ping_counter >> 32) & 0xff);
+  p->id[4] = (uint8_t)((t->global.ping_counter >> 24) & 0xff);
+  p->id[5] = (uint8_t)((t->global.ping_counter >> 16) & 0xff);
+  p->id[6] = (uint8_t)((t->global.ping_counter >> 8) & 0xff);
+  p->id[7] = (uint8_t)(t->global.ping_counter & 0xff);
+  p->on_recv = on_recv;
+  gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id));
+}
+
+void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
+                          grpc_chttp2_transport_parsing *transport_parsing,
+                          const uint8_t *opaque_8bytes) {
+  grpc_chttp2_outstanding_ping *ping;
+  grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
+  grpc_chttp2_transport_global *transport_global = &t->global;
+  lock(t);
+  for (ping = transport_global->pings.next; ping != &transport_global->pings;
+       ping = ping->next) {
+    if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
+      grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, true, NULL);
+      ping->next->prev = ping->prev;
+      ping->prev->next = ping->next;
+      gpr_free(ping);
+      break;
+    }
+  }
+  unlock(exec_ctx, t);
+}
+
+static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
+                                        grpc_chttp2_transport *t,
+                                        grpc_transport_op *op) {
+  bool close_transport = false;
+
+  grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
+
+  if (op->on_connectivity_state_change != NULL) {
+    grpc_connectivity_state_notify_on_state_change(
+        exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state,
+        op->on_connectivity_state_change);
+  }
+
+  if (op->send_goaway) {
+    t->global.sent_goaway = 1;
+    grpc_chttp2_goaway_append(
+        t->global.last_incoming_stream_id,
+        (uint32_t)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
+        gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
+    close_transport = !grpc_chttp2_has_streams(t);
+  }
+
+  if (op->set_accept_stream) {
+    t->channel_callback.accept_stream = op->set_accept_stream_fn;
+    t->channel_callback.accept_stream_user_data =
+        op->set_accept_stream_user_data;
+  }
+
+  if (op->bind_pollset) {
+    add_to_pollset_locked(exec_ctx, t, op->bind_pollset);
+  }
+
+  if (op->bind_pollset_set) {
+    add_to_pollset_set_locked(exec_ctx, t, op->bind_pollset_set);
+  }
+
+  if (op->send_ping) {
+    send_ping_locked(t, op->send_ping);
+  }
+
+  if (op->disconnect) {
+    close_transport_locked(exec_ctx, t);
+  }
+
+  if (close_transport) {
+    close_transport_locked(exec_ctx, t);
+  }
+}
+
+static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                                 grpc_transport_op *op) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+
+  lock(t);
+
+  /* If there's a set_accept_stream ensure that we're not parsing
+     to avoid changing things out from underneath */
+  if (t->parsing_active && op->set_accept_stream) {
+    GPR_ASSERT(t->post_parsing_op == NULL);
+    t->post_parsing_op = gpr_malloc(sizeof(*op));
+    memcpy(t->post_parsing_op, op, sizeof(*op));
+  } else {
+    perform_transport_op_locked(exec_ctx, t, op);
+  }
+
+  unlock(exec_ctx, t);
+}
+
+/*******************************************************************************
+ * INPUT PROCESSING
+ */
+
+static void check_read_ops(grpc_exec_ctx *exec_ctx,
+                           grpc_chttp2_transport_global *transport_global) {
+  grpc_chttp2_stream_global *stream_global;
+  grpc_byte_stream *bs;
+  while (
+      grpc_chttp2_list_pop_check_read_ops(transport_global, &stream_global)) {
+    if (stream_global->recv_initial_metadata_ready != NULL &&
+        stream_global->published_initial_metadata) {
+      grpc_chttp2_incoming_metadata_buffer_publish(
+          &stream_global->received_initial_metadata,
+          stream_global->recv_initial_metadata);
+      grpc_exec_ctx_enqueue(
+          exec_ctx, stream_global->recv_initial_metadata_ready, true, NULL);
+      stream_global->recv_initial_metadata_ready = NULL;
+    }
+    if (stream_global->recv_message_ready != NULL) {
+      while (stream_global->seen_error &&
+             (bs = grpc_chttp2_incoming_frame_queue_pop(
+                  &stream_global->incoming_frames)) != NULL) {
+        grpc_byte_stream_destroy(exec_ctx, bs);
+      }
+      if (stream_global->incoming_frames.head != NULL) {
+        *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
+            &stream_global->incoming_frames);
+        GPR_ASSERT(*stream_global->recv_message != NULL);
+        grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
+                              NULL);
+        stream_global->recv_message_ready = NULL;
+      } else if (stream_global->published_trailing_metadata) {
+        *stream_global->recv_message = NULL;
+        grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
+                              NULL);
+        stream_global->recv_message_ready = NULL;
+      }
+    }
+    if (stream_global->recv_trailing_metadata_finished != NULL &&
+        stream_global->read_closed && stream_global->write_closed) {
+      while (stream_global->seen_error &&
+             (bs = grpc_chttp2_incoming_frame_queue_pop(
+                  &stream_global->incoming_frames)) != NULL) {
+        grpc_byte_stream_destroy(exec_ctx, bs);
+      }
+      if (stream_global->incoming_frames.head == NULL) {
+        grpc_chttp2_incoming_metadata_buffer_publish(
+            &stream_global->received_trailing_metadata,
+            stream_global->recv_trailing_metadata);
+        grpc_chttp2_complete_closure_step(
+            exec_ctx, stream_global,
+            &stream_global->recv_trailing_metadata_finished, 1);
+      }
+    }
+  }
+}
+
+static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                          uint32_t id) {
+  size_t new_stream_count;
+  grpc_chttp2_stream *s =
+      grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
+  if (!s) {
+    s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
+  }
+  GPR_ASSERT(s);
+  s->global.in_stream_map = 0;
+  if (t->parsing.incoming_stream == &s->parsing) {
+    t->parsing.incoming_stream = NULL;
+    grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing);
+  }
+  if (s->parsing.data_parser.parsing_frame != NULL) {
+    grpc_chttp2_incoming_byte_stream_finished(
+        exec_ctx, s->parsing.data_parser.parsing_frame, 0, 0);
+    s->parsing.data_parser.parsing_frame = NULL;
+  }
+
+  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
+    close_transport_locked(exec_ctx, t);
+  }
+  if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
+    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
+  }
+
+  new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
+                     grpc_chttp2_stream_map_size(&t->new_stream_map);
+  GPR_ASSERT(new_stream_count <= UINT32_MAX);
+  if (new_stream_count != t->global.concurrent_stream_count) {
+    t->global.concurrent_stream_count = (uint32_t)new_stream_count;
+    maybe_start_some_streams(exec_ctx, &t->global);
+  }
+}
+
+static void cancel_from_api(grpc_exec_ctx *exec_ctx,
+                            grpc_chttp2_transport_global *transport_global,
+                            grpc_chttp2_stream_global *stream_global,
+                            grpc_status_code status) {
+  if (!stream_global->read_closed || !stream_global->write_closed) {
+    if (stream_global->id != 0) {
+      gpr_slice_buffer_add(
+          &transport_global->qbuf,
+          grpc_chttp2_rst_stream_create(
+              stream_global->id,
+              (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status),
+              &stream_global->stats.outgoing));
+    }
+    grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
+                            NULL);
+  }
+  if (status != GRPC_STATUS_OK && !stream_global->seen_error) {
+    stream_global->seen_error = 1;
+    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+  }
+  grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
+                                 1);
+}
+
+void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_global *transport_global,
+                             grpc_chttp2_stream_global *stream_global,
+                             grpc_status_code status, gpr_slice *slice) {
+  if (status != GRPC_STATUS_OK) {
+    stream_global->seen_error = 1;
+    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+  }
+  /* stream_global->recv_trailing_metadata_finished gives us a
+     last chance replacement: we've received trailing metadata,
+     but something more important has become available to signal
+     to the upper layers - drop what we've got, and then publish
+     what we want - which is safe because we haven't told anyone
+     about the metadata yet */
+  if (!stream_global->published_trailing_metadata ||
+      stream_global->recv_trailing_metadata_finished != NULL) {
+    char status_string[GPR_LTOA_MIN_BUFSIZE];
+    gpr_ltoa(status, status_string);
+    grpc_chttp2_incoming_metadata_buffer_add(
+        &stream_global->received_trailing_metadata,
+        grpc_mdelem_from_metadata_strings(
+            GRPC_MDSTR_GRPC_STATUS, grpc_mdstr_from_string(status_string)));
+    if (slice) {
+      grpc_chttp2_incoming_metadata_buffer_add(
+          &stream_global->received_trailing_metadata,
+          grpc_mdelem_from_metadata_strings(
+              GRPC_MDSTR_GRPC_MESSAGE,
+              grpc_mdstr_from_slice(gpr_slice_ref(*slice))));
+    }
+    stream_global->published_trailing_metadata = 1;
+    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+  }
+  if (slice) {
+    gpr_slice_unref(*slice);
+  }
+}
+
+static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
+                                grpc_chttp2_stream_global *stream_global) {
+  grpc_chttp2_complete_closure_step(
+      exec_ctx, stream_global, &stream_global->send_initial_metadata_finished,
+      0);
+  grpc_chttp2_complete_closure_step(
+      exec_ctx, stream_global, &stream_global->send_trailing_metadata_finished,
+      0);
+  grpc_chttp2_complete_closure_step(exec_ctx, stream_global,
+                                    &stream_global->send_message_finished, 0);
+}
+
+void grpc_chttp2_mark_stream_closed(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, int close_reads,
+    int close_writes) {
+  if (stream_global->read_closed && stream_global->write_closed) {
+    /* already closed */
+    return;
+  }
+  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+  if (close_reads && !stream_global->read_closed) {
+    stream_global->read_closed = 1;
+    stream_global->published_initial_metadata = 1;
+    stream_global->published_trailing_metadata = 1;
+  }
+  if (close_writes && !stream_global->write_closed) {
+    stream_global->write_closed = 1;
+    if (TRANSPORT_FROM_GLOBAL(transport_global)->writing_active) {
+      GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes");
+      grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
+                                                      stream_global);
+    } else {
+      fail_pending_writes(exec_ctx, stream_global);
+    }
+  }
+  if (stream_global->read_closed && stream_global->write_closed) {
+    if (stream_global->id != 0 &&
+        TRANSPORT_FROM_GLOBAL(transport_global)->parsing_active) {
+      grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
+                                                      stream_global);
+    } else {
+      if (stream_global->id != 0) {
+        remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
+                      stream_global->id);
+      }
+      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
+    }
+  }
+}
+
+static void close_from_api(grpc_exec_ctx *exec_ctx,
+                           grpc_chttp2_transport_global *transport_global,
+                           grpc_chttp2_stream_global *stream_global,
+                           grpc_status_code status,
+                           gpr_slice *optional_message) {
+  gpr_slice hdr;
+  gpr_slice status_hdr;
+  gpr_slice message_pfx;
+  uint8_t *p;
+  uint32_t len = 0;
+
+  GPR_ASSERT(status >= 0 && (int)status < 100);
+
+  GPR_ASSERT(stream_global->id != 0);
+
+  /* Hand roll a header block.
+     This is unnecessarily ugly - at some point we should find a more elegant
+     solution.
+     It's complicated by the fact that our send machinery would be dead by the
+     time we got around to sending this, so instead we ignore HPACK compression
+     and just write the uncompressed bytes onto the wire. */
+  status_hdr = gpr_slice_malloc(15 + (status >= 10));
+  p = GPR_SLICE_START_PTR(status_hdr);
+  *p++ = 0x40; /* literal header */
+  *p++ = 11;   /* len(grpc-status) */
+  *p++ = 'g';
+  *p++ = 'r';
+  *p++ = 'p';
+  *p++ = 'c';
+  *p++ = '-';
+  *p++ = 's';
+  *p++ = 't';
+  *p++ = 'a';
+  *p++ = 't';
+  *p++ = 'u';
+  *p++ = 's';
+  if (status < 10) {
+    *p++ = 1;
+    *p++ = (uint8_t)('0' + status);
+  } else {
+    *p++ = 2;
+    *p++ = (uint8_t)('0' + (status / 10));
+    *p++ = (uint8_t)('0' + (status % 10));
+  }
+  GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
+  len += (uint32_t)GPR_SLICE_LENGTH(status_hdr);
+
+  if (optional_message) {
+    GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127);
+    message_pfx = gpr_slice_malloc(15);
+    p = GPR_SLICE_START_PTR(message_pfx);
+    *p++ = 0x40;
+    *p++ = 12; /* len(grpc-message) */
+    *p++ = 'g';
+    *p++ = 'r';
+    *p++ = 'p';
+    *p++ = 'c';
+    *p++ = '-';
+    *p++ = 'm';
+    *p++ = 'e';
+    *p++ = 's';
+    *p++ = 's';
+    *p++ = 'a';
+    *p++ = 'g';
+    *p++ = 'e';
+    *p++ = (uint8_t)GPR_SLICE_LENGTH(*optional_message);
+    GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
+    len += (uint32_t)GPR_SLICE_LENGTH(message_pfx);
+    len += (uint32_t)GPR_SLICE_LENGTH(*optional_message);
+  }
+
+  hdr = gpr_slice_malloc(9);
+  p = GPR_SLICE_START_PTR(hdr);
+  *p++ = (uint8_t)(len >> 16);
+  *p++ = (uint8_t)(len >> 8);
+  *p++ = (uint8_t)(len);
+  *p++ = GRPC_CHTTP2_FRAME_HEADER;
+  *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
+  *p++ = (uint8_t)(stream_global->id >> 24);
+  *p++ = (uint8_t)(stream_global->id >> 16);
+  *p++ = (uint8_t)(stream_global->id >> 8);
+  *p++ = (uint8_t)(stream_global->id);
+  GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr));
+
+  gpr_slice_buffer_add(&transport_global->qbuf, hdr);
+  gpr_slice_buffer_add(&transport_global->qbuf, status_hdr);
+  if (optional_message) {
+    gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
+    gpr_slice_buffer_add(&transport_global->qbuf,
+                         gpr_slice_ref(*optional_message));
+  }
+
+  gpr_slice_buffer_add(
+      &transport_global->qbuf,
+      grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR,
+                                    &stream_global->stats.outgoing));
+
+  if (optional_message) {
+    gpr_slice_ref(*optional_message);
+  }
+  grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
+                          optional_message);
+  grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
+                                 1);
+}
+
+static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
+                             void *user_data,
+                             grpc_chttp2_stream_global *stream_global) {
+  cancel_from_api(user_data, transport_global, stream_global,
+                  GRPC_STATUS_UNAVAILABLE);
+}
+
+static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_transport *t) {
+  grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb);
+}
+
+static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
+  close_transport_locked(exec_ctx, t);
+  end_all_the_calls(exec_ctx, t);
+}
+
+/** update window from a settings change */
+static void update_global_window(void *args, uint32_t id, void *stream) {
+  grpc_chttp2_transport *t = args;
+  grpc_chttp2_stream *s = stream;
+  grpc_chttp2_transport_global *transport_global = &t->global;
+  grpc_chttp2_stream_global *stream_global = &s->global;
+  int was_zero;
+  int is_zero;
+  int64_t initial_window_update = t->parsing.initial_window_update;
+
+  was_zero = stream_global->outgoing_window <= 0;
+  GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", transport_global, stream_global,
+                                 outgoing_window, initial_window_update);
+  is_zero = stream_global->outgoing_window <= 0;
+
+  if (was_zero && !is_zero) {
+    grpc_chttp2_become_writable(transport_global, stream_global);
+  }
+}
+
+static void read_error_locked(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_transport *t) {
+  t->endpoint_reading = 0;
+  if (!t->writing_active && t->ep) {
+    destroy_endpoint(exec_ctx, t);
+  }
+}
+
+/* tcp read callback */
+static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
+  size_t i;
+  int keep_reading = 0;
+  grpc_chttp2_transport *t = tp;
+  grpc_chttp2_transport_global *transport_global = &t->global;
+  grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
+  grpc_chttp2_stream_global *stream_global;
+
+  GPR_TIMER_BEGIN("recv_data", 0);
+
+  lock(t);
+  i = 0;
+  GPR_ASSERT(!t->parsing_active);
+  if (!t->closed) {
+    t->parsing_active = 1;
+    /* merge stream lists */
+    grpc_chttp2_stream_map_move_into(&t->new_stream_map,
+                                     &t->parsing_stream_map);
+    grpc_chttp2_prepare_to_read(transport_global, transport_parsing);
+    gpr_mu_unlock(&t->mu);
+    GPR_TIMER_BEGIN("recv_data.parse", 0);
+    for (; i < t->read_buffer.count &&
+           grpc_chttp2_perform_read(exec_ctx, transport_parsing,
+                                    t->read_buffer.slices[i]);
+         i++)
+      ;
+    GPR_TIMER_END("recv_data.parse", 0);
+    gpr_mu_lock(&t->mu);
+    /* copy parsing qbuf to global qbuf */
+    gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf);
+    if (i != t->read_buffer.count) {
+      unlock(exec_ctx, t);
+      lock(t);
+      drop_connection(exec_ctx, t);
+    }
+    /* merge stream lists */
+    grpc_chttp2_stream_map_move_into(&t->new_stream_map,
+                                     &t->parsing_stream_map);
+    transport_global->concurrent_stream_count =
+        (uint32_t)grpc_chttp2_stream_map_size(&t->parsing_stream_map);
+    if (transport_parsing->initial_window_update != 0) {
+      grpc_chttp2_stream_map_for_each(&t->parsing_stream_map,
+                                      update_global_window, t);
+      transport_parsing->initial_window_update = 0;
+    }
+    /* handle higher level things */
+    grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing);
+    t->parsing_active = 0;
+    /* handle delayed transport ops (if there is one) */
+    if (t->post_parsing_op) {
+      grpc_transport_op *op = t->post_parsing_op;
+      t->post_parsing_op = NULL;
+      perform_transport_op_locked(exec_ctx, t, op);
+      gpr_free(op);
+    }
+    /* if a stream is in the stream map, and gets cancelled, we need to ensure
+     * we are not parsing before continuing the cancellation to keep things in
+     * a sane state */
+    while (grpc_chttp2_list_pop_closed_waiting_for_parsing(transport_global,
+                                                           &stream_global)) {
+      GPR_ASSERT(stream_global->in_stream_map);
+      GPR_ASSERT(stream_global->write_closed);
+      GPR_ASSERT(stream_global->read_closed);
+      remove_stream(exec_ctx, t, stream_global->id);
+      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
+    }
+  }
+  if (!success || i != t->read_buffer.count || t->closed) {
+    drop_connection(exec_ctx, t);
+    read_error_locked(exec_ctx, t);
+  } else if (!t->closed) {
+    keep_reading = 1;
+    REF_TRANSPORT(t, "keep_reading");
+    prevent_endpoint_shutdown(t);
+  }
+  gpr_slice_buffer_reset_and_unref(&t->read_buffer);
+  unlock(exec_ctx, t);
+
+  if (keep_reading) {
+    grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->recv_data);
+    allow_endpoint_shutdown_unlocked(exec_ctx, t);
+    UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
+  } else {
+    UNREF_TRANSPORT(exec_ctx, t, "recv_data");
+  }
+
+  GPR_TIMER_END("recv_data", 0);
+}
+
+/*******************************************************************************
+ * CALLBACK LOOP
+ */
+
+static void connectivity_state_set(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_connectivity_state state, const char *reason) {
+  GRPC_CHTTP2_IF_TRACING(
+      gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
+  grpc_connectivity_state_set(
+      exec_ctx,
+      &TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker,
+      state, reason);
+}
+
+/*******************************************************************************
+ * POLLSET STUFF
+ */
+
+static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
+                                  grpc_chttp2_transport *t,
+                                  grpc_pollset *pollset) {
+  if (t->ep) {
+    grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset);
+  }
+}
+
+static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
+                                      grpc_chttp2_transport *t,
+                                      grpc_pollset_set *pollset_set) {
+  if (t->ep) {
+    grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set);
+  }
+}
+
+static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                        grpc_stream *gs, grpc_pollset *pollset) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+  lock(t);
+  add_to_pollset_locked(exec_ctx, t, pollset);
+  unlock(exec_ctx, t);
+}
+
+/*******************************************************************************
+ * BYTE STREAM
+ */
+
+static void incoming_byte_stream_update_flow_control(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
+    size_t have_already) {
+  uint32_t max_recv_bytes;
+
+  /* clamp max recv hint to an allowable size */
+  if (max_size_hint >= UINT32_MAX - transport_global->stream_lookahead) {
+    max_recv_bytes = UINT32_MAX - transport_global->stream_lookahead;
+  } else {
+    max_recv_bytes = (uint32_t)max_size_hint;
+  }
+
+  /* account for bytes already received but unknown to higher layers */
+  if (max_recv_bytes >= have_already) {
+    max_recv_bytes -= (uint32_t)have_already;
+  } else {
+    max_recv_bytes = 0;
+  }
+
+  /* add some small lookahead to keep pipelines flowing */
+  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - transport_global->stream_lookahead);
+  max_recv_bytes += transport_global->stream_lookahead;
+  if (stream_global->max_recv_bytes < max_recv_bytes) {
+    uint32_t add_max_recv_bytes =
+        max_recv_bytes - stream_global->max_recv_bytes;
+    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
+                                   max_recv_bytes, add_max_recv_bytes);
+    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
+                                   unannounced_incoming_window_for_parse,
+                                   add_max_recv_bytes);
+    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
+                                   unannounced_incoming_window_for_writing,
+                                   add_max_recv_bytes);
+    grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
+                                                               stream_global);
+    grpc_chttp2_become_writable(transport_global, stream_global);
+  }
+}
+
+static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx,
+                                     grpc_byte_stream *byte_stream,
+                                     gpr_slice *slice, size_t max_size_hint,
+                                     grpc_closure *on_complete) {
+  grpc_chttp2_incoming_byte_stream *bs =
+      (grpc_chttp2_incoming_byte_stream *)byte_stream;
+  grpc_chttp2_transport_global *transport_global = &bs->transport->global;
+  grpc_chttp2_stream_global *stream_global = &bs->stream->global;
+
+  lock(bs->transport);
+  if (bs->is_tail) {
+    incoming_byte_stream_update_flow_control(transport_global, stream_global,
+                                             max_size_hint, bs->slices.length);
+  }
+  if (bs->slices.count > 0) {
+    *slice = gpr_slice_buffer_take_first(&bs->slices);
+    unlock(exec_ctx, bs->transport);
+    return 1;
+  } else if (bs->failed) {
+    grpc_exec_ctx_enqueue(exec_ctx, on_complete, false, NULL);
+    unlock(exec_ctx, bs->transport);
+    return 0;
+  } else {
+    bs->on_next = on_complete;
+    bs->next = slice;
+    unlock(exec_ctx, bs->transport);
+    return 0;
+  }
+}
+
+static void incoming_byte_stream_unref(grpc_chttp2_incoming_byte_stream *bs) {
+  if (gpr_unref(&bs->refs)) {
+    gpr_slice_buffer_destroy(&bs->slices);
+    gpr_free(bs);
+  }
+}
+
+static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
+                                         grpc_byte_stream *byte_stream) {
+  incoming_byte_stream_unref((grpc_chttp2_incoming_byte_stream *)byte_stream);
+}
+
+void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
+                                           grpc_chttp2_incoming_byte_stream *bs,
+                                           gpr_slice slice) {
+  gpr_mu_lock(&bs->transport->mu);
+  if (bs->on_next != NULL) {
+    *bs->next = slice;
+    grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, true, NULL);
+    bs->on_next = NULL;
+  } else {
+    gpr_slice_buffer_add(&bs->slices, slice);
+  }
+  gpr_mu_unlock(&bs->transport->mu);
+}
+
+void grpc_chttp2_incoming_byte_stream_finished(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
+    int from_parsing_thread) {
+  if (!success) {
+    if (from_parsing_thread) {
+      gpr_mu_lock(&bs->transport->mu);
+    }
+    grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, false, NULL);
+    bs->on_next = NULL;
+    bs->failed = 1;
+    if (from_parsing_thread) {
+      gpr_mu_unlock(&bs->transport->mu);
+    }
+  } else {
+#ifndef NDEBUG
+    if (from_parsing_thread) {
+      gpr_mu_lock(&bs->transport->mu);
+    }
+    GPR_ASSERT(bs->on_next == NULL);
+    if (from_parsing_thread) {
+      gpr_mu_unlock(&bs->transport->mu);
+    }
+#endif
+  }
+  incoming_byte_stream_unref(bs);
+}
+
+grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, uint32_t frame_size,
+    uint32_t flags, grpc_chttp2_incoming_frame_queue *add_to_queue) {
+  grpc_chttp2_incoming_byte_stream *incoming_byte_stream =
+      gpr_malloc(sizeof(*incoming_byte_stream));
+  incoming_byte_stream->base.length = frame_size;
+  incoming_byte_stream->base.flags = flags;
+  incoming_byte_stream->base.next = incoming_byte_stream_next;
+  incoming_byte_stream->base.destroy = incoming_byte_stream_destroy;
+  gpr_ref_init(&incoming_byte_stream->refs, 2);
+  incoming_byte_stream->next_message = NULL;
+  incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing);
+  incoming_byte_stream->stream = STREAM_FROM_PARSING(stream_parsing);
+  gpr_slice_buffer_init(&incoming_byte_stream->slices);
+  incoming_byte_stream->on_next = NULL;
+  incoming_byte_stream->is_tail = 1;
+  incoming_byte_stream->failed = 0;
+  if (add_to_queue->head == NULL) {
+    add_to_queue->head = incoming_byte_stream;
+  } else {
+    add_to_queue->tail->is_tail = 0;
+    add_to_queue->tail->next_message = incoming_byte_stream;
+  }
+  add_to_queue->tail = incoming_byte_stream;
+  return incoming_byte_stream;
+}
+
+/*******************************************************************************
+ * TRACING
+ */
+
+static char *format_flowctl_context_var(const char *context, const char *var,
+                                        int64_t val, uint32_t id,
+                                        char **scope) {
+  char *underscore_pos;
+  char *result;
+  if (context == NULL) {
+    *scope = NULL;
+    gpr_asprintf(&result, "%s(%lld)", var, val);
+    return result;
+  }
+  underscore_pos = strchr(context, '_');
+  *scope = gpr_strdup(context);
+  (*scope)[underscore_pos - context] = 0;
+  if (id != 0) {
+    char *tmp = *scope;
+    gpr_asprintf(scope, "%s[%d]", tmp, id);
+    gpr_free(tmp);
+  }
+  gpr_asprintf(&result, "%s.%s(%lld)", underscore_pos + 1, var, val);
+  return result;
+}
+
+static int samestr(char *a, char *b) {
+  if (a == NULL) {
+    return b == NULL;
+  }
+  if (b == NULL) {
+    return 0;
+  }
+  return 0 == strcmp(a, b);
+}
+
+void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
+                               grpc_chttp2_flowctl_op op, const char *context1,
+                               const char *var1, const char *context2,
+                               const char *var2, int is_client,
+                               uint32_t stream_id, int64_t val1, int64_t val2) {
+  char *scope1;
+  char *scope2;
+  char *label1 =
+      format_flowctl_context_var(context1, var1, val1, stream_id, &scope1);
+  char *label2 =
+      format_flowctl_context_var(context2, var2, val2, stream_id, &scope2);
+  char *clisvr = is_client ? "client" : "server";
+  char *prefix;
+
+  gpr_asprintf(&prefix, "FLOW % 8s: %s % 11s ", phase, clisvr, scope1);
+
+  switch (op) {
+    case GRPC_CHTTP2_FLOWCTL_MOVE:
+      GPR_ASSERT(samestr(scope1, scope2));
+      if (val2 != 0) {
+        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+                "%sMOVE   % 40s <- % 40s giving %d", prefix, label1, label2,
+                val1 + val2);
+      }
+      break;
+    case GRPC_CHTTP2_FLOWCTL_CREDIT:
+      GPR_ASSERT(val2 >= 0);
+      if (val2 != 0) {
+        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+                "%sCREDIT % 40s by % 40s giving %d", prefix, label1, label2,
+                val1 + val2);
+      }
+      break;
+    case GRPC_CHTTP2_FLOWCTL_DEBIT:
+      GPR_ASSERT(val2 >= 0);
+      if (val2 != 0) {
+        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+                "%sDEBIT  % 40s by % 40s giving %d", prefix, label1, label2,
+                val1 - val2);
+      }
+      break;
+  }
+
+  gpr_free(scope1);
+  gpr_free(scope2);
+  gpr_free(label1);
+  gpr_free(label2);
+  gpr_free(prefix);
+}
+
+/*******************************************************************************
+ * INTEGRATION GLUE
+ */
+
+static char *chttp2_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
+  return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
+}
+
+static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
+                                             "chttp2",
+                                             init_stream,
+                                             set_pollset,
+                                             perform_stream_op,
+                                             perform_transport_op,
+                                             destroy_stream,
+                                             destroy_transport,
+                                             chttp2_get_peer};
+
+grpc_transport *grpc_create_chttp2_transport(
+    grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
+    grpc_endpoint *ep, int is_client) {
+  grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
+  init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
+  return &t->base;
+}
+
+void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
+                                         grpc_transport *transport,
+                                         gpr_slice *slices, size_t nslices) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
+  REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */
+  gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
+  recv_data(exec_ctx, t, 1);
+}
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/src/core/ext/transport/chttp2/transport/chttp2_transport.h
new file mode 100644
index 0000000..5da4276
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.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_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H
+
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/transport/transport.h"
+
+extern int grpc_http_trace;
+extern int grpc_flowctl_trace;
+
+grpc_transport *grpc_create_chttp2_transport(
+    grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
+    grpc_endpoint *ep, int is_client);
+
+void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
+                                         grpc_transport *transport,
+                                         gpr_slice *slices, size_t nslices);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame.h b/src/core/ext/transport/chttp2/transport/frame.h
new file mode 100644
index 0000000..5c72d91
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+
+/* Common definitions for frame handling in the chttp2 transport */
+
+typedef enum {
+  GRPC_CHTTP2_PARSE_OK,
+  GRPC_CHTTP2_STREAM_ERROR,
+  GRPC_CHTTP2_CONNECTION_ERROR
+} grpc_chttp2_parse_error;
+
+/* defined in internal.h */
+typedef struct grpc_chttp2_stream_parsing grpc_chttp2_stream_parsing;
+typedef struct grpc_chttp2_transport_parsing grpc_chttp2_transport_parsing;
+
+#define GRPC_CHTTP2_FRAME_DATA 0
+#define GRPC_CHTTP2_FRAME_HEADER 1
+#define GRPC_CHTTP2_FRAME_CONTINUATION 9
+#define GRPC_CHTTP2_FRAME_RST_STREAM 3
+#define GRPC_CHTTP2_FRAME_SETTINGS 4
+#define GRPC_CHTTP2_FRAME_PING 6
+#define GRPC_CHTTP2_FRAME_GOAWAY 7
+#define GRPC_CHTTP2_FRAME_WINDOW_UPDATE 8
+
+#define GRPC_CHTTP2_MAX_PAYLOAD_LENGTH ((1 << 14) - 1)
+
+#define GRPC_CHTTP2_DATA_FLAG_END_STREAM 1
+#define GRPC_CHTTP2_FLAG_ACK 1
+#define GRPC_CHTTP2_DATA_FLAG_END_HEADERS 4
+#define GRPC_CHTTP2_DATA_FLAG_PADDED 8
+#define GRPC_CHTTP2_FLAG_HAS_PRIORITY 0x20
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.c b/src/core/ext/transport/chttp2/transport/frame_data.c
new file mode 100644
index 0000000..3a6d80e
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_data.c
@@ -0,0 +1,264 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/frame_data.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/transport.h"
+
+grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
+    grpc_chttp2_data_parser *parser) {
+  parser->state = GRPC_CHTTP2_DATA_FH_0;
+  parser->parsing_frame = NULL;
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
+                                     grpc_chttp2_data_parser *parser) {
+  grpc_byte_stream *bs;
+  if (parser->parsing_frame) {
+    grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame,
+                                              0, 1);
+  }
+  while (
+      (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
+    grpc_byte_stream_destroy(exec_ctx, bs);
+  }
+}
+
+grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
+    grpc_chttp2_data_parser *parser, uint8_t flags) {
+  if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
+    gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
+    return GRPC_CHTTP2_STREAM_ERROR;
+  }
+
+  if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
+    parser->is_last_frame = 1;
+  } else {
+    parser->is_last_frame = 0;
+  }
+
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+void grpc_chttp2_incoming_frame_queue_merge(
+    grpc_chttp2_incoming_frame_queue *head_dst,
+    grpc_chttp2_incoming_frame_queue *tail_src) {
+  if (tail_src->head == NULL) {
+    return;
+  }
+
+  if (head_dst->head == NULL) {
+    *head_dst = *tail_src;
+    memset(tail_src, 0, sizeof(*tail_src));
+    return;
+  }
+
+  head_dst->tail->next_message = tail_src->head;
+  head_dst->tail = tail_src->tail;
+  memset(tail_src, 0, sizeof(*tail_src));
+}
+
+grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
+    grpc_chttp2_incoming_frame_queue *q) {
+  grpc_byte_stream *out;
+  if (q->head == NULL) {
+    return NULL;
+  }
+  out = &q->head->base;
+  if (q->head == q->tail) {
+    memset(q, 0, sizeof(*q));
+  } else {
+    q->head = q->head->next_message;
+  }
+  return out;
+}
+
+void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf,
+                             uint32_t write_bytes, int is_eof,
+                             grpc_transport_one_way_stats *stats,
+                             gpr_slice_buffer *outbuf) {
+  gpr_slice hdr;
+  uint8_t *p;
+  static const size_t header_size = 9;
+
+  hdr = gpr_slice_malloc(header_size);
+  p = GPR_SLICE_START_PTR(hdr);
+  GPR_ASSERT(write_bytes < (1 << 24));
+  *p++ = (uint8_t)(write_bytes >> 16);
+  *p++ = (uint8_t)(write_bytes >> 8);
+  *p++ = (uint8_t)(write_bytes);
+  *p++ = GRPC_CHTTP2_FRAME_DATA;
+  *p++ = is_eof ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0;
+  *p++ = (uint8_t)(id >> 24);
+  *p++ = (uint8_t)(id >> 16);
+  *p++ = (uint8_t)(id >> 8);
+  *p++ = (uint8_t)(id);
+  gpr_slice_buffer_add(outbuf, hdr);
+
+  gpr_slice_buffer_move_first(inbuf, write_bytes, outbuf);
+
+  stats->framing_bytes += header_size;
+  stats->data_bytes += write_bytes;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
+  uint8_t *const end = GPR_SLICE_END_PTR(slice);
+  uint8_t *cur = beg;
+  grpc_chttp2_data_parser *p = parser;
+  uint32_t message_flags;
+  grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
+
+  if (is_last && p->is_last_frame) {
+    stream_parsing->received_close = 1;
+  }
+
+  if (cur == end) {
+    return GRPC_CHTTP2_PARSE_OK;
+  }
+
+  switch (p->state) {
+    case GRPC_CHTTP2_DATA_ERROR:
+      p->state = GRPC_CHTTP2_DATA_ERROR;
+      return GRPC_CHTTP2_STREAM_ERROR;
+    fh_0:
+    case GRPC_CHTTP2_DATA_FH_0:
+      stream_parsing->stats.incoming.framing_bytes++;
+      p->frame_type = *cur;
+      switch (p->frame_type) {
+        case 0:
+          p->is_frame_compressed = 0; /* GPR_FALSE */
+          break;
+        case 1:
+          p->is_frame_compressed = 1; /* GPR_TRUE */
+          break;
+        default:
+          gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
+          p->state = GRPC_CHTTP2_DATA_ERROR;
+          return GRPC_CHTTP2_STREAM_ERROR;
+      }
+      if (++cur == end) {
+        p->state = GRPC_CHTTP2_DATA_FH_1;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+    /* fallthrough */
+    case GRPC_CHTTP2_DATA_FH_1:
+      stream_parsing->stats.incoming.framing_bytes++;
+      p->frame_size = ((uint32_t)*cur) << 24;
+      if (++cur == end) {
+        p->state = GRPC_CHTTP2_DATA_FH_2;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+    /* fallthrough */
+    case GRPC_CHTTP2_DATA_FH_2:
+      stream_parsing->stats.incoming.framing_bytes++;
+      p->frame_size |= ((uint32_t)*cur) << 16;
+      if (++cur == end) {
+        p->state = GRPC_CHTTP2_DATA_FH_3;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+    /* fallthrough */
+    case GRPC_CHTTP2_DATA_FH_3:
+      stream_parsing->stats.incoming.framing_bytes++;
+      p->frame_size |= ((uint32_t)*cur) << 8;
+      if (++cur == end) {
+        p->state = GRPC_CHTTP2_DATA_FH_4;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+    /* fallthrough */
+    case GRPC_CHTTP2_DATA_FH_4:
+      stream_parsing->stats.incoming.framing_bytes++;
+      p->frame_size |= ((uint32_t)*cur);
+      p->state = GRPC_CHTTP2_DATA_FRAME;
+      ++cur;
+      message_flags = 0;
+      if (p->is_frame_compressed) {
+        message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
+      }
+      p->parsing_frame = incoming_byte_stream =
+          grpc_chttp2_incoming_byte_stream_create(
+              exec_ctx, transport_parsing, stream_parsing, p->frame_size,
+              message_flags, &p->incoming_frames);
+    /* fallthrough */
+    case GRPC_CHTTP2_DATA_FRAME:
+      grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
+                                               stream_parsing);
+      if (cur == end) {
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      uint32_t remaining = (uint32_t)(end - cur);
+      if (remaining == p->frame_size) {
+        stream_parsing->stats.incoming.data_bytes += p->frame_size;
+        grpc_chttp2_incoming_byte_stream_push(
+            exec_ctx, p->parsing_frame,
+            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
+        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
+                                                  1);
+        p->parsing_frame = NULL;
+        p->state = GRPC_CHTTP2_DATA_FH_0;
+        return GRPC_CHTTP2_PARSE_OK;
+      } else if (remaining > p->frame_size) {
+        stream_parsing->stats.incoming.data_bytes += p->frame_size;
+        grpc_chttp2_incoming_byte_stream_push(
+            exec_ctx, p->parsing_frame,
+            gpr_slice_sub(slice, (size_t)(cur - beg),
+                          (size_t)(cur + p->frame_size - beg)));
+        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
+                                                  1);
+        p->parsing_frame = NULL;
+        cur += p->frame_size;
+        goto fh_0; /* loop */
+      } else {
+        GPR_ASSERT(remaining <= p->frame_size);
+        grpc_chttp2_incoming_byte_stream_push(
+            exec_ctx, p->parsing_frame,
+            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
+        p->frame_size -= remaining;
+        stream_parsing->stats.incoming.data_bytes += remaining;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+  }
+
+  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
+}
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.h b/src/core/ext/transport/chttp2/transport/frame_data.h
new file mode 100644
index 0000000..af71f48
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_data.h
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H
+
+/* Parser for GRPC streams embedded in DATA frames */
+
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/transport/byte_stream.h"
+#include "src/core/lib/transport/transport.h"
+
+typedef enum {
+  GRPC_CHTTP2_DATA_FH_0,
+  GRPC_CHTTP2_DATA_FH_1,
+  GRPC_CHTTP2_DATA_FH_2,
+  GRPC_CHTTP2_DATA_FH_3,
+  GRPC_CHTTP2_DATA_FH_4,
+  GRPC_CHTTP2_DATA_FRAME,
+  GRPC_CHTTP2_DATA_ERROR
+} grpc_chttp2_stream_state;
+
+typedef struct grpc_chttp2_incoming_byte_stream
+    grpc_chttp2_incoming_byte_stream;
+
+typedef struct grpc_chttp2_incoming_frame_queue {
+  grpc_chttp2_incoming_byte_stream *head;
+  grpc_chttp2_incoming_byte_stream *tail;
+} grpc_chttp2_incoming_frame_queue;
+
+typedef struct {
+  grpc_chttp2_stream_state state;
+  uint8_t is_last_frame;
+  uint8_t frame_type;
+  uint32_t frame_size;
+
+  int is_frame_compressed;
+  grpc_chttp2_incoming_frame_queue incoming_frames;
+  grpc_chttp2_incoming_byte_stream *parsing_frame;
+} grpc_chttp2_data_parser;
+
+void grpc_chttp2_incoming_frame_queue_merge(
+    grpc_chttp2_incoming_frame_queue *head_dst,
+    grpc_chttp2_incoming_frame_queue *tail_src);
+grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
+    grpc_chttp2_incoming_frame_queue *q);
+
+/* initialize per-stream state for data frame parsing */
+grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
+    grpc_chttp2_data_parser *parser);
+
+void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
+                                     grpc_chttp2_data_parser *parser);
+
+/* start processing a new data frame */
+grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
+    grpc_chttp2_data_parser *parser, uint8_t flags);
+
+/* handle a slice of a data frame - is_last indicates the last slice of a
+   frame */
+grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf,
+                             uint32_t write_bytes, int is_eof,
+                             grpc_transport_one_way_stats *stats,
+                             gpr_slice_buffer *outbuf);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.c b/src/core/ext/transport/chttp2/transport/frame_goaway.c
new file mode 100644
index 0000000..69accb7
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.c
@@ -0,0 +1,193 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/frame_goaway.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) {
+  p->debug_data = NULL;
+}
+
+void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p) {
+  gpr_free(p->debug_data);
+}
+
+grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
+    grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) {
+  if (length < 8) {
+    gpr_log(GPR_ERROR, "goaway frame too short (%d bytes)", length);
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  }
+
+  gpr_free(p->debug_data);
+  p->debug_length = length - 8;
+  p->debug_data = gpr_malloc(p->debug_length);
+  p->debug_pos = 0;
+  p->state = GRPC_CHTTP2_GOAWAY_LSI0;
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
+  uint8_t *const end = GPR_SLICE_END_PTR(slice);
+  uint8_t *cur = beg;
+  grpc_chttp2_goaway_parser *p = parser;
+
+  switch (p->state) {
+    case GRPC_CHTTP2_GOAWAY_LSI0:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_LSI0;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->last_stream_id = ((uint32_t)*cur) << 24;
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_LSI1:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_LSI1;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->last_stream_id |= ((uint32_t)*cur) << 16;
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_LSI2:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_LSI2;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->last_stream_id |= ((uint32_t)*cur) << 8;
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_LSI3:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_LSI3;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->last_stream_id |= ((uint32_t)*cur);
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_ERR0:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_ERR0;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->error_code = ((uint32_t)*cur) << 24;
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_ERR1:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_ERR1;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->error_code |= ((uint32_t)*cur) << 16;
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_ERR2:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_ERR2;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->error_code |= ((uint32_t)*cur) << 8;
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_ERR3:
+      if (cur == end) {
+        p->state = GRPC_CHTTP2_GOAWAY_ERR3;
+        return GRPC_CHTTP2_PARSE_OK;
+      }
+      p->error_code |= ((uint32_t)*cur);
+      ++cur;
+    /* fallthrough */
+    case GRPC_CHTTP2_GOAWAY_DEBUG:
+      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;
+      if (is_last) {
+        transport_parsing->goaway_received = 1;
+        transport_parsing->goaway_last_stream_index = p->last_stream_id;
+        gpr_slice_unref(transport_parsing->goaway_text);
+        transport_parsing->goaway_error = (grpc_status_code)p->error_code;
+        transport_parsing->goaway_text =
+            gpr_slice_new(p->debug_data, p->debug_length, gpr_free);
+        p->debug_data = NULL;
+      }
+      return GRPC_CHTTP2_PARSE_OK;
+  }
+  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
+}
+
+void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,
+                               gpr_slice debug_data,
+                               gpr_slice_buffer *slice_buffer) {
+  gpr_slice header = gpr_slice_malloc(9 + 4 + 4);
+  uint8_t *p = GPR_SLICE_START_PTR(header);
+  uint32_t frame_length;
+  GPR_ASSERT(GPR_SLICE_LENGTH(debug_data) < UINT32_MAX - 4 - 4);
+  frame_length = 4 + 4 + (uint32_t)GPR_SLICE_LENGTH(debug_data);
+
+  /* frame header: length */
+  *p++ = (uint8_t)(frame_length >> 16);
+  *p++ = (uint8_t)(frame_length >> 8);
+  *p++ = (uint8_t)(frame_length);
+  /* frame header: type */
+  *p++ = GRPC_CHTTP2_FRAME_GOAWAY;
+  /* frame header: flags */
+  *p++ = 0;
+  /* frame header: stream id */
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = 0;
+  /* payload: last stream id */
+  *p++ = (uint8_t)(last_stream_id >> 24);
+  *p++ = (uint8_t)(last_stream_id >> 16);
+  *p++ = (uint8_t)(last_stream_id >> 8);
+  *p++ = (uint8_t)(last_stream_id);
+  /* payload: error code */
+  *p++ = (uint8_t)(error_code >> 24);
+  *p++ = (uint8_t)(error_code >> 16);
+  *p++ = (uint8_t)(error_code >> 8);
+  *p++ = (uint8_t)(error_code);
+  GPR_ASSERT(p == GPR_SLICE_END_PTR(header));
+  gpr_slice_buffer_add(slice_buffer, header);
+  gpr_slice_buffer_add(slice_buffer, debug_data);
+}
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.h b/src/core/ext/transport/chttp2/transport/frame_goaway.h
new file mode 100644
index 0000000..7c38b26
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+typedef enum {
+  GRPC_CHTTP2_GOAWAY_LSI0,
+  GRPC_CHTTP2_GOAWAY_LSI1,
+  GRPC_CHTTP2_GOAWAY_LSI2,
+  GRPC_CHTTP2_GOAWAY_LSI3,
+  GRPC_CHTTP2_GOAWAY_ERR0,
+  GRPC_CHTTP2_GOAWAY_ERR1,
+  GRPC_CHTTP2_GOAWAY_ERR2,
+  GRPC_CHTTP2_GOAWAY_ERR3,
+  GRPC_CHTTP2_GOAWAY_DEBUG
+} grpc_chttp2_goaway_parse_state;
+
+typedef struct {
+  grpc_chttp2_goaway_parse_state state;
+  uint32_t last_stream_id;
+  uint32_t error_code;
+  char *debug_data;
+  uint32_t debug_length;
+  uint32_t debug_pos;
+} grpc_chttp2_goaway_parser;
+
+void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p);
+void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p);
+grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
+    grpc_chttp2_goaway_parser *parser, uint32_t length, uint8_t flags);
+grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,
+                               gpr_slice debug_data,
+                               gpr_slice_buffer *slice_buffer);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.c b/src/core/ext/transport/chttp2/transport/frame_ping.c
new file mode 100644
index 0000000..7e1815f
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -0,0 +1,97 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/frame_ping.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
+  gpr_slice slice = gpr_slice_malloc(9 + 8);
+  uint8_t *p = GPR_SLICE_START_PTR(slice);
+
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = 8;
+  *p++ = GRPC_CHTTP2_FRAME_PING;
+  *p++ = ack ? 1 : 0;
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = 0;
+  memcpy(p, opaque_8bytes, 8);
+
+  return slice;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
+    grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags) {
+  if (flags & 0xfe || length != 8) {
+    gpr_log(GPR_ERROR, "invalid ping: length=%d, flags=%02x", length, flags);
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  }
+  parser->byte = 0;
+  parser->is_ack = flags;
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
+  uint8_t *const end = GPR_SLICE_END_PTR(slice);
+  uint8_t *cur = beg;
+  grpc_chttp2_ping_parser *p = parser;
+
+  while (p->byte != 8 && cur != end) {
+    p->opaque_8bytes[p->byte] = *cur;
+    cur++;
+    p->byte++;
+  }
+
+  if (p->byte == 8) {
+    GPR_ASSERT(is_last);
+    if (p->is_ack) {
+      grpc_chttp2_ack_ping(exec_ctx, transport_parsing, p->opaque_8bytes);
+    } else {
+      gpr_slice_buffer_add(&transport_parsing->qbuf,
+                           grpc_chttp2_ping_create(1, p->opaque_8bytes));
+    }
+  }
+
+  return GRPC_CHTTP2_PARSE_OK;
+}
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.h b/src/core/ext/transport/chttp2/transport/frame_ping.h
new file mode 100644
index 0000000..4f7fcc1
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H
+
+#include <grpc/support/slice.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+typedef struct {
+  uint8_t byte;
+  uint8_t is_ack;
+  uint8_t opaque_8bytes[8];
+} grpc_chttp2_ping_parser;
+
+gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes);
+
+grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
+    grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags);
+grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
new file mode 100644
index 0000000..22467e9
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/frame_rst_stream.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+
+gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code,
+                                        grpc_transport_one_way_stats *stats) {
+  static const size_t frame_size = 13;
+  gpr_slice slice = gpr_slice_malloc(frame_size);
+  stats->framing_bytes += frame_size;
+  uint8_t *p = GPR_SLICE_START_PTR(slice);
+
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = 4;
+  *p++ = GRPC_CHTTP2_FRAME_RST_STREAM;
+  *p++ = 0;
+  *p++ = (uint8_t)(id >> 24);
+  *p++ = (uint8_t)(id >> 16);
+  *p++ = (uint8_t)(id >> 8);
+  *p++ = (uint8_t)(id);
+  *p++ = (uint8_t)(code >> 24);
+  *p++ = (uint8_t)(code >> 16);
+  *p++ = (uint8_t)(code >> 8);
+  *p++ = (uint8_t)(code);
+
+  return slice;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
+    grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags) {
+  if (length != 4) {
+    gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length,
+            flags);
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  }
+  parser->byte = 0;
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
+  uint8_t *const end = GPR_SLICE_END_PTR(slice);
+  uint8_t *cur = beg;
+  grpc_chttp2_rst_stream_parser *p = parser;
+
+  while (p->byte != 4 && cur != end) {
+    p->reason_bytes[p->byte] = *cur;
+    cur++;
+    p->byte++;
+  }
+  stream_parsing->stats.incoming.framing_bytes += (uint64_t)(end - cur);
+
+  if (p->byte == 4) {
+    GPR_ASSERT(is_last);
+    stream_parsing->received_close = 1;
+    stream_parsing->saw_rst_stream = 1;
+    stream_parsing->rst_stream_reason = (((uint32_t)p->reason_bytes[0]) << 24) |
+                                        (((uint32_t)p->reason_bytes[1]) << 16) |
+                                        (((uint32_t)p->reason_bytes[2]) << 8) |
+                                        (((uint32_t)p->reason_bytes[3]));
+  }
+
+  return GRPC_CHTTP2_PARSE_OK;
+}
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
new file mode 100644
index 0000000..9c1e756
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H
+
+#include <grpc/support/slice.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/transport/transport.h"
+
+typedef struct {
+  uint8_t byte;
+  uint8_t reason_bytes[4];
+} grpc_chttp2_rst_stream_parser;
+
+gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code,
+                                        grpc_transport_one_way_stats *stats);
+
+grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
+    grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags);
+grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c
new file mode 100644
index 0000000..a3c1e15
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.c
@@ -0,0 +1,259 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/frame_settings.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <string.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
+#include "src/core/lib/debug/trace.h"
+
+#define MAX_MAX_HEADER_LIST_SIZE (1024 * 1024 * 1024)
+
+/* HTTP/2 mandated initial connection settings */
+const grpc_chttp2_setting_parameters
+    grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {
+        {NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
+         GRPC_CHTTP2_PROTOCOL_ERROR},
+        {"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff,
+         GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
+        {"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
+         GRPC_CHTTP2_PROTOCOL_ERROR},
+        {"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu,
+         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
+        {"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu,
+         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
+         GRPC_CHTTP2_FLOW_CONTROL_ERROR},
+        {"MAX_FRAME_SIZE", 16384, 16384, 16777215,
+         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
+        {"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0,
+         MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE,
+         GRPC_CHTTP2_PROTOCOL_ERROR},
+};
+
+static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) {
+  *out++ = (uint8_t)(length >> 16);
+  *out++ = (uint8_t)(length >> 8);
+  *out++ = (uint8_t)(length);
+  *out++ = GRPC_CHTTP2_FRAME_SETTINGS;
+  *out++ = flags;
+  *out++ = 0;
+  *out++ = 0;
+  *out++ = 0;
+  *out++ = 0;
+  return out;
+}
+
+gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
+                                      uint32_t force_mask, size_t count) {
+  size_t i;
+  uint32_t n = 0;
+  gpr_slice output;
+  uint8_t *p;
+
+  for (i = 0; i < count; i++) {
+    n += (new[i] != old[i] || (force_mask & (1u << i)) != 0);
+  }
+
+  output = gpr_slice_malloc(9 + 6 * n);
+  p = fill_header(GPR_SLICE_START_PTR(output), 6 * n, 0);
+
+  for (i = 0; i < count; i++) {
+    if (new[i] != old[i] || (force_mask & (1u << i)) != 0) {
+      GPR_ASSERT(i);
+      *p++ = (uint8_t)(i >> 8);
+      *p++ = (uint8_t)(i);
+      *p++ = (uint8_t)(new[i] >> 24);
+      *p++ = (uint8_t)(new[i] >> 16);
+      *p++ = (uint8_t)(new[i] >> 8);
+      *p++ = (uint8_t)(new[i]);
+      old[i] = new[i];
+    }
+  }
+
+  GPR_ASSERT(p == GPR_SLICE_END_PTR(output));
+
+  return output;
+}
+
+gpr_slice grpc_chttp2_settings_ack_create(void) {
+  gpr_slice output = gpr_slice_malloc(9);
+  fill_header(GPR_SLICE_START_PTR(output), 0, GRPC_CHTTP2_FLAG_ACK);
+  return output;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
+    grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
+    uint32_t *settings) {
+  parser->target_settings = settings;
+  memcpy(parser->incoming_settings, settings,
+         GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
+  parser->is_ack = 0;
+  parser->state = GRPC_CHTTP2_SPS_ID0;
+  if (flags == GRPC_CHTTP2_FLAG_ACK) {
+    parser->is_ack = 1;
+    if (length != 0) {
+      gpr_log(GPR_ERROR, "non-empty settings ack frame received");
+      return GRPC_CHTTP2_CONNECTION_ERROR;
+    }
+    return GRPC_CHTTP2_PARSE_OK;
+  } else if (flags != 0) {
+    gpr_log(GPR_ERROR, "invalid flags on settings frame");
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  } else if (length % 6 != 0) {
+    gpr_log(GPR_ERROR, "settings frames must be a multiple of six bytes");
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  } else {
+    return GRPC_CHTTP2_PARSE_OK;
+  }
+}
+
+grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *p,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  grpc_chttp2_settings_parser *parser = p;
+  const uint8_t *cur = GPR_SLICE_START_PTR(slice);
+  const uint8_t *end = GPR_SLICE_END_PTR(slice);
+
+  if (parser->is_ack) {
+    return GRPC_CHTTP2_PARSE_OK;
+  }
+
+  for (;;) {
+    switch (parser->state) {
+      case GRPC_CHTTP2_SPS_ID0:
+        if (cur == end) {
+          parser->state = GRPC_CHTTP2_SPS_ID0;
+          if (is_last) {
+            transport_parsing->settings_updated = 1;
+            memcpy(parser->target_settings, parser->incoming_settings,
+                   GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
+            gpr_slice_buffer_add(&transport_parsing->qbuf,
+                                 grpc_chttp2_settings_ack_create());
+          }
+          return GRPC_CHTTP2_PARSE_OK;
+        }
+        parser->id = (uint16_t)(((uint16_t)*cur) << 8);
+        cur++;
+      /* fallthrough */
+      case GRPC_CHTTP2_SPS_ID1:
+        if (cur == end) {
+          parser->state = GRPC_CHTTP2_SPS_ID1;
+          return GRPC_CHTTP2_PARSE_OK;
+        }
+        parser->id = (uint16_t)(parser->id | (*cur));
+        cur++;
+      /* fallthrough */
+      case GRPC_CHTTP2_SPS_VAL0:
+        if (cur == end) {
+          parser->state = GRPC_CHTTP2_SPS_VAL0;
+          return GRPC_CHTTP2_PARSE_OK;
+        }
+        parser->value = ((uint32_t)*cur) << 24;
+        cur++;
+      /* fallthrough */
+      case GRPC_CHTTP2_SPS_VAL1:
+        if (cur == end) {
+          parser->state = GRPC_CHTTP2_SPS_VAL1;
+          return GRPC_CHTTP2_PARSE_OK;
+        }
+        parser->value |= ((uint32_t)*cur) << 16;
+        cur++;
+      /* fallthrough */
+      case GRPC_CHTTP2_SPS_VAL2:
+        if (cur == end) {
+          parser->state = GRPC_CHTTP2_SPS_VAL2;
+          return GRPC_CHTTP2_PARSE_OK;
+        }
+        parser->value |= ((uint32_t)*cur) << 8;
+        cur++;
+      /* fallthrough */
+      case GRPC_CHTTP2_SPS_VAL3:
+        if (cur == end) {
+          parser->state = GRPC_CHTTP2_SPS_VAL3;
+          return GRPC_CHTTP2_PARSE_OK;
+        } else {
+          parser->state = GRPC_CHTTP2_SPS_ID0;
+        }
+        parser->value |= *cur;
+        cur++;
+
+        if (parser->id > 0 && parser->id < GRPC_CHTTP2_NUM_SETTINGS) {
+          const grpc_chttp2_setting_parameters *sp =
+              &grpc_chttp2_settings_parameters[parser->id];
+          if (parser->value < sp->min_value || parser->value > sp->max_value) {
+            switch (sp->invalid_value_behavior) {
+              case GRPC_CHTTP2_CLAMP_INVALID_VALUE:
+                parser->value =
+                    GPR_CLAMP(parser->value, sp->min_value, sp->max_value);
+                break;
+              case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE:
+                grpc_chttp2_goaway_append(
+                    transport_parsing->last_incoming_stream_id, sp->error_value,
+                    gpr_slice_from_static_string("HTTP2 settings error"),
+                    &transport_parsing->qbuf);
+                gpr_log(GPR_ERROR, "invalid value %u passed for %s",
+                        parser->value, sp->name);
+                return GRPC_CHTTP2_CONNECTION_ERROR;
+            }
+          }
+          if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
+              parser->incoming_settings[parser->id] != parser->value) {
+            transport_parsing->initial_window_update =
+                (int64_t)parser->value - parser->incoming_settings[parser->id];
+            if (grpc_http_trace) {
+              gpr_log(GPR_DEBUG, "adding %d for initial_window change",
+                      (int)transport_parsing->initial_window_update);
+            }
+          }
+          parser->incoming_settings[parser->id] = parser->value;
+          if (grpc_http_trace) {
+            gpr_log(GPR_DEBUG, "CHTTP2:%s: got setting %d = %d",
+                    transport_parsing->is_client ? "CLI" : "SVR", parser->id,
+                    parser->value);
+          }
+        } else {
+          gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
+                  parser->id, parser->value);
+        }
+        break;
+    }
+  }
+}
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h
new file mode 100644
index 0000000..d9e30f1
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.h
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+typedef enum {
+  GRPC_CHTTP2_SPS_ID0,
+  GRPC_CHTTP2_SPS_ID1,
+  GRPC_CHTTP2_SPS_VAL0,
+  GRPC_CHTTP2_SPS_VAL1,
+  GRPC_CHTTP2_SPS_VAL2,
+  GRPC_CHTTP2_SPS_VAL3
+} grpc_chttp2_settings_parse_state;
+
+/* The things HTTP/2 defines as connection level settings */
+typedef enum {
+  GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 1,
+  GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 2,
+  GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 3,
+  GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 4,
+  GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 5,
+  GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 6,
+  GRPC_CHTTP2_NUM_SETTINGS
+} grpc_chttp2_setting_id;
+
+typedef struct {
+  grpc_chttp2_settings_parse_state state;
+  uint32_t *target_settings;
+  uint8_t is_ack;
+  uint16_t id;
+  uint32_t value;
+  uint32_t incoming_settings[GRPC_CHTTP2_NUM_SETTINGS];
+} grpc_chttp2_settings_parser;
+
+typedef enum {
+  GRPC_CHTTP2_CLAMP_INVALID_VALUE,
+  GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
+} grpc_chttp2_invalid_value_behavior;
+
+typedef struct {
+  const char *name;
+  uint32_t default_value;
+  uint32_t min_value;
+  uint32_t max_value;
+  grpc_chttp2_invalid_value_behavior invalid_value_behavior;
+  uint32_t error_value;
+} grpc_chttp2_setting_parameters;
+
+/* HTTP/2 mandated connection setting parameters */
+extern const grpc_chttp2_setting_parameters
+    grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
+
+/* Create a settings frame by diffing old & new, and updating old to be new */
+gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
+                                      uint32_t force_mask, size_t count);
+/* Create an ack settings frame */
+gpr_slice grpc_chttp2_settings_ack_create(void);
+
+grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
+    grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
+    uint32_t *settings);
+grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.c b/src/core/ext/transport/chttp2/transport/frame_window_update.c
new file mode 100644
index 0000000..9024341
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/frame_window_update.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <grpc/support/log.h>
+
+gpr_slice grpc_chttp2_window_update_create(
+    uint32_t id, uint32_t window_update, grpc_transport_one_way_stats *stats) {
+  static const size_t frame_size = 13;
+  gpr_slice slice = gpr_slice_malloc(frame_size);
+  stats->header_bytes += frame_size;
+  uint8_t *p = GPR_SLICE_START_PTR(slice);
+
+  GPR_ASSERT(window_update);
+
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = 4;
+  *p++ = GRPC_CHTTP2_FRAME_WINDOW_UPDATE;
+  *p++ = 0;
+  *p++ = (uint8_t)(id >> 24);
+  *p++ = (uint8_t)(id >> 16);
+  *p++ = (uint8_t)(id >> 8);
+  *p++ = (uint8_t)(id);
+  *p++ = (uint8_t)(window_update >> 24);
+  *p++ = (uint8_t)(window_update >> 16);
+  *p++ = (uint8_t)(window_update >> 8);
+  *p++ = (uint8_t)(window_update);
+
+  return slice;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
+    grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags) {
+  if (flags || length != 4) {
+    gpr_log(GPR_ERROR, "invalid window update: length=%d, flags=%02x", length,
+            flags);
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  }
+  parser->byte = 0;
+  parser->amount = 0;
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
+  uint8_t *const end = GPR_SLICE_END_PTR(slice);
+  uint8_t *cur = beg;
+  grpc_chttp2_window_update_parser *p = parser;
+
+  while (p->byte != 4 && cur != end) {
+    p->amount |= ((uint32_t)*cur) << (8 * (3 - p->byte));
+    cur++;
+    p->byte++;
+  }
+
+  if (stream_parsing != NULL) {
+    stream_parsing->stats.incoming.framing_bytes += (uint32_t)(end - cur);
+  }
+
+  if (p->byte == 4) {
+    uint32_t received_update = p->amount;
+    if (received_update == 0 || (received_update & 0x80000000u)) {
+      gpr_log(GPR_ERROR, "invalid window update bytes: %d", p->amount);
+      return GRPC_CHTTP2_CONNECTION_ERROR;
+    }
+    GPR_ASSERT(is_last);
+
+    if (transport_parsing->incoming_stream_id != 0) {
+      if (stream_parsing != NULL) {
+        GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", transport_parsing,
+                                       stream_parsing, outgoing_window,
+                                       received_update);
+        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
+                                                 stream_parsing);
+      }
+    } else {
+      GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parse", transport_parsing,
+                                        outgoing_window, received_update);
+    }
+  }
+
+  return GRPC_CHTTP2_PARSE_OK;
+}
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.h b/src/core/ext/transport/chttp2/transport/frame_window_update.h
new file mode 100644
index 0000000..d6e87b9
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H
+
+#include <grpc/support/slice.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/transport/transport.h"
+
+typedef struct {
+  uint8_t byte;
+  uint8_t is_connection_update;
+  uint32_t amount;
+} grpc_chttp2_window_update_parser;
+
+gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta,
+                                           grpc_transport_one_way_stats *stats);
+
+grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
+    grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags);
+grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
new file mode 100644
index 0000000..555027c
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
@@ -0,0 +1,573 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/hpack_encoder.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* This is here for grpc_is_binary_header
+ * TODO(murgatroid99): Remove this
+ */
+#include <grpc/grpc.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_table.h"
+#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
+#include "src/core/ext/transport/chttp2/transport/varint.h"
+#include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+#define HASH_FRAGMENT_1(x) ((x)&255)
+#define HASH_FRAGMENT_2(x) ((x >> 8) & 255)
+#define HASH_FRAGMENT_3(x) ((x >> 16) & 255)
+#define HASH_FRAGMENT_4(x) ((x >> 24) & 255)
+
+/* if the probability of this item being seen again is < 1/x then don't add
+   it to the table */
+#define ONE_ON_ADD_PROBABILITY 128
+/* don't consider adding anything bigger than this to the hpack table */
+#define MAX_DECODER_SPACE_USAGE 512
+
+typedef struct {
+  int is_first_frame;
+  /* number of bytes in 'output' when we started the frame - used to calculate
+     frame length */
+  size_t output_length_at_start_of_frame;
+  /* index (in output) of the header for the current frame */
+  size_t header_idx;
+  /* have we seen a regular (non-colon-prefixed) header yet? */
+  uint8_t seen_regular_header;
+  /* output stream id */
+  uint32_t stream_id;
+  gpr_slice_buffer *output;
+  grpc_transport_one_way_stats *stats;
+} framer_state;
+
+/* fills p (which is expected to be 9 bytes long) with a data frame header */
+static void fill_header(uint8_t *p, uint8_t type, uint32_t id, size_t len,
+                        uint8_t flags) {
+  GPR_ASSERT(len < 16777316);
+  *p++ = (uint8_t)(len >> 16);
+  *p++ = (uint8_t)(len >> 8);
+  *p++ = (uint8_t)(len);
+  *p++ = type;
+  *p++ = flags;
+  *p++ = (uint8_t)(id >> 24);
+  *p++ = (uint8_t)(id >> 16);
+  *p++ = (uint8_t)(id >> 8);
+  *p++ = (uint8_t)(id);
+}
+
+/* finish a frame - fill in the previously reserved header */
+static void finish_frame(framer_state *st, int is_header_boundary,
+                         int is_last_in_stream) {
+  uint8_t type = 0xff;
+  type = st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER
+                            : GRPC_CHTTP2_FRAME_CONTINUATION;
+  fill_header(
+      GPR_SLICE_START_PTR(st->output->slices[st->header_idx]), type,
+      st->stream_id, st->output->length - st->output_length_at_start_of_frame,
+      (uint8_t)((is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) |
+                (is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0)));
+  st->stats->framing_bytes += 9;
+  st->is_first_frame = 0;
+}
+
+/* begin a new frame: reserve off header space, remember how many bytes we'd
+   output before beginning */
+static void begin_frame(framer_state *st) {
+  st->header_idx =
+      gpr_slice_buffer_add_indexed(st->output, gpr_slice_malloc(9));
+  st->output_length_at_start_of_frame = st->output->length;
+}
+
+/* make sure that the current frame is of the type desired, and has sufficient
+   space to add at least about_to_add bytes -- finishes the current frame if
+   needed */
+static void ensure_space(framer_state *st, size_t need_bytes) {
+  if (st->output->length - st->output_length_at_start_of_frame + need_bytes <=
+      GRPC_CHTTP2_MAX_PAYLOAD_LENGTH) {
+    return;
+  }
+  finish_frame(st, 0, 0);
+  begin_frame(st);
+}
+
+/* increment a filter count, halve all counts if one element reaches max */
+static void inc_filter(uint8_t idx, uint32_t *sum, uint8_t *elems) {
+  elems[idx]++;
+  if (elems[idx] < 255) {
+    (*sum)++;
+  } else {
+    int i;
+    *sum = 0;
+    for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_FILTERS; i++) {
+      elems[i] /= 2;
+      (*sum) += elems[i];
+    }
+  }
+}
+
+static void add_header_data(framer_state *st, gpr_slice slice) {
+  size_t len = GPR_SLICE_LENGTH(slice);
+  size_t remaining;
+  if (len == 0) return;
+  remaining = GRPC_CHTTP2_MAX_PAYLOAD_LENGTH +
+              st->output_length_at_start_of_frame - st->output->length;
+  if (len <= remaining) {
+    st->stats->header_bytes += len;
+    gpr_slice_buffer_add(st->output, slice);
+  } else {
+    st->stats->header_bytes += remaining;
+    gpr_slice_buffer_add(st->output, gpr_slice_split_head(&slice, remaining));
+    finish_frame(st, 0, 0);
+    begin_frame(st);
+    add_header_data(st, slice);
+  }
+}
+
+static uint8_t *add_tiny_header_data(framer_state *st, size_t len) {
+  ensure_space(st, len);
+  return gpr_slice_buffer_tiny_add(st->output, len);
+}
+
+static void evict_entry(grpc_chttp2_hpack_compressor *c) {
+  c->tail_remote_index++;
+  GPR_ASSERT(c->tail_remote_index > 0);
+  GPR_ASSERT(c->table_size >=
+             c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
+  GPR_ASSERT(c->table_elems > 0);
+  c->table_size =
+      (uint16_t)(c->table_size -
+                 c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
+  c->table_elems--;
+}
+
+/* add an element to the decoder table */
+static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) {
+  uint32_t key_hash = elem->key->hash;
+  uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
+  uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
+  size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
+
+  GPR_ASSERT(elem_size < 65536);
+
+  if (elem_size > c->max_table_size) {
+    while (c->table_size > 0) {
+      evict_entry(c);
+    }
+    return;
+  }
+
+  /* Reserve space for this element in the remote table: if this overflows
+     the current table, drop elements until it fits, matching the decompressor
+     algorithm */
+  while (c->table_size + elem_size > c->max_table_size) {
+    evict_entry(c);
+  }
+  GPR_ASSERT(c->table_elems < c->max_table_size);
+  c->table_elem_size[new_index % c->cap_table_elems] = (uint16_t)elem_size;
+  c->table_size = (uint16_t)(c->table_size + elem_size);
+  c->table_elems++;
+
+  /* Store this element into {entries,indices}_elem */
+  if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem) {
+    /* already there: update with new index */
+    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
+  } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem) {
+    /* already there (cuckoo): update with new index */
+    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+  } else if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == NULL) {
+    /* not there, but a free element: add */
+    c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
+    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
+  } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == NULL) {
+    /* not there (cuckoo), but a free element: add */
+    c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
+    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+  } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] <
+             c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) {
+    /* not there: replace oldest */
+    GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_2(elem_hash)]);
+    c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
+    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
+  } else {
+    /* not there: replace oldest */
+    GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_3(elem_hash)]);
+    c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
+    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+  }
+
+  /* do exactly the same for the key (so we can find by that again too) */
+
+  if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key) {
+    c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
+  } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) {
+    c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
+  } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) {
+    c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
+    c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
+  } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) {
+    c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
+    c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
+  } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
+             c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
+    GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
+    c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
+    c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
+  } else {
+    GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
+    c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
+    c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
+  }
+}
+
+static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
+                         framer_state *st) {
+  uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1);
+  GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len),
+                           len);
+}
+
+static gpr_slice get_wire_value(grpc_mdelem *elem, uint8_t *huffman_prefix) {
+  if (grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(elem->key->slice),
+                            GPR_SLICE_LENGTH(elem->key->slice))) {
+    *huffman_prefix = 0x80;
+    return grpc_mdstr_as_base64_encoded_and_huffman_compressed(elem->value);
+  }
+  /* TODO(ctiller): opportunistically compress non-binary headers */
+  *huffman_prefix = 0x00;
+  return elem->value->slice;
+}
+
+static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
+                               uint32_t key_index, grpc_mdelem *elem,
+                               framer_state *st) {
+  uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
+  uint8_t huffman_prefix;
+  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
+  size_t len_val = GPR_SLICE_LENGTH(value_slice);
+  uint32_t len_val_len;
+  GPR_ASSERT(len_val <= UINT32_MAX);
+  len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
+  GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40,
+                           add_tiny_header_data(st, len_pfx), len_pfx);
+  GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
+                           add_tiny_header_data(st, len_val_len), len_val_len);
+  add_header_data(st, gpr_slice_ref(value_slice));
+}
+
+static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
+                              uint32_t key_index, grpc_mdelem *elem,
+                              framer_state *st) {
+  uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
+  uint8_t huffman_prefix;
+  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
+  size_t len_val = GPR_SLICE_LENGTH(value_slice);
+  uint32_t len_val_len;
+  GPR_ASSERT(len_val <= UINT32_MAX);
+  len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
+  GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00,
+                           add_tiny_header_data(st, len_pfx), len_pfx);
+  GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
+                           add_tiny_header_data(st, len_val_len), len_val_len);
+  add_header_data(st, gpr_slice_ref(value_slice));
+}
+
+static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
+                                 grpc_mdelem *elem, framer_state *st) {
+  uint32_t len_key = (uint32_t)GPR_SLICE_LENGTH(elem->key->slice);
+  uint8_t huffman_prefix;
+  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
+  uint32_t len_val = (uint32_t)GPR_SLICE_LENGTH(value_slice);
+  uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
+  uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
+  GPR_ASSERT(len_key <= UINT32_MAX);
+  GPR_ASSERT(GPR_SLICE_LENGTH(value_slice) <= UINT32_MAX);
+  *add_tiny_header_data(st, 1) = 0x40;
+  GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
+                           add_tiny_header_data(st, len_key_len), len_key_len);
+  add_header_data(st, gpr_slice_ref(elem->key->slice));
+  GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
+                           add_tiny_header_data(st, len_val_len), len_val_len);
+  add_header_data(st, gpr_slice_ref(value_slice));
+}
+
+static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
+                                grpc_mdelem *elem, framer_state *st) {
+  uint32_t len_key = (uint32_t)GPR_SLICE_LENGTH(elem->key->slice);
+  uint8_t huffman_prefix;
+  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
+  uint32_t len_val = (uint32_t)GPR_SLICE_LENGTH(value_slice);
+  uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
+  uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
+  GPR_ASSERT(len_key <= UINT32_MAX);
+  GPR_ASSERT(GPR_SLICE_LENGTH(value_slice) <= UINT32_MAX);
+  *add_tiny_header_data(st, 1) = 0x00;
+  GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
+                           add_tiny_header_data(st, len_key_len), len_key_len);
+  add_header_data(st, gpr_slice_ref(elem->key->slice));
+  GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
+                           add_tiny_header_data(st, len_val_len), len_val_len);
+  add_header_data(st, gpr_slice_ref(value_slice));
+}
+
+static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
+                                             framer_state *st) {
+  uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(c->max_table_size, 3);
+  GRPC_CHTTP2_WRITE_VARINT(c->max_table_size, 3, 0x20,
+                           add_tiny_header_data(st, len), len);
+  c->advertise_table_size_change = 0;
+}
+
+static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) {
+  return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index +
+         c->table_elems - elem_index;
+}
+
+/* encode an mdelem */
+static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem,
+                      framer_state *st) {
+  uint32_t key_hash = elem->key->hash;
+  uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
+  size_t decoder_space_usage;
+  uint32_t indices_key;
+  int should_add_elem;
+
+  GPR_ASSERT(GPR_SLICE_LENGTH(elem->key->slice) > 0);
+  if (GPR_SLICE_START_PTR(elem->key->slice)[0] != ':') { /* regular header */
+    st->seen_regular_header = 1;
+  } else {
+    GPR_ASSERT(
+        st->seen_regular_header == 0 &&
+        "Reserved header (colon-prefixed) happening after regular ones.");
+  }
+
+  inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems);
+
+  /* is this elem currently in the decoders table? */
+
+  if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem &&
+      c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
+    /* HIT: complete element (first cuckoo hash) */
+    emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
+                 st);
+    return;
+  }
+
+  if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem &&
+      c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
+    /* HIT: complete element (second cuckoo hash) */
+    emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
+                 st);
+    return;
+  }
+
+  /* should this elem be in the table? */
+  decoder_space_usage = grpc_mdelem_get_size_in_hpack_table(elem);
+  should_add_elem = decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
+                    c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
+                        c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
+
+  /* no hits for the elem... maybe there's a key? */
+
+  indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
+  if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key &&
+      indices_key > c->tail_remote_index) {
+    /* HIT: key (first cuckoo hash) */
+    if (should_add_elem) {
+      emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st);
+      add_elem(c, elem);
+      return;
+    } else {
+      emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
+      return;
+    }
+    GPR_UNREACHABLE_CODE(return );
+  }
+
+  indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
+  if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key &&
+      indices_key > c->tail_remote_index) {
+    /* HIT: key (first cuckoo hash) */
+    if (should_add_elem) {
+      emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st);
+      add_elem(c, elem);
+      return;
+    } else {
+      emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
+      return;
+    }
+    GPR_UNREACHABLE_CODE(return );
+  }
+
+  /* no elem, key in the table... fall back to literal emission */
+
+  if (should_add_elem) {
+    emit_lithdr_incidx_v(c, elem, st);
+    add_elem(c, elem);
+    return;
+  } else {
+    emit_lithdr_noidx_v(c, elem, st);
+    return;
+  }
+  GPR_UNREACHABLE_CODE(return );
+}
+
+#define STRLEN_LIT(x) (sizeof(x) - 1)
+#define TIMEOUT_KEY "grpc-timeout"
+
+static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
+                         framer_state *st) {
+  char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
+  grpc_mdelem *mdelem;
+  grpc_chttp2_encode_timeout(
+      gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
+  mdelem = grpc_mdelem_from_metadata_strings(
+      GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str));
+  hpack_enc(c, mdelem, st);
+  GRPC_MDELEM_UNREF(mdelem);
+}
+
+static uint32_t elems_for_bytes(uint32_t bytes) { return (bytes + 31) / 32; }
+
+void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) {
+  memset(c, 0, sizeof(*c));
+  c->max_table_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
+  c->cap_table_elems = elems_for_bytes(c->max_table_size);
+  c->max_table_elems = c->cap_table_elems;
+  c->max_usable_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
+  c->table_elem_size =
+      gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
+  memset(c->table_elem_size, 0,
+         sizeof(*c->table_elem_size) * c->cap_table_elems);
+}
+
+void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
+  int i;
+  for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
+    if (c->entries_keys[i]) GRPC_MDSTR_UNREF(c->entries_keys[i]);
+    if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]);
+  }
+  gpr_free(c->table_elem_size);
+}
+
+void grpc_chttp2_hpack_compressor_set_max_usable_size(
+    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) {
+  c->max_usable_size = max_table_size;
+  grpc_chttp2_hpack_compressor_set_max_table_size(
+      c, GPR_MIN(c->max_table_size, max_table_size));
+}
+
+static void rebuild_elems(grpc_chttp2_hpack_compressor *c, uint32_t new_cap) {
+  uint16_t *table_elem_size = gpr_malloc(sizeof(*table_elem_size) * new_cap);
+  uint32_t i;
+
+  memset(table_elem_size, 0, sizeof(*table_elem_size) * new_cap);
+  GPR_ASSERT(c->table_elems <= new_cap);
+
+  for (i = 0; i < c->table_elems; i++) {
+    uint32_t ofs = c->tail_remote_index + i + 1;
+    table_elem_size[ofs % new_cap] =
+        c->table_elem_size[ofs % c->cap_table_elems];
+  }
+
+  c->cap_table_elems = new_cap;
+  gpr_free(c->table_elem_size);
+  c->table_elem_size = table_elem_size;
+}
+
+void grpc_chttp2_hpack_compressor_set_max_table_size(
+    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) {
+  max_table_size = GPR_MIN(max_table_size, c->max_usable_size);
+  if (max_table_size == c->max_table_size) {
+    return;
+  }
+  while (c->table_size > 0 && c->table_size > max_table_size) {
+    evict_entry(c);
+  }
+  c->max_table_size = max_table_size;
+  c->max_table_elems = elems_for_bytes(max_table_size);
+  if (c->max_table_elems > c->cap_table_elems) {
+    rebuild_elems(c, GPR_MAX(c->max_table_elems, 2 * c->cap_table_elems));
+  } else if (c->max_table_elems < c->cap_table_elems / 3) {
+    uint32_t new_cap = GPR_MAX(c->max_table_elems, 16);
+    if (new_cap != c->cap_table_elems) {
+      rebuild_elems(c, new_cap);
+    }
+  }
+  c->advertise_table_size_change = 1;
+  gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size);
+}
+
+void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
+                               uint32_t stream_id,
+                               grpc_metadata_batch *metadata, int is_eof,
+                               grpc_transport_one_way_stats *stats,
+                               gpr_slice_buffer *outbuf) {
+  framer_state st;
+  grpc_linked_mdelem *l;
+  gpr_timespec deadline;
+
+  GPR_ASSERT(stream_id != 0);
+
+  st.seen_regular_header = 0;
+  st.stream_id = stream_id;
+  st.output = outbuf;
+  st.is_first_frame = 1;
+  st.stats = stats;
+
+  /* Encode a metadata batch; store the returned values, representing
+     a metadata element that needs to be unreffed back into the metadata
+     slot. THIS MAY NOT BE THE SAME ELEMENT (if a decoder table slot got
+     updated). After this loop, we'll do a batch unref of elements. */
+  begin_frame(&st);
+  if (c->advertise_table_size_change != 0) {
+    emit_advertise_table_size_change(c, &st);
+  }
+  grpc_metadata_batch_assert_ok(metadata);
+  for (l = metadata->list.head; l; l = l->next) {
+    hpack_enc(c, l->md, &st);
+  }
+  deadline = metadata->deadline;
+  if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) {
+    deadline_enc(c, deadline, &st);
+  }
+
+  finish_frame(&st, 1, is_eof);
+}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
new file mode 100644
index 0000000..0f7b0b0
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
@@ -0,0 +1,97 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/metadata_batch.h"
+#include "src/core/lib/transport/transport.h"
+
+#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256
+#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256
+/* initial table size, per spec */
+#define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096
+/* maximum table size we'll actually use */
+#define GRPC_CHTTP2_HPACKC_MAX_TABLE_SIZE (1024 * 1024)
+
+typedef struct {
+  uint32_t filter_elems_sum;
+  uint32_t max_table_size;
+  uint32_t max_table_elems;
+  uint32_t cap_table_elems;
+  /** if non-zero, advertise to the decoder that we'll start using a table
+      of this size */
+  uint8_t advertise_table_size_change;
+  /** maximum number of bytes we'll use for the decode table (to guard against
+      peers ooming us by setting decode table size high) */
+  uint32_t max_usable_size;
+  /* one before the lowest usable table index */
+  uint32_t tail_remote_index;
+  uint32_t table_size;
+  uint32_t table_elems;
+
+  /* filter tables for elems: this tables provides an approximate
+     popularity count for particular hashes, and are used to determine whether
+     a new literal should be added to the compression table or not.
+     They track a single integer that counts how often a particular value has
+     been seen. When that count reaches max (255), all values are halved. */
+  uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_FILTERS];
+
+  /* entry tables for keys & elems: these tables track values that have been
+     seen and *may* be in the decompressor table */
+  grpc_mdstr *entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+  grpc_mdelem *entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+  uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+  uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+
+  uint16_t *table_elem_size;
+} grpc_chttp2_hpack_compressor;
+
+void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c);
+void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c);
+void grpc_chttp2_hpack_compressor_set_max_table_size(
+    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size);
+void grpc_chttp2_hpack_compressor_set_max_usable_size(
+    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size);
+
+void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, uint32_t id,
+                               grpc_metadata_batch *metadata, int is_eof,
+                               grpc_transport_one_way_stats *stats,
+                               gpr_slice_buffer *outbuf);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
new file mode 100644
index 0000000..687936b
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -0,0 +1,1466 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/hpack_parser.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+
+/* This is here for grpc_is_binary_header
+ * TODO(murgatroid99): Remove this
+ */
+#include <grpc/grpc.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+
+extern int grpc_http_trace;
+
+typedef enum {
+  NOT_BINARY,
+  B64_BYTE0,
+  B64_BYTE1,
+  B64_BYTE2,
+  B64_BYTE3
+} binary_state;
+
+/* How parsing works:
+
+   The parser object keeps track of a function pointer which represents the
+   current parse state.
+
+   Each time new bytes are presented, we call into the current state, which
+   recursively parses until all bytes in the given chunk are exhausted.
+
+   The parse state that terminates then saves its function pointer to be the
+   current state so that it can resume when more bytes are available.
+
+   It's expected that most optimizing compilers will turn this code into
+   a set of indirect jumps, and so not waste stack space. */
+
+/* forward declarations for parsing states */
+static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                       const uint8_t *end);
+static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                       const uint8_t *end);
+static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                            const uint8_t *end);
+
+static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end);
+static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                            const uint8_t *end);
+static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
+                                               const uint8_t *cur,
+                                               const uint8_t *end);
+static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
+                                               const uint8_t *cur,
+                                               const uint8_t *end);
+
+static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end);
+static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end);
+static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end);
+static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end);
+static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end);
+static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                          const uint8_t *end);
+
+static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end);
+static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end);
+static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end);
+static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end);
+static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end);
+static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end);
+static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end);
+static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end);
+static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end);
+static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end);
+static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end);
+static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                              const uint8_t *end);
+static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end);
+
+/* we translate the first byte of a hpack field into one of these decoding
+   cases, then use a lookup table to jump directly to the appropriate parser.
+
+   _X => the integer index is all ones, meaning we need to do varint decoding
+   _V => the integer index is all zeros, meaning we need to decode an additional
+         string value */
+typedef enum {
+  INDEXED_FIELD,
+  INDEXED_FIELD_X,
+  LITHDR_INCIDX,
+  LITHDR_INCIDX_X,
+  LITHDR_INCIDX_V,
+  LITHDR_NOTIDX,
+  LITHDR_NOTIDX_X,
+  LITHDR_NOTIDX_V,
+  LITHDR_NVRIDX,
+  LITHDR_NVRIDX_X,
+  LITHDR_NVRIDX_V,
+  MAX_TBL_SIZE,
+  MAX_TBL_SIZE_X,
+  ILLEGAL
+} first_byte_type;
+
+/* jump table of parse state functions -- order must match first_byte_type
+   above */
+static const grpc_chttp2_hpack_parser_state first_byte_action[] = {
+    parse_indexed_field,   parse_indexed_field_x, parse_lithdr_incidx,
+    parse_lithdr_incidx_x, parse_lithdr_incidx_v, parse_lithdr_notidx,
+    parse_lithdr_notidx_x, parse_lithdr_notidx_v, parse_lithdr_nvridx,
+    parse_lithdr_nvridx_x, parse_lithdr_nvridx_v, parse_max_tbl_size,
+    parse_max_tbl_size_x,  parse_illegal_op};
+
+/* indexes the first byte to a parse state function - generated by
+   gen_hpack_tables.c */
+static const uint8_t first_byte_lut[256] = {
+    LITHDR_NOTIDX_V, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX,
+    LITHDR_NOTIDX,   LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX,
+    LITHDR_NOTIDX,   LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX,
+    LITHDR_NOTIDX,   LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX_X,
+    LITHDR_NVRIDX_V, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
+    LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
+    LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
+    LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX_X,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE_X,
+    LITHDR_INCIDX_V, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
+    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX_X,
+    ILLEGAL,         INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
+    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD_X,
+};
+
+/* state table for huffman decoding: given a state, gives an index/16 into
+   next_sub_tbl. Taking that index and adding the value of the nibble being
+   considered returns the next state.
+
+   generated by gen_hpack_tables.c */
+static const uint8_t next_tbl[256] = {
+    0,  1,  2,  3,  4,  1,  2, 5,  6,  1, 7,  8,  1,  3,  3,  9,  10, 11, 1,  1,
+    1,  12, 1,  2,  13, 1,  1, 1,  1,  1, 1,  1,  1,  1,  1,  1,  1,  1,  1,  2,
+    14, 1,  15, 16, 1,  17, 1, 15, 2,  7, 3,  18, 19, 1,  1,  1,  1,  20, 1,  1,
+    1,  1,  1,  1,  1,  1,  1, 1,  15, 2, 2,  7,  21, 1,  22, 1,  1,  1,  1,  1,
+    1,  1,  1,  15, 2,  2,  2, 2,  2,  2, 23, 24, 25, 1,  1,  1,  1,  2,  2,  2,
+    26, 3,  3,  27, 10, 28, 1, 1,  1,  1, 1,  1,  2,  3,  29, 10, 30, 1,  1,  1,
+    1,  1,  1,  1,  1,  1,  1, 1,  1,  1, 1,  31, 1,  1,  1,  1,  1,  1,  1,  2,
+    2,  2,  2,  2,  2,  2,  2, 32, 1,  1, 15, 33, 1,  34, 35, 9,  36, 1,  1,  1,
+    1,  1,  1,  1,  37, 1,  1, 1,  1,  1, 1,  2,  2,  2,  2,  2,  2,  2,  26, 9,
+    38, 1,  1,  1,  1,  1,  1, 1,  15, 2, 2,  2,  2,  26, 3,  3,  39, 1,  1,  1,
+    1,  1,  1,  1,  1,  1,  1, 1,  2,  2, 2,  2,  2,  2,  7,  3,  3,  3,  40, 2,
+    41, 1,  1,  1,  42, 43, 1, 1,  44, 1, 1,  1,  1,  15, 2,  2,  2,  2,  2,  2,
+    3,  3,  3,  45, 46, 1,  1, 2,  2,  2, 35, 3,  3,  18, 47, 2,
+};
+
+/* next state, based upon current state and the current nibble: see above.
+   generated by gen_hpack_tables.c */
+static const int16_t next_sub_tbl[48 * 16] = {
+    1,   204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
+    218, 2,   6,   10,  13,  14,  15,  16,  17,  2,   6,   10,  13,  14,  15,
+    16,  17,  3,   7,   11,  24,  3,   7,   11,  24,  3,   7,   11,  24,  3,
+    7,   11,  24,  4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,
+    4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,
+    199, 200, 201, 202, 203, 4,   8,   4,   8,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   9,   133, 134, 135, 136, 137, 138, 139, 140,
+    141, 142, 143, 144, 145, 146, 147, 3,   7,   11,  24,  3,   7,   11,  24,
+    4,   8,   4,   8,   4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   12,  132, 4,   8,   4,   8,   4,   8,
+    4,   8,   4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   18,  19,  20,  21,  4,   8,   4,
+    8,   4,   8,   4,   8,   4,   8,   0,   0,   0,   22,  23,  91,  25,  26,
+    27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  3,
+    7,   11,  24,  3,   7,   11,  24,  0,   0,   0,   0,   0,   41,  42,  43,
+    2,   6,   10,  13,  14,  15,  16,  17,  3,   7,   11,  24,  3,   7,   11,
+    24,  4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   0,   0,
+    44,  45,  2,   6,   10,  13,  14,  15,  16,  17,  46,  47,  48,  49,  50,
+    51,  52,  57,  4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   53,  54,  55,  56,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,
+    68,  69,  70,  71,  72,  74,  0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   73,  75,  76,  77,  78,  79,  80,  81,  82,
+    83,  84,  85,  86,  87,  88,  89,  90,  3,   7,   11,  24,  3,   7,   11,
+    24,  3,   7,   11,  24,  0,   0,   0,   0,   3,   7,   11,  24,  3,   7,
+    11,  24,  4,   8,   4,   8,   0,   0,   0,   92,  0,   0,   0,   93,  94,
+    95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 3,   7,   11,  24,
+    4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,
+    8,   4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 4,
+    8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   0,   0,
+    0,   117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+    131, 2,   6,   10,  13,  14,  15,  16,  17,  4,   8,   4,   8,   4,   8,
+    4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   148,
+    149, 150, 151, 3,   7,   11,  24,  4,   8,   4,   8,   0,   0,   0,   0,
+    0,   0,   152, 153, 3,   7,   11,  24,  3,   7,   11,  24,  3,   7,   11,
+    24,  154, 155, 156, 164, 3,   7,   11,  24,  3,   7,   11,  24,  3,   7,
+    11,  24,  4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    157, 158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172,
+    173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+    188, 189, 190, 191, 192, 193, 194, 195, 196, 4,   8,   4,   8,   4,   8,
+    4,   8,   4,   8,   4,   8,   4,   8,   197, 198, 4,   8,   4,   8,   4,
+    8,   4,   8,   0,   0,   0,   0,   0,   0,   219, 220, 3,   7,   11,  24,
+    4,   8,   4,   8,   4,   8,   0,   0,   221, 222, 223, 224, 3,   7,   11,
+    24,  3,   7,   11,  24,  4,   8,   4,   8,   4,   8,   225, 228, 4,   8,
+    4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   226, 227, 229,
+    230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
+    4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   245, 246, 247, 248, 249, 250, 251, 252,
+    253, 254, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   255,
+};
+
+/* emission table: indexed like next_tbl, ultimately gives the byte to be
+   emitted, or -1 for no byte, or 256 for end of stream
+
+   generated by gen_hpack_tables.c */
+static const uint16_t emit_tbl[256] = {
+    0,   1,   2,   3,   4,   5,   6,   7,   0,   8,   9,   10,  11,  12,  13,
+    14,  15,  16,  17,  18,  19,  20,  21,  22,  0,   23,  24,  25,  26,  27,
+    28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
+    43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  0,   55,  56,
+    57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  0,
+    71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
+    86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100,
+    101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+    116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+    131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+    146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 0,
+    160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+    0,   175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+    189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+    204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+    219, 220, 221, 0,   222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
+    233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+    248,
+};
+
+/* generated by gen_hpack_tables.c */
+static const int16_t emit_sub_tbl[249 * 16] = {
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  48,  48,  48,  48,  48,  48,  48,  48,  49,  49,  49,  49,  49,  49,
+    49,  49,  48,  48,  48,  48,  49,  49,  49,  49,  50,  50,  50,  50,  97,
+    97,  97,  97,  48,  48,  49,  49,  50,  50,  97,  97,  99,  99,  101, 101,
+    105, 105, 111, 111, 48,  49,  50,  97,  99,  101, 105, 111, 115, 116, -1,
+    -1,  -1,  -1,  -1,  -1,  32,  32,  32,  32,  32,  32,  32,  32,  37,  37,
+    37,  37,  37,  37,  37,  37,  99,  99,  99,  99,  101, 101, 101, 101, 105,
+    105, 105, 105, 111, 111, 111, 111, 115, 115, 116, 116, 32,  37,  45,  46,
+    47,  51,  52,  53,  54,  55,  56,  57,  61,  61,  61,  61,  61,  61,  61,
+    61,  65,  65,  65,  65,  65,  65,  65,  65,  115, 115, 115, 115, 116, 116,
+    116, 116, 32,  32,  37,  37,  45,  45,  46,  46,  61,  65,  95,  98,  100,
+    102, 103, 104, 108, 109, 110, 112, 114, 117, -1,  -1,  58,  58,  58,  58,
+    58,  58,  58,  58,  66,  66,  66,  66,  66,  66,  66,  66,  47,  47,  51,
+    51,  52,  52,  53,  53,  54,  54,  55,  55,  56,  56,  57,  57,  61,  61,
+    65,  65,  95,  95,  98,  98,  100, 100, 102, 102, 103, 103, 104, 104, 108,
+    108, 109, 109, 110, 110, 112, 112, 114, 114, 117, 117, 58,  66,  67,  68,
+    69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
+    84,  85,  86,  87,  89,  106, 107, 113, 118, 119, 120, 121, 122, -1,  -1,
+    -1,  -1,  38,  38,  38,  38,  38,  38,  38,  38,  42,  42,  42,  42,  42,
+    42,  42,  42,  44,  44,  44,  44,  44,  44,  44,  44,  59,  59,  59,  59,
+    59,  59,  59,  59,  88,  88,  88,  88,  88,  88,  88,  88,  90,  90,  90,
+    90,  90,  90,  90,  90,  33,  33,  34,  34,  40,  40,  41,  41,  63,  63,
+    39,  43,  124, -1,  -1,  -1,  35,  35,  35,  35,  35,  35,  35,  35,  62,
+    62,  62,  62,  62,  62,  62,  62,  0,   0,   0,   0,   36,  36,  36,  36,
+    64,  64,  64,  64,  91,  91,  91,  91,  69,  69,  69,  69,  69,  69,  69,
+    69,  70,  70,  70,  70,  70,  70,  70,  70,  71,  71,  71,  71,  71,  71,
+    71,  71,  72,  72,  72,  72,  72,  72,  72,  72,  73,  73,  73,  73,  73,
+    73,  73,  73,  74,  74,  74,  74,  74,  74,  74,  74,  75,  75,  75,  75,
+    75,  75,  75,  75,  76,  76,  76,  76,  76,  76,  76,  76,  77,  77,  77,
+    77,  77,  77,  77,  77,  78,  78,  78,  78,  78,  78,  78,  78,  79,  79,
+    79,  79,  79,  79,  79,  79,  80,  80,  80,  80,  80,  80,  80,  80,  81,
+    81,  81,  81,  81,  81,  81,  81,  82,  82,  82,  82,  82,  82,  82,  82,
+    83,  83,  83,  83,  83,  83,  83,  83,  84,  84,  84,  84,  84,  84,  84,
+    84,  85,  85,  85,  85,  85,  85,  85,  85,  86,  86,  86,  86,  86,  86,
+    86,  86,  87,  87,  87,  87,  87,  87,  87,  87,  89,  89,  89,  89,  89,
+    89,  89,  89,  106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107,
+    107, 107, 107, 107, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118,
+    118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 120, 120,
+    120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 122,
+    122, 122, 122, 122, 122, 122, 122, 38,  38,  38,  38,  42,  42,  42,  42,
+    44,  44,  44,  44,  59,  59,  59,  59,  88,  88,  88,  88,  90,  90,  90,
+    90,  33,  34,  40,  41,  63,  -1,  -1,  -1,  39,  39,  39,  39,  39,  39,
+    39,  39,  43,  43,  43,  43,  43,  43,  43,  43,  124, 124, 124, 124, 124,
+    124, 124, 124, 35,  35,  35,  35,  62,  62,  62,  62,  0,   0,   36,  36,
+    64,  64,  91,  91,  93,  93,  126, 126, 94,  125, -1,  -1,  60,  60,  60,
+    60,  60,  60,  60,  60,  96,  96,  96,  96,  96,  96,  96,  96,  123, 123,
+    123, 123, 123, 123, 123, 123, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  92,
+    92,  92,  92,  92,  92,  92,  92,  195, 195, 195, 195, 195, 195, 195, 195,
+    208, 208, 208, 208, 208, 208, 208, 208, 128, 128, 128, 128, 130, 130, 130,
+    130, 131, 131, 131, 131, 162, 162, 162, 162, 184, 184, 184, 184, 194, 194,
+    194, 194, 224, 224, 224, 224, 226, 226, 226, 226, 153, 153, 161, 161, 167,
+    167, 172, 172, 176, 176, 177, 177, 179, 179, 209, 209, 216, 216, 217, 217,
+    227, 227, 229, 229, 230, 230, 129, 132, 133, 134, 136, 146, 154, 156, 160,
+    163, 164, 169, 170, 173, 178, 181, 185, 186, 187, 189, 190, 196, 198, 228,
+    232, 233, -1,  -1,  -1,  -1,  1,   1,   1,   1,   1,   1,   1,   1,   135,
+    135, 135, 135, 135, 135, 135, 135, 137, 137, 137, 137, 137, 137, 137, 137,
+    138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, 139, 139, 139,
+    139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141,
+    141, 141, 143, 143, 143, 143, 143, 143, 143, 143, 147, 147, 147, 147, 147,
+    147, 147, 147, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150,
+    150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, 152,
+    152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 157, 157,
+    157, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 165,
+    165, 165, 165, 165, 165, 165, 165, 166, 166, 166, 166, 166, 166, 166, 166,
+    168, 168, 168, 168, 168, 168, 168, 168, 174, 174, 174, 174, 174, 174, 174,
+    174, 175, 175, 175, 175, 175, 175, 175, 175, 180, 180, 180, 180, 180, 180,
+    180, 180, 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, 183, 183, 183,
+    183, 183, 183, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191,
+    191, 191, 191, 191, 197, 197, 197, 197, 197, 197, 197, 197, 231, 231, 231,
+    231, 231, 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 9,   9,
+    9,   9,   142, 142, 142, 142, 144, 144, 144, 144, 145, 145, 145, 145, 148,
+    148, 148, 148, 159, 159, 159, 159, 171, 171, 171, 171, 206, 206, 206, 206,
+    215, 215, 215, 215, 225, 225, 225, 225, 236, 236, 236, 236, 237, 237, 237,
+    237, 199, 199, 207, 207, 234, 234, 235, 235, 192, 193, 200, 201, 202, 205,
+    210, 213, 218, 219, 238, 240, 242, 243, 255, -1,  203, 203, 203, 203, 203,
+    203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 211, 211, 211, 211,
+    211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 214, 214, 214,
+    214, 214, 214, 214, 214, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222,
+    222, 222, 222, 222, 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 241,
+    241, 241, 241, 241, 241, 241, 241, 244, 244, 244, 244, 244, 244, 244, 244,
+    245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246,
+    246, 247, 247, 247, 247, 247, 247, 247, 247, 248, 248, 248, 248, 248, 248,
+    248, 248, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251,
+    251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253,
+    253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 2,   2,   2,
+    2,   3,   3,   3,   3,   4,   4,   4,   4,   5,   5,   5,   5,   6,   6,
+    6,   6,   7,   7,   7,   7,   8,   8,   8,   8,   11,  11,  11,  11,  12,
+    12,  12,  12,  14,  14,  14,  14,  15,  15,  15,  15,  16,  16,  16,  16,
+    17,  17,  17,  17,  18,  18,  18,  18,  19,  19,  19,  19,  20,  20,  20,
+    20,  21,  21,  21,  21,  23,  23,  23,  23,  24,  24,  24,  24,  25,  25,
+    25,  25,  26,  26,  26,  26,  27,  27,  27,  27,  28,  28,  28,  28,  29,
+    29,  29,  29,  30,  30,  30,  30,  31,  31,  31,  31,  127, 127, 127, 127,
+    220, 220, 220, 220, 249, 249, 249, 249, 10,  13,  22,  256, 93,  93,  93,
+    93,  126, 126, 126, 126, 94,  94,  125, 125, 60,  96,  123, -1,  92,  195,
+    208, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  128,
+    128, 128, 128, 128, 128, 128, 128, 130, 130, 130, 130, 130, 130, 130, 130,
+    131, 131, 131, 131, 131, 131, 131, 131, 162, 162, 162, 162, 162, 162, 162,
+    162, 184, 184, 184, 184, 184, 184, 184, 184, 194, 194, 194, 194, 194, 194,
+    194, 194, 224, 224, 224, 224, 224, 224, 224, 224, 226, 226, 226, 226, 226,
+    226, 226, 226, 153, 153, 153, 153, 161, 161, 161, 161, 167, 167, 167, 167,
+    172, 172, 172, 172, 176, 176, 176, 176, 177, 177, 177, 177, 179, 179, 179,
+    179, 209, 209, 209, 209, 216, 216, 216, 216, 217, 217, 217, 217, 227, 227,
+    227, 227, 229, 229, 229, 229, 230, 230, 230, 230, 129, 129, 132, 132, 133,
+    133, 134, 134, 136, 136, 146, 146, 154, 154, 156, 156, 160, 160, 163, 163,
+    164, 164, 169, 169, 170, 170, 173, 173, 178, 178, 181, 181, 185, 185, 186,
+    186, 187, 187, 189, 189, 190, 190, 196, 196, 198, 198, 228, 228, 232, 232,
+    233, 233, 1,   135, 137, 138, 139, 140, 141, 143, 147, 149, 150, 151, 152,
+    155, 157, 158, 165, 166, 168, 174, 175, 180, 182, 183, 188, 191, 197, 231,
+    239, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  9,   9,   9,
+    9,   9,   9,   9,   9,   142, 142, 142, 142, 142, 142, 142, 142, 144, 144,
+    144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 148,
+    148, 148, 148, 148, 148, 148, 148, 159, 159, 159, 159, 159, 159, 159, 159,
+    171, 171, 171, 171, 171, 171, 171, 171, 206, 206, 206, 206, 206, 206, 206,
+    206, 215, 215, 215, 215, 215, 215, 215, 215, 225, 225, 225, 225, 225, 225,
+    225, 225, 236, 236, 236, 236, 236, 236, 236, 236, 237, 237, 237, 237, 237,
+    237, 237, 237, 199, 199, 199, 199, 207, 207, 207, 207, 234, 234, 234, 234,
+    235, 235, 235, 235, 192, 192, 193, 193, 200, 200, 201, 201, 202, 202, 205,
+    205, 210, 210, 213, 213, 218, 218, 219, 219, 238, 238, 240, 240, 242, 242,
+    243, 243, 255, 255, 203, 204, 211, 212, 214, 221, 222, 223, 241, 244, 245,
+    246, 247, 248, 250, 251, 252, 253, 254, -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  2,   2,   2,   2,   2,   2,   2,
+    2,   3,   3,   3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   4,
+    4,   4,   5,   5,   5,   5,   5,   5,   5,   5,   6,   6,   6,   6,   6,
+    6,   6,   6,   7,   7,   7,   7,   7,   7,   7,   7,   8,   8,   8,   8,
+    8,   8,   8,   8,   11,  11,  11,  11,  11,  11,  11,  11,  12,  12,  12,
+    12,  12,  12,  12,  12,  14,  14,  14,  14,  14,  14,  14,  14,  15,  15,
+    15,  15,  15,  15,  15,  15,  16,  16,  16,  16,  16,  16,  16,  16,  17,
+    17,  17,  17,  17,  17,  17,  17,  18,  18,  18,  18,  18,  18,  18,  18,
+    19,  19,  19,  19,  19,  19,  19,  19,  20,  20,  20,  20,  20,  20,  20,
+    20,  21,  21,  21,  21,  21,  21,  21,  21,  23,  23,  23,  23,  23,  23,
+    23,  23,  24,  24,  24,  24,  24,  24,  24,  24,  25,  25,  25,  25,  25,
+    25,  25,  25,  26,  26,  26,  26,  26,  26,  26,  26,  27,  27,  27,  27,
+    27,  27,  27,  27,  28,  28,  28,  28,  28,  28,  28,  28,  29,  29,  29,
+    29,  29,  29,  29,  29,  30,  30,  30,  30,  30,  30,  30,  30,  31,  31,
+    31,  31,  31,  31,  31,  31,  127, 127, 127, 127, 127, 127, 127, 127, 220,
+    220, 220, 220, 220, 220, 220, 220, 249, 249, 249, 249, 249, 249, 249, 249,
+    10,  10,  13,  13,  22,  22,  256, 256, 67,  67,  67,  67,  67,  67,  67,
+    67,  68,  68,  68,  68,  68,  68,  68,  68,  95,  95,  95,  95,  95,  95,
+    95,  95,  98,  98,  98,  98,  98,  98,  98,  98,  100, 100, 100, 100, 100,
+    100, 100, 100, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103,
+    103, 103, 103, 103, 104, 104, 104, 104, 104, 104, 104, 104, 108, 108, 108,
+    108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 110, 110,
+    110, 110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 112, 112, 114,
+    114, 114, 114, 114, 114, 114, 114, 117, 117, 117, 117, 117, 117, 117, 117,
+    58,  58,  58,  58,  66,  66,  66,  66,  67,  67,  67,  67,  68,  68,  68,
+    68,  69,  69,  69,  69,  70,  70,  70,  70,  71,  71,  71,  71,  72,  72,
+    72,  72,  73,  73,  73,  73,  74,  74,  74,  74,  75,  75,  75,  75,  76,
+    76,  76,  76,  77,  77,  77,  77,  78,  78,  78,  78,  79,  79,  79,  79,
+    80,  80,  80,  80,  81,  81,  81,  81,  82,  82,  82,  82,  83,  83,  83,
+    83,  84,  84,  84,  84,  85,  85,  85,  85,  86,  86,  86,  86,  87,  87,
+    87,  87,  89,  89,  89,  89,  106, 106, 106, 106, 107, 107, 107, 107, 113,
+    113, 113, 113, 118, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 120,
+    121, 121, 121, 121, 122, 122, 122, 122, 38,  38,  42,  42,  44,  44,  59,
+    59,  88,  88,  90,  90,  -1,  -1,  -1,  -1,  33,  33,  33,  33,  33,  33,
+    33,  33,  34,  34,  34,  34,  34,  34,  34,  34,  40,  40,  40,  40,  40,
+    40,  40,  40,  41,  41,  41,  41,  41,  41,  41,  41,  63,  63,  63,  63,
+    63,  63,  63,  63,  39,  39,  39,  39,  43,  43,  43,  43,  124, 124, 124,
+    124, 35,  35,  62,  62,  0,   36,  64,  91,  93,  126, -1,  -1,  94,  94,
+    94,  94,  94,  94,  94,  94,  125, 125, 125, 125, 125, 125, 125, 125, 60,
+    60,  60,  60,  96,  96,  96,  96,  123, 123, 123, 123, -1,  -1,  -1,  -1,
+    92,  92,  92,  92,  195, 195, 195, 195, 208, 208, 208, 208, 128, 128, 130,
+    130, 131, 131, 162, 162, 184, 184, 194, 194, 224, 224, 226, 226, 153, 161,
+    167, 172, 176, 177, 179, 209, 216, 217, 227, 229, 230, -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  129, 129, 129, 129, 129, 129, 129, 129, 132, 132, 132, 132,
+    132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, 134,
+    134, 134, 134, 134, 134, 136, 136, 136, 136, 136, 136, 136, 136, 146, 146,
+    146, 146, 146, 146, 146, 146, 154, 154, 154, 154, 154, 154, 154, 154, 156,
+    156, 156, 156, 156, 156, 156, 156, 160, 160, 160, 160, 160, 160, 160, 160,
+    163, 163, 163, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 164, 164,
+    164, 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170,
+    170, 170, 173, 173, 173, 173, 173, 173, 173, 173, 178, 178, 178, 178, 178,
+    178, 178, 178, 181, 181, 181, 181, 181, 181, 181, 181, 185, 185, 185, 185,
+    185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187,
+    187, 187, 187, 187, 187, 189, 189, 189, 189, 189, 189, 189, 189, 190, 190,
+    190, 190, 190, 190, 190, 190, 196, 196, 196, 196, 196, 196, 196, 196, 198,
+    198, 198, 198, 198, 198, 198, 198, 228, 228, 228, 228, 228, 228, 228, 228,
+    232, 232, 232, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233,
+    233, 1,   1,   1,   1,   135, 135, 135, 135, 137, 137, 137, 137, 138, 138,
+    138, 138, 139, 139, 139, 139, 140, 140, 140, 140, 141, 141, 141, 141, 143,
+    143, 143, 143, 147, 147, 147, 147, 149, 149, 149, 149, 150, 150, 150, 150,
+    151, 151, 151, 151, 152, 152, 152, 152, 155, 155, 155, 155, 157, 157, 157,
+    157, 158, 158, 158, 158, 165, 165, 165, 165, 166, 166, 166, 166, 168, 168,
+    168, 168, 174, 174, 174, 174, 175, 175, 175, 175, 180, 180, 180, 180, 182,
+    182, 182, 182, 183, 183, 183, 183, 188, 188, 188, 188, 191, 191, 191, 191,
+    197, 197, 197, 197, 231, 231, 231, 231, 239, 239, 239, 239, 9,   9,   142,
+    142, 144, 144, 145, 145, 148, 148, 159, 159, 171, 171, 206, 206, 215, 215,
+    225, 225, 236, 236, 237, 237, 199, 207, 234, 235, 192, 192, 192, 192, 192,
+    192, 192, 192, 193, 193, 193, 193, 193, 193, 193, 193, 200, 200, 200, 200,
+    200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 201, 202, 202, 202,
+    202, 202, 202, 202, 202, 205, 205, 205, 205, 205, 205, 205, 205, 210, 210,
+    210, 210, 210, 210, 210, 210, 213, 213, 213, 213, 213, 213, 213, 213, 218,
+    218, 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 219, 219, 219, 219,
+    238, 238, 238, 238, 238, 238, 238, 238, 240, 240, 240, 240, 240, 240, 240,
+    240, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243, 243, 243,
+    243, 243, 255, 255, 255, 255, 255, 255, 255, 255, 203, 203, 203, 203, 204,
+    204, 204, 204, 211, 211, 211, 211, 212, 212, 212, 212, 214, 214, 214, 214,
+    221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 241, 241, 241,
+    241, 244, 244, 244, 244, 245, 245, 245, 245, 246, 246, 246, 246, 247, 247,
+    247, 247, 248, 248, 248, 248, 250, 250, 250, 250, 251, 251, 251, 251, 252,
+    252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254, 2,   2,   3,   3,
+    4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   11,  11,  12,  12,  14,
+    14,  15,  15,  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,
+    23,  23,  24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,
+    30,  31,  31,  127, 127, 220, 220, 249, 249, -1,  -1,  10,  10,  10,  10,
+    10,  10,  10,  10,  13,  13,  13,  13,  13,  13,  13,  13,  22,  22,  22,
+    22,  22,  22,  22,  22,  256, 256, 256, 256, 256, 256, 256, 256, 45,  45,
+    45,  45,  45,  45,  45,  45,  46,  46,  46,  46,  46,  46,  46,  46,  47,
+    47,  47,  47,  47,  47,  47,  47,  51,  51,  51,  51,  51,  51,  51,  51,
+    52,  52,  52,  52,  52,  52,  52,  52,  53,  53,  53,  53,  53,  53,  53,
+    53,  54,  54,  54,  54,  54,  54,  54,  54,  55,  55,  55,  55,  55,  55,
+    55,  55,  56,  56,  56,  56,  56,  56,  56,  56,  57,  57,  57,  57,  57,
+    57,  57,  57,  50,  50,  50,  50,  50,  50,  50,  50,  97,  97,  97,  97,
+    97,  97,  97,  97,  99,  99,  99,  99,  99,  99,  99,  99,  101, 101, 101,
+    101, 101, 101, 101, 101, 105, 105, 105, 105, 105, 105, 105, 105, 111, 111,
+    111, 111, 111, 111, 111, 111, 115, 115, 115, 115, 115, 115, 115, 115, 116,
+    116, 116, 116, 116, 116, 116, 116, 32,  32,  32,  32,  37,  37,  37,  37,
+    45,  45,  45,  45,  46,  46,  46,  46,  47,  47,  47,  47,  51,  51,  51,
+    51,  52,  52,  52,  52,  53,  53,  53,  53,  54,  54,  54,  54,  55,  55,
+    55,  55,  56,  56,  56,  56,  57,  57,  57,  57,  61,  61,  61,  61,  65,
+    65,  65,  65,  95,  95,  95,  95,  98,  98,  98,  98,  100, 100, 100, 100,
+    102, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 104, 108, 108, 108,
+    108, 109, 109, 109, 109, 110, 110, 110, 110, 112, 112, 112, 112, 114, 114,
+    114, 114, 117, 117, 117, 117, 58,  58,  66,  66,  67,  67,  68,  68,  69,
+    69,  70,  70,  71,  71,  72,  72,  73,  73,  74,  74,  75,  75,  76,  76,
+    77,  77,  78,  78,  79,  79,  80,  80,  81,  81,  82,  82,  83,  83,  84,
+    84,  85,  85,  86,  86,  87,  87,  89,  89,  106, 106, 107, 107, 113, 113,
+    118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 38,  42,  44,  59,  88,
+    90,  -1,  -1,  33,  33,  33,  33,  34,  34,  34,  34,  40,  40,  40,  40,
+    41,  41,  41,  41,  63,  63,  63,  63,  39,  39,  43,  43,  124, 124, 35,
+    62,  -1,  -1,  -1,  -1,  0,   0,   0,   0,   0,   0,   0,   0,   36,  36,
+    36,  36,  36,  36,  36,  36,  64,  64,  64,  64,  64,  64,  64,  64,  91,
+    91,  91,  91,  91,  91,  91,  91,  93,  93,  93,  93,  93,  93,  93,  93,
+    126, 126, 126, 126, 126, 126, 126, 126, 94,  94,  94,  94,  125, 125, 125,
+    125, 60,  60,  96,  96,  123, 123, -1,  -1,  92,  92,  195, 195, 208, 208,
+    128, 130, 131, 162, 184, 194, 224, 226, -1,  -1,  153, 153, 153, 153, 153,
+    153, 153, 153, 161, 161, 161, 161, 161, 161, 161, 161, 167, 167, 167, 167,
+    167, 167, 167, 167, 172, 172, 172, 172, 172, 172, 172, 172, 176, 176, 176,
+    176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 177, 177, 179, 179,
+    179, 179, 179, 179, 179, 179, 209, 209, 209, 209, 209, 209, 209, 209, 216,
+    216, 216, 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 217,
+    227, 227, 227, 227, 227, 227, 227, 227, 229, 229, 229, 229, 229, 229, 229,
+    229, 230, 230, 230, 230, 230, 230, 230, 230, 129, 129, 129, 129, 132, 132,
+    132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 136, 136, 136, 136, 146,
+    146, 146, 146, 154, 154, 154, 154, 156, 156, 156, 156, 160, 160, 160, 160,
+    163, 163, 163, 163, 164, 164, 164, 164, 169, 169, 169, 169, 170, 170, 170,
+    170, 173, 173, 173, 173, 178, 178, 178, 178, 181, 181, 181, 181, 185, 185,
+    185, 185, 186, 186, 186, 186, 187, 187, 187, 187, 189, 189, 189, 189, 190,
+    190, 190, 190, 196, 196, 196, 196, 198, 198, 198, 198, 228, 228, 228, 228,
+    232, 232, 232, 232, 233, 233, 233, 233, 1,   1,   135, 135, 137, 137, 138,
+    138, 139, 139, 140, 140, 141, 141, 143, 143, 147, 147, 149, 149, 150, 150,
+    151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 165, 165, 166, 166, 168,
+    168, 174, 174, 175, 175, 180, 180, 182, 182, 183, 183, 188, 188, 191, 191,
+    197, 197, 231, 231, 239, 239, 9,   142, 144, 145, 148, 159, 171, 206, 215,
+    225, 236, 237, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  199, 199,
+    199, 199, 199, 199, 199, 199, 207, 207, 207, 207, 207, 207, 207, 207, 234,
+    234, 234, 234, 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235,
+    192, 192, 192, 192, 193, 193, 193, 193, 200, 200, 200, 200, 201, 201, 201,
+    201, 202, 202, 202, 202, 205, 205, 205, 205, 210, 210, 210, 210, 213, 213,
+    213, 213, 218, 218, 218, 218, 219, 219, 219, 219, 238, 238, 238, 238, 240,
+    240, 240, 240, 242, 242, 242, 242, 243, 243, 243, 243, 255, 255, 255, 255,
+    203, 203, 204, 204, 211, 211, 212, 212, 214, 214, 221, 221, 222, 222, 223,
+    223, 241, 241, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 250, 250,
+    251, 251, 252, 252, 253, 253, 254, 254, 2,   3,   4,   5,   6,   7,   8,
+    11,  12,  14,  15,  16,  17,  18,  19,  20,  21,  23,  24,  25,  26,  27,
+    28,  29,  30,  31,  127, 220, 249, -1,  10,  10,  10,  10,  13,  13,  13,
+    13,  22,  22,  22,  22,  256, 256, 256, 256,
+};
+
+static const uint8_t inverse_base64[256] = {
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62,  255,
+    255, 255, 63,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  255, 255,
+    255, 64,  255, 255, 255, 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
+    10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
+    25,  255, 255, 255, 255, 255, 255, 26,  27,  28,  29,  30,  31,  32,  33,
+    34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+    49,  50,  51,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255,
+};
+
+/* emission helpers */
+static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
+                  int add_to_table) {
+  if (add_to_table) {
+    if (!grpc_chttp2_hptbl_add(&p->table, md)) {
+      return 0;
+    }
+  }
+  if (p->on_header == NULL) {
+    GRPC_MDELEM_UNREF(md);
+    return 0;
+  }
+  p->on_header(p->on_header_user_data, md);
+  return 1;
+}
+
+static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
+                               grpc_chttp2_hpack_parser_string *str) {
+  grpc_mdstr *s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length);
+  str->length = 0;
+  return s;
+}
+
+/* jump to the next state */
+static int parse_next(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                      const uint8_t *end) {
+  p->state = *p->next_state++;
+  return p->state(p, cur, end);
+}
+
+/* begin parsing a header: all functionality is encoded into lookup tables
+   above */
+static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                       const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_begin;
+    return 1;
+  }
+
+  return first_byte_action[first_byte_lut[*cur]](p, cur, end);
+}
+
+/* stream dependency and prioritization data: we just skip it */
+static int parse_stream_weight(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_stream_weight;
+    return 1;
+  }
+
+  return p->after_prioritization(p, cur + 1, end);
+}
+
+static int parse_stream_dep3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                             const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_stream_dep3;
+    return 1;
+  }
+
+  return parse_stream_weight(p, cur + 1, end);
+}
+
+static int parse_stream_dep2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                             const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_stream_dep2;
+    return 1;
+  }
+
+  return parse_stream_dep3(p, cur + 1, end);
+}
+
+static int parse_stream_dep1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                             const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_stream_dep1;
+    return 1;
+  }
+
+  return parse_stream_dep2(p, cur + 1, end);
+}
+
+static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                             const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_stream_dep0;
+    return 1;
+  }
+
+  return parse_stream_dep1(p, cur + 1, end);
+}
+
+/* emit an indexed field; for now just logs it to console; jumps to
+   begin the next field on completion */
+static int finish_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
+  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  if (md == NULL) {
+    if (grpc_http_trace) {
+      gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
+    }
+    return 0;
+  }
+  GRPC_MDELEM_REF(md);
+  return on_hdr(p, md, 0) && parse_begin(p, cur, end);
+}
+
+/* parse an indexed field with index < 127 */
+static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
+  p->dynamic_table_update_allowed = 0;
+  p->index = (*cur) & 0x7f;
+  return finish_indexed_field(p, cur + 1, end);
+}
+
+/* parse an indexed field with index >= 127 */
+static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      finish_indexed_field};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  p->index = 0x7f;
+  p->parsing.value = &p->index;
+  return parse_value0(p, cur + 1, end);
+}
+
+/* finish a literal header with incremental indexing: just log, and jump to '
+   begin */
+static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
+  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  GPR_ASSERT(md != NULL); /* handled in string parsing */
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+                                                     take_string(p, &p->value)),
+                1) &&
+         parse_begin(p, cur, end);
+}
+
+/* finish a literal header with incremental indexing with no index */
+static int finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+                                  const uint8_t *cur, const uint8_t *end) {
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+                                                     take_string(p, &p->value)),
+                1) &&
+         parse_begin(p, cur, end);
+}
+
+/* parse a literal header with incremental indexing; index < 63 */
+static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_value_string_with_indexed_key, finish_lithdr_incidx};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  p->index = (*cur) & 0x3f;
+  return parse_string_prefix(p, cur + 1, end);
+}
+
+/* parse a literal header with incremental indexing; index >= 63 */
+static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_string_prefix, parse_value_string_with_indexed_key,
+      finish_lithdr_incidx};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  p->index = 0x3f;
+  p->parsing.value = &p->index;
+  return parse_value0(p, cur + 1, end);
+}
+
+/* parse a literal header with incremental indexing; index = 0 */
+static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_key_string, parse_string_prefix,
+      parse_value_string_with_literal_key, finish_lithdr_incidx_v};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  return parse_string_prefix(p, cur + 1, end);
+}
+
+/* finish a literal header without incremental indexing */
+static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
+  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  GPR_ASSERT(md != NULL); /* handled in string parsing */
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
+}
+
+/* finish a literal header without incremental indexing with index = 0 */
+static int finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+                                  const uint8_t *cur, const uint8_t *end) {
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
+}
+
+/* parse a literal header without incremental indexing; index < 15 */
+static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_value_string_with_indexed_key, finish_lithdr_notidx};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  p->index = (*cur) & 0xf;
+  return parse_string_prefix(p, cur + 1, end);
+}
+
+/* parse a literal header without incremental indexing; index >= 15 */
+static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_string_prefix, parse_value_string_with_indexed_key,
+      finish_lithdr_notidx};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  p->index = 0xf;
+  p->parsing.value = &p->index;
+  return parse_value0(p, cur + 1, end);
+}
+
+/* parse a literal header without incremental indexing; index == 0 */
+static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_key_string, parse_string_prefix,
+      parse_value_string_with_literal_key, finish_lithdr_notidx_v};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  return parse_string_prefix(p, cur + 1, end);
+}
+
+/* finish a literal header that is never indexed */
+static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
+  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  GPR_ASSERT(md != NULL); /* handled in string parsing */
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
+}
+
+/* finish a literal header that is never indexed with an extra value */
+static int finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+                                  const uint8_t *cur, const uint8_t *end) {
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
+}
+
+/* parse a literal header that is never indexed; index < 15 */
+static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_value_string_with_indexed_key, finish_lithdr_nvridx};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  p->index = (*cur) & 0xf;
+  return parse_string_prefix(p, cur + 1, end);
+}
+
+/* parse a literal header that is never indexed; index >= 15 */
+static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_string_prefix, parse_value_string_with_indexed_key,
+      finish_lithdr_nvridx};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  p->index = 0xf;
+  p->parsing.value = &p->index;
+  return parse_value0(p, cur + 1, end);
+}
+
+/* parse a literal header that is never indexed; index == 0 */
+static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      parse_key_string, parse_string_prefix,
+      parse_value_string_with_literal_key, finish_lithdr_nvridx_v};
+  p->dynamic_table_update_allowed = 0;
+  p->next_state = and_then;
+  return parse_string_prefix(p, cur + 1, end);
+}
+
+/* finish parsing a max table size change */
+static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
+  if (grpc_http_trace) {
+    gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index);
+  }
+  return grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index) &&
+         parse_begin(p, cur, end);
+}
+
+/* parse a max table size change, max size < 15 */
+static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                              const uint8_t *end) {
+  if (p->dynamic_table_update_allowed == 0) {
+    return 0;
+  }
+  p->dynamic_table_update_allowed--;
+  p->index = (*cur) & 0x1f;
+  return finish_max_tbl_size(p, cur + 1, end);
+}
+
+/* parse a max table size change, max size >= 15 */
+static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
+  static const grpc_chttp2_hpack_parser_state and_then[] = {
+      finish_max_tbl_size};
+  if (p->dynamic_table_update_allowed == 0) {
+    return 0;
+  }
+  p->dynamic_table_update_allowed--;
+  p->next_state = and_then;
+  p->index = 0x1f;
+  p->parsing.value = &p->index;
+  return parse_value0(p, cur + 1, end);
+}
+
+/* a parse error: jam the parse state into parse_error, and return error */
+static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                       const uint8_t *end) {
+  p->state = parse_error;
+  return 0;
+}
+
+static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                            const uint8_t *end) {
+  GPR_ASSERT(cur != end);
+  if (grpc_http_trace) {
+    gpr_log(GPR_DEBUG, "Illegal hpack op code %d", *cur);
+  }
+  return parse_error(p, cur, end);
+}
+
+/* parse the 1st byte of a varint into p->parsing.value
+   no overflow is possible */
+static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_value0;
+    return 1;
+  }
+
+  *p->parsing.value += (*cur) & 0x7f;
+
+  if ((*cur) & 0x80) {
+    return parse_value1(p, cur + 1, end);
+  } else {
+    return parse_next(p, cur + 1, end);
+  }
+}
+
+/* parse the 2nd byte of a varint into p->parsing.value
+   no overflow is possible */
+static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_value1;
+    return 1;
+  }
+
+  *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 7;
+
+  if ((*cur) & 0x80) {
+    return parse_value2(p, cur + 1, end);
+  } else {
+    return parse_next(p, cur + 1, end);
+  }
+}
+
+/* parse the 3rd byte of a varint into p->parsing.value
+   no overflow is possible */
+static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_value2;
+    return 1;
+  }
+
+  *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 14;
+
+  if ((*cur) & 0x80) {
+    return parse_value3(p, cur + 1, end);
+  } else {
+    return parse_next(p, cur + 1, end);
+  }
+}
+
+/* parse the 4th byte of a varint into p->parsing.value
+   no overflow is possible */
+static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_value3;
+    return 1;
+  }
+
+  *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 21;
+
+  if ((*cur) & 0x80) {
+    return parse_value4(p, cur + 1, end);
+  } else {
+    return parse_next(p, cur + 1, end);
+  }
+}
+
+/* parse the 5th byte of a varint into p->parsing.value
+   depending on the byte, we may overflow, and care must be taken */
+static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end) {
+  uint8_t c;
+  uint32_t cur_value;
+  uint32_t add_value;
+
+  if (cur == end) {
+    p->state = parse_value4;
+    return 1;
+  }
+
+  c = (*cur) & 0x7f;
+  if (c > 0xf) {
+    goto error;
+  }
+
+  cur_value = *p->parsing.value;
+  add_value = ((uint32_t)c) << 28;
+  if (add_value > 0xffffffffu - cur_value) {
+    goto error;
+  }
+
+  *p->parsing.value = cur_value + add_value;
+
+  if ((*cur) & 0x80) {
+    return parse_value5up(p, cur + 1, end);
+  } else {
+    return parse_next(p, cur + 1, end);
+  }
+
+error:
+  if (grpc_http_trace) {
+    gpr_log(GPR_ERROR,
+            "integer overflow in hpack integer decoding: have 0x%08x, "
+            "got byte 0x%02x on byte 5",
+            *p->parsing.value, *cur);
+  }
+  return parse_error(p, cur, end);
+}
+
+/* parse any trailing bytes in a varint: it's possible to append an arbitrary
+   number of 0x80's and not affect the value - a zero will terminate - and
+   anything else will overflow */
+static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                          const uint8_t *end) {
+  while (cur != end && *cur == 0x80) {
+    ++cur;
+  }
+
+  if (cur == end) {
+    p->state = parse_value5up;
+    return 1;
+  }
+
+  if (*cur == 0) {
+    return parse_next(p, cur + 1, end);
+  }
+
+  if (grpc_http_trace) {
+    gpr_log(GPR_ERROR,
+            "integer overflow in hpack integer decoding: have 0x%08x, "
+            "got byte 0x%02x sometime after byte 5",
+            *p->parsing.value, *cur);
+  }
+  return parse_error(p, cur, end);
+}
+
+/* parse a string prefix */
+static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
+  if (cur == end) {
+    p->state = parse_string_prefix;
+    return 1;
+  }
+
+  p->strlen = (*cur) & 0x7f;
+  p->huff = (*cur) >> 7;
+  if (p->strlen == 0x7f) {
+    p->parsing.value = &p->strlen;
+    return parse_value0(p, cur + 1, end);
+  } else {
+    return parse_next(p, cur + 1, end);
+  }
+}
+
+/* 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 + str->length > str->capacity) {
+    GPR_ASSERT(str->length + length <= UINT32_MAX);
+    str->capacity = (uint32_t)(str->length + length);
+    str->str = gpr_realloc(str->str, str->capacity);
+  }
+  memcpy(str->str + str->length, data, length);
+  GPR_ASSERT(length <= UINT32_MAX - str->length);
+  str->length += (uint32_t)length;
+}
+
+static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                         const uint8_t *end) {
+  grpc_chttp2_hpack_parser_string *str = p->parsing.str;
+  uint32_t bits;
+  uint8_t decoded[3];
+  switch ((binary_state)p->binary) {
+    case NOT_BINARY:
+      append_bytes(str, cur, (size_t)(end - cur));
+      return 1;
+    b64_byte0:
+    case B64_BYTE0:
+      if (cur == end) {
+        p->binary = B64_BYTE0;
+        return 1;
+      }
+      bits = inverse_base64[*cur];
+      ++cur;
+      if (bits == 255)
+        return 0;
+      else if (bits == 64)
+        goto b64_byte0;
+      p->base64_buffer = bits << 18;
+    /* fallthrough */
+    b64_byte1:
+    case B64_BYTE1:
+      if (cur == end) {
+        p->binary = B64_BYTE1;
+        return 1;
+      }
+      bits = inverse_base64[*cur];
+      ++cur;
+      if (bits == 255)
+        return 0;
+      else if (bits == 64)
+        goto b64_byte1;
+      p->base64_buffer |= bits << 12;
+    /* fallthrough */
+    b64_byte2:
+    case B64_BYTE2:
+      if (cur == end) {
+        p->binary = B64_BYTE2;
+        return 1;
+      }
+      bits = inverse_base64[*cur];
+      ++cur;
+      if (bits == 255)
+        return 0;
+      else if (bits == 64)
+        goto b64_byte2;
+      p->base64_buffer |= bits << 6;
+    /* fallthrough */
+    b64_byte3:
+    case B64_BYTE3:
+      if (cur == end) {
+        p->binary = B64_BYTE3;
+        return 1;
+      }
+      bits = inverse_base64[*cur];
+      ++cur;
+      if (bits == 255)
+        return 0;
+      else if (bits == 64)
+        goto b64_byte3;
+      p->base64_buffer |= bits;
+      bits = p->base64_buffer;
+      decoded[0] = (uint8_t)(bits >> 16);
+      decoded[1] = (uint8_t)(bits >> 8);
+      decoded[2] = (uint8_t)(bits);
+      append_bytes(str, decoded, 3);
+      goto b64_byte0;
+  }
+  GPR_UNREACHABLE_CODE(return 1);
+}
+
+/* append a null terminator to a string */
+static int finish_str(grpc_chttp2_hpack_parser *p) {
+  uint8_t terminator = 0;
+  uint8_t decoded[2];
+  uint32_t bits;
+  grpc_chttp2_hpack_parser_string *str = p->parsing.str;
+  switch ((binary_state)p->binary) {
+    case NOT_BINARY:
+      break;
+    case B64_BYTE0:
+      break;
+    case B64_BYTE1:
+      gpr_log(GPR_ERROR, "illegal base64 encoding");
+      return 0; /* illegal encoding */
+    case B64_BYTE2:
+      bits = p->base64_buffer;
+      if (bits & 0xffff) {
+        gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%04x",
+                bits & 0xffff);
+        return 0;
+      }
+      decoded[0] = (uint8_t)(bits >> 16);
+      append_bytes(str, decoded, 1);
+      break;
+    case B64_BYTE3:
+      bits = p->base64_buffer;
+      if (bits & 0xff) {
+        gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%02x",
+                bits & 0xff);
+        return 0;
+      }
+      decoded[0] = (uint8_t)(bits >> 16);
+      decoded[1] = (uint8_t)(bits >> 8);
+      append_bytes(str, decoded, 2);
+      break;
+  }
+  append_bytes(str, &terminator, 1);
+  p->parsing.str->length--; /* don't actually count the null terminator */
+  return 1;
+}
+
+/* decode a nibble from a huffman encoded stream */
+static int huff_nibble(grpc_chttp2_hpack_parser *p, uint8_t nibble) {
+  int16_t emit = emit_sub_tbl[16 * emit_tbl[p->huff_state] + nibble];
+  int16_t next = next_sub_tbl[16 * next_tbl[p->huff_state] + nibble];
+  if (emit != -1) {
+    if (emit >= 0 && emit < 256) {
+      uint8_t c = (uint8_t)emit;
+      if (!append_string(p, &c, (&c) + 1)) return 0;
+    } else {
+      assert(emit == 256);
+    }
+  }
+  p->huff_state = next;
+  return 1;
+}
+
+/* decode full bytes from a huffman encoded stream */
+static int add_huff_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                          const uint8_t *end) {
+  for (; cur != end; ++cur) {
+    if (!huff_nibble(p, *cur >> 4) || !huff_nibble(p, *cur & 0xf)) return 0;
+  }
+  return 1;
+}
+
+/* decode some string bytes based on the current decoding mode
+   (huffman or not) */
+static int add_str_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                         const uint8_t *end) {
+  if (p->huff) {
+    return add_huff_bytes(p, cur, end);
+  } else {
+    return append_string(p, cur, end);
+  }
+}
+
+/* parse a string - tries to do large chunks at a time */
+static int parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                        const uint8_t *end) {
+  size_t remaining = p->strlen - p->strgot;
+  size_t given = (size_t)(end - cur);
+  if (remaining <= given) {
+    return add_str_bytes(p, cur, cur + remaining) && finish_str(p) &&
+           parse_next(p, cur + remaining, end);
+  } else {
+    if (!add_str_bytes(p, cur, cur + given)) return 0;
+    GPR_ASSERT(given <= UINT32_MAX - p->strgot);
+    p->strgot += (uint32_t)given;
+    p->state = parse_string;
+    return 1;
+  }
+}
+
+/* begin parsing a string - performs setup, calls parse_string */
+static int begin_parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                              const uint8_t *end, uint8_t binary,
+                              grpc_chttp2_hpack_parser_string *str) {
+  p->strgot = 0;
+  str->length = 0;
+  p->parsing.str = str;
+  p->huff_state = 0;
+  p->binary = binary;
+  return parse_string(p, cur, end);
+}
+
+/* parse the key string */
+static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                            const uint8_t *end) {
+  return begin_parse_string(p, cur, end, NOT_BINARY, &p->key);
+}
+
+/* check if a key represents a binary header or not */
+typedef enum { BINARY_HEADER, PLAINTEXT_HEADER, ERROR_HEADER } is_binary_header;
+
+static is_binary_header is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
+  return grpc_is_binary_header(p->key.str, p->key.length) ? BINARY_HEADER
+                                                          : PLAINTEXT_HEADER;
+}
+
+static is_binary_header is_binary_indexed_header(grpc_chttp2_hpack_parser *p) {
+  grpc_mdelem *elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  if (!elem) {
+    if (grpc_http_trace) {
+      gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
+    }
+    return ERROR_HEADER;
+  }
+  return grpc_is_binary_header(
+             (const char *)GPR_SLICE_START_PTR(elem->key->slice),
+             GPR_SLICE_LENGTH(elem->key->slice))
+             ? BINARY_HEADER
+             : PLAINTEXT_HEADER;
+}
+
+/* parse the value string */
+static int parse_value_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                              const uint8_t *end, is_binary_header type) {
+  switch (type) {
+    case BINARY_HEADER:
+      return begin_parse_string(p, cur, end, B64_BYTE0, &p->value);
+    case PLAINTEXT_HEADER:
+      return begin_parse_string(p, cur, end, NOT_BINARY, &p->value);
+    case ERROR_HEADER:
+      return 0;
+  }
+  /* Add code to prevent return without value error */
+  GPR_UNREACHABLE_CODE(return 0);
+}
+
+static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
+                                               const uint8_t *cur,
+                                               const uint8_t *end) {
+  return parse_value_string(p, cur, end, is_binary_indexed_header(p));
+}
+
+static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
+                                               const uint8_t *cur,
+                                               const uint8_t *end) {
+  return parse_value_string(p, cur, end, is_binary_literal_header(p));
+}
+
+/* PUBLIC INTERFACE */
+
+void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p) {
+  p->on_header = NULL;
+  p->on_header_user_data = NULL;
+  p->state = parse_begin;
+  p->key.str = NULL;
+  p->key.capacity = 0;
+  p->key.length = 0;
+  p->value.str = NULL;
+  p->value.capacity = 0;
+  p->value.length = 0;
+  p->dynamic_table_update_allowed = 2;
+  grpc_chttp2_hptbl_init(&p->table);
+}
+
+void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p) {
+  p->after_prioritization = p->state;
+  p->state = parse_stream_dep0;
+}
+
+void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p) {
+  grpc_chttp2_hptbl_destroy(&p->table);
+  gpr_free(p->key.str);
+  gpr_free(p->value.str);
+}
+
+int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
+                                   const uint8_t *beg, const uint8_t *end) {
+  /* TODO(ctiller): limit the distance of end from beg, and perform multiple
+     steps in the event of a large chunk of data to limit
+     stack space usage when no tail call optimization is
+     available */
+  return p->state(p, beg, end);
+}
+
+grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *hpack_parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  grpc_chttp2_hpack_parser *parser = hpack_parser;
+  GPR_TIMER_BEGIN("grpc_chttp2_hpack_parser_parse", 0);
+  if (stream_parsing != NULL) {
+    stream_parsing->stats.incoming.header_bytes += GPR_SLICE_LENGTH(slice);
+  }
+  if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice),
+                                      GPR_SLICE_END_PTR(slice))) {
+    GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  }
+  if (is_last) {
+    if (parser->is_boundary && parser->state != parse_begin) {
+      gpr_log(GPR_ERROR,
+              "end of header frame not aligned with a hpack record boundary");
+      GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
+      return GRPC_CHTTP2_CONNECTION_ERROR;
+    }
+    /* need to check for null stream: this can occur if we receive an invalid
+       stream id on a header */
+    if (stream_parsing != NULL) {
+      if (parser->is_boundary) {
+        stream_parsing
+            ->got_metadata_on_parse[stream_parsing->header_frames_received] = 1;
+        stream_parsing->header_frames_received++;
+        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
+                                                 stream_parsing);
+      }
+      if (parser->is_eof) {
+        stream_parsing->received_close = 1;
+      }
+    }
+    parser->on_header = NULL;
+    parser->on_header_user_data = NULL;
+    parser->is_boundary = 0xde;
+    parser->is_eof = 0xde;
+    parser->dynamic_table_update_allowed = 2;
+  }
+  GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
+  return GRPC_CHTTP2_PARSE_OK;
+}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.h b/src/core/ext/transport/chttp2/transport/hpack_parser.h
new file mode 100644
index 0000000..855d6c5
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.h
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H
+
+#include <stddef.h>
+
+#include <grpc/support/port_platform.h>
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_table.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/transport/metadata.h"
+
+typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser;
+
+typedef int (*grpc_chttp2_hpack_parser_state)(grpc_chttp2_hpack_parser *p,
+                                              const uint8_t *beg,
+                                              const uint8_t *end);
+
+typedef struct {
+  char *str;
+  uint32_t length;
+  uint32_t capacity;
+} grpc_chttp2_hpack_parser_string;
+
+struct grpc_chttp2_hpack_parser {
+  /* user specified callback for each header output */
+  void (*on_header)(void *user_data, grpc_mdelem *md);
+  void *on_header_user_data;
+
+  /* current parse state - or a function that implements it */
+  grpc_chttp2_hpack_parser_state state;
+  /* future states dependent on the opening op code */
+  const grpc_chttp2_hpack_parser_state *next_state;
+  /* what to do after skipping prioritization data */
+  grpc_chttp2_hpack_parser_state after_prioritization;
+  /* the value we're currently parsing */
+  union {
+    uint32_t *value;
+    grpc_chttp2_hpack_parser_string *str;
+  } parsing;
+  /* string parameters for each chunk */
+  grpc_chttp2_hpack_parser_string key;
+  grpc_chttp2_hpack_parser_string value;
+  /* parsed index */
+  uint32_t index;
+  /* length of source bytes for the currently parsing string */
+  uint32_t strlen;
+  /* number of source bytes read for the currently parsing string */
+  uint32_t strgot;
+  /* huffman decoding state */
+  int16_t huff_state;
+  /* is the string being decoded binary? */
+  uint8_t binary;
+  /* is the current string huffman encoded? */
+  uint8_t huff;
+  /* is a dynamic table update allowed? */
+  uint8_t dynamic_table_update_allowed;
+  /* set by higher layers, used by grpc_chttp2_header_parser_parse to signal
+     it should append a metadata boundary at the end of frame */
+  uint8_t is_boundary;
+  uint8_t is_eof;
+  uint32_t base64_buffer;
+
+  /* hpack table */
+  grpc_chttp2_hptbl table;
+};
+
+void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p);
+void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p);
+
+void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p);
+
+/* returns 1 on success, 0 on error */
+int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
+                                   const uint8_t *beg, const uint8_t *end);
+
+/* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
+   the transport */
+grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
+    grpc_exec_ctx *exec_ctx, void *hpack_parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.c b/src/core/ext/transport/chttp2/transport/hpack_table.c
new file mode 100644
index 0000000..4d64506
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.c
@@ -0,0 +1,369 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/hpack_table.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/support/murmur_hash.h"
+
+extern int grpc_http_trace;
+
+static struct {
+  const char *key;
+  const char *value;
+} static_table[] = {
+    /* 0: */
+    {NULL, NULL},
+    /* 1: */
+    {":authority", ""},
+    /* 2: */
+    {":method", "GET"},
+    /* 3: */
+    {":method", "POST"},
+    /* 4: */
+    {":path", "/"},
+    /* 5: */
+    {":path", "/index.html"},
+    /* 6: */
+    {":scheme", "http"},
+    /* 7: */
+    {":scheme", "https"},
+    /* 8: */
+    {":status", "200"},
+    /* 9: */
+    {":status", "204"},
+    /* 10: */
+    {":status", "206"},
+    /* 11: */
+    {":status", "304"},
+    /* 12: */
+    {":status", "400"},
+    /* 13: */
+    {":status", "404"},
+    /* 14: */
+    {":status", "500"},
+    /* 15: */
+    {"accept-charset", ""},
+    /* 16: */
+    {"accept-encoding", "gzip, deflate"},
+    /* 17: */
+    {"accept-language", ""},
+    /* 18: */
+    {"accept-ranges", ""},
+    /* 19: */
+    {"accept", ""},
+    /* 20: */
+    {"access-control-allow-origin", ""},
+    /* 21: */
+    {"age", ""},
+    /* 22: */
+    {"allow", ""},
+    /* 23: */
+    {"authorization", ""},
+    /* 24: */
+    {"cache-control", ""},
+    /* 25: */
+    {"content-disposition", ""},
+    /* 26: */
+    {"content-encoding", ""},
+    /* 27: */
+    {"content-language", ""},
+    /* 28: */
+    {"content-length", ""},
+    /* 29: */
+    {"content-location", ""},
+    /* 30: */
+    {"content-range", ""},
+    /* 31: */
+    {"content-type", ""},
+    /* 32: */
+    {"cookie", ""},
+    /* 33: */
+    {"date", ""},
+    /* 34: */
+    {"etag", ""},
+    /* 35: */
+    {"expect", ""},
+    /* 36: */
+    {"expires", ""},
+    /* 37: */
+    {"from", ""},
+    /* 38: */
+    {"host", ""},
+    /* 39: */
+    {"if-match", ""},
+    /* 40: */
+    {"if-modified-since", ""},
+    /* 41: */
+    {"if-none-match", ""},
+    /* 42: */
+    {"if-range", ""},
+    /* 43: */
+    {"if-unmodified-since", ""},
+    /* 44: */
+    {"last-modified", ""},
+    /* 45: */
+    {"link", ""},
+    /* 46: */
+    {"location", ""},
+    /* 47: */
+    {"max-forwards", ""},
+    /* 48: */
+    {"proxy-authenticate", ""},
+    /* 49: */
+    {"proxy-authorization", ""},
+    /* 50: */
+    {"range", ""},
+    /* 51: */
+    {"referer", ""},
+    /* 52: */
+    {"refresh", ""},
+    /* 53: */
+    {"retry-after", ""},
+    /* 54: */
+    {"server", ""},
+    /* 55: */
+    {"set-cookie", ""},
+    /* 56: */
+    {"strict-transport-security", ""},
+    /* 57: */
+    {"transfer-encoding", ""},
+    /* 58: */
+    {"user-agent", ""},
+    /* 59: */
+    {"vary", ""},
+    /* 60: */
+    {"via", ""},
+    /* 61: */
+    {"www-authenticate", ""},
+};
+
+static uint32_t entries_for_bytes(uint32_t bytes) {
+  return (bytes + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) /
+         GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
+}
+
+void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl) {
+  size_t i;
+
+  memset(tbl, 0, sizeof(*tbl));
+  tbl->current_table_bytes = tbl->max_bytes =
+      GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE;
+  tbl->max_entries = tbl->cap_entries =
+      entries_for_bytes(tbl->current_table_bytes);
+  tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
+  memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
+  for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
+    tbl->static_ents[i - 1] =
+        grpc_mdelem_from_strings(static_table[i].key, static_table[i].value);
+  }
+}
+
+void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) {
+  size_t i;
+  for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
+    GRPC_MDELEM_UNREF(tbl->static_ents[i]);
+  }
+  for (i = 0; i < tbl->num_ents; i++) {
+    GRPC_MDELEM_UNREF(tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]);
+  }
+  gpr_free(tbl->ents);
+}
+
+grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
+                                      uint32_t tbl_index) {
+  /* Static table comes first, just return an entry from it */
+  if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) {
+    return tbl->static_ents[tbl_index - 1];
+  }
+  /* Otherwise, find the value in the list of valid entries */
+  tbl_index -= (GRPC_CHTTP2_LAST_STATIC_ENTRY + 1);
+  if (tbl_index < tbl->num_ents) {
+    uint32_t offset =
+        (tbl->num_ents - 1u - tbl_index + tbl->first_ent) % tbl->cap_entries;
+    return tbl->ents[offset];
+  }
+  /* Invalid entry: return error */
+  return NULL;
+}
+
+/* Evict one element from the table */
+static void evict1(grpc_chttp2_hptbl *tbl) {
+  grpc_mdelem *first_ent = tbl->ents[tbl->first_ent];
+  size_t elem_bytes = GPR_SLICE_LENGTH(first_ent->key->slice) +
+                      GPR_SLICE_LENGTH(first_ent->value->slice) +
+                      GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
+  GPR_ASSERT(elem_bytes <= tbl->mem_used);
+  tbl->mem_used -= (uint32_t)elem_bytes;
+  tbl->first_ent = ((tbl->first_ent + 1) % tbl->cap_entries);
+  tbl->num_ents--;
+  GRPC_MDELEM_UNREF(first_ent);
+}
+
+static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) {
+  grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap);
+  uint32_t i;
+
+  for (i = 0; i < tbl->num_ents; i++) {
+    ents[i] = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
+  }
+  gpr_free(tbl->ents);
+  tbl->ents = ents;
+  tbl->cap_entries = new_cap;
+  tbl->first_ent = 0;
+}
+
+void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
+                                     uint32_t max_bytes) {
+  if (tbl->max_bytes == max_bytes) {
+    return;
+  }
+  gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes);
+  while (tbl->mem_used > max_bytes) {
+    evict1(tbl);
+  }
+  tbl->max_bytes = max_bytes;
+}
+
+int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
+                                             uint32_t bytes) {
+  if (tbl->current_table_bytes == bytes) {
+    return 1;
+  }
+  if (bytes > tbl->max_bytes) {
+    if (grpc_http_trace) {
+      gpr_log(GPR_ERROR,
+              "Attempt to make hpack table %d bytes when max is %d bytes",
+              bytes, tbl->max_bytes);
+    }
+    return 0;
+  }
+  if (grpc_http_trace) {
+    gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
+  }
+  while (tbl->mem_used > bytes) {
+    evict1(tbl);
+  }
+  tbl->current_table_bytes = bytes;
+  tbl->max_entries = entries_for_bytes(bytes);
+  if (tbl->max_entries > tbl->cap_entries) {
+    rebuild_ents(tbl, GPR_MAX(tbl->max_entries, 2 * tbl->cap_entries));
+  } else if (tbl->max_entries < tbl->cap_entries / 3) {
+    uint32_t new_cap = GPR_MAX(tbl->max_entries, 16u);
+    if (new_cap != tbl->cap_entries) {
+      rebuild_ents(tbl, new_cap);
+    }
+  }
+  return 1;
+}
+
+int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
+  /* determine how many bytes of buffer this entry represents */
+  size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) +
+                      GPR_SLICE_LENGTH(md->value->slice) +
+                      GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
+
+  if (tbl->current_table_bytes > tbl->max_bytes) {
+    if (grpc_http_trace) {
+      gpr_log(GPR_ERROR,
+              "HPACK max table size reduced to %d but not reflected by hpack "
+              "stream (still at %d)",
+              tbl->max_bytes, tbl->current_table_bytes);
+    }
+    return 0;
+  }
+
+  /* we can't add elements bigger than the max table size */
+  if (elem_bytes > tbl->current_table_bytes) {
+    /* HPACK draft 10 section 4.4 states:
+     * If the size of the new entry is less than or equal to the maximum
+     * size, that entry is added to the table.  It is not an error to
+     * attempt to add an entry that is larger than the maximum size; an
+     * attempt to add an entry larger than the entire table causes
+     * the table
+     * to be emptied of all existing entries, and results in an
+     * empty table.
+     */
+    while (tbl->num_ents) {
+      evict1(tbl);
+    }
+    return 1;
+  }
+
+  /* evict entries to ensure no overflow */
+  while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) {
+    evict1(tbl);
+  }
+
+  /* copy the finalized entry in */
+  tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] =
+      GRPC_MDELEM_REF(md);
+
+  /* update accounting values */
+  tbl->num_ents++;
+  tbl->mem_used += (uint32_t)elem_bytes;
+  return 1;
+}
+
+grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
+    const grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
+  grpc_chttp2_hptbl_find_result r = {0, 0};
+  uint32_t i;
+
+  /* See if the string is in the static table */
+  for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
+    grpc_mdelem *ent = tbl->static_ents[i];
+    if (md->key != ent->key) continue;
+    r.index = i + 1u;
+    r.has_value = md->value == ent->value;
+    if (r.has_value) return r;
+  }
+
+  /* Scan the dynamic table */
+  for (i = 0; i < tbl->num_ents; i++) {
+    uint32_t idx =
+        (uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
+    grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
+    if (md->key != ent->key) continue;
+    r.index = idx;
+    r.has_value = md->value == ent->value;
+    if (r.has_value) return r;
+  }
+
+  return r;
+}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.h b/src/core/ext/transport/chttp2/transport/hpack_table.h
new file mode 100644
index 0000000..074fea3
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.h
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include "src/core/lib/transport/metadata.h"
+
+/* HPACK header table */
+
+/* last index in the static table */
+#define GRPC_CHTTP2_LAST_STATIC_ENTRY 61
+
+/* Initial table size as per the spec */
+#define GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE 4096
+/* Maximum table size that we'll use */
+#define GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE
+/* Per entry overhead bytes as per the spec */
+#define GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD 32
+#if 0
+/* Maximum number of entries we could possibly fit in the table, given defined
+   overheads */
+#define GRPC_CHTTP2_MAX_TABLE_COUNT                                            \
+  ((GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / \
+   GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD)
+#endif
+
+/* hpack decoder table */
+typedef struct {
+  /* the first used entry in ents */
+  uint32_t first_ent;
+  /* how many entries are in the table */
+  uint32_t num_ents;
+  /* the amount of memory used by the table, according to the hpack algorithm */
+  uint32_t mem_used;
+  /* the max memory allowed to be used by the table, according to the hpack
+     algorithm */
+  uint32_t max_bytes;
+  /* the currently agreed size of the table, according to the hpack algorithm */
+  uint32_t current_table_bytes;
+  /* Maximum number of entries we could possibly fit in the table, given defined
+     overheads */
+  uint32_t max_entries;
+  /* Number of entries allocated in ents */
+  uint32_t cap_entries;
+  /* a circular buffer of headers - this is stored in the opposite order to
+     what hpack specifies, in order to simplify table management a little...
+     meaning lookups need to SUBTRACT from the end position */
+  grpc_mdelem **ents;
+  grpc_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY];
+} grpc_chttp2_hptbl;
+
+/* initialize a hpack table */
+void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl);
+void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl);
+void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
+                                     uint32_t max_bytes);
+int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
+                                             uint32_t bytes);
+
+/* lookup a table entry based on its hpack index */
+grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
+                                      uint32_t index);
+/* add a table entry to the index */
+int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
+                          grpc_mdelem *md) GRPC_MUST_USE_RESULT;
+/* Find a key/value pair in the table... returns the index in the table of the
+   most similar entry, or 0 if the value was not found */
+typedef struct {
+  uint32_t index;
+  int has_value;
+} grpc_chttp2_hptbl_find_result;
+grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
+    const grpc_chttp2_hptbl *tbl, grpc_mdelem *md);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H */
diff --git a/src/core/transport/chttp2/hpack_tables.txt b/src/core/ext/transport/chttp2/transport/hpack_tables.txt
similarity index 100%
rename from src/core/transport/chttp2/hpack_tables.txt
rename to src/core/ext/transport/chttp2/transport/hpack_tables.txt
diff --git a/src/core/ext/transport/chttp2/transport/http2_errors.h b/src/core/ext/transport/chttp2/transport/http2_errors.h
new file mode 100644
index 0000000..deab2b7
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/http2_errors.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_ERRORS_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_ERRORS_H
+
+/* error codes for RST_STREAM from http2 draft 14 section 7 */
+typedef enum {
+  GRPC_CHTTP2_NO_ERROR = 0x0,
+  GRPC_CHTTP2_PROTOCOL_ERROR = 0x1,
+  GRPC_CHTTP2_INTERNAL_ERROR = 0x2,
+  GRPC_CHTTP2_FLOW_CONTROL_ERROR = 0x3,
+  GRPC_CHTTP2_SETTINGS_TIMEOUT = 0x4,
+  GRPC_CHTTP2_STREAM_CLOSED = 0x5,
+  GRPC_CHTTP2_FRAME_SIZE_ERROR = 0x6,
+  GRPC_CHTTP2_REFUSED_STREAM = 0x7,
+  GRPC_CHTTP2_CANCEL = 0x8,
+  GRPC_CHTTP2_COMPRESSION_ERROR = 0x9,
+  GRPC_CHTTP2_CONNECT_ERROR = 0xa,
+  GRPC_CHTTP2_ENHANCE_YOUR_CALM = 0xb,
+  GRPC_CHTTP2_INADEQUATE_SECURITY = 0xc,
+  /* force use of a default clause */
+  GRPC_CHTTP2__ERROR_DO_NOT_USE = -1
+} grpc_chttp2_error_code;
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_ERRORS_H */
diff --git a/src/core/ext/transport/chttp2/transport/huffsyms.c b/src/core/ext/transport/chttp2/transport/huffsyms.c
new file mode 100644
index 0000000..68b34e4
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/huffsyms.c
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/huffsyms.h"
+
+/* Constants pulled from the HPACK spec, and converted to C using the vim
+   command:
+   :%s/.*   \([0-9a-f]\+\)  \[ *\([0-9]\+\)\]/{0x\1, \2},/g */
+const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS] = {
+    {0x1ff8, 13},     {0x7fffd8, 23},   {0xfffffe2, 28},  {0xfffffe3, 28},
+    {0xfffffe4, 28},  {0xfffffe5, 28},  {0xfffffe6, 28},  {0xfffffe7, 28},
+    {0xfffffe8, 28},  {0xffffea, 24},   {0x3ffffffc, 30}, {0xfffffe9, 28},
+    {0xfffffea, 28},  {0x3ffffffd, 30}, {0xfffffeb, 28},  {0xfffffec, 28},
+    {0xfffffed, 28},  {0xfffffee, 28},  {0xfffffef, 28},  {0xffffff0, 28},
+    {0xffffff1, 28},  {0xffffff2, 28},  {0x3ffffffe, 30}, {0xffffff3, 28},
+    {0xffffff4, 28},  {0xffffff5, 28},  {0xffffff6, 28},  {0xffffff7, 28},
+    {0xffffff8, 28},  {0xffffff9, 28},  {0xffffffa, 28},  {0xffffffb, 28},
+    {0x14, 6},        {0x3f8, 10},      {0x3f9, 10},      {0xffa, 12},
+    {0x1ff9, 13},     {0x15, 6},        {0xf8, 8},        {0x7fa, 11},
+    {0x3fa, 10},      {0x3fb, 10},      {0xf9, 8},        {0x7fb, 11},
+    {0xfa, 8},        {0x16, 6},        {0x17, 6},        {0x18, 6},
+    {0x0, 5},         {0x1, 5},         {0x2, 5},         {0x19, 6},
+    {0x1a, 6},        {0x1b, 6},        {0x1c, 6},        {0x1d, 6},
+    {0x1e, 6},        {0x1f, 6},        {0x5c, 7},        {0xfb, 8},
+    {0x7ffc, 15},     {0x20, 6},        {0xffb, 12},      {0x3fc, 10},
+    {0x1ffa, 13},     {0x21, 6},        {0x5d, 7},        {0x5e, 7},
+    {0x5f, 7},        {0x60, 7},        {0x61, 7},        {0x62, 7},
+    {0x63, 7},        {0x64, 7},        {0x65, 7},        {0x66, 7},
+    {0x67, 7},        {0x68, 7},        {0x69, 7},        {0x6a, 7},
+    {0x6b, 7},        {0x6c, 7},        {0x6d, 7},        {0x6e, 7},
+    {0x6f, 7},        {0x70, 7},        {0x71, 7},        {0x72, 7},
+    {0xfc, 8},        {0x73, 7},        {0xfd, 8},        {0x1ffb, 13},
+    {0x7fff0, 19},    {0x1ffc, 13},     {0x3ffc, 14},     {0x22, 6},
+    {0x7ffd, 15},     {0x3, 5},         {0x23, 6},        {0x4, 5},
+    {0x24, 6},        {0x5, 5},         {0x25, 6},        {0x26, 6},
+    {0x27, 6},        {0x6, 5},         {0x74, 7},        {0x75, 7},
+    {0x28, 6},        {0x29, 6},        {0x2a, 6},        {0x7, 5},
+    {0x2b, 6},        {0x76, 7},        {0x2c, 6},        {0x8, 5},
+    {0x9, 5},         {0x2d, 6},        {0x77, 7},        {0x78, 7},
+    {0x79, 7},        {0x7a, 7},        {0x7b, 7},        {0x7ffe, 15},
+    {0x7fc, 11},      {0x3ffd, 14},     {0x1ffd, 13},     {0xffffffc, 28},
+    {0xfffe6, 20},    {0x3fffd2, 22},   {0xfffe7, 20},    {0xfffe8, 20},
+    {0x3fffd3, 22},   {0x3fffd4, 22},   {0x3fffd5, 22},   {0x7fffd9, 23},
+    {0x3fffd6, 22},   {0x7fffda, 23},   {0x7fffdb, 23},   {0x7fffdc, 23},
+    {0x7fffdd, 23},   {0x7fffde, 23},   {0xffffeb, 24},   {0x7fffdf, 23},
+    {0xffffec, 24},   {0xffffed, 24},   {0x3fffd7, 22},   {0x7fffe0, 23},
+    {0xffffee, 24},   {0x7fffe1, 23},   {0x7fffe2, 23},   {0x7fffe3, 23},
+    {0x7fffe4, 23},   {0x1fffdc, 21},   {0x3fffd8, 22},   {0x7fffe5, 23},
+    {0x3fffd9, 22},   {0x7fffe6, 23},   {0x7fffe7, 23},   {0xffffef, 24},
+    {0x3fffda, 22},   {0x1fffdd, 21},   {0xfffe9, 20},    {0x3fffdb, 22},
+    {0x3fffdc, 22},   {0x7fffe8, 23},   {0x7fffe9, 23},   {0x1fffde, 21},
+    {0x7fffea, 23},   {0x3fffdd, 22},   {0x3fffde, 22},   {0xfffff0, 24},
+    {0x1fffdf, 21},   {0x3fffdf, 22},   {0x7fffeb, 23},   {0x7fffec, 23},
+    {0x1fffe0, 21},   {0x1fffe1, 21},   {0x3fffe0, 22},   {0x1fffe2, 21},
+    {0x7fffed, 23},   {0x3fffe1, 22},   {0x7fffee, 23},   {0x7fffef, 23},
+    {0xfffea, 20},    {0x3fffe2, 22},   {0x3fffe3, 22},   {0x3fffe4, 22},
+    {0x7ffff0, 23},   {0x3fffe5, 22},   {0x3fffe6, 22},   {0x7ffff1, 23},
+    {0x3ffffe0, 26},  {0x3ffffe1, 26},  {0xfffeb, 20},    {0x7fff1, 19},
+    {0x3fffe7, 22},   {0x7ffff2, 23},   {0x3fffe8, 22},   {0x1ffffec, 25},
+    {0x3ffffe2, 26},  {0x3ffffe3, 26},  {0x3ffffe4, 26},  {0x7ffffde, 27},
+    {0x7ffffdf, 27},  {0x3ffffe5, 26},  {0xfffff1, 24},   {0x1ffffed, 25},
+    {0x7fff2, 19},    {0x1fffe3, 21},   {0x3ffffe6, 26},  {0x7ffffe0, 27},
+    {0x7ffffe1, 27},  {0x3ffffe7, 26},  {0x7ffffe2, 27},  {0xfffff2, 24},
+    {0x1fffe4, 21},   {0x1fffe5, 21},   {0x3ffffe8, 26},  {0x3ffffe9, 26},
+    {0xffffffd, 28},  {0x7ffffe3, 27},  {0x7ffffe4, 27},  {0x7ffffe5, 27},
+    {0xfffec, 20},    {0xfffff3, 24},   {0xfffed, 20},    {0x1fffe6, 21},
+    {0x3fffe9, 22},   {0x1fffe7, 21},   {0x1fffe8, 21},   {0x7ffff3, 23},
+    {0x3fffea, 22},   {0x3fffeb, 22},   {0x1ffffee, 25},  {0x1ffffef, 25},
+    {0xfffff4, 24},   {0xfffff5, 24},   {0x3ffffea, 26},  {0x7ffff4, 23},
+    {0x3ffffeb, 26},  {0x7ffffe6, 27},  {0x3ffffec, 26},  {0x3ffffed, 26},
+    {0x7ffffe7, 27},  {0x7ffffe8, 27},  {0x7ffffe9, 27},  {0x7ffffea, 27},
+    {0x7ffffeb, 27},  {0xffffffe, 28},  {0x7ffffec, 27},  {0x7ffffed, 27},
+    {0x7ffffee, 27},  {0x7ffffef, 27},  {0x7fffff0, 27},  {0x3ffffee, 26},
+    {0x3fffffff, 30},
+};
diff --git a/src/core/ext/transport/chttp2/transport/huffsyms.h b/src/core/ext/transport/chttp2/transport/huffsyms.h
new file mode 100644
index 0000000..fee0095
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/huffsyms.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_HUFFSYMS_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HUFFSYMS_H
+
+/* HPACK static huffman table */
+
+#define GRPC_CHTTP2_NUM_HUFFSYMS 257
+
+typedef struct {
+  unsigned bits;
+  unsigned length;
+} grpc_chttp2_huffsym;
+
+extern const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS];
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HUFFSYMS_H */
diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.c b/src/core/ext/transport/chttp2/transport/incoming_metadata.c
new file mode 100644
index 0000000..db21744
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.c
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/incoming_metadata.h"
+
+#include <string.h>
+
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+void grpc_chttp2_incoming_metadata_buffer_init(
+    grpc_chttp2_incoming_metadata_buffer *buffer) {
+  buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
+}
+
+void grpc_chttp2_incoming_metadata_buffer_destroy(
+    grpc_chttp2_incoming_metadata_buffer *buffer) {
+  size_t i;
+  if (!buffer->published) {
+    for (i = 0; i < buffer->count; i++) {
+      GRPC_MDELEM_UNREF(buffer->elems[i].md);
+    }
+  }
+  gpr_free(buffer->elems);
+}
+
+void grpc_chttp2_incoming_metadata_buffer_add(
+    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) {
+  GPR_ASSERT(!buffer->published);
+  if (buffer->capacity == buffer->count) {
+    buffer->capacity = GPR_MAX(8, 2 * buffer->capacity);
+    buffer->elems =
+        gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity);
+  }
+  buffer->elems[buffer->count++].md = elem;
+}
+
+void grpc_chttp2_incoming_metadata_buffer_set_deadline(
+    grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) {
+  GPR_ASSERT(!buffer->published);
+  buffer->deadline = deadline;
+}
+
+void grpc_chttp2_incoming_metadata_buffer_publish(
+    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) {
+  GPR_ASSERT(!buffer->published);
+  buffer->published = 1;
+  if (buffer->count > 0) {
+    size_t i;
+    for (i = 1; i < buffer->count; i++) {
+      buffer->elems[i].prev = &buffer->elems[i - 1];
+    }
+    for (i = 0; i < buffer->count - 1; i++) {
+      buffer->elems[i].next = &buffer->elems[i + 1];
+    }
+    buffer->elems[0].prev = NULL;
+    buffer->elems[buffer->count - 1].next = NULL;
+    batch->list.head = &buffer->elems[0];
+    batch->list.tail = &buffer->elems[buffer->count - 1];
+  } else {
+    batch->list.head = batch->list.tail = NULL;
+  }
+  batch->deadline = buffer->deadline;
+}
diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h
new file mode 100644
index 0000000..17ecf8e
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H
+
+#include "src/core/lib/transport/transport.h"
+
+typedef struct {
+  grpc_linked_mdelem *elems;
+  size_t count;
+  size_t capacity;
+  gpr_timespec deadline;
+  int published;
+} grpc_chttp2_incoming_metadata_buffer;
+
+/** assumes everything initially zeroed */
+void grpc_chttp2_incoming_metadata_buffer_init(
+    grpc_chttp2_incoming_metadata_buffer *buffer);
+void grpc_chttp2_incoming_metadata_buffer_destroy(
+    grpc_chttp2_incoming_metadata_buffer *buffer);
+void grpc_chttp2_incoming_metadata_buffer_publish(
+    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch);
+
+void grpc_chttp2_incoming_metadata_buffer_add(
+    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem);
+void grpc_chttp2_incoming_metadata_buffer_set_deadline(
+    grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H */
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
new file mode 100644
index 0000000..98cd38a
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -0,0 +1,788 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/ext/transport/chttp2/transport/frame_data.h"
+#include "src/core/ext/transport/chttp2/transport/frame_goaway.h"
+#include "src/core/ext/transport/chttp2/transport/frame_ping.h"
+#include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h"
+#include "src/core/ext/transport/chttp2/transport/frame_settings.h"
+#include "src/core/ext/transport/chttp2/transport/frame_window_update.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
+#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
+#include "src/core/ext/transport/chttp2/transport/stream_map.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/transport_impl.h"
+
+typedef struct grpc_chttp2_transport grpc_chttp2_transport;
+typedef struct grpc_chttp2_stream grpc_chttp2_stream;
+
+/* streams are kept in various linked lists depending on what things need to
+   happen to them... this enum labels each list */
+typedef enum {
+  GRPC_CHTTP2_LIST_ALL_STREAMS,
+  GRPC_CHTTP2_LIST_CHECK_READ_OPS,
+  GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE,
+  GRPC_CHTTP2_LIST_WRITABLE,
+  GRPC_CHTTP2_LIST_WRITING,
+  GRPC_CHTTP2_LIST_WRITTEN,
+  GRPC_CHTTP2_LIST_PARSING_SEEN,
+  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
+  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING,
+  GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT,
+  /* streams waiting for the outgoing window in the writing path, they will be
+   * merged to the stalled list or writable list under transport lock. */
+  GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT,
+  /** streams that are waiting to start because there are too many concurrent
+      streams on the connection */
+  GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
+  STREAM_LIST_COUNT /* must be last */
+} grpc_chttp2_stream_list_id;
+
+/* deframer state for the overall http2 stream of bytes */
+typedef enum {
+  /* prefix: one entry per http2 connection prefix byte */
+  GRPC_DTS_CLIENT_PREFIX_0 = 0,
+  GRPC_DTS_CLIENT_PREFIX_1,
+  GRPC_DTS_CLIENT_PREFIX_2,
+  GRPC_DTS_CLIENT_PREFIX_3,
+  GRPC_DTS_CLIENT_PREFIX_4,
+  GRPC_DTS_CLIENT_PREFIX_5,
+  GRPC_DTS_CLIENT_PREFIX_6,
+  GRPC_DTS_CLIENT_PREFIX_7,
+  GRPC_DTS_CLIENT_PREFIX_8,
+  GRPC_DTS_CLIENT_PREFIX_9,
+  GRPC_DTS_CLIENT_PREFIX_10,
+  GRPC_DTS_CLIENT_PREFIX_11,
+  GRPC_DTS_CLIENT_PREFIX_12,
+  GRPC_DTS_CLIENT_PREFIX_13,
+  GRPC_DTS_CLIENT_PREFIX_14,
+  GRPC_DTS_CLIENT_PREFIX_15,
+  GRPC_DTS_CLIENT_PREFIX_16,
+  GRPC_DTS_CLIENT_PREFIX_17,
+  GRPC_DTS_CLIENT_PREFIX_18,
+  GRPC_DTS_CLIENT_PREFIX_19,
+  GRPC_DTS_CLIENT_PREFIX_20,
+  GRPC_DTS_CLIENT_PREFIX_21,
+  GRPC_DTS_CLIENT_PREFIX_22,
+  GRPC_DTS_CLIENT_PREFIX_23,
+  /* frame header byte 0... */
+  /* must follow from the prefix states */
+  GRPC_DTS_FH_0,
+  GRPC_DTS_FH_1,
+  GRPC_DTS_FH_2,
+  GRPC_DTS_FH_3,
+  GRPC_DTS_FH_4,
+  GRPC_DTS_FH_5,
+  GRPC_DTS_FH_6,
+  GRPC_DTS_FH_7,
+  /* ... frame header byte 8 */
+  GRPC_DTS_FH_8,
+  /* inside a http2 frame */
+  GRPC_DTS_FRAME
+} grpc_chttp2_deframe_transport_state;
+
+typedef struct {
+  grpc_chttp2_stream *head;
+  grpc_chttp2_stream *tail;
+} grpc_chttp2_stream_list;
+
+typedef struct {
+  grpc_chttp2_stream *next;
+  grpc_chttp2_stream *prev;
+} grpc_chttp2_stream_link;
+
+/* We keep several sets of connection wide parameters */
+typedef enum {
+  /* The settings our peer has asked for (and we have acked) */
+  GRPC_PEER_SETTINGS = 0,
+  /* The settings we'd like to have */
+  GRPC_LOCAL_SETTINGS,
+  /* The settings we've published to our peer */
+  GRPC_SENT_SETTINGS,
+  /* The settings the peer has acked */
+  GRPC_ACKED_SETTINGS,
+  GRPC_NUM_SETTING_SETS
+} grpc_chttp2_setting_set;
+
+/* Outstanding ping request data */
+typedef struct grpc_chttp2_outstanding_ping {
+  uint8_t id[8];
+  grpc_closure *on_recv;
+  struct grpc_chttp2_outstanding_ping *next;
+  struct grpc_chttp2_outstanding_ping *prev;
+} grpc_chttp2_outstanding_ping;
+
+/* forward declared in frame_data.h */
+struct grpc_chttp2_incoming_byte_stream {
+  grpc_byte_stream base;
+  gpr_refcount refs;
+  struct grpc_chttp2_incoming_byte_stream *next_message;
+  int failed;
+
+  grpc_chttp2_transport *transport;
+  grpc_chttp2_stream *stream;
+  int is_tail;
+  gpr_slice_buffer slices;
+  grpc_closure *on_next;
+  gpr_slice *next;
+};
+
+typedef struct {
+  /** data to write next write */
+  gpr_slice_buffer qbuf;
+
+  /** window available for us to send to peer */
+  int64_t outgoing_window;
+  /** window available to announce to peer */
+  int64_t announce_incoming_window;
+  /** how much window would we like to have for incoming_window */
+  uint32_t connection_window_target;
+
+  /** have we seen a goaway */
+  uint8_t seen_goaway;
+  /** have we sent a goaway */
+  uint8_t sent_goaway;
+
+  /** is this transport a client? */
+  uint8_t is_client;
+  /** are the local settings dirty and need to be sent? */
+  uint8_t dirtied_local_settings;
+  /** have local settings been sent? */
+  uint8_t sent_local_settings;
+  /** bitmask of setting indexes to send out */
+  uint32_t force_send_settings;
+  /** settings values */
+  uint32_t settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
+
+  /** what is the next stream id to be allocated by this peer?
+      copied to next_stream_id in parsing when parsing commences */
+  uint32_t next_stream_id;
+
+  /** how far to lookahead in a stream? */
+  uint32_t stream_lookahead;
+
+  /** last received stream id */
+  uint32_t last_incoming_stream_id;
+
+  /** pings awaiting responses */
+  grpc_chttp2_outstanding_ping pings;
+  /** next payload for an outgoing ping */
+  uint64_t ping_counter;
+
+  /** concurrent stream count: updated when not parsing,
+      so this is a strict over-estimation on the client */
+  uint32_t concurrent_stream_count;
+} grpc_chttp2_transport_global;
+
+typedef struct {
+  /** data to write now */
+  gpr_slice_buffer outbuf;
+  /** hpack encoding */
+  grpc_chttp2_hpack_compressor hpack_compressor;
+  int64_t outgoing_window;
+  /** is this a client? */
+  uint8_t is_client;
+  /** callback for when writing is done */
+  grpc_closure done_cb;
+} grpc_chttp2_transport_writing;
+
+struct grpc_chttp2_transport_parsing {
+  /** is this transport a client? (boolean) */
+  uint8_t is_client;
+
+  /** were settings updated? */
+  uint8_t settings_updated;
+  /** was a settings ack received? */
+  uint8_t settings_ack_received;
+  /** was a goaway frame received? */
+  uint8_t goaway_received;
+
+  /** the last sent max_table_size setting */
+  uint32_t last_sent_max_table_size;
+
+  /** initial window change */
+  int64_t initial_window_update;
+
+  /** data to write later - after parsing */
+  gpr_slice_buffer qbuf;
+  /** parser for headers */
+  grpc_chttp2_hpack_parser hpack_parser;
+  /** simple one shot parsers */
+  union {
+    grpc_chttp2_window_update_parser window_update;
+    grpc_chttp2_settings_parser settings;
+    grpc_chttp2_ping_parser ping;
+    grpc_chttp2_rst_stream_parser rst_stream;
+  } simple;
+  /** parser for goaway frames */
+  grpc_chttp2_goaway_parser goaway_parser;
+
+  /** window available for peer to send to us */
+  int64_t incoming_window;
+
+  /** next stream id available at the time of beginning parsing */
+  uint32_t next_stream_id;
+  uint32_t last_incoming_stream_id;
+
+  /* deframing */
+  grpc_chttp2_deframe_transport_state deframe_state;
+  uint8_t incoming_frame_type;
+  uint8_t incoming_frame_flags;
+  uint8_t header_eof;
+  uint32_t expect_continuation_stream_id;
+  uint32_t incoming_frame_size;
+  uint32_t incoming_stream_id;
+
+  /* active parser */
+  void *parser_data;
+  grpc_chttp2_stream_parsing *incoming_stream;
+  grpc_chttp2_parse_error (*parser)(
+      grpc_exec_ctx *exec_ctx, void *parser_user_data,
+      grpc_chttp2_transport_parsing *transport_parsing,
+      grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+
+  /* received settings */
+  uint32_t settings[GRPC_CHTTP2_NUM_SETTINGS];
+
+  /* goaway data */
+  grpc_status_code goaway_error;
+  uint32_t goaway_last_stream_index;
+  gpr_slice goaway_text;
+
+  int64_t outgoing_window;
+};
+
+struct grpc_chttp2_transport {
+  grpc_transport base; /* must be first */
+  grpc_endpoint *ep;
+  gpr_refcount refs;
+  char *peer_string;
+
+  /** when this drops to zero it's safe to shutdown the endpoint */
+  gpr_refcount shutdown_ep_refs;
+
+  gpr_mu mu;
+
+  /** is the transport destroying itself? */
+  uint8_t destroying;
+  /** has the upper layer closed the transport? */
+  uint8_t closed;
+
+  /** is a thread currently writing */
+  uint8_t writing_active;
+  /** is a thread currently parsing */
+  uint8_t parsing_active;
+
+  /** is there a read request to the endpoint outstanding? */
+  uint8_t endpoint_reading;
+
+  /** various lists of streams */
+  grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
+
+  /** global state for reading/writing */
+  grpc_chttp2_transport_global global;
+  /** state only accessible by the chain of execution that
+      set writing_active=1 */
+  grpc_chttp2_transport_writing writing;
+  /** state only accessible by the chain of execution that
+      set parsing_active=1 */
+  grpc_chttp2_transport_parsing parsing;
+
+  /** maps stream id to grpc_chttp2_stream objects;
+      owned by the parsing thread when parsing */
+  grpc_chttp2_stream_map parsing_stream_map;
+
+  /** streams created by the client (possibly during parsing);
+      merged with parsing_stream_map during unlock when no
+      parsing is occurring */
+  grpc_chttp2_stream_map new_stream_map;
+
+  /** closure to execute writing */
+  grpc_closure writing_action;
+  /** closure to finish reading from the endpoint */
+  grpc_closure recv_data;
+
+  /** incoming read bytes */
+  gpr_slice_buffer read_buffer;
+
+  /** address to place a newly accepted stream - set and unset by
+      grpc_chttp2_parsing_accept_stream; used by init_stream to
+      publish the accepted server stream */
+  grpc_chttp2_stream **accepting_stream;
+
+  struct {
+    /* accept stream callback */
+    void (*accept_stream)(grpc_exec_ctx *exec_ctx, void *user_data,
+                          grpc_transport *transport, const void *server_data);
+    void *accept_stream_user_data;
+
+    /** connectivity tracking */
+    grpc_connectivity_state_tracker state_tracker;
+  } channel_callback;
+
+  /** Transport op to be applied post-parsing */
+  grpc_transport_op *post_parsing_op;
+};
+
+typedef struct {
+  /** HTTP2 stream id for this stream, or zero if one has not been assigned */
+  uint32_t id;
+
+  /** window available for us to send to peer */
+  int64_t outgoing_window;
+  /** The number of bytes the upper layers have offered to receive.
+      As the upper layer offers more bytes, this value increases.
+      As bytes are read, this value decreases. */
+  uint32_t max_recv_bytes;
+  /** The number of bytes the upper layer has offered to read but we have
+      not yet announced to HTTP2 flow control.
+      As the upper layers offer to read more bytes, this value increases.
+      As we advertise incoming flow control window, this value decreases. */
+  uint32_t unannounced_incoming_window_for_parse;
+  uint32_t unannounced_incoming_window_for_writing;
+  /** things the upper layers would like to send */
+  grpc_metadata_batch *send_initial_metadata;
+  grpc_closure *send_initial_metadata_finished;
+  grpc_byte_stream *send_message;
+  grpc_closure *send_message_finished;
+  grpc_metadata_batch *send_trailing_metadata;
+  grpc_closure *send_trailing_metadata_finished;
+
+  grpc_metadata_batch *recv_initial_metadata;
+  grpc_closure *recv_initial_metadata_ready;
+  grpc_byte_stream **recv_message;
+  grpc_closure *recv_message_ready;
+  grpc_metadata_batch *recv_trailing_metadata;
+  grpc_closure *recv_trailing_metadata_finished;
+
+  grpc_transport_stream_stats *collecting_stats;
+  grpc_transport_stream_stats stats;
+
+  /** when the application requests writes be closed, the write_closed is
+      'queued'; when the close is flow controlled into the send path, we are
+      'sending' it; when the write has been performed it is 'sent' */
+  uint8_t write_closed;
+  /** is this stream reading half-closed (boolean) */
+  uint8_t read_closed;
+  /** is this stream in the stream map? (boolean) */
+  uint8_t in_stream_map;
+  /** has this stream seen an error? if 1, then pending incoming frames
+      can be thrown away */
+  uint8_t seen_error;
+
+  uint8_t published_initial_metadata;
+  uint8_t published_trailing_metadata;
+  uint8_t faked_trailing_metadata;
+
+  grpc_chttp2_incoming_metadata_buffer received_initial_metadata;
+  grpc_chttp2_incoming_metadata_buffer received_trailing_metadata;
+
+  grpc_chttp2_incoming_frame_queue incoming_frames;
+} grpc_chttp2_stream_global;
+
+typedef struct {
+  /** HTTP2 stream id for this stream, or zero if one has not been assigned */
+  uint32_t id;
+  uint8_t fetching;
+  bool sent_initial_metadata;
+  uint8_t sent_message;
+  uint8_t sent_trailing_metadata;
+  uint8_t read_closed;
+  /** send this initial metadata */
+  grpc_metadata_batch *send_initial_metadata;
+  grpc_byte_stream *send_message;
+  grpc_metadata_batch *send_trailing_metadata;
+  int64_t outgoing_window;
+  /** how much window should we announce? */
+  uint32_t announce_window;
+  gpr_slice_buffer flow_controlled_buffer;
+  gpr_slice fetching_slice;
+  size_t stream_fetched;
+  grpc_closure finished_fetch;
+  /** stats gathered during the write */
+  grpc_transport_one_way_stats stats;
+} grpc_chttp2_stream_writing;
+
+struct grpc_chttp2_stream_parsing {
+  /** HTTP2 stream id for this stream, or zero if one has not been assigned */
+  uint32_t id;
+  /** has this stream received a close */
+  uint8_t received_close;
+  /** saw a rst_stream */
+  uint8_t saw_rst_stream;
+  /** how many header frames have we received? */
+  uint8_t header_frames_received;
+  /** which metadata did we get (on this parse) */
+  uint8_t got_metadata_on_parse[2];
+  /** should we raise the seen_error flag in transport_global */
+  uint8_t seen_error;
+  /** window available for peer to send to us */
+  int64_t incoming_window;
+  /** parsing state for data frames */
+  grpc_chttp2_data_parser data_parser;
+  /** reason give to rst_stream */
+  uint32_t rst_stream_reason;
+  /** amount of window given */
+  int64_t outgoing_window;
+  /** number of bytes received - reset at end of parse thread execution */
+  int64_t received_bytes;
+  /** stats gathered during the parse */
+  grpc_transport_stream_stats stats;
+
+  /** incoming metadata */
+  grpc_chttp2_incoming_metadata_buffer metadata_buffer[2];
+};
+
+struct grpc_chttp2_stream {
+  grpc_stream_refcount *refcount;
+  grpc_chttp2_stream_global global;
+  grpc_chttp2_stream_writing writing;
+  grpc_chttp2_stream_parsing parsing;
+
+  grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
+  uint8_t included[STREAM_LIST_COUNT];
+};
+
+/** Transport writing call flow:
+    chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
+   are required;
+    if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
+   writes.
+    Once writes have been completed (meaning another write could potentially be
+   started),
+    grpc_chttp2_terminate_writing is called. This will call
+   grpc_chttp2_cleanup_writing, at which
+    point the write phase is complete. */
+
+/** Someone is unlocking the transport mutex: check to see if writes
+    are required, and schedule them if so */
+int grpc_chttp2_unlocking_check_writes(grpc_exec_ctx *exec_ctx,
+                                       grpc_chttp2_transport_global *global,
+                                       grpc_chttp2_transport_writing *writing,
+                                       int is_parsing);
+void grpc_chttp2_perform_writes(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
+    grpc_endpoint *endpoint);
+void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
+                                   void *transport_writing, bool success);
+void grpc_chttp2_cleanup_writing(grpc_exec_ctx *exec_ctx,
+                                 grpc_chttp2_transport_global *global,
+                                 grpc_chttp2_transport_writing *writing);
+
+void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
+                                 grpc_chttp2_transport_parsing *parsing);
+/** Process one slice of incoming data; return 1 if the connection is still
+    viable after reading, or 0 if the connection should be torn down */
+int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_parsing *transport_parsing,
+                             gpr_slice slice);
+void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx,
+                               grpc_chttp2_transport_global *global,
+                               grpc_chttp2_transport_parsing *parsing);
+
+bool grpc_chttp2_list_add_writable_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+/** Get a writable stream
+    returns non-zero if there was a stream available */
+int grpc_chttp2_list_pop_writable_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_writing **stream_writing);
+bool grpc_chttp2_list_remove_writable_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) GRPC_MUST_USE_RESULT;
+
+void grpc_chttp2_list_add_writing_stream(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing);
+int grpc_chttp2_list_have_writing_streams(
+    grpc_chttp2_transport_writing *transport_writing);
+int grpc_chttp2_list_pop_writing_stream(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing **stream_writing);
+
+void grpc_chttp2_list_add_written_stream(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing);
+int grpc_chttp2_list_pop_written_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_writing **stream_writing);
+
+void grpc_chttp2_list_add_parsing_seen_stream(
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing);
+int grpc_chttp2_list_pop_parsing_seen_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_parsing **stream_parsing);
+
+void grpc_chttp2_list_add_waiting_for_concurrency(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+int grpc_chttp2_list_pop_waiting_for_concurrency(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global);
+
+void grpc_chttp2_list_add_check_read_ops(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+int grpc_chttp2_list_pop_check_read_ops(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global);
+
+void grpc_chttp2_list_add_writing_stalled_by_transport(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing);
+void grpc_chttp2_list_flush_writing_stalled_by_transport(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
+    bool is_window_available);
+
+void grpc_chttp2_list_add_stalled_by_transport(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing);
+int grpc_chttp2_list_pop_stalled_by_transport(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global);
+void grpc_chttp2_list_remove_stalled_by_transport(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+
+void grpc_chttp2_list_add_unannounced_incoming_window_available(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+void grpc_chttp2_list_remove_unannounced_incoming_window_available(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+int grpc_chttp2_list_pop_unannounced_incoming_window_available(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_parsing **stream_parsing);
+
+void grpc_chttp2_list_add_closed_waiting_for_parsing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+int grpc_chttp2_list_pop_closed_waiting_for_parsing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global);
+
+void grpc_chttp2_list_add_closed_waiting_for_writing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global);
+int grpc_chttp2_list_pop_closed_waiting_for_writing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global);
+
+grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
+    grpc_chttp2_transport_parsing *transport_parsing, uint32_t id);
+grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    uint32_t id);
+
+void grpc_chttp2_add_incoming_goaway(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    uint32_t goaway_error, gpr_slice goaway_text);
+
+void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
+                                 grpc_chttp2_stream *s);
+/* returns 1 if this is the last stream, 0 otherwise */
+int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
+                                  grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
+int grpc_chttp2_has_streams(grpc_chttp2_transport *t);
+void grpc_chttp2_for_all_streams(
+    grpc_chttp2_transport_global *transport_global, void *user_data,
+    void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
+               grpc_chttp2_stream_global *stream_global));
+
+void grpc_chttp2_parsing_become_skip_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+
+void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
+                                       grpc_chttp2_stream_global *stream_global,
+                                       grpc_closure **pclosure, int success);
+
+#define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
+  (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
+
+extern int grpc_http_trace;
+extern int grpc_flowctl_trace;
+
+#define GRPC_CHTTP2_IF_TRACING(stmt) \
+  if (!(grpc_http_trace))            \
+    ;                                \
+  else                               \
+  stmt
+
+typedef enum {
+  GRPC_CHTTP2_FLOWCTL_MOVE,
+  GRPC_CHTTP2_FLOWCTL_CREDIT,
+  GRPC_CHTTP2_FLOWCTL_DEBIT
+} grpc_chttp2_flowctl_op;
+
+#define GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, id1, id2, dst_context, \
+                                     dst_var, src_context, src_var)           \
+  do {                                                                        \
+    assert(id1 == id2);                                                       \
+    if (grpc_flowctl_trace) {                                                 \
+      grpc_chttp2_flowctl_trace(                                              \
+          __FILE__, __LINE__, phase, GRPC_CHTTP2_FLOWCTL_MOVE, #dst_context,  \
+          #dst_var, #src_context, #src_var, transport->is_client, id1,        \
+          dst_context->dst_var, src_context->src_var);                        \
+    }                                                                         \
+    dst_context->dst_var += src_context->src_var;                             \
+    src_context->src_var = 0;                                                 \
+  } while (0)
+
+#define GRPC_CHTTP2_FLOW_MOVE_STREAM(phase, transport, dst_context, dst_var, \
+                                     src_context, src_var)                   \
+  GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, dst_context->id,            \
+                               src_context->id, dst_context, dst_var,        \
+                               src_context, src_var)
+#define GRPC_CHTTP2_FLOW_MOVE_TRANSPORT(phase, dst_context, dst_var,           \
+                                        src_context, src_var)                  \
+  GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, dst_context, 0, 0, dst_context, dst_var, \
+                               src_context, src_var)
+
+#define GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, id, dst_context,      \
+                                       dst_var, amount)                        \
+  do {                                                                         \
+    if (grpc_flowctl_trace) {                                                  \
+      grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase,                     \
+                                GRPC_CHTTP2_FLOWCTL_CREDIT, #dst_context,      \
+                                #dst_var, NULL, #amount, transport->is_client, \
+                                id, dst_context->dst_var, amount);             \
+    }                                                                          \
+    dst_context->dst_var += amount;                                            \
+  } while (0)
+
+#define GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, dst_var, \
+                                       amount)                                 \
+  GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, dst_context->id,            \
+                                 dst_context, dst_var, amount)
+#define GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT(phase, dst_context, dst_var, amount) \
+  GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var,  \
+                                 amount)
+
+#define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context,       \
+                                      dst_var, amount)                         \
+  do {                                                                         \
+    if (grpc_flowctl_trace) {                                                  \
+      grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase,                     \
+                                GRPC_CHTTP2_FLOWCTL_DEBIT, #dst_context,       \
+                                #dst_var, NULL, #amount, transport->is_client, \
+                                id, dst_context->dst_var, amount);             \
+    }                                                                          \
+    dst_context->dst_var -= amount;                                            \
+  } while (0)
+
+#define GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, dst_var, \
+                                      amount)                                 \
+  GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, dst_context->id,            \
+                                dst_context, dst_var, amount)
+#define GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT(phase, dst_context, dst_var, amount) \
+  GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, dst_context, 0, dst_context, dst_var,  \
+                                amount)
+
+void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
+                               grpc_chttp2_flowctl_op op, const char *context1,
+                               const char *var1, const char *context2,
+                               const char *var2, int is_client,
+                               uint32_t stream_id, int64_t val1, int64_t val2);
+
+void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_global *transport_global,
+                             grpc_chttp2_stream_global *stream,
+                             grpc_status_code status, gpr_slice *details);
+void grpc_chttp2_mark_stream_closed(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, int close_reads,
+    int close_writes);
+void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx,
+                               grpc_chttp2_transport_global *transport_global);
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+#define GRPC_CHTTP2_STREAM_REF(stream_global, reason) \
+  grpc_chttp2_stream_ref(stream_global, reason)
+#define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, reason) \
+  grpc_chttp2_stream_unref(exec_ctx, stream_global, reason)
+void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global,
+                            const char *reason);
+void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_stream_global *stream_global,
+                              const char *reason);
+#else
+#define GRPC_CHTTP2_STREAM_REF(stream_global, reason) \
+  grpc_chttp2_stream_ref(stream_global)
+#define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, reason) \
+  grpc_chttp2_stream_unref(exec_ctx, stream_global)
+void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global);
+void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_stream_global *stream_global);
+#endif
+
+grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, uint32_t frame_size,
+    uint32_t flags, grpc_chttp2_incoming_frame_queue *add_to_queue);
+void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
+                                           grpc_chttp2_incoming_byte_stream *bs,
+                                           gpr_slice slice);
+void grpc_chttp2_incoming_byte_stream_finished(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
+    int from_parsing_thread);
+
+void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
+                          grpc_chttp2_transport_parsing *parsing,
+                          const uint8_t *opaque_8bytes);
+
+/** add a ref to the stream and add it to the writable list;
+    ref will be dropped in writing.c */
+void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
+                                 grpc_chttp2_stream_global *stream_global);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
new file mode 100644
index 0000000..e827a43
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -0,0 +1,886 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/internal.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
+#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
+#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+static int init_frame_parser(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_parsing *transport_parsing);
+static int init_header_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    int is_continuation);
+static int init_data_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+static int init_rst_stream_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+static int init_settings_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+static int init_window_update_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+static int init_ping_parser(grpc_exec_ctx *exec_ctx,
+                            grpc_chttp2_transport_parsing *transport_parsing);
+static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_transport_parsing *transport_parsing);
+static int init_skip_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    int is_header);
+
+static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_parsing *transport_parsing,
+                             gpr_slice slice, int is_last);
+
+void grpc_chttp2_prepare_to_read(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_parsing *transport_parsing) {
+  grpc_chttp2_stream_global *stream_global;
+  grpc_chttp2_stream_parsing *stream_parsing;
+
+  GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
+
+  transport_parsing->next_stream_id = transport_global->next_stream_id;
+  transport_parsing->last_sent_max_table_size =
+      transport_global->settings[GRPC_SENT_SETTINGS]
+                                [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
+
+  /* update the parsing view of incoming window */
+  while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
+      transport_global, transport_parsing, &stream_global, &stream_parsing)) {
+    GRPC_CHTTP2_FLOW_MOVE_STREAM("parse", transport_parsing, stream_parsing,
+                                 incoming_window, stream_global,
+                                 unannounced_incoming_window_for_parse);
+  }
+
+  GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0);
+}
+
+void grpc_chttp2_publish_reads(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_parsing *transport_parsing) {
+  grpc_chttp2_stream_global *stream_global;
+  grpc_chttp2_stream_parsing *stream_parsing;
+  int was_zero;
+  int is_zero;
+
+  /* transport_parsing->last_incoming_stream_id is used as
+     last-grpc_chttp2_stream-id when
+     sending GOAWAY frame.
+     https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
+     says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
+     ID.  So,
+     since we don't have server pushed streams, client should send
+     GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
+  if (!transport_parsing->is_client) {
+    transport_global->last_incoming_stream_id =
+        transport_parsing->last_incoming_stream_id;
+  }
+
+  /* update global settings */
+  if (transport_parsing->settings_updated) {
+    memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
+           transport_parsing->settings, sizeof(transport_parsing->settings));
+    transport_parsing->settings_updated = 0;
+  }
+
+  /* update settings based on ack if received */
+  if (transport_parsing->settings_ack_received) {
+    memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
+           transport_global->settings[GRPC_SENT_SETTINGS],
+           GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
+    transport_parsing->settings_ack_received = 0;
+    transport_global->sent_local_settings = 0;
+  }
+
+  /* move goaway to the global state if we received one (it will be
+     published later */
+  if (transport_parsing->goaway_received) {
+    grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
+                                    (uint32_t)transport_parsing->goaway_error,
+                                    transport_parsing->goaway_text);
+    transport_parsing->goaway_text = gpr_empty_slice();
+    transport_parsing->goaway_received = 0;
+  }
+
+  /* propagate flow control tokens to global state */
+  was_zero = transport_global->outgoing_window <= 0;
+  GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window,
+                                  transport_parsing, outgoing_window);
+  is_zero = transport_global->outgoing_window <= 0;
+  if (was_zero && !is_zero) {
+    while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
+                                                     &stream_global)) {
+      grpc_chttp2_become_writable(transport_global, stream_global);
+    }
+  }
+
+  if (transport_parsing->incoming_window <
+      transport_global->connection_window_target * 3 / 4) {
+    int64_t announce_bytes = transport_global->connection_window_target -
+                             transport_parsing->incoming_window;
+    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global,
+                                      announce_incoming_window, announce_bytes);
+    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
+                                      incoming_window, announce_bytes);
+  }
+
+  /* for each stream that saw an update, fixup global state */
+  while (grpc_chttp2_list_pop_parsing_seen_stream(
+      transport_global, transport_parsing, &stream_global, &stream_parsing)) {
+    if (stream_parsing->seen_error) {
+      stream_global->seen_error = 1;
+      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+    }
+
+    /* flush stats to global stream state */
+    grpc_transport_move_stats(&stream_parsing->stats, &stream_global->stats);
+
+    /* update outgoing flow control window */
+    was_zero = stream_global->outgoing_window <= 0;
+    GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global,
+                                 outgoing_window, stream_parsing,
+                                 outgoing_window);
+    is_zero = stream_global->outgoing_window <= 0;
+    if (was_zero && !is_zero) {
+      grpc_chttp2_become_writable(transport_global, stream_global);
+    }
+
+    stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(
+        stream_global->max_recv_bytes, stream_parsing->received_bytes);
+    stream_parsing->received_bytes = 0;
+
+    /* publish incoming stream ops */
+    if (stream_global->incoming_frames.tail != NULL) {
+      stream_global->incoming_frames.tail->is_tail = 0;
+    }
+    if (stream_parsing->data_parser.incoming_frames.head != NULL) {
+      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+    }
+    grpc_chttp2_incoming_frame_queue_merge(
+        &stream_global->incoming_frames,
+        &stream_parsing->data_parser.incoming_frames);
+    if (stream_global->incoming_frames.tail != NULL) {
+      stream_global->incoming_frames.tail->is_tail = 1;
+    }
+
+    if (!stream_global->published_initial_metadata &&
+        stream_parsing->got_metadata_on_parse[0]) {
+      stream_parsing->got_metadata_on_parse[0] = 0;
+      stream_global->published_initial_metadata = 1;
+      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
+               stream_parsing->metadata_buffer[0],
+               stream_global->received_initial_metadata);
+      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+    }
+    if (!stream_global->published_trailing_metadata &&
+        stream_parsing->got_metadata_on_parse[1]) {
+      stream_parsing->got_metadata_on_parse[1] = 0;
+      stream_global->published_trailing_metadata = 1;
+      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
+               stream_parsing->metadata_buffer[1],
+               stream_global->received_trailing_metadata);
+      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
+    }
+
+    if (stream_parsing->saw_rst_stream) {
+      if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
+        grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
+            (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
+        char *status_details;
+        gpr_slice slice_details;
+        gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
+                     stream_parsing->rst_stream_reason);
+        slice_details = gpr_slice_from_copied_string(status_details);
+        gpr_free(status_details);
+        grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
+                                status_code, &slice_details);
+      }
+      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
+                                     1, 1);
+    }
+
+    if (stream_parsing->received_close) {
+      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
+                                     1, 0);
+    }
+  }
+}
+
+int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_parsing *transport_parsing,
+                             gpr_slice slice) {
+  uint8_t *beg = GPR_SLICE_START_PTR(slice);
+  uint8_t *end = GPR_SLICE_END_PTR(slice);
+  uint8_t *cur = beg;
+
+  if (cur == end) return 1;
+
+  switch (transport_parsing->deframe_state) {
+    case GRPC_DTS_CLIENT_PREFIX_0:
+    case GRPC_DTS_CLIENT_PREFIX_1:
+    case GRPC_DTS_CLIENT_PREFIX_2:
+    case GRPC_DTS_CLIENT_PREFIX_3:
+    case GRPC_DTS_CLIENT_PREFIX_4:
+    case GRPC_DTS_CLIENT_PREFIX_5:
+    case GRPC_DTS_CLIENT_PREFIX_6:
+    case GRPC_DTS_CLIENT_PREFIX_7:
+    case GRPC_DTS_CLIENT_PREFIX_8:
+    case GRPC_DTS_CLIENT_PREFIX_9:
+    case GRPC_DTS_CLIENT_PREFIX_10:
+    case GRPC_DTS_CLIENT_PREFIX_11:
+    case GRPC_DTS_CLIENT_PREFIX_12:
+    case GRPC_DTS_CLIENT_PREFIX_13:
+    case GRPC_DTS_CLIENT_PREFIX_14:
+    case GRPC_DTS_CLIENT_PREFIX_15:
+    case GRPC_DTS_CLIENT_PREFIX_16:
+    case GRPC_DTS_CLIENT_PREFIX_17:
+    case GRPC_DTS_CLIENT_PREFIX_18:
+    case GRPC_DTS_CLIENT_PREFIX_19:
+    case GRPC_DTS_CLIENT_PREFIX_20:
+    case GRPC_DTS_CLIENT_PREFIX_21:
+    case GRPC_DTS_CLIENT_PREFIX_22:
+    case GRPC_DTS_CLIENT_PREFIX_23:
+      while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
+        if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
+                                                          ->deframe_state]) {
+          gpr_log(GPR_INFO,
+                  "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
+                  "at byte %d",
+                  GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
+                                                        ->deframe_state],
+                  (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
+                      [transport_parsing->deframe_state],
+                  *cur, (int)*cur, transport_parsing->deframe_state);
+          return 0;
+        }
+        ++cur;
+        ++transport_parsing->deframe_state;
+      }
+      if (cur == end) {
+        return 1;
+      }
+    /* fallthrough */
+    dts_fh_0:
+    case GRPC_DTS_FH_0:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_1;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_1:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_2;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_2:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_frame_size |= *cur;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_3;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_3:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_frame_type = *cur;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_4;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_4:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_frame_flags = *cur;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_5;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_5:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_6;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_6:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_7;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_7:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8;
+      if (++cur == end) {
+        transport_parsing->deframe_state = GRPC_DTS_FH_8;
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FH_8:
+      GPR_ASSERT(cur < end);
+      transport_parsing->incoming_stream_id |= ((uint32_t)*cur);
+      transport_parsing->deframe_state = GRPC_DTS_FRAME;
+      if (!init_frame_parser(exec_ctx, transport_parsing)) {
+        return 0;
+      }
+      if (transport_parsing->incoming_stream_id != 0 &&
+          transport_parsing->incoming_stream_id >
+              transport_parsing->last_incoming_stream_id) {
+        transport_parsing->last_incoming_stream_id =
+            transport_parsing->incoming_stream_id;
+      }
+      if (transport_parsing->incoming_frame_size == 0) {
+        if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
+                               1)) {
+          return 0;
+        }
+        transport_parsing->incoming_stream = NULL;
+        if (++cur == end) {
+          transport_parsing->deframe_state = GRPC_DTS_FH_0;
+          return 1;
+        }
+        goto dts_fh_0; /* loop */
+      }
+      if (++cur == end) {
+        return 1;
+      }
+    /* fallthrough */
+    case GRPC_DTS_FRAME:
+      GPR_ASSERT(cur < end);
+      if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) {
+        if (!parse_frame_slice(exec_ctx, transport_parsing,
+                               gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
+                                                    (size_t)(end - beg)),
+                               1)) {
+          return 0;
+        }
+        transport_parsing->deframe_state = GRPC_DTS_FH_0;
+        transport_parsing->incoming_stream = NULL;
+        return 1;
+      } else if ((uint32_t)(end - cur) >
+                 transport_parsing->incoming_frame_size) {
+        size_t cur_offset = (size_t)(cur - beg);
+        if (!parse_frame_slice(
+                exec_ctx, transport_parsing,
+                gpr_slice_sub_no_ref(
+                    slice, cur_offset,
+                    cur_offset + transport_parsing->incoming_frame_size),
+                1)) {
+          return 0;
+        }
+        cur += transport_parsing->incoming_frame_size;
+        transport_parsing->incoming_stream = NULL;
+        goto dts_fh_0; /* loop */
+      } else {
+        if (!parse_frame_slice(exec_ctx, transport_parsing,
+                               gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
+                                                    (size_t)(end - beg)),
+                               0)) {
+          return 0;
+        }
+        transport_parsing->incoming_frame_size -= (uint32_t)(end - cur);
+        return 1;
+      }
+      GPR_UNREACHABLE_CODE(return 0);
+  }
+
+  GPR_UNREACHABLE_CODE(return 0);
+}
+
+static int init_frame_parser(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_parsing *transport_parsing) {
+  if (transport_parsing->expect_continuation_stream_id != 0) {
+    if (transport_parsing->incoming_frame_type !=
+        GRPC_CHTTP2_FRAME_CONTINUATION) {
+      gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
+              transport_parsing->incoming_frame_type);
+      return 0;
+    }
+    if (transport_parsing->expect_continuation_stream_id !=
+        transport_parsing->incoming_stream_id) {
+      gpr_log(GPR_ERROR,
+              "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
+              "grpc_chttp2_stream %08x",
+              transport_parsing->expect_continuation_stream_id,
+              transport_parsing->incoming_stream_id);
+      return 0;
+    }
+    return init_header_frame_parser(exec_ctx, transport_parsing, 1);
+  }
+  switch (transport_parsing->incoming_frame_type) {
+    case GRPC_CHTTP2_FRAME_DATA:
+      return init_data_frame_parser(exec_ctx, transport_parsing);
+    case GRPC_CHTTP2_FRAME_HEADER:
+      return init_header_frame_parser(exec_ctx, transport_parsing, 0);
+    case GRPC_CHTTP2_FRAME_CONTINUATION:
+      gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
+      return 0;
+    case GRPC_CHTTP2_FRAME_RST_STREAM:
+      return init_rst_stream_parser(exec_ctx, transport_parsing);
+    case GRPC_CHTTP2_FRAME_SETTINGS:
+      return init_settings_frame_parser(exec_ctx, transport_parsing);
+    case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
+      return init_window_update_frame_parser(exec_ctx, transport_parsing);
+    case GRPC_CHTTP2_FRAME_PING:
+      return init_ping_parser(exec_ctx, transport_parsing);
+    case GRPC_CHTTP2_FRAME_GOAWAY:
+      return init_goaway_parser(exec_ctx, transport_parsing);
+    default:
+      gpr_log(GPR_ERROR, "Unknown frame type %02x",
+              transport_parsing->incoming_frame_type);
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
+  }
+}
+
+static grpc_chttp2_parse_error skip_parser(
+    grpc_exec_ctx *exec_ctx, void *parser,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
+
+static int init_skip_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    int is_header) {
+  if (is_header) {
+    uint8_t is_eoh = transport_parsing->expect_continuation_stream_id != 0;
+    transport_parsing->parser = grpc_chttp2_header_parser_parse;
+    transport_parsing->parser_data = &transport_parsing->hpack_parser;
+    transport_parsing->hpack_parser.on_header = skip_header;
+    transport_parsing->hpack_parser.on_header_user_data = NULL;
+    transport_parsing->hpack_parser.is_boundary = is_eoh;
+    transport_parsing->hpack_parser.is_eof =
+        (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
+  } else {
+    transport_parsing->parser = skip_parser;
+  }
+  return 1;
+}
+
+void grpc_chttp2_parsing_become_skip_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
+  init_skip_frame_parser(
+      exec_ctx, transport_parsing,
+      transport_parsing->parser == grpc_chttp2_header_parser_parse);
+}
+
+static grpc_chttp2_parse_error update_incoming_window(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing) {
+  uint32_t incoming_frame_size = transport_parsing->incoming_frame_size;
+  if (incoming_frame_size > transport_parsing->incoming_window) {
+    gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
+            transport_parsing->incoming_frame_size,
+            transport_parsing->incoming_window);
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  }
+
+  if (incoming_frame_size > stream_parsing->incoming_window) {
+    gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
+            transport_parsing->incoming_frame_size,
+            stream_parsing->incoming_window);
+    return GRPC_CHTTP2_CONNECTION_ERROR;
+  }
+
+  GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
+                                   incoming_frame_size);
+  GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", transport_parsing, stream_parsing,
+                                incoming_window, incoming_frame_size);
+  stream_parsing->received_bytes += incoming_frame_size;
+
+  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
+
+  return GRPC_CHTTP2_PARSE_OK;
+}
+
+static int init_data_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
+  grpc_chttp2_stream_parsing *stream_parsing =
+      grpc_chttp2_parsing_lookup_stream(transport_parsing,
+                                        transport_parsing->incoming_stream_id);
+  grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
+  if (stream_parsing == NULL) {
+    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
+  }
+  stream_parsing->stats.incoming.framing_bytes += 9;
+  if (stream_parsing->received_close) {
+    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
+  }
+  if (err == GRPC_CHTTP2_PARSE_OK) {
+    err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
+  }
+  if (err == GRPC_CHTTP2_PARSE_OK) {
+    err = grpc_chttp2_data_parser_begin_frame(
+        &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
+  }
+  switch (err) {
+    case GRPC_CHTTP2_PARSE_OK:
+      transport_parsing->incoming_stream = stream_parsing;
+      transport_parsing->parser = grpc_chttp2_data_parser_parse;
+      transport_parsing->parser_data = &stream_parsing->data_parser;
+      return 1;
+    case GRPC_CHTTP2_STREAM_ERROR:
+      stream_parsing->received_close = 1;
+      stream_parsing->saw_rst_stream = 1;
+      stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
+      gpr_slice_buffer_add(
+          &transport_parsing->qbuf,
+          grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
+                                        GRPC_CHTTP2_PROTOCOL_ERROR,
+                                        &stream_parsing->stats.outgoing));
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
+    case GRPC_CHTTP2_CONNECTION_ERROR:
+      return 0;
+  }
+  GPR_UNREACHABLE_CODE(return 0);
+}
+
+static void free_timeout(void *p) { gpr_free(p); }
+
+static void on_initial_header(void *tp, grpc_mdelem *md) {
+  grpc_chttp2_transport_parsing *transport_parsing = tp;
+  grpc_chttp2_stream_parsing *stream_parsing =
+      transport_parsing->incoming_stream;
+
+  GPR_TIMER_BEGIN("on_initial_header", 0);
+
+  GPR_ASSERT(stream_parsing);
+
+  GRPC_CHTTP2_IF_TRACING(gpr_log(
+      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
+      transport_parsing->is_client ? "CLI" : "SVR",
+      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
+
+  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
+    /* TODO(ctiller): check for a status like " 0" */
+    stream_parsing->seen_error = 1;
+  }
+
+  if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
+    gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
+    if (!cached_timeout) {
+      /* not already parsed: parse it now, and store the result away */
+      cached_timeout = gpr_malloc(sizeof(gpr_timespec));
+      if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
+                                      cached_timeout)) {
+        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
+                grpc_mdstr_as_c_string(md->value));
+        *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
+      }
+      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+    }
+    grpc_chttp2_incoming_metadata_buffer_set_deadline(
+        &stream_parsing->metadata_buffer[0],
+        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
+    GRPC_MDELEM_UNREF(md);
+  } else {
+    grpc_chttp2_incoming_metadata_buffer_add(
+        &stream_parsing->metadata_buffer[0], md);
+  }
+
+  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
+
+  GPR_TIMER_END("on_initial_header", 0);
+}
+
+static void on_trailing_header(void *tp, grpc_mdelem *md) {
+  grpc_chttp2_transport_parsing *transport_parsing = tp;
+  grpc_chttp2_stream_parsing *stream_parsing =
+      transport_parsing->incoming_stream;
+
+  GPR_TIMER_BEGIN("on_trailing_header", 0);
+
+  GPR_ASSERT(stream_parsing);
+
+  GRPC_CHTTP2_IF_TRACING(gpr_log(
+      GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", stream_parsing->id,
+      transport_parsing->is_client ? "CLI" : "SVR",
+      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
+
+  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
+    /* TODO(ctiller): check for a status like " 0" */
+    stream_parsing->seen_error = 1;
+  }
+
+  grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1],
+                                           md);
+
+  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
+
+  GPR_TIMER_END("on_trailing_header", 0);
+}
+
+static int init_header_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    int is_continuation) {
+  uint8_t is_eoh = (transport_parsing->incoming_frame_flags &
+                    GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
+  int via_accept = 0;
+  grpc_chttp2_stream_parsing *stream_parsing;
+
+  /* TODO(ctiller): when to increment header_frames_received? */
+
+  if (is_eoh) {
+    transport_parsing->expect_continuation_stream_id = 0;
+  } else {
+    transport_parsing->expect_continuation_stream_id =
+        transport_parsing->incoming_stream_id;
+  }
+
+  if (!is_continuation) {
+    transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
+                                     GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
+  }
+
+  /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
+  stream_parsing = grpc_chttp2_parsing_lookup_stream(
+      transport_parsing, transport_parsing->incoming_stream_id);
+  if (stream_parsing == NULL) {
+    if (is_continuation) {
+      gpr_log(GPR_ERROR,
+              "grpc_chttp2_stream disbanded before CONTINUATION received");
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
+    }
+    if (transport_parsing->is_client) {
+      if ((transport_parsing->incoming_stream_id & 1) &&
+          transport_parsing->incoming_stream_id <
+              transport_parsing->next_stream_id) {
+        /* this is an old (probably cancelled) grpc_chttp2_stream */
+      } else {
+        gpr_log(GPR_ERROR,
+                "ignoring new grpc_chttp2_stream creation on client");
+      }
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
+    } else if (transport_parsing->last_incoming_stream_id >
+               transport_parsing->incoming_stream_id) {
+      gpr_log(GPR_ERROR,
+              "ignoring out of order new grpc_chttp2_stream request on server; "
+              "last grpc_chttp2_stream "
+              "id=%d, new grpc_chttp2_stream id=%d",
+              transport_parsing->last_incoming_stream_id,
+              transport_parsing->incoming_stream_id);
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
+    } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
+      gpr_log(GPR_ERROR,
+              "ignoring grpc_chttp2_stream with non-client generated index %d",
+              transport_parsing->incoming_stream_id);
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
+    }
+    stream_parsing = transport_parsing->incoming_stream =
+        grpc_chttp2_parsing_accept_stream(
+            exec_ctx, transport_parsing, transport_parsing->incoming_stream_id);
+    if (stream_parsing == NULL) {
+      gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
+    }
+    via_accept = 1;
+  } else {
+    transport_parsing->incoming_stream = stream_parsing;
+  }
+  GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
+  stream_parsing->stats.incoming.framing_bytes += 9;
+  if (stream_parsing->received_close) {
+    gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
+    transport_parsing->incoming_stream = NULL;
+    return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
+  }
+  transport_parsing->parser = grpc_chttp2_header_parser_parse;
+  transport_parsing->parser_data = &transport_parsing->hpack_parser;
+  switch (stream_parsing->header_frames_received) {
+    case 0:
+      transport_parsing->hpack_parser.on_header = on_initial_header;
+      break;
+    case 1:
+      transport_parsing->hpack_parser.on_header = on_trailing_header;
+      break;
+    case 2:
+      gpr_log(GPR_ERROR, "too many header frames received");
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
+  }
+  transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
+  transport_parsing->hpack_parser.is_boundary = is_eoh;
+  transport_parsing->hpack_parser.is_eof =
+      (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
+  if (!is_continuation && (transport_parsing->incoming_frame_flags &
+                           GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
+    grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
+  }
+  return 1;
+}
+
+static int init_window_update_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
+  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
+                                       &transport_parsing->simple.window_update,
+                                       transport_parsing->incoming_frame_size,
+                                       transport_parsing->incoming_frame_flags);
+  if (transport_parsing->incoming_stream_id != 0) {
+    grpc_chttp2_stream_parsing *stream_parsing =
+        transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
+            transport_parsing, transport_parsing->incoming_stream_id);
+    if (stream_parsing == NULL) {
+      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
+    }
+    stream_parsing->stats.incoming.framing_bytes += 9;
+  }
+  transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
+  transport_parsing->parser_data = &transport_parsing->simple.window_update;
+  return ok;
+}
+
+static int init_ping_parser(grpc_exec_ctx *exec_ctx,
+                            grpc_chttp2_transport_parsing *transport_parsing) {
+  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
+                                       &transport_parsing->simple.ping,
+                                       transport_parsing->incoming_frame_size,
+                                       transport_parsing->incoming_frame_flags);
+  transport_parsing->parser = grpc_chttp2_ping_parser_parse;
+  transport_parsing->parser_data = &transport_parsing->simple.ping;
+  return ok;
+}
+
+static int init_rst_stream_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
+  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
+                                       &transport_parsing->simple.rst_stream,
+                                       transport_parsing->incoming_frame_size,
+                                       transport_parsing->incoming_frame_flags);
+  grpc_chttp2_stream_parsing *stream_parsing =
+      transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
+          transport_parsing, transport_parsing->incoming_stream_id);
+  if (!transport_parsing->incoming_stream) {
+    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
+  }
+  stream_parsing->stats.incoming.framing_bytes += 9;
+  transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
+  transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
+  return ok;
+}
+
+static int init_goaway_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
+  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
+                                       &transport_parsing->goaway_parser,
+                                       transport_parsing->incoming_frame_size,
+                                       transport_parsing->incoming_frame_flags);
+  transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
+  transport_parsing->parser_data = &transport_parsing->goaway_parser;
+  return ok;
+}
+
+static int init_settings_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
+  int ok;
+
+  if (transport_parsing->incoming_stream_id != 0) {
+    gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
+            transport_parsing->incoming_stream_id);
+    return 0;
+  }
+
+  ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
+                                   &transport_parsing->simple.settings,
+                                   transport_parsing->incoming_frame_size,
+                                   transport_parsing->incoming_frame_flags,
+                                   transport_parsing->settings);
+  if (!ok) {
+    return 0;
+  }
+  if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
+    transport_parsing->settings_ack_received = 1;
+    grpc_chttp2_hptbl_set_max_bytes(
+        &transport_parsing->hpack_parser.table,
+        transport_parsing->last_sent_max_table_size);
+  }
+  transport_parsing->parser = grpc_chttp2_settings_parser_parse;
+  transport_parsing->parser_data = &transport_parsing->simple.settings;
+  return ok;
+}
+
+/*
+static int is_window_update_legal(int64_t window_update, int64_t window) {
+  return window + window_update < MAX_WINDOW;
+}
+*/
+
+static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
+                             grpc_chttp2_transport_parsing *transport_parsing,
+                             gpr_slice slice, int is_last) {
+  grpc_chttp2_stream_parsing *stream_parsing =
+      transport_parsing->incoming_stream;
+  switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
+                                    transport_parsing, stream_parsing, slice,
+                                    is_last)) {
+    case GRPC_CHTTP2_PARSE_OK:
+      if (stream_parsing) {
+        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
+                                                 stream_parsing);
+      }
+      return 1;
+    case GRPC_CHTTP2_STREAM_ERROR:
+      grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
+      if (stream_parsing) {
+        stream_parsing->saw_rst_stream = 1;
+        stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
+        gpr_slice_buffer_add(
+            &transport_parsing->qbuf,
+            grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
+                                          GRPC_CHTTP2_PROTOCOL_ERROR,
+                                          &stream_parsing->stats.outgoing));
+      }
+      return 1;
+    case GRPC_CHTTP2_CONNECTION_ERROR:
+      return 0;
+  }
+  GPR_UNREACHABLE_CODE(return 0);
+}
diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.c b/src/core/ext/transport/chttp2/transport/status_conversion.c
new file mode 100644
index 0000000..c42fb9b
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/status_conversion.c
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/status_conversion.h"
+
+int grpc_chttp2_grpc_status_to_http2_error(grpc_status_code status) {
+  switch (status) {
+    case GRPC_STATUS_OK:
+      return GRPC_CHTTP2_NO_ERROR;
+    case GRPC_STATUS_CANCELLED:
+      return GRPC_CHTTP2_CANCEL;
+    case GRPC_STATUS_RESOURCE_EXHAUSTED:
+      return GRPC_CHTTP2_ENHANCE_YOUR_CALM;
+    case GRPC_STATUS_PERMISSION_DENIED:
+      return GRPC_CHTTP2_INADEQUATE_SECURITY;
+    case GRPC_STATUS_UNAVAILABLE:
+      return GRPC_CHTTP2_REFUSED_STREAM;
+    default:
+      return GRPC_CHTTP2_INTERNAL_ERROR;
+  }
+}
+
+grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
+    grpc_chttp2_error_code error) {
+  switch (error) {
+    case GRPC_CHTTP2_NO_ERROR:
+      /* should never be received */
+      return GRPC_STATUS_INTERNAL;
+    case GRPC_CHTTP2_CANCEL:
+      return GRPC_STATUS_CANCELLED;
+    case GRPC_CHTTP2_ENHANCE_YOUR_CALM:
+      return GRPC_STATUS_RESOURCE_EXHAUSTED;
+    case GRPC_CHTTP2_INADEQUATE_SECURITY:
+      return GRPC_STATUS_PERMISSION_DENIED;
+    case GRPC_CHTTP2_REFUSED_STREAM:
+      return GRPC_STATUS_UNAVAILABLE;
+    default:
+      return GRPC_STATUS_INTERNAL;
+  }
+}
+
+grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status) {
+  switch (status) {
+    /* these HTTP2 status codes are called out explicitly in status.proto */
+    case 200:
+      return GRPC_STATUS_OK;
+    case 400:
+      return GRPC_STATUS_INVALID_ARGUMENT;
+    case 401:
+      return GRPC_STATUS_UNAUTHENTICATED;
+    case 403:
+      return GRPC_STATUS_PERMISSION_DENIED;
+    case 404:
+      return GRPC_STATUS_NOT_FOUND;
+    case 409:
+      return GRPC_STATUS_ABORTED;
+    case 412:
+      return GRPC_STATUS_FAILED_PRECONDITION;
+    case 429:
+      return GRPC_STATUS_RESOURCE_EXHAUSTED;
+    case 499:
+      return GRPC_STATUS_CANCELLED;
+    case 500:
+      return GRPC_STATUS_UNKNOWN;
+    case 501:
+      return GRPC_STATUS_UNIMPLEMENTED;
+    case 503:
+      return GRPC_STATUS_UNAVAILABLE;
+    case 504:
+      return GRPC_STATUS_DEADLINE_EXCEEDED;
+    /* everything else is unknown */
+    default:
+      return GRPC_STATUS_UNKNOWN;
+  }
+}
+
+int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status) {
+  return 200;
+}
diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.h b/src/core/ext/transport/chttp2/transport/status_conversion.h
new file mode 100644
index 0000000..e7285e6
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/status_conversion.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_STATUS_CONVERSION_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STATUS_CONVERSION_H
+
+#include <grpc/grpc.h>
+#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
+
+/* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */
+grpc_chttp2_error_code grpc_chttp2_grpc_status_to_http2_error(
+    grpc_status_code status);
+grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
+    grpc_chttp2_error_code error);
+
+/* Conversion of HTTP status codes (:status) to grpc status codes */
+grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status);
+int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STATUS_CONVERSION_H */
diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.c b/src/core/ext/transport/chttp2/transport/stream_lists.c
new file mode 100644
index 0000000..e5b35aa
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/stream_lists.c
@@ -0,0 +1,442 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/internal.h"
+
+#include <grpc/support/log.h>
+
+#define TRANSPORT_FROM_GLOBAL(tg)                                         \
+  ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
+                                                   global)))
+
+#define STREAM_FROM_GLOBAL(sg) \
+  ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
+
+#define TRANSPORT_FROM_WRITING(tw)                                        \
+  ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
+                                                   writing)))
+
+#define STREAM_FROM_WRITING(sw) \
+  ((grpc_chttp2_stream *)((char *)(sw)-offsetof(grpc_chttp2_stream, writing)))
+
+#define TRANSPORT_FROM_PARSING(tp)                                        \
+  ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
+                                                   parsing)))
+
+#define STREAM_FROM_PARSING(sp) \
+  ((grpc_chttp2_stream *)((char *)(sp)-offsetof(grpc_chttp2_stream, parsing)))
+
+/* core list management */
+
+static int stream_list_empty(grpc_chttp2_transport *t,
+                             grpc_chttp2_stream_list_id id) {
+  return t->lists[id].head == NULL;
+}
+
+static int stream_list_pop(grpc_chttp2_transport *t,
+                           grpc_chttp2_stream **stream,
+                           grpc_chttp2_stream_list_id id) {
+  grpc_chttp2_stream *s = t->lists[id].head;
+  if (s) {
+    grpc_chttp2_stream *new_head = s->links[id].next;
+    GPR_ASSERT(s->included[id]);
+    if (new_head) {
+      t->lists[id].head = new_head;
+      new_head->links[id].prev = NULL;
+    } else {
+      t->lists[id].head = NULL;
+      t->lists[id].tail = NULL;
+    }
+    s->included[id] = 0;
+  }
+  *stream = s;
+  return s != 0;
+}
+
+static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
+                               grpc_chttp2_stream_list_id id) {
+  GPR_ASSERT(s->included[id]);
+  s->included[id] = 0;
+  if (s->links[id].prev) {
+    s->links[id].prev->links[id].next = s->links[id].next;
+  } else {
+    GPR_ASSERT(t->lists[id].head == s);
+    t->lists[id].head = s->links[id].next;
+  }
+  if (s->links[id].next) {
+    s->links[id].next->links[id].prev = s->links[id].prev;
+  } else {
+    t->lists[id].tail = s->links[id].prev;
+  }
+}
+
+static bool stream_list_maybe_remove(grpc_chttp2_transport *t,
+                                     grpc_chttp2_stream *s,
+                                     grpc_chttp2_stream_list_id id) {
+  if (s->included[id]) {
+    stream_list_remove(t, s, id);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+static void stream_list_add_tail(grpc_chttp2_transport *t,
+                                 grpc_chttp2_stream *s,
+                                 grpc_chttp2_stream_list_id id) {
+  grpc_chttp2_stream *old_tail;
+  GPR_ASSERT(!s->included[id]);
+  old_tail = t->lists[id].tail;
+  s->links[id].next = NULL;
+  s->links[id].prev = old_tail;
+  if (old_tail) {
+    old_tail->links[id].next = s;
+  } else {
+    t->lists[id].head = s;
+  }
+  t->lists[id].tail = s;
+  s->included[id] = 1;
+}
+
+static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
+                            grpc_chttp2_stream_list_id id) {
+  if (s->included[id]) {
+    return false;
+  }
+  stream_list_add_tail(t, s, id);
+  return true;
+}
+
+/* wrappers for specializations */
+
+bool grpc_chttp2_list_add_writable_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  GPR_ASSERT(stream_global->id != 0);
+  return stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+                         STREAM_FROM_GLOBAL(stream_global),
+                         GRPC_CHTTP2_LIST_WRITABLE);
+}
+
+int grpc_chttp2_list_pop_writable_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_writing **stream_writing) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+                          GRPC_CHTTP2_LIST_WRITABLE);
+  if (r != 0) {
+    *stream_global = &stream->global;
+    *stream_writing = &stream->writing;
+  }
+  return r;
+}
+
+bool grpc_chttp2_list_remove_writable_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  return stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
+                                  STREAM_FROM_GLOBAL(stream_global),
+                                  GRPC_CHTTP2_LIST_WRITABLE);
+}
+
+void grpc_chttp2_list_add_writing_stream(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing) {
+  GPR_ASSERT(stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
+                             STREAM_FROM_WRITING(stream_writing),
+                             GRPC_CHTTP2_LIST_WRITING));
+}
+
+int grpc_chttp2_list_have_writing_streams(
+    grpc_chttp2_transport_writing *transport_writing) {
+  return !stream_list_empty(TRANSPORT_FROM_WRITING(transport_writing),
+                            GRPC_CHTTP2_LIST_WRITING);
+}
+
+int grpc_chttp2_list_pop_writing_stream(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing **stream_writing) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
+                          GRPC_CHTTP2_LIST_WRITING);
+  if (r != 0) {
+    *stream_writing = &stream->writing;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_add_written_stream(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing) {
+  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
+                  STREAM_FROM_WRITING(stream_writing),
+                  GRPC_CHTTP2_LIST_WRITTEN);
+}
+
+int grpc_chttp2_list_pop_written_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_writing **stream_writing) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
+                          GRPC_CHTTP2_LIST_WRITTEN);
+  if (r != 0) {
+    *stream_global = &stream->global;
+    *stream_writing = &stream->writing;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_add_unannounced_incoming_window_available(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  GPR_ASSERT(stream_global->id != 0);
+  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+                  STREAM_FROM_GLOBAL(stream_global),
+                  GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
+}
+
+void grpc_chttp2_list_remove_unannounced_incoming_window_available(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  stream_list_maybe_remove(
+      TRANSPORT_FROM_GLOBAL(transport_global),
+      STREAM_FROM_GLOBAL(stream_global),
+      GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
+}
+
+int grpc_chttp2_list_pop_unannounced_incoming_window_available(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_parsing **stream_parsing) {
+  grpc_chttp2_stream *stream;
+  int r =
+      stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+                      GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
+  if (r != 0) {
+    *stream_global = &stream->global;
+    *stream_parsing = &stream->parsing;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_add_parsing_seen_stream(
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_parsing *stream_parsing) {
+  stream_list_add(TRANSPORT_FROM_PARSING(transport_parsing),
+                  STREAM_FROM_PARSING(stream_parsing),
+                  GRPC_CHTTP2_LIST_PARSING_SEEN);
+}
+
+int grpc_chttp2_list_pop_parsing_seen_stream(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_parsing *transport_parsing,
+    grpc_chttp2_stream_global **stream_global,
+    grpc_chttp2_stream_parsing **stream_parsing) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_PARSING(transport_parsing), &stream,
+                          GRPC_CHTTP2_LIST_PARSING_SEEN);
+  if (r != 0) {
+    *stream_global = &stream->global;
+    *stream_parsing = &stream->parsing;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_add_waiting_for_concurrency(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+                  STREAM_FROM_GLOBAL(stream_global),
+                  GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
+}
+
+int grpc_chttp2_list_pop_waiting_for_concurrency(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+                          GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
+  if (r != 0) {
+    *stream_global = &stream->global;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_add_check_read_ops(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+                  STREAM_FROM_GLOBAL(stream_global),
+                  GRPC_CHTTP2_LIST_CHECK_READ_OPS);
+}
+
+int grpc_chttp2_list_pop_check_read_ops(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+                          GRPC_CHTTP2_LIST_CHECK_READ_OPS);
+  if (r != 0) {
+    *stream_global = &stream->global;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_add_writing_stalled_by_transport(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing) {
+  grpc_chttp2_stream *stream = STREAM_FROM_WRITING(stream_writing);
+  if (!stream->included[GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT]) {
+    GRPC_CHTTP2_STREAM_REF(&stream->global, "chttp2_writing_stalled");
+  }
+  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), stream,
+                  GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT);
+}
+
+void grpc_chttp2_list_flush_writing_stalled_by_transport(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
+    bool is_window_available) {
+  grpc_chttp2_stream *stream;
+  grpc_chttp2_transport *transport = TRANSPORT_FROM_WRITING(transport_writing);
+  while (stream_list_pop(transport, &stream,
+                         GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) {
+    if (is_window_available) {
+      grpc_chttp2_become_writable(&transport->global, &stream->global);
+    } else {
+      grpc_chttp2_list_add_stalled_by_transport(transport_writing,
+                                                &stream->writing);
+    }
+    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &stream->global,
+                             "chttp2_writing_stalled");
+  }
+}
+
+void grpc_chttp2_list_add_stalled_by_transport(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing) {
+  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
+                  STREAM_FROM_WRITING(stream_writing),
+                  GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
+}
+
+int grpc_chttp2_list_pop_stalled_by_transport(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+                          GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
+  if (r != 0) {
+    *stream_global = &stream->global;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_remove_stalled_by_transport(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
+                           STREAM_FROM_GLOBAL(stream_global),
+                           GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
+}
+
+void grpc_chttp2_list_add_closed_waiting_for_parsing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+                  STREAM_FROM_GLOBAL(stream_global),
+                  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
+}
+
+int grpc_chttp2_list_pop_closed_waiting_for_parsing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+                          GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
+  if (r != 0) {
+    *stream_global = &stream->global;
+  }
+  return r;
+}
+
+void grpc_chttp2_list_add_closed_waiting_for_writing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global) {
+  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+                  STREAM_FROM_GLOBAL(stream_global),
+                  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING);
+}
+
+int grpc_chttp2_list_pop_closed_waiting_for_writing(
+    grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global **stream_global) {
+  grpc_chttp2_stream *stream;
+  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+                          GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING);
+  if (r != 0) {
+    *stream_global = &stream->global;
+  }
+  return r;
+}
+
+void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
+                                 grpc_chttp2_stream *s) {
+  stream_list_add_tail(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
+}
+
+int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
+                                  grpc_chttp2_stream *s) {
+  stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
+  return stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
+}
+
+int grpc_chttp2_has_streams(grpc_chttp2_transport *t) {
+  return !stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
+}
+
+void grpc_chttp2_for_all_streams(
+    grpc_chttp2_transport_global *transport_global, void *user_data,
+    void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
+               grpc_chttp2_stream_global *stream_global)) {
+  grpc_chttp2_stream *s;
+  grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global);
+  for (s = t->lists[GRPC_CHTTP2_LIST_ALL_STREAMS].head; s != NULL;
+       s = s->links[GRPC_CHTTP2_LIST_ALL_STREAMS].next) {
+    cb(transport_global, user_data, &s->global);
+  }
+}
diff --git a/src/core/ext/transport/chttp2/transport/stream_map.c b/src/core/ext/transport/chttp2/transport/stream_map.c
new file mode 100644
index 0000000..f70791c
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/stream_map.c
@@ -0,0 +1,197 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/stream_map.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map,
+                                 size_t initial_capacity) {
+  GPR_ASSERT(initial_capacity > 1);
+  map->keys = gpr_malloc(sizeof(uint32_t) * initial_capacity);
+  map->values = gpr_malloc(sizeof(void *) * initial_capacity);
+  map->count = 0;
+  map->free = 0;
+  map->capacity = initial_capacity;
+}
+
+void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map) {
+  gpr_free(map->keys);
+  gpr_free(map->values);
+}
+
+static size_t compact(uint32_t *keys, void **values, size_t count) {
+  size_t i, out;
+
+  for (i = 0, out = 0; i < count; i++) {
+    if (values[i]) {
+      keys[out] = keys[i];
+      values[out] = values[i];
+      out++;
+    }
+  }
+
+  return out;
+}
+
+void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key,
+                                void *value) {
+  size_t count = map->count;
+  size_t capacity = map->capacity;
+  uint32_t *keys = map->keys;
+  void **values = map->values;
+
+  GPR_ASSERT(count == 0 || keys[count - 1] < key);
+  GPR_ASSERT(value);
+
+  if (count == capacity) {
+    if (map->free > capacity / 4) {
+      count = compact(keys, values, count);
+      map->free = 0;
+    } else {
+      /* resize when less than 25% of the table is free, because compaction
+         won't help much */
+      map->capacity = capacity = 3 * capacity / 2;
+      map->keys = keys = gpr_realloc(keys, capacity * sizeof(uint32_t));
+      map->values = values = gpr_realloc(values, capacity * sizeof(void *));
+    }
+  }
+
+  keys[count] = key;
+  values[count] = value;
+  map->count = count + 1;
+}
+
+void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src,
+                                      grpc_chttp2_stream_map *dst) {
+  /* if src is empty we dont need to do anything */
+  if (src->count == src->free) {
+    return;
+  }
+  /* if dst is empty we simply need to swap */
+  if (dst->count == dst->free) {
+    GPR_SWAP(grpc_chttp2_stream_map, *src, *dst);
+    return;
+  }
+  /* the first element of src must be greater than the last of dst...
+   * however the maps may need compacting for this property to hold */
+  if (src->keys[0] <= dst->keys[dst->count - 1]) {
+    src->count = compact(src->keys, src->values, src->count);
+    src->free = 0;
+    dst->count = compact(dst->keys, dst->values, dst->count);
+    dst->free = 0;
+  }
+  GPR_ASSERT(src->keys[0] > dst->keys[dst->count - 1]);
+  /* if dst doesn't have capacity, resize */
+  if (dst->count + src->count > dst->capacity) {
+    dst->capacity = GPR_MAX(dst->capacity * 3 / 2, dst->count + src->count);
+    dst->keys = gpr_realloc(dst->keys, dst->capacity * sizeof(uint32_t));
+    dst->values = gpr_realloc(dst->values, dst->capacity * sizeof(void *));
+  }
+  memcpy(dst->keys + dst->count, src->keys, src->count * sizeof(uint32_t));
+  memcpy(dst->values + dst->count, src->values, src->count * sizeof(void *));
+  dst->count += src->count;
+  dst->free += src->free;
+  src->count = 0;
+  src->free = 0;
+}
+
+static void **find(grpc_chttp2_stream_map *map, uint32_t key) {
+  size_t min_idx = 0;
+  size_t max_idx = map->count;
+  size_t mid_idx;
+  uint32_t *keys = map->keys;
+  void **values = map->values;
+  uint32_t mid_key;
+
+  if (max_idx == 0) return NULL;
+
+  while (min_idx < max_idx) {
+    /* find the midpoint, avoiding overflow */
+    mid_idx = min_idx + ((max_idx - min_idx) / 2);
+    mid_key = keys[mid_idx];
+
+    if (mid_key < key) {
+      min_idx = mid_idx + 1;
+    } else if (mid_key > key) {
+      max_idx = mid_idx;
+    } else /* mid_key == key */
+    {
+      return &values[mid_idx];
+    }
+  }
+
+  return NULL;
+}
+
+void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key) {
+  void **pvalue = find(map, key);
+  void *out = NULL;
+  if (pvalue != NULL) {
+    out = *pvalue;
+    *pvalue = NULL;
+    map->free += (out != NULL);
+    /* recognize complete emptyness and ensure we can skip
+     * defragmentation later */
+    if (map->free == map->count) {
+      map->free = map->count = 0;
+    }
+  }
+  return out;
+}
+
+void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key) {
+  void **pvalue = find(map, key);
+  return pvalue != NULL ? *pvalue : NULL;
+}
+
+size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map) {
+  return map->count - map->free;
+}
+
+void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map,
+                                     void (*f)(void *user_data, uint32_t key,
+                                               void *value),
+                                     void *user_data) {
+  size_t i;
+
+  for (i = 0; i < map->count; i++) {
+    if (map->values[i]) {
+      f(user_data, map->keys[i], map->values[i]);
+    }
+  }
+}
diff --git a/src/core/ext/transport/chttp2/transport/stream_map.h b/src/core/ext/transport/chttp2/transport/stream_map.h
new file mode 100644
index 0000000..b1d59ca
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/stream_map.h
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stddef.h>
+
+/* Data structure to map a uint32_t to a data object (represented by a void*)
+
+   Represented as a sorted array of keys, and a corresponding array of values.
+   Lookups are performed with binary search.
+   Adds are restricted to strictly higher keys than previously seen (this is
+   guaranteed by http2). */
+typedef struct {
+  uint32_t *keys;
+  void **values;
+  size_t count;
+  size_t free;
+  size_t capacity;
+} grpc_chttp2_stream_map;
+
+void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map,
+                                 size_t initial_capacity);
+void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map);
+
+/* Add a new key: given http2 semantics, new keys must always be greater than
+   existing keys - this is asserted */
+void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key,
+                                void *value);
+
+/* Delete an existing key - returns the previous value of the key if it existed,
+   or NULL otherwise */
+void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key);
+
+/* Move all elements of src into dst */
+void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src,
+                                      grpc_chttp2_stream_map *dst);
+
+/* Return an existing key, or NULL if it does not exist */
+void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key);
+
+/* How many (populated) entries are in the stream map? */
+size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map);
+
+/* Callback on each stream */
+void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map,
+                                     void (*f)(void *user_data, uint32_t key,
+                                               void *value),
+                                     void *user_data);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H */
diff --git a/src/core/ext/transport/chttp2/transport/timeout_encoding.c b/src/core/ext/transport/chttp2/transport/timeout_encoding.c
new file mode 100644
index 0000000..b7f7912
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/timeout_encoding.c
@@ -0,0 +1,188 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/timeout_encoding.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/port_platform.h>
+#include "src/core/lib/support/string.h"
+
+static int64_t round_up(int64_t x, int64_t divisor) {
+  return (x / divisor + (x % divisor != 0)) * divisor;
+}
+
+/* round an integer up to the next value with three significant figures */
+static int64_t round_up_to_three_sig_figs(int64_t x) {
+  if (x < 1000) return x;
+  if (x < 10000) return round_up(x, 10);
+  if (x < 100000) return round_up(x, 100);
+  if (x < 1000000) return round_up(x, 1000);
+  if (x < 10000000) return round_up(x, 10000);
+  if (x < 100000000) return round_up(x, 100000);
+  if (x < 1000000000) return round_up(x, 1000000);
+  return round_up(x, 10000000);
+}
+
+/* encode our minimum viable timeout value */
+static void enc_tiny(char *buffer) { memcpy(buffer, "1n", 3); }
+
+static void enc_ext(char *buffer, int64_t value, char ext) {
+  int n = int64_ttoa(value, buffer);
+  buffer[n] = ext;
+  buffer[n + 1] = 0;
+}
+
+static void enc_seconds(char *buffer, int64_t sec) {
+  if (sec % 3600 == 0) {
+    enc_ext(buffer, sec / 3600, 'H');
+  } else if (sec % 60 == 0) {
+    enc_ext(buffer, sec / 60, 'M');
+  } else {
+    enc_ext(buffer, sec, 'S');
+  }
+}
+
+static void enc_nanos(char *buffer, int64_t x) {
+  x = round_up_to_three_sig_figs(x);
+  if (x < 100000) {
+    if (x % 1000 == 0) {
+      enc_ext(buffer, x / 1000, 'u');
+    } else {
+      enc_ext(buffer, x, 'n');
+    }
+  } else if (x < 100000000) {
+    if (x % 1000000 == 0) {
+      enc_ext(buffer, x / 1000000, 'm');
+    } else {
+      enc_ext(buffer, x / 1000, 'u');
+    }
+  } else if (x < 1000000000) {
+    enc_ext(buffer, x / 1000000, 'm');
+  } else {
+    /* note that this is only ever called with times of less than one second,
+       so if we reach here the time must have been rounded up to a whole second
+       (and no more) */
+    memcpy(buffer, "1S", 3);
+  }
+}
+
+static void enc_micros(char *buffer, int64_t x) {
+  x = round_up_to_three_sig_figs(x);
+  if (x < 100000) {
+    if (x % 1000 == 0) {
+      enc_ext(buffer, x / 1000, 'm');
+    } else {
+      enc_ext(buffer, x, 'u');
+    }
+  } else if (x < 100000000) {
+    if (x % 1000000 == 0) {
+      enc_ext(buffer, x / 1000000, 'S');
+    } else {
+      enc_ext(buffer, x / 1000, 'm');
+    }
+  } else {
+    enc_ext(buffer, x / 1000000, 'S');
+  }
+}
+
+void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer) {
+  if (timeout.tv_sec < 0) {
+    enc_tiny(buffer);
+  } else if (timeout.tv_sec == 0) {
+    enc_nanos(buffer, timeout.tv_nsec);
+  } else if (timeout.tv_sec < 1000 && timeout.tv_nsec != 0) {
+    enc_micros(buffer,
+               (int64_t)(timeout.tv_sec * 1000000) +
+                   (timeout.tv_nsec / 1000 + (timeout.tv_nsec % 1000 != 0)));
+  } else {
+    enc_seconds(buffer, timeout.tv_sec + (timeout.tv_nsec != 0));
+  }
+}
+
+static int is_all_whitespace(const char *p) {
+  while (*p == ' ') p++;
+  return *p == 0;
+}
+
+int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout) {
+  int32_t x = 0;
+  const uint8_t *p = (const uint8_t *)buffer;
+  int have_digit = 0;
+  /* skip whitespace */
+  for (; *p == ' '; p++)
+    ;
+  /* decode numeric part */
+  for (; *p >= '0' && *p <= '9'; p++) {
+    int32_t digit = (int32_t)(*p - (uint8_t)'0');
+    have_digit = 1;
+    /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */
+    if (x >= (100 * 1000 * 1000)) {
+      if (x != (100 * 1000 * 1000) || digit != 0) {
+        *timeout = gpr_inf_future(GPR_TIMESPAN);
+        return 1;
+      }
+    }
+    x = x * 10 + digit;
+  }
+  if (!have_digit) return 0;
+  /* skip whitespace */
+  for (; *p == ' '; p++)
+    ;
+  /* decode unit specifier */
+  switch (*p) {
+    case 'n':
+      *timeout = gpr_time_from_nanos(x, GPR_TIMESPAN);
+      break;
+    case 'u':
+      *timeout = gpr_time_from_micros(x, GPR_TIMESPAN);
+      break;
+    case 'm':
+      *timeout = gpr_time_from_millis(x, GPR_TIMESPAN);
+      break;
+    case 'S':
+      *timeout = gpr_time_from_seconds(x, GPR_TIMESPAN);
+      break;
+    case 'M':
+      *timeout = gpr_time_from_minutes(x, GPR_TIMESPAN);
+      break;
+    case 'H':
+      *timeout = gpr_time_from_hours(x, GPR_TIMESPAN);
+      break;
+    default:
+      return 0;
+  }
+  p++;
+  return is_all_whitespace((const char *)p);
+}
diff --git a/src/core/ext/transport/chttp2/transport/timeout_encoding.h b/src/core/ext/transport/chttp2/transport/timeout_encoding.h
new file mode 100644
index 0000000..df2324c
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/timeout_encoding.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H
+
+#include <grpc/support/time.h>
+#include "src/core/lib/support/string.h"
+
+#define GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1)
+
+/* Encode/decode timeouts to the GRPC over HTTP2 format;
+   encoding may round up arbitrarily */
+void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer);
+int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H */
diff --git a/src/core/ext/transport/chttp2/transport/varint.c b/src/core/ext/transport/chttp2/transport/varint.c
new file mode 100644
index 0000000..e434ad3
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/varint.c
@@ -0,0 +1,65 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/varint.h"
+
+uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value) {
+  if (tail_value < (1 << 7)) {
+    return 2;
+  } else if (tail_value < (1 << 14)) {
+    return 3;
+  } else if (tail_value < (1 << 21)) {
+    return 4;
+  } else if (tail_value < (1 << 28)) {
+    return 5;
+  } else {
+    return 6;
+  }
+}
+
+void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target,
+                                         uint32_t tail_length) {
+  switch (tail_length) {
+    case 5:
+      target[4] = (uint8_t)((tail_value >> 28) | 0x80);
+    case 4:
+      target[3] = (uint8_t)((tail_value >> 21) | 0x80);
+    case 3:
+      target[2] = (uint8_t)((tail_value >> 14) | 0x80);
+    case 2:
+      target[1] = (uint8_t)((tail_value >> 7) | 0x80);
+    case 1:
+      target[0] = (uint8_t)((tail_value) | 0x80);
+  }
+  target[tail_length - 1] &= 0x7f;
+}
diff --git a/src/core/ext/transport/chttp2/transport/varint.h b/src/core/ext/transport/chttp2/transport/varint.h
new file mode 100644
index 0000000..450e5fd
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/varint.h
@@ -0,0 +1,75 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_VARINT_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_VARINT_H
+
+#include <grpc/support/port_platform.h>
+
+/* Helpers for hpack varint encoding */
+
+/* length of a value that needs varint tail encoding (it's bigger than can be
+   bitpacked into the opcode byte) - returned value includes the length of the
+   opcode byte */
+uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value);
+
+void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target,
+                                         uint32_t tail_length);
+
+/* maximum value that can be bitpacked with the opcode if the opcode has a
+   prefix
+   of length prefix_bits */
+#define GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits) \
+  ((uint32_t)((1 << (8 - (prefix_bits))) - 1))
+
+/* length required to bitpack a value */
+#define GRPC_CHTTP2_VARINT_LENGTH(n, prefix_bits) \
+  ((n) < GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits)   \
+       ? 1u                                       \
+       : grpc_chttp2_hpack_varint_length(         \
+             (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits)))
+
+#define GRPC_CHTTP2_WRITE_VARINT(n, prefix_bits, prefix_or, target, length)   \
+  do {                                                                        \
+    uint8_t* tgt = target;                                                    \
+    if ((length) == 1u) {                                                     \
+      (tgt)[0] = (uint8_t)((prefix_or) | (n));                                \
+    } else {                                                                  \
+      (tgt)[0] =                                                              \
+          (prefix_or) | (uint8_t)GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits);      \
+      grpc_chttp2_hpack_write_varint_tail(                                    \
+          (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits), (tgt) + 1, (length)-1); \
+    }                                                                         \
+  } while (0)
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_VARINT_H */
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
new file mode 100644
index 0000000..a8fb463
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -0,0 +1,360 @@
+/*
+ *
+ * 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/ext/transport/chttp2/transport/internal.h"
+
+#include <limits.h>
+
+#include <grpc/support/log.h>
+
+#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
+#include "src/core/lib/profiling/timers.h"
+
+static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
+                            grpc_chttp2_transport_writing *transport_writing);
+
+int grpc_chttp2_unlocking_check_writes(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_writing *transport_writing, int is_parsing) {
+  grpc_chttp2_stream_global *stream_global;
+  grpc_chttp2_stream_writing *stream_writing;
+
+  GPR_TIMER_BEGIN("grpc_chttp2_unlocking_check_writes", 0);
+
+  /* simple writes are queued to qbuf, and flushed here */
+  gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf);
+  GPR_ASSERT(transport_global->qbuf.count == 0);
+
+  grpc_chttp2_hpack_compressor_set_max_table_size(
+      &transport_writing->hpack_compressor,
+      transport_global->settings[GRPC_PEER_SETTINGS]
+                                [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
+
+  if (transport_global->dirtied_local_settings &&
+      !transport_global->sent_local_settings && !is_parsing) {
+    gpr_slice_buffer_add(
+        &transport_writing->outbuf,
+        grpc_chttp2_settings_create(
+            transport_global->settings[GRPC_SENT_SETTINGS],
+            transport_global->settings[GRPC_LOCAL_SETTINGS],
+            transport_global->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS));
+    transport_global->force_send_settings = 0;
+    transport_global->dirtied_local_settings = 0;
+    transport_global->sent_local_settings = 1;
+  }
+
+  GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window,
+                                  transport_global, outgoing_window);
+  bool is_window_available = transport_writing->outgoing_window > 0;
+  grpc_chttp2_list_flush_writing_stalled_by_transport(
+      exec_ctx, transport_writing, is_window_available);
+
+  /* for each grpc_chttp2_stream that's become writable, frame it's data
+     (according to available window sizes) and add to the output buffer */
+  while (grpc_chttp2_list_pop_writable_stream(
+      transport_global, transport_writing, &stream_global, &stream_writing)) {
+    bool sent_initial_metadata = stream_writing->sent_initial_metadata;
+    bool become_writable = false;
+
+    stream_writing->id = stream_global->id;
+    stream_writing->read_closed = stream_global->read_closed;
+
+    GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_writing, stream_writing,
+                                 outgoing_window, stream_global,
+                                 outgoing_window);
+
+    if (!sent_initial_metadata && stream_global->send_initial_metadata) {
+      stream_writing->send_initial_metadata =
+          stream_global->send_initial_metadata;
+      stream_global->send_initial_metadata = NULL;
+      become_writable = true;
+      sent_initial_metadata = true;
+    }
+    if (sent_initial_metadata) {
+      if (stream_global->send_message != NULL) {
+        gpr_slice hdr = gpr_slice_malloc(5);
+        uint8_t *p = GPR_SLICE_START_PTR(hdr);
+        uint32_t len = stream_global->send_message->length;
+        GPR_ASSERT(stream_writing->send_message == NULL);
+        p[0] = (stream_global->send_message->flags &
+                GRPC_WRITE_INTERNAL_COMPRESS) != 0;
+        p[1] = (uint8_t)(len >> 24);
+        p[2] = (uint8_t)(len >> 16);
+        p[3] = (uint8_t)(len >> 8);
+        p[4] = (uint8_t)(len);
+        gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer, hdr);
+        if (stream_global->send_message->length > 0) {
+          stream_writing->send_message = stream_global->send_message;
+        } else {
+          stream_writing->send_message = NULL;
+        }
+        stream_writing->stream_fetched = 0;
+        stream_global->send_message = NULL;
+      }
+      if ((stream_writing->send_message != NULL ||
+           stream_writing->flow_controlled_buffer.length > 0) &&
+          stream_writing->outgoing_window > 0) {
+        if (transport_writing->outgoing_window > 0) {
+          become_writable = true;
+        } else {
+          grpc_chttp2_list_add_stalled_by_transport(transport_writing,
+                                                    stream_writing);
+        }
+      }
+      if (stream_global->send_trailing_metadata) {
+        stream_writing->send_trailing_metadata =
+            stream_global->send_trailing_metadata;
+        stream_global->send_trailing_metadata = NULL;
+        become_writable = true;
+      }
+    }
+
+    if (!stream_global->read_closed &&
+        stream_global->unannounced_incoming_window_for_writing > 1024) {
+      GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing,
+                                   announce_window, stream_global,
+                                   unannounced_incoming_window_for_writing);
+      become_writable = true;
+    }
+
+    if (become_writable) {
+      grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
+    } else {
+      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
+    }
+  }
+
+  /* if the grpc_chttp2_transport is ready to send a window update, do so here
+     also; 3/4 is a magic number that will likely get tuned soon */
+  if (transport_global->announce_incoming_window > 0) {
+    uint32_t announced = (uint32_t)GPR_MIN(
+        transport_global->announce_incoming_window, UINT32_MAX);
+    GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_global,
+                                     announce_incoming_window, announced);
+    grpc_transport_one_way_stats throwaway_stats;
+    gpr_slice_buffer_add(
+        &transport_writing->outbuf,
+        grpc_chttp2_window_update_create(0, announced, &throwaway_stats));
+  }
+
+  GPR_TIMER_END("grpc_chttp2_unlocking_check_writes", 0);
+
+  return transport_writing->outbuf.count > 0 ||
+         grpc_chttp2_list_have_writing_streams(transport_writing);
+}
+
+void grpc_chttp2_perform_writes(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
+    grpc_endpoint *endpoint) {
+  GPR_ASSERT(transport_writing->outbuf.count > 0 ||
+             grpc_chttp2_list_have_writing_streams(transport_writing));
+
+  finalize_outbuf(exec_ctx, transport_writing);
+
+  GPR_ASSERT(endpoint);
+
+  if (transport_writing->outbuf.count > 0) {
+    grpc_endpoint_write(exec_ctx, endpoint, &transport_writing->outbuf,
+                        &transport_writing->done_cb);
+  } else {
+    grpc_exec_ctx_enqueue(exec_ctx, &transport_writing->done_cb, true, NULL);
+  }
+}
+
+static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
+                            grpc_chttp2_transport_writing *transport_writing) {
+  grpc_chttp2_stream_writing *stream_writing;
+
+  GPR_TIMER_BEGIN("finalize_outbuf", 0);
+
+  while (
+      grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) {
+    uint32_t max_outgoing =
+        (uint32_t)GPR_MIN(GRPC_CHTTP2_MAX_PAYLOAD_LENGTH,
+                          GPR_MIN(stream_writing->outgoing_window,
+                                  transport_writing->outgoing_window));
+    /* send initial metadata if it's available */
+    if (stream_writing->send_initial_metadata != NULL) {
+      grpc_chttp2_encode_header(
+          &transport_writing->hpack_compressor, stream_writing->id,
+          stream_writing->send_initial_metadata, 0, &stream_writing->stats,
+          &transport_writing->outbuf);
+      stream_writing->send_initial_metadata = NULL;
+      stream_writing->sent_initial_metadata = 1;
+    }
+    /* send any window updates */
+    if (stream_writing->announce_window > 0 &&
+        stream_writing->send_initial_metadata == NULL) {
+      uint32_t announce = stream_writing->announce_window;
+      gpr_slice_buffer_add(
+          &transport_writing->outbuf,
+          grpc_chttp2_window_update_create(stream_writing->id,
+                                           stream_writing->announce_window,
+                                           &stream_writing->stats));
+      GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, stream_writing,
+                                    announce_window, announce);
+      stream_writing->announce_window = 0;
+    }
+    /* fetch any body bytes */
+    while (!stream_writing->fetching && stream_writing->send_message &&
+           stream_writing->flow_controlled_buffer.length < max_outgoing &&
+           stream_writing->stream_fetched <
+               stream_writing->send_message->length) {
+      if (grpc_byte_stream_next(exec_ctx, stream_writing->send_message,
+                                &stream_writing->fetching_slice, max_outgoing,
+                                &stream_writing->finished_fetch)) {
+        stream_writing->stream_fetched +=
+            GPR_SLICE_LENGTH(stream_writing->fetching_slice);
+        if (stream_writing->stream_fetched ==
+            stream_writing->send_message->length) {
+          stream_writing->send_message = NULL;
+        }
+        gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer,
+                             stream_writing->fetching_slice);
+      } else {
+        stream_writing->fetching = 1;
+      }
+    }
+    /* send any body bytes */
+    if (stream_writing->flow_controlled_buffer.length > 0) {
+      if (max_outgoing > 0) {
+        uint32_t send_bytes = (uint32_t)GPR_MIN(
+            max_outgoing, stream_writing->flow_controlled_buffer.length);
+        int is_last_data_frame =
+            stream_writing->send_message == NULL &&
+            send_bytes == stream_writing->flow_controlled_buffer.length;
+        int is_last_frame = is_last_data_frame &&
+                            stream_writing->send_trailing_metadata != NULL &&
+                            grpc_metadata_batch_is_empty(
+                                stream_writing->send_trailing_metadata);
+        grpc_chttp2_encode_data(
+            stream_writing->id, &stream_writing->flow_controlled_buffer,
+            send_bytes, is_last_frame, &stream_writing->stats,
+            &transport_writing->outbuf);
+        GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing,
+                                      stream_writing, outgoing_window,
+                                      send_bytes);
+        GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_writing,
+                                         outgoing_window, send_bytes);
+        if (is_last_frame) {
+          stream_writing->send_trailing_metadata = NULL;
+          stream_writing->sent_trailing_metadata = 1;
+        }
+        if (is_last_data_frame) {
+          GPR_ASSERT(stream_writing->send_message == NULL);
+          stream_writing->sent_message = 1;
+        }
+      } else if (transport_writing->outgoing_window == 0) {
+        grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
+                                                          stream_writing);
+        grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
+      }
+    }
+    /* send trailing metadata if it's available and we're ready for it */
+    if (stream_writing->send_message == NULL &&
+        stream_writing->flow_controlled_buffer.length == 0 &&
+        stream_writing->send_trailing_metadata != NULL) {
+      if (grpc_metadata_batch_is_empty(
+              stream_writing->send_trailing_metadata)) {
+        grpc_chttp2_encode_data(
+            stream_writing->id, &stream_writing->flow_controlled_buffer, 0, 1,
+            &stream_writing->stats, &transport_writing->outbuf);
+      } else {
+        grpc_chttp2_encode_header(
+            &transport_writing->hpack_compressor, stream_writing->id,
+            stream_writing->send_trailing_metadata, 1, &stream_writing->stats,
+            &transport_writing->outbuf);
+      }
+      if (!transport_writing->is_client && !stream_writing->read_closed) {
+        gpr_slice_buffer_add(&transport_writing->outbuf,
+                             grpc_chttp2_rst_stream_create(
+                                 stream_writing->id, GRPC_CHTTP2_NO_ERROR,
+                                 &stream_writing->stats));
+      }
+      stream_writing->send_trailing_metadata = NULL;
+      stream_writing->sent_trailing_metadata = 1;
+    }
+    /* if there's more to write, then loop, otherwise prepare to finish the
+     * write */
+    if ((stream_writing->flow_controlled_buffer.length > 0 ||
+         (stream_writing->send_message && !stream_writing->fetching)) &&
+        stream_writing->outgoing_window > 0) {
+      if (transport_writing->outgoing_window > 0) {
+        grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
+      } else {
+        grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
+                                                          stream_writing);
+        grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
+      }
+    } else {
+      grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
+    }
+  }
+
+  GPR_TIMER_END("finalize_outbuf", 0);
+}
+
+void grpc_chttp2_cleanup_writing(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_transport_writing *transport_writing) {
+  grpc_chttp2_stream_writing *stream_writing;
+  grpc_chttp2_stream_global *stream_global;
+
+  while (grpc_chttp2_list_pop_written_stream(
+      transport_global, transport_writing, &stream_global, &stream_writing)) {
+    if (stream_writing->sent_initial_metadata) {
+      grpc_chttp2_complete_closure_step(
+          exec_ctx, stream_global,
+          &stream_global->send_initial_metadata_finished, 1);
+    }
+    grpc_transport_move_one_way_stats(&stream_writing->stats,
+                                      &stream_global->stats.outgoing);
+    if (stream_writing->sent_message) {
+      GPR_ASSERT(stream_writing->send_message == NULL);
+      grpc_chttp2_complete_closure_step(
+          exec_ctx, stream_global, &stream_global->send_message_finished, 1);
+      stream_writing->sent_message = 0;
+    }
+    if (stream_writing->sent_trailing_metadata) {
+      grpc_chttp2_complete_closure_step(
+          exec_ctx, stream_global,
+          &stream_global->send_trailing_metadata_finished, 1);
+    }
+    if (stream_writing->sent_trailing_metadata) {
+      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
+                                     !transport_global->is_client, 1);
+    }
+    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
+  }
+  gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf);
+}
diff --git a/src/core/httpcli/format_request.c b/src/core/httpcli/format_request.c
deleted file mode 100644
index 04f2a2d..0000000
--- a/src/core/httpcli/format_request.c
+++ /dev/null
@@ -1,120 +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/httpcli/format_request.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-static void fill_common_header(const grpc_httpcli_request *request,
-                               gpr_strvec *buf) {
-  size_t i;
-  gpr_strvec_add(buf, gpr_strdup(request->path));
-  gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n"));
-  /* just in case some crazy server really expects HTTP/1.1 */
-  gpr_strvec_add(buf, gpr_strdup("Host: "));
-  gpr_strvec_add(buf, gpr_strdup(request->host));
-  gpr_strvec_add(buf, gpr_strdup("\r\n"));
-  gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n"));
-  gpr_strvec_add(buf,
-                 gpr_strdup("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n"));
-  /* user supplied headers */
-  for (i = 0; i < request->hdr_count; i++) {
-    gpr_strvec_add(buf, gpr_strdup(request->hdrs[i].key));
-    gpr_strvec_add(buf, gpr_strdup(": "));
-    gpr_strvec_add(buf, gpr_strdup(request->hdrs[i].value));
-    gpr_strvec_add(buf, gpr_strdup("\r\n"));
-  }
-}
-
-gpr_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request) {
-  gpr_strvec out;
-  char *flat;
-  size_t flat_len;
-
-  gpr_strvec_init(&out);
-  gpr_strvec_add(&out, gpr_strdup("GET "));
-  fill_common_header(request, &out);
-  gpr_strvec_add(&out, gpr_strdup("\r\n"));
-
-  flat = gpr_strvec_flatten(&out, &flat_len);
-  gpr_strvec_destroy(&out);
-
-  return gpr_slice_new(flat, flat_len, gpr_free);
-}
-
-gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request,
-                                           const char *body_bytes,
-                                           size_t body_size) {
-  gpr_strvec out;
-  char *tmp;
-  size_t out_len;
-  size_t i;
-
-  gpr_strvec_init(&out);
-
-  gpr_strvec_add(&out, gpr_strdup("POST "));
-  fill_common_header(request, &out);
-  if (body_bytes) {
-    uint8_t has_content_type = 0;
-    for (i = 0; i < request->hdr_count; i++) {
-      if (strcmp(request->hdrs[i].key, "Content-Type") == 0) {
-        has_content_type = 1;
-        break;
-      }
-    }
-    if (!has_content_type) {
-      gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n"));
-    }
-    gpr_asprintf(&tmp, "Content-Length: %lu\r\n", (unsigned long)body_size);
-    gpr_strvec_add(&out, tmp);
-  }
-  gpr_strvec_add(&out, gpr_strdup("\r\n"));
-  tmp = gpr_strvec_flatten(&out, &out_len);
-  gpr_strvec_destroy(&out);
-
-  if (body_bytes) {
-    tmp = gpr_realloc(tmp, out_len + body_size);
-    memcpy(tmp + out_len, body_bytes, body_size);
-    out_len += body_size;
-  }
-
-  return gpr_slice_new(tmp, out_len, gpr_free);
-}
diff --git a/src/core/httpcli/format_request.h b/src/core/httpcli/format_request.h
deleted file mode 100644
index eb47cc9..0000000
--- a/src/core/httpcli/format_request.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_HTTPCLI_FORMAT_REQUEST_H
-#define GRPC_CORE_HTTPCLI_FORMAT_REQUEST_H
-
-#include "src/core/httpcli/httpcli.h"
-#include <grpc/support/slice.h>
-
-gpr_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request);
-gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request,
-                                           const char *body_bytes,
-                                           size_t body_size);
-
-#endif /* GRPC_CORE_HTTPCLI_FORMAT_REQUEST_H */
diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c
deleted file mode 100644
index 1219c44..0000000
--- a/src/core/httpcli/httpcli.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- *
- * 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/httpcli/httpcli.h"
-#include "src/core/iomgr/sockaddr.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/httpcli/format_request.h"
-#include "src/core/httpcli/parser.h"
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/tcp_client.h"
-#include "src/core/support/string.h"
-
-typedef struct {
-  gpr_slice request_text;
-  grpc_httpcli_parser parser;
-  grpc_resolved_addresses *addresses;
-  size_t next_address;
-  grpc_endpoint *ep;
-  char *host;
-  char *ssl_host_override;
-  gpr_timespec deadline;
-  int have_read_byte;
-  const grpc_httpcli_handshaker *handshaker;
-  grpc_httpcli_response_cb on_response;
-  void *user_data;
-  grpc_httpcli_context *context;
-  grpc_pollset *pollset;
-  grpc_iomgr_object iomgr_obj;
-  gpr_slice_buffer incoming;
-  gpr_slice_buffer outgoing;
-  grpc_closure on_read;
-  grpc_closure done_write;
-  grpc_closure connected;
-} internal_request;
-
-static grpc_httpcli_get_override g_get_override = NULL;
-static grpc_httpcli_post_override g_post_override = NULL;
-
-static void plaintext_handshake(grpc_exec_ctx *exec_ctx, void *arg,
-                                grpc_endpoint *endpoint, const char *host,
-                                void (*on_done)(grpc_exec_ctx *exec_ctx,
-                                                void *arg,
-                                                grpc_endpoint *endpoint)) {
-  on_done(exec_ctx, arg, endpoint);
-}
-
-const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http",
-                                                        plaintext_handshake};
-
-void grpc_httpcli_context_init(grpc_httpcli_context *context) {
-  context->pollset_set = grpc_pollset_set_create();
-}
-
-void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
-  grpc_pollset_set_destroy(context->pollset_set);
-}
-
-static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
-
-static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
-                   int success) {
-  grpc_pollset_set_del_pollset(exec_ctx, req->context->pollset_set,
-                               req->pollset);
-  req->on_response(exec_ctx, req->user_data, success ? &req->parser.r : NULL);
-  grpc_httpcli_parser_destroy(&req->parser);
-  if (req->addresses != NULL) {
-    grpc_resolved_addresses_destroy(req->addresses);
-  }
-  if (req->ep != NULL) {
-    grpc_endpoint_destroy(exec_ctx, req->ep);
-  }
-  gpr_slice_unref(req->request_text);
-  gpr_free(req->host);
-  gpr_free(req->ssl_host_override);
-  grpc_iomgr_unregister_object(&req->iomgr_obj);
-  gpr_slice_buffer_destroy(&req->incoming);
-  gpr_slice_buffer_destroy(&req->outgoing);
-  gpr_free(req);
-}
-
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success);
-
-static void do_read(grpc_exec_ctx *exec_ctx, internal_request *req) {
-  grpc_endpoint_read(exec_ctx, req->ep, &req->incoming, &req->on_read);
-}
-
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
-  internal_request *req = user_data;
-  size_t i;
-
-  for (i = 0; i < req->incoming.count; i++) {
-    if (GPR_SLICE_LENGTH(req->incoming.slices[i])) {
-      req->have_read_byte = 1;
-      if (!grpc_httpcli_parser_parse(&req->parser, req->incoming.slices[i])) {
-        finish(exec_ctx, req, 0);
-        return;
-      }
-    }
-  }
-
-  if (success) {
-    do_read(exec_ctx, req);
-  } else if (!req->have_read_byte) {
-    next_address(exec_ctx, req);
-  } else {
-    finish(exec_ctx, req, grpc_httpcli_parser_eof(&req->parser));
-  }
-}
-
-static void on_written(grpc_exec_ctx *exec_ctx, internal_request *req) {
-  do_read(exec_ctx, req);
-}
-
-static void done_write(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  internal_request *req = arg;
-  if (success) {
-    on_written(exec_ctx, req);
-  } else {
-    next_address(exec_ctx, req);
-  }
-}
-
-static void start_write(grpc_exec_ctx *exec_ctx, internal_request *req) {
-  gpr_slice_ref(req->request_text);
-  gpr_slice_buffer_add(&req->outgoing, req->request_text);
-  grpc_endpoint_write(exec_ctx, req->ep, &req->outgoing, &req->done_write);
-}
-
-static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
-                              grpc_endpoint *ep) {
-  internal_request *req = arg;
-
-  if (!ep) {
-    next_address(exec_ctx, req);
-    return;
-  }
-
-  req->ep = ep;
-  start_write(exec_ctx, req);
-}
-
-static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  internal_request *req = arg;
-
-  if (!req->ep) {
-    next_address(exec_ctx, req);
-    return;
-  }
-  req->handshaker->handshake(
-      exec_ctx, req, req->ep,
-      req->ssl_host_override ? req->ssl_host_override : req->host,
-      on_handshake_done);
-}
-
-static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
-  grpc_resolved_address *addr;
-  if (req->next_address == req->addresses->naddrs) {
-    finish(exec_ctx, req, 0);
-    return;
-  }
-  addr = &req->addresses->addrs[req->next_address++];
-  grpc_closure_init(&req->connected, on_connected, req);
-  grpc_tcp_client_connect(
-      exec_ctx, &req->connected, &req->ep, req->context->pollset_set,
-      (struct sockaddr *)&addr->addr, addr->len, req->deadline);
-}
-
-static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                        grpc_resolved_addresses *addresses) {
-  internal_request *req = arg;
-  if (!addresses) {
-    finish(exec_ctx, req, 0);
-    return;
-  }
-  req->addresses = addresses;
-  req->next_address = 0;
-  next_address(exec_ctx, req);
-}
-
-static void internal_request_begin(
-    grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
-    grpc_pollset *pollset, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data, const char *name, gpr_slice request_text) {
-  internal_request *req = gpr_malloc(sizeof(internal_request));
-  memset(req, 0, sizeof(*req));
-  req->request_text = request_text;
-  grpc_httpcli_parser_init(&req->parser);
-  req->on_response = on_response;
-  req->user_data = user_data;
-  req->deadline = deadline;
-  req->handshaker =
-      request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
-  req->context = context;
-  req->pollset = pollset;
-  grpc_closure_init(&req->on_read, on_read, req);
-  grpc_closure_init(&req->done_write, done_write, req);
-  gpr_slice_buffer_init(&req->incoming);
-  gpr_slice_buffer_init(&req->outgoing);
-  grpc_iomgr_register_object(&req->iomgr_obj, name);
-  req->host = gpr_strdup(request->host);
-  req->ssl_host_override = gpr_strdup(request->ssl_host_override);
-
-  grpc_pollset_set_add_pollset(exec_ctx, req->context->pollset_set,
-                               req->pollset);
-  grpc_resolve_address(request->host, req->handshaker->default_port,
-                       on_resolved, req);
-}
-
-void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
-                      grpc_pollset *pollset,
-                      const grpc_httpcli_request *request,
-                      gpr_timespec deadline,
-                      grpc_httpcli_response_cb on_response, void *user_data) {
-  char *name;
-  if (g_get_override &&
-      g_get_override(exec_ctx, request, deadline, on_response, user_data)) {
-    return;
-  }
-  gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path);
-  internal_request_begin(exec_ctx, context, pollset, request, deadline,
-                         on_response, user_data, name,
-                         grpc_httpcli_format_get_request(request));
-  gpr_free(name);
-}
-
-void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
-                       grpc_pollset *pollset,
-                       const grpc_httpcli_request *request,
-                       const char *body_bytes, size_t body_size,
-                       gpr_timespec deadline,
-                       grpc_httpcli_response_cb on_response, void *user_data) {
-  char *name;
-  if (g_post_override &&
-      g_post_override(exec_ctx, request, body_bytes, body_size, deadline,
-                      on_response, user_data)) {
-    return;
-  }
-  gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->path);
-  internal_request_begin(
-      exec_ctx, context, pollset, request, deadline, on_response, user_data,
-      name, grpc_httpcli_format_post_request(request, body_bytes, body_size));
-  gpr_free(name);
-}
-
-void grpc_httpcli_set_override(grpc_httpcli_get_override get,
-                               grpc_httpcli_post_override post) {
-  g_get_override = get;
-  g_post_override = post;
-}
diff --git a/src/core/httpcli/httpcli.h b/src/core/httpcli/httpcli.h
deleted file mode 100644
index 1fe5782..0000000
--- a/src/core/httpcli/httpcli.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_HTTPCLI_HTTPCLI_H
-#define GRPC_CORE_HTTPCLI_HTTPCLI_H
-
-#include <stddef.h>
-
-#include <grpc/support/time.h>
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/pollset_set.h"
-
-/* User agent this library reports */
-#define GRPC_HTTPCLI_USER_AGENT "grpc-httpcli/0.0"
-/* Maximum length of a header string of the form 'Key: Value\r\n' */
-#define GRPC_HTTPCLI_MAX_HEADER_LENGTH 4096
-
-/* A single header to be passed in a request */
-typedef struct grpc_httpcli_header {
-  char *key;
-  char *value;
-} grpc_httpcli_header;
-
-/* Tracks in-progress http requests
-   TODO(ctiller): allow caching and capturing multiple requests for the
-                  same content and combining them */
-typedef struct grpc_httpcli_context {
-  grpc_pollset_set *pollset_set;
-} grpc_httpcli_context;
-
-typedef struct {
-  const char *default_port;
-  void (*handshake)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint,
-                    const char *host,
-                    void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
-                                    grpc_endpoint *endpoint));
-} grpc_httpcli_handshaker;
-
-extern const grpc_httpcli_handshaker grpc_httpcli_plaintext;
-extern const grpc_httpcli_handshaker grpc_httpcli_ssl;
-
-/* A request */
-typedef struct grpc_httpcli_request {
-  /* The host name to connect to */
-  char *host;
-  /* The host to verify in the SSL handshake (or NULL) */
-  char *ssl_host_override;
-  /* The path of the resource to fetch */
-  char *path;
-  /* Additional headers: count and key/values; the following are supplied
-     automatically and MUST NOT be set here:
-     Host, Connection, User-Agent */
-  size_t hdr_count;
-  grpc_httpcli_header *hdrs;
-  /* handshaker to use ssl for the request */
-  const grpc_httpcli_handshaker *handshaker;
-} grpc_httpcli_request;
-
-/* A response */
-typedef struct grpc_httpcli_response {
-  /* HTTP status code */
-  int status;
-  /* Headers: count and key/values */
-  size_t hdr_count;
-  grpc_httpcli_header *hdrs;
-  /* Body: length and contents; contents are NOT null-terminated */
-  size_t body_length;
-  char *body;
-} grpc_httpcli_response;
-
-/* Callback for grpc_httpcli_get and grpc_httpcli_post. */
-typedef void (*grpc_httpcli_response_cb)(grpc_exec_ctx *exec_ctx,
-                                         void *user_data,
-                                         const grpc_httpcli_response *response);
-
-void grpc_httpcli_context_init(grpc_httpcli_context *context);
-void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
-
-/* Asynchronously perform a HTTP GET.
-   'context' specifies the http context under which to do the get
-   'pollset' indicates a grpc_pollset that is interested in the result
-     of the get - work on this pollset may be used to progress the get
-     operation
-   'request' contains request parameters - these are caller owned and can be
-     destroyed once the call returns
-   'deadline' contains a deadline for the request (or gpr_inf_future)
-   'on_response' is a callback to report results to (and 'user_data' is a user
-     supplied pointer to pass to said call) */
-void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
-                      grpc_pollset *pollset,
-                      const grpc_httpcli_request *request,
-                      gpr_timespec deadline,
-                      grpc_httpcli_response_cb on_response, void *user_data);
-
-/* Asynchronously perform a HTTP POST.
-   'context' specifies the http context under which to do the post
-   'pollset' indicates a grpc_pollset that is interested in the result
-     of the post - work on this pollset may be used to progress the post
-     operation
-   'request' contains request parameters - these are caller owned and can be
-     destroyed once the call returns
-   'body_bytes' and 'body_size' specify the payload for the post.
-     When there is no body, pass in NULL as body_bytes.
-   'deadline' contains a deadline for the request (or gpr_inf_future)
-   'em' points to a caller owned event manager that must be alive for the
-     lifetime of the request
-   'on_response' is a callback to report results to (and 'user_data' is a user
-     supplied pointer to pass to said call)
-   Does not support ?var1=val1&var2=val2 in the path. */
-void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
-                       grpc_pollset *pollset,
-                       const grpc_httpcli_request *request,
-                       const char *body_bytes, size_t body_size,
-                       gpr_timespec deadline,
-                       grpc_httpcli_response_cb on_response, void *user_data);
-
-/* override functions return 1 if they handled the request, 0 otherwise */
-typedef int (*grpc_httpcli_get_override)(grpc_exec_ctx *exec_ctx,
-                                         const grpc_httpcli_request *request,
-                                         gpr_timespec deadline,
-                                         grpc_httpcli_response_cb on_response,
-                                         void *user_data);
-typedef int (*grpc_httpcli_post_override)(
-    grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    const char *body_bytes, size_t body_size, gpr_timespec deadline,
-    grpc_httpcli_response_cb on_response, void *user_data);
-
-void grpc_httpcli_set_override(grpc_httpcli_get_override get,
-                               grpc_httpcli_post_override post);
-
-#endif /* GRPC_CORE_HTTPCLI_HTTPCLI_H */
diff --git a/src/core/httpcli/httpcli_security_connector.c b/src/core/httpcli/httpcli_security_connector.c
deleted file mode 100644
index 156961a..0000000
--- a/src/core/httpcli/httpcli_security_connector.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *
- * 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/httpcli/httpcli.h"
-
-#include <string.h>
-
-#include "src/core/security/handshake.h"
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include "src/core/tsi/ssl_transport_security.h"
-
-typedef struct {
-  grpc_channel_security_connector base;
-  tsi_ssl_handshaker_factory *handshaker_factory;
-  char *secure_peer_name;
-} grpc_httpcli_ssl_channel_security_connector;
-
-static void httpcli_ssl_destroy(grpc_security_connector *sc) {
-  grpc_httpcli_ssl_channel_security_connector *c =
-      (grpc_httpcli_ssl_channel_security_connector *)sc;
-  if (c->handshaker_factory != NULL) {
-    tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
-  }
-  if (c->secure_peer_name != NULL) gpr_free(c->secure_peer_name);
-  gpr_free(sc);
-}
-
-static void httpcli_ssl_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_httpcli_ssl_channel_security_connector *c =
-      (grpc_httpcli_ssl_channel_security_connector *)sc;
-  tsi_result result = TSI_OK;
-  tsi_handshaker *handshaker;
-  if (c->handshaker_factory == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
-    return;
-  }
-  result = tsi_ssl_handshaker_factory_create_handshaker(
-      c->handshaker_factory, c->secure_peer_name, &handshaker);
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
-            tsi_result_to_string(result));
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
-  } else {
-    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
-                               nonsecure_endpoint, cb, user_data);
-  }
-}
-
-static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,
-                                   grpc_security_connector *sc, tsi_peer peer,
-                                   grpc_security_peer_check_cb cb,
-                                   void *user_data) {
-  grpc_httpcli_ssl_channel_security_connector *c =
-      (grpc_httpcli_ssl_channel_security_connector *)sc;
-  grpc_security_status status = GRPC_SECURITY_OK;
-
-  /* Check the peer name. */
-  if (c->secure_peer_name != NULL &&
-      !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) {
-    gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate",
-            c->secure_peer_name);
-    status = GRPC_SECURITY_ERROR;
-  }
-  cb(exec_ctx, user_data, status, NULL);
-  tsi_peer_destruct(&peer);
-}
-
-static grpc_security_connector_vtable httpcli_ssl_vtable = {
-    httpcli_ssl_destroy, httpcli_ssl_check_peer};
-
-static grpc_security_status httpcli_ssl_channel_security_connector_create(
-    const unsigned char *pem_root_certs, size_t pem_root_certs_size,
-    const char *secure_peer_name, grpc_channel_security_connector **sc) {
-  tsi_result result = TSI_OK;
-  grpc_httpcli_ssl_channel_security_connector *c;
-
-  if (secure_peer_name != NULL && pem_root_certs == NULL) {
-    gpr_log(GPR_ERROR,
-            "Cannot assert a secure peer name without a trust root.");
-    return GRPC_SECURITY_ERROR;
-  }
-
-  c = gpr_malloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
-  memset(c, 0, sizeof(grpc_httpcli_ssl_channel_security_connector));
-
-  gpr_ref_init(&c->base.base.refcount, 1);
-  c->base.base.vtable = &httpcli_ssl_vtable;
-  if (secure_peer_name != NULL) {
-    c->secure_peer_name = gpr_strdup(secure_peer_name);
-  }
-  result = tsi_create_ssl_client_handshaker_factory(
-      NULL, 0, NULL, 0, pem_root_certs, pem_root_certs_size, NULL, NULL, NULL,
-      0, &c->handshaker_factory);
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
-            tsi_result_to_string(result));
-    httpcli_ssl_destroy(&c->base.base);
-    *sc = NULL;
-    return GRPC_SECURITY_ERROR;
-  }
-  c->base.do_handshake = httpcli_ssl_do_handshake;
-  *sc = &c->base;
-  return GRPC_SECURITY_OK;
-}
-
-/* handshaker */
-
-typedef struct {
-  void (*func)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint);
-  void *arg;
-} on_done_closure;
-
-static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
-                                           grpc_security_status status,
-                                           grpc_endpoint *secure_endpoint,
-                                           grpc_auth_context *auth_context) {
-  on_done_closure *c = rp;
-  if (status != GRPC_SECURITY_OK) {
-    gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
-    c->func(exec_ctx, c->arg, NULL);
-  } else {
-    c->func(exec_ctx, c->arg, secure_endpoint);
-  }
-  gpr_free(c);
-}
-
-static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
-                          grpc_endpoint *tcp, const char *host,
-                          void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
-                                          grpc_endpoint *endpoint)) {
-  grpc_channel_security_connector *sc = NULL;
-  const unsigned char *pem_root_certs = NULL;
-  on_done_closure *c = gpr_malloc(sizeof(*c));
-  size_t 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.");
-    on_done(exec_ctx, arg, NULL);
-    gpr_free(c);
-    return;
-  }
-  c->func = on_done;
-  c->arg = arg;
-  GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
-                 pem_root_certs, pem_root_certs_size, host, &sc) ==
-             GRPC_SECURITY_OK);
-  grpc_channel_security_connector_do_handshake(
-      exec_ctx, sc, tcp, on_secure_transport_setup_done, c);
-  GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
-}
-
-const grpc_httpcli_handshaker grpc_httpcli_ssl = {"https", ssl_handshake};
diff --git a/src/core/httpcli/parser.c b/src/core/httpcli/parser.c
deleted file mode 100644
index c314f02..0000000
--- a/src/core/httpcli/parser.c
+++ /dev/null
@@ -1,211 +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/httpcli/parser.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-static int handle_response_line(grpc_httpcli_parser *parser) {
-  uint8_t *beg = parser->cur_line;
-  uint8_t *cur = beg;
-  uint8_t *end = beg + parser->cur_line_length;
-
-  if (cur == end || *cur++ != 'H') goto error;
-  if (cur == end || *cur++ != 'T') goto error;
-  if (cur == end || *cur++ != 'T') goto error;
-  if (cur == end || *cur++ != 'P') goto error;
-  if (cur == end || *cur++ != '/') goto error;
-  if (cur == end || *cur++ != '1') goto error;
-  if (cur == end || *cur++ != '.') goto error;
-  if (cur == end || *cur < '0' || *cur++ > '1') goto error;
-  if (cur == end || *cur++ != ' ') goto error;
-  if (cur == end || *cur < '1' || *cur++ > '9') goto error;
-  if (cur == end || *cur < '0' || *cur++ > '9') goto error;
-  if (cur == end || *cur < '0' || *cur++ > '9') goto error;
-  parser->r.status =
-      (cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0');
-  if (cur == end || *cur++ != ' ') goto error;
-
-  /* we don't really care about the status code message */
-
-  return 1;
-
-error:
-  gpr_log(GPR_ERROR, "Failed parsing response line");
-  return 0;
-}
-
-static char *buf2str(void *buffer, size_t length) {
-  char *out = gpr_malloc(length + 1);
-  memcpy(out, buffer, length);
-  out[length] = 0;
-  return out;
-}
-
-static int add_header(grpc_httpcli_parser *parser) {
-  uint8_t *beg = parser->cur_line;
-  uint8_t *cur = beg;
-  uint8_t *end = beg + parser->cur_line_length;
-  grpc_httpcli_header hdr = {NULL, NULL};
-
-  GPR_ASSERT(cur != end);
-
-  if (*cur == ' ' || *cur == '\t') {
-    gpr_log(GPR_ERROR, "Continued header lines not supported yet");
-    goto error;
-  }
-
-  while (cur != end && *cur != ':') {
-    cur++;
-  }
-  if (cur == end) {
-    gpr_log(GPR_ERROR, "Didn't find ':' in header string");
-    goto error;
-  }
-  GPR_ASSERT(cur >= beg);
-  hdr.key = buf2str(beg, (size_t)(cur - beg));
-  cur++; /* skip : */
-
-  while (cur != end && (*cur == ' ' || *cur == '\t')) {
-    cur++;
-  }
-  GPR_ASSERT(end - cur >= 2);
-  hdr.value = buf2str(cur, (size_t)(end - cur) - 2);
-
-  if (parser->r.hdr_count == parser->hdr_capacity) {
-    parser->hdr_capacity =
-        GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2);
-    parser->r.hdrs = gpr_realloc(
-        parser->r.hdrs, parser->hdr_capacity * sizeof(*parser->r.hdrs));
-  }
-  parser->r.hdrs[parser->r.hdr_count++] = hdr;
-  return 1;
-
-error:
-  gpr_free(hdr.key);
-  gpr_free(hdr.value);
-  return 0;
-}
-
-static int finish_line(grpc_httpcli_parser *parser) {
-  switch (parser->state) {
-    case GRPC_HTTPCLI_INITIAL_RESPONSE:
-      if (!handle_response_line(parser)) {
-        return 0;
-      }
-      parser->state = GRPC_HTTPCLI_HEADERS;
-      break;
-    case GRPC_HTTPCLI_HEADERS:
-      if (parser->cur_line_length == 2) {
-        parser->state = GRPC_HTTPCLI_BODY;
-        break;
-      }
-      if (!add_header(parser)) {
-        return 0;
-      }
-      break;
-    case GRPC_HTTPCLI_BODY:
-      GPR_UNREACHABLE_CODE(return 0);
-  }
-
-  parser->cur_line_length = 0;
-  return 1;
-}
-
-static int addbyte(grpc_httpcli_parser *parser, uint8_t byte) {
-  switch (parser->state) {
-    case GRPC_HTTPCLI_INITIAL_RESPONSE:
-    case GRPC_HTTPCLI_HEADERS:
-      if (parser->cur_line_length >= GRPC_HTTPCLI_MAX_HEADER_LENGTH) {
-        gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded",
-                GRPC_HTTPCLI_MAX_HEADER_LENGTH);
-        return 0;
-      }
-      parser->cur_line[parser->cur_line_length] = byte;
-      parser->cur_line_length++;
-      if (parser->cur_line_length >= 2 &&
-          parser->cur_line[parser->cur_line_length - 2] == '\r' &&
-          parser->cur_line[parser->cur_line_length - 1] == '\n') {
-        return finish_line(parser);
-      } else {
-        return 1;
-      }
-      GPR_UNREACHABLE_CODE(return 0);
-    case GRPC_HTTPCLI_BODY:
-      if (parser->r.body_length == parser->body_capacity) {
-        parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2);
-        parser->r.body =
-            gpr_realloc((void *)parser->r.body, parser->body_capacity);
-      }
-      parser->r.body[parser->r.body_length] = (char)byte;
-      parser->r.body_length++;
-      return 1;
-  }
-  GPR_UNREACHABLE_CODE(return 0);
-}
-
-void grpc_httpcli_parser_init(grpc_httpcli_parser *parser) {
-  memset(parser, 0, sizeof(*parser));
-  parser->state = GRPC_HTTPCLI_INITIAL_RESPONSE;
-  parser->r.status = 500;
-}
-
-void grpc_httpcli_parser_destroy(grpc_httpcli_parser *parser) {
-  size_t i;
-  gpr_free(parser->r.body);
-  for (i = 0; i < parser->r.hdr_count; i++) {
-    gpr_free(parser->r.hdrs[i].key);
-    gpr_free(parser->r.hdrs[i].value);
-  }
-  gpr_free(parser->r.hdrs);
-}
-
-int grpc_httpcli_parser_parse(grpc_httpcli_parser *parser, gpr_slice slice) {
-  size_t i;
-
-  for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) {
-    if (!addbyte(parser, GPR_SLICE_START_PTR(slice)[i])) {
-      return 0;
-    }
-  }
-
-  return 1;
-}
-
-int grpc_httpcli_parser_eof(grpc_httpcli_parser *parser) {
-  return parser->state == GRPC_HTTPCLI_BODY;
-}
diff --git a/src/core/httpcli/parser.h b/src/core/httpcli/parser.h
deleted file mode 100644
index cd4a737..0000000
--- a/src/core/httpcli/parser.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_HTTPCLI_PARSER_H
-#define GRPC_CORE_HTTPCLI_PARSER_H
-
-#include "src/core/httpcli/httpcli.h"
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice.h>
-
-typedef enum {
-  GRPC_HTTPCLI_INITIAL_RESPONSE,
-  GRPC_HTTPCLI_HEADERS,
-  GRPC_HTTPCLI_BODY
-} grpc_httpcli_parser_state;
-
-typedef struct {
-  grpc_httpcli_parser_state state;
-
-  grpc_httpcli_response r;
-  size_t body_capacity;
-  size_t hdr_capacity;
-
-  uint8_t cur_line[GRPC_HTTPCLI_MAX_HEADER_LENGTH];
-  size_t cur_line_length;
-} grpc_httpcli_parser;
-
-void grpc_httpcli_parser_init(grpc_httpcli_parser* parser);
-void grpc_httpcli_parser_destroy(grpc_httpcli_parser* parser);
-
-int grpc_httpcli_parser_parse(grpc_httpcli_parser* parser, gpr_slice slice);
-int grpc_httpcli_parser_eof(grpc_httpcli_parser* parser);
-
-#endif /* GRPC_CORE_HTTPCLI_PARSER_H */
diff --git a/src/core/iomgr/closure.c b/src/core/iomgr/closure.c
deleted file mode 100644
index 3a96f73..0000000
--- a/src/core/iomgr/closure.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *
- * 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/iomgr/closure.h"
-
-#include <grpc/support/alloc.h>
-
-void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
-                       void *cb_arg) {
-  closure->cb = cb;
-  closure->cb_arg = cb_arg;
-  closure->final_data = 0;
-}
-
-void grpc_closure_list_add(grpc_closure_list *closure_list,
-                           grpc_closure *closure, bool success) {
-  if (closure == NULL) return;
-  closure->final_data = (success != 0);
-  if (closure_list->head == NULL) {
-    closure_list->head = closure;
-  } else {
-    closure_list->tail->final_data |= (uintptr_t)closure;
-  }
-  closure_list->tail = closure;
-}
-
-bool grpc_closure_list_empty(grpc_closure_list closure_list) {
-  return closure_list.head == NULL;
-}
-
-void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst) {
-  if (src->head == NULL) {
-    return;
-  }
-  if (dst->head == NULL) {
-    *dst = *src;
-  } else {
-    dst->tail->final_data |= (uintptr_t)src->head;
-    dst->tail = src->tail;
-  }
-  src->head = src->tail = NULL;
-}
-
-typedef struct {
-  grpc_iomgr_cb_func cb;
-  void *cb_arg;
-  grpc_closure wrapper;
-} wrapped_closure;
-
-static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  wrapped_closure *wc = arg;
-  grpc_iomgr_cb_func cb = wc->cb;
-  void *cb_arg = wc->cb_arg;
-  gpr_free(wc);
-  cb(exec_ctx, cb_arg, success);
-}
-
-grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg) {
-  wrapped_closure *wc = gpr_malloc(sizeof(*wc));
-  wc->cb = cb;
-  wc->cb_arg = cb_arg;
-  grpc_closure_init(&wc->wrapper, closure_wrapper, wc);
-  return &wc->wrapper;
-}
-
-grpc_closure *grpc_closure_next(grpc_closure *closure) {
-  return (grpc_closure *)(closure->final_data & ~(uintptr_t)1);
-}
diff --git a/src/core/iomgr/closure.h b/src/core/iomgr/closure.h
deleted file mode 100644
index d5e1f45..0000000
--- a/src/core/iomgr/closure.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_CLOSURE_H
-#define GRPC_CORE_IOMGR_CLOSURE_H
-
-#include <grpc/support/port_platform.h>
-#include <stdbool.h>
-
-struct grpc_closure;
-typedef struct grpc_closure grpc_closure;
-
-/* forward declaration for exec_ctx.h */
-struct grpc_exec_ctx;
-typedef struct grpc_exec_ctx grpc_exec_ctx;
-
-typedef struct grpc_closure_list {
-  grpc_closure *head;
-  grpc_closure *tail;
-} grpc_closure_list;
-
-/** gRPC Callback definition.
- *
- * \param arg Arbitrary input.
- * \param success An indication on the state of the iomgr. On false, cleanup
- * actions should be taken (eg, shutdown). */
-typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg,
-                                   bool success);
-
-/** A closure over a grpc_iomgr_cb_func. */
-struct grpc_closure {
-  /** Bound callback. */
-  grpc_iomgr_cb_func cb;
-
-  /** Arguments to be passed to "cb". */
-  void *cb_arg;
-
-  /** Once enqueued, contains in the lower bit the success of the closure,
-      and in the upper bits the pointer to the next closure in the list.
-      Before enqueing for execution, this is usable for scratch data. */
-  uintptr_t final_data;
-};
-
-/** Initializes \a closure with \a cb and \a cb_arg. */
-void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
-                       void *cb_arg);
-
-/* Create a heap allocated closure: try to avoid except for very rare events */
-grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg);
-
-#define GRPC_CLOSURE_LIST_INIT \
-  { NULL, NULL }
-
-/** add \a closure to the end of \a list and set \a closure's success to \a
- * success */
-void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure,
-                           bool success);
-
-/** append all closures from \a src to \a dst and empty \a src. */
-void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst);
-
-/** return whether \a list is empty. */
-bool grpc_closure_list_empty(grpc_closure_list list);
-
-/** return the next pointer for a queued closure list */
-grpc_closure *grpc_closure_next(grpc_closure *closure);
-
-#endif /* GRPC_CORE_IOMGR_CLOSURE_H */
diff --git a/src/core/iomgr/endpoint.c b/src/core/iomgr/endpoint.c
deleted file mode 100644
index bd64707..0000000
--- a/src/core/iomgr/endpoint.c
+++ /dev/null
@@ -1,67 +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/iomgr/endpoint.h"
-
-void grpc_endpoint_read(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
-                        gpr_slice_buffer* slices, grpc_closure* cb) {
-  ep->vtable->read(exec_ctx, ep, slices, cb);
-}
-
-void grpc_endpoint_write(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
-                         gpr_slice_buffer* slices, grpc_closure* cb) {
-  ep->vtable->write(exec_ctx, ep, slices, cb);
-}
-
-void grpc_endpoint_add_to_pollset(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
-                                  grpc_pollset* pollset) {
-  ep->vtable->add_to_pollset(exec_ctx, ep, pollset);
-}
-
-void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx,
-                                      grpc_endpoint* ep,
-                                      grpc_pollset_set* pollset_set) {
-  ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set);
-}
-
-void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
-  ep->vtable->shutdown(exec_ctx, ep);
-}
-
-void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
-  ep->vtable->destroy(exec_ctx, ep);
-}
-
-char* grpc_endpoint_get_peer(grpc_endpoint* ep) {
-  return ep->vtable->get_peer(ep);
-}
diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h
deleted file mode 100644
index 788f3ac..0000000
--- a/src/core/iomgr/endpoint.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_ENDPOINT_H
-#define GRPC_CORE_IOMGR_ENDPOINT_H
-
-#include "src/core/iomgr/pollset.h"
-#include "src/core/iomgr/pollset_set.h"
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/time.h>
-
-/* An endpoint caps a streaming channel between two communicating processes.
-   Examples may be: a tcp socket, <stdin+stdout>, or some shared memory. */
-
-typedef struct grpc_endpoint grpc_endpoint;
-typedef struct grpc_endpoint_vtable grpc_endpoint_vtable;
-
-struct grpc_endpoint_vtable {
-  void (*read)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-               gpr_slice_buffer *slices, grpc_closure *cb);
-  void (*write)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                gpr_slice_buffer *slices, grpc_closure *cb);
-  void (*add_to_pollset)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                         grpc_pollset *pollset);
-  void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                             grpc_pollset_set *pollset);
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
-  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
-  char *(*get_peer)(grpc_endpoint *ep);
-};
-
-/* When data is available on the connection, calls the callback with slices.
-   Callback success indicates that the endpoint can accept more reads, failure
-   indicates the endpoint is closed.
-   Valid slices may be placed into \a slices even on callback success == 0. */
-void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                        gpr_slice_buffer *slices, grpc_closure *cb);
-
-char *grpc_endpoint_get_peer(grpc_endpoint *ep);
-
-/* Write slices out to the socket.
-
-   If the connection is ready for more data after the end of the call, it
-   returns GRPC_ENDPOINT_DONE.
-   Otherwise it returns GRPC_ENDPOINT_PENDING and calls cb when the
-   connection is ready for more data.
-   \a slices may be mutated at will by the endpoint until cb is called.
-   No guarantee is made to the content of slices after a write EXCEPT that
-   it is a valid slice buffer.
-   */
-void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                         gpr_slice_buffer *slices, grpc_closure *cb);
-
-/* Causes any pending read/write callbacks to run immediately with
-   success==0 */
-void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
-void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
-
-/* Add an endpoint to a pollset, so that when the pollset is polled, events from
-   this endpoint are considered */
-void grpc_endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                                  grpc_pollset *pollset);
-void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx,
-                                      grpc_endpoint *ep,
-                                      grpc_pollset_set *pollset_set);
-
-struct grpc_endpoint {
-  const grpc_endpoint_vtable *vtable;
-};
-
-#endif /* GRPC_CORE_IOMGR_ENDPOINT_H */
diff --git a/src/core/iomgr/endpoint_pair.h b/src/core/iomgr/endpoint_pair.h
deleted file mode 100644
index 59015d8..0000000
--- a/src/core/iomgr/endpoint_pair.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_ENDPOINT_PAIR_H
-#define GRPC_CORE_IOMGR_ENDPOINT_PAIR_H
-
-#include "src/core/iomgr/endpoint.h"
-
-typedef struct {
-  grpc_endpoint *client;
-  grpc_endpoint *server;
-} grpc_endpoint_pair;
-
-grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
-                                                   size_t read_slice_size);
-
-#endif /* GRPC_CORE_IOMGR_ENDPOINT_PAIR_H */
diff --git a/src/core/iomgr/endpoint_pair_posix.c b/src/core/iomgr/endpoint_pair_posix.c
deleted file mode 100644
index 56f6f14..0000000
--- a/src/core/iomgr/endpoint_pair_posix.c
+++ /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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/iomgr/socket_utils_posix.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include "src/core/iomgr/tcp_posix.h"
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-static void create_sockets(int sv[2]) {
-  int flags;
-  GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
-  flags = fcntl(sv[0], F_GETFL, 0);
-  GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
-  flags = fcntl(sv[1], F_GETFL, 0);
-  GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
-  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]));
-  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]));
-}
-
-grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
-                                                   size_t read_slice_size) {
-  int sv[2];
-  grpc_endpoint_pair p;
-  char *final_name;
-  create_sockets(sv);
-
-  gpr_asprintf(&final_name, "%s:client", name);
-  p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size,
-                             "socketpair-server");
-  gpr_free(final_name);
-  gpr_asprintf(&final_name, "%s:server", name);
-  p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size,
-                             "socketpair-client");
-  gpr_free(final_name);
-  return p;
-}
-
-#endif
diff --git a/src/core/iomgr/endpoint_pair_windows.c b/src/core/iomgr/endpoint_pair_windows.c
deleted file mode 100644
index db9d092..0000000
--- a/src/core/iomgr/endpoint_pair_windows.c
+++ /dev/null
@@ -1,97 +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_WINSOCK_SOCKET
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/iomgr/endpoint_pair.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "src/core/iomgr/tcp_windows.h"
-#include "src/core/iomgr/socket_windows.h"
-#include <grpc/support/log.h>
-
-static void create_sockets(SOCKET sv[2]) {
-  SOCKET svr_sock = INVALID_SOCKET;
-  SOCKET lst_sock = INVALID_SOCKET;
-  SOCKET cli_sock = INVALID_SOCKET;
-  SOCKADDR_IN addr;
-  int addr_len = sizeof(addr);
-
-  lst_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
-                       WSA_FLAG_OVERLAPPED);
-  GPR_ASSERT(lst_sock != INVALID_SOCKET);
-
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-  addr.sin_family = AF_INET;
-  GPR_ASSERT(bind(lst_sock, (struct sockaddr *)&addr, sizeof(addr)) !=
-             SOCKET_ERROR);
-  GPR_ASSERT(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR);
-  GPR_ASSERT(getsockname(lst_sock, (struct sockaddr *)&addr, &addr_len) !=
-             SOCKET_ERROR);
-
-  cli_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
-                       WSA_FLAG_OVERLAPPED);
-  GPR_ASSERT(cli_sock != INVALID_SOCKET);
-
-  GPR_ASSERT(WSAConnect(cli_sock, (struct sockaddr *)&addr, addr_len, NULL,
-                        NULL, NULL, NULL) == 0);
-  svr_sock = accept(lst_sock, (struct sockaddr *)&addr, &addr_len);
-  GPR_ASSERT(svr_sock != INVALID_SOCKET);
-
-  closesocket(lst_sock);
-  grpc_tcp_prepare_socket(cli_sock);
-  grpc_tcp_prepare_socket(svr_sock);
-
-  sv[1] = cli_sock;
-  sv[0] = svr_sock;
-}
-
-grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
-                                                   size_t read_slice_size) {
-  SOCKET sv[2];
-  grpc_endpoint_pair p;
-  create_sockets(sv);
-  p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"),
-                             "endpoint:server");
-  p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"),
-                             "endpoint:client");
-  return p;
-}
-
-#endif
diff --git a/src/core/iomgr/exec_ctx.c b/src/core/iomgr/exec_ctx.c
deleted file mode 100644
index 893fe45..0000000
--- a/src/core/iomgr/exec_ctx.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *
- * 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/iomgr/exec_ctx.h"
-
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-
-#include "src/core/profiling/timers.h"
-
-#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
-bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
-  bool did_something = 0;
-  GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
-  while (!grpc_closure_list_empty(exec_ctx->closure_list)) {
-    grpc_closure *c = exec_ctx->closure_list.head;
-    exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
-    while (c != NULL) {
-      bool success = (bool)(c->final_data & 1);
-      grpc_closure *next = (grpc_closure *)(c->final_data & ~(uintptr_t)1);
-      did_something = true;
-      GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
-      c->cb(exec_ctx, c->cb_arg, success);
-      GPR_TIMER_END("grpc_exec_ctx_flush.cb", 0);
-      c = next;
-    }
-  }
-  GPR_TIMER_END("grpc_exec_ctx_flush", 0);
-  return did_something;
-}
-
-void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
-  grpc_exec_ctx_flush(exec_ctx);
-}
-
-void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
-                           bool success,
-                           grpc_workqueue *offload_target_or_null) {
-  GPR_ASSERT(offload_target_or_null == NULL);
-  grpc_closure_list_add(&exec_ctx->closure_list, closure, success);
-}
-
-void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
-                                grpc_closure_list *list,
-                                grpc_workqueue *offload_target_or_null) {
-  GPR_ASSERT(offload_target_or_null == NULL);
-  grpc_closure_list_move(list, &exec_ctx->closure_list);
-}
-
-void grpc_exec_ctx_global_init(void) {}
-void grpc_exec_ctx_global_shutdown(void) {}
-#else
-static gpr_mu g_mu;
-static gpr_cv g_cv;
-static int g_threads = 0;
-
-static void run_closure(void *arg) {
-  grpc_closure *closure = arg;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  closure->cb(&exec_ctx, closure->cb_arg, (closure->final_data & 1) != 0);
-  grpc_exec_ctx_finish(&exec_ctx);
-  gpr_mu_lock(&g_mu);
-  if (--g_threads == 0) {
-    gpr_cv_signal(&g_cv);
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-static void start_closure(grpc_closure *closure) {
-  gpr_thd_id id;
-  gpr_mu_lock(&g_mu);
-  g_threads++;
-  gpr_mu_unlock(&g_mu);
-  gpr_thd_new(&id, run_closure, closure, NULL);
-}
-
-bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { return false; }
-
-void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {}
-
-void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
-                           bool success,
-                           grpc_workqueue *offload_target_or_null) {
-  GPR_ASSERT(offload_target_or_null == NULL);
-  if (closure == NULL) return;
-  closure->final_data = success;
-  start_closure(closure);
-}
-
-void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
-                                grpc_closure_list *list,
-                                grpc_workqueue *offload_target_or_null) {
-  GPR_ASSERT(offload_target_or_null == NULL);
-  if (list == NULL) return;
-  grpc_closure *p = list->head;
-  while (p) {
-    grpc_closure *start = p;
-    p = grpc_closure_next(start);
-    start_closure(start);
-  }
-  grpc_closure_list r = GRPC_CLOSURE_LIST_INIT;
-  *list = r;
-}
-
-void grpc_exec_ctx_global_init(void) {
-  gpr_mu_init(&g_mu);
-  gpr_cv_init(&g_cv);
-}
-
-void grpc_exec_ctx_global_shutdown(void) {
-  gpr_mu_lock(&g_mu);
-  while (g_threads != 0) {
-    gpr_cv_wait(&g_cv, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
-  }
-  gpr_mu_unlock(&g_mu);
-
-  gpr_mu_destroy(&g_mu);
-  gpr_cv_destroy(&g_cv);
-}
-#endif
diff --git a/src/core/iomgr/exec_ctx.h b/src/core/iomgr/exec_ctx.h
deleted file mode 100644
index 07b54a0..0000000
--- a/src/core/iomgr/exec_ctx.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_EXEC_CTX_H
-#define GRPC_CORE_IOMGR_EXEC_CTX_H
-
-#include "src/core/iomgr/closure.h"
-
-/* #define GRPC_EXECUTION_CONTEXT_SANITIZER 1 */
-
-/** A workqueue represents a list of work to be executed asynchronously.
-    Forward declared here to avoid a circular dependency with workqueue.h. */
-struct grpc_workqueue;
-typedef struct grpc_workqueue grpc_workqueue;
-
-#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
-/** Execution context.
- *  A bag of data that collects information along a callstack.
- *  Generally created at public API entry points, and passed down as
- *  pointer to child functions that manipulate it.
- *
- *  Specific responsibilities (this may grow in the future):
- *  - track a list of work that needs to be delayed until the top of the
- *    call stack (this provides a convenient mechanism to run callbacks
- *    without worrying about locking issues)
- *
- *  CONVENTIONS:
- *  Instance of this must ALWAYS be constructed on the stack, never
- *  heap allocated. Instances and pointers to them must always be called
- *  exec_ctx. Instances are always passed as the first argument
- *  to a function that takes it, and always as a pointer (grpc_exec_ctx
- *  is never copied).
- */
-struct grpc_exec_ctx {
-  grpc_closure_list closure_list;
-};
-
-#define GRPC_EXEC_CTX_INIT \
-  { GRPC_CLOSURE_LIST_INIT }
-#else
-struct grpc_exec_ctx {
-  int unused;
-};
-#define GRPC_EXEC_CTX_INIT \
-  { 0 }
-#endif
-
-/** Flush any work that has been enqueued onto this grpc_exec_ctx.
- *  Caller must guarantee that no interfering locks are held.
- *  Returns true if work was performed, false otherwise. */
-bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx);
-/** Finish any pending work for a grpc_exec_ctx. Must be called before
- *  the instance is destroyed, or work may be lost. */
-void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx);
-/** Add a closure to be executed at the next flush/finish point */
-void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
-                           bool success,
-                           grpc_workqueue *offload_target_or_null);
-/** Add a list of closures to be executed at the next flush/finish point.
- *  Leaves \a list empty. */
-void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
-                                grpc_closure_list *list,
-                                grpc_workqueue *offload_target_or_null);
-
-void grpc_exec_ctx_global_init(void);
-void grpc_exec_ctx_global_shutdown(void);
-
-#endif /* GRPC_CORE_IOMGR_EXEC_CTX_H */
diff --git a/src/core/iomgr/executor.c b/src/core/iomgr/executor.c
deleted file mode 100644
index f22d8f3..0000000
--- a/src/core/iomgr/executor.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *
- * 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/iomgr/executor.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include "src/core/iomgr/exec_ctx.h"
-
-typedef struct grpc_executor_data {
-  int busy;          /**< is the thread currently running? */
-  int shutting_down; /**< has \a grpc_shutdown() been invoked? */
-  int pending_join;  /**< has the thread finished but not been joined? */
-  grpc_closure_list closures; /**< collection of pending work */
-  gpr_thd_id tid; /**< thread id of the thread, only valid if \a busy or \a
-                     pending_join are true */
-  gpr_thd_options options;
-  gpr_mu mu;
-} grpc_executor;
-
-static grpc_executor g_executor;
-
-void grpc_executor_init() {
-  memset(&g_executor, 0, sizeof(grpc_executor));
-  gpr_mu_init(&g_executor.mu);
-  g_executor.options = gpr_thd_options_default();
-  gpr_thd_options_set_joinable(&g_executor.options);
-}
-
-/* thread body */
-static void closure_exec_thread_func(void *ignored) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  while (1) {
-    gpr_mu_lock(&g_executor.mu);
-    if (g_executor.shutting_down != 0) {
-      gpr_mu_unlock(&g_executor.mu);
-      break;
-    }
-    if (grpc_closure_list_empty(g_executor.closures)) {
-      /* no more work, time to die */
-      GPR_ASSERT(g_executor.busy == 1);
-      g_executor.busy = 0;
-      gpr_mu_unlock(&g_executor.mu);
-      break;
-    } else {
-      grpc_exec_ctx_enqueue_list(&exec_ctx, &g_executor.closures, NULL);
-    }
-    gpr_mu_unlock(&g_executor.mu);
-    grpc_exec_ctx_flush(&exec_ctx);
-  }
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-/* Spawn the thread if new work has arrived a no thread is up */
-static void maybe_spawn_locked() {
-  if (grpc_closure_list_empty(g_executor.closures) == 1) {
-    return;
-  }
-  if (g_executor.shutting_down == 1) {
-    return;
-  }
-
-  if (g_executor.busy != 0) {
-    /* Thread still working. New work will be picked up by already running
-     * thread. Not spawning anything. */
-    return;
-  } else if (g_executor.pending_join != 0) {
-    /* Pickup the remains of the previous incarnations of the thread. */
-    gpr_thd_join(g_executor.tid);
-    g_executor.pending_join = 0;
-  }
-
-  /* All previous instances of the thread should have been joined at this point.
-   * Spawn time! */
-  g_executor.busy = 1;
-  gpr_thd_new(&g_executor.tid, closure_exec_thread_func, NULL,
-              &g_executor.options);
-  g_executor.pending_join = 1;
-}
-
-void grpc_executor_enqueue(grpc_closure *closure, bool success) {
-  gpr_mu_lock(&g_executor.mu);
-  if (g_executor.shutting_down == 0) {
-    grpc_closure_list_add(&g_executor.closures, closure, success);
-    maybe_spawn_locked();
-  }
-  gpr_mu_unlock(&g_executor.mu);
-}
-
-void grpc_executor_shutdown() {
-  int pending_join;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  gpr_mu_lock(&g_executor.mu);
-  pending_join = g_executor.pending_join;
-  g_executor.shutting_down = 1;
-  gpr_mu_unlock(&g_executor.mu);
-  /* we can release the lock at this point despite the access to the closure
-   * list below because we aren't accepting new work */
-
-  /* Execute pending callbacks, some may be performing cleanups */
-  grpc_exec_ctx_enqueue_list(&exec_ctx, &g_executor.closures, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
-  GPR_ASSERT(grpc_closure_list_empty(g_executor.closures));
-  if (pending_join) {
-    gpr_thd_join(g_executor.tid);
-  }
-  gpr_mu_destroy(&g_executor.mu);
-}
diff --git a/src/core/iomgr/executor.h b/src/core/iomgr/executor.h
deleted file mode 100644
index f66b356..0000000
--- a/src/core/iomgr/executor.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_EXECUTOR_H
-#define GRPC_CORE_IOMGR_EXECUTOR_H
-
-#include "src/core/iomgr/closure.h"
-
-/** Initialize the global executor.
- *
- * This mechanism is meant to outsource work (grpc_closure instances) to a
- * thread, for those cases where blocking isn't an option but there isn't a
- * non-blocking solution available. */
-void grpc_executor_init();
-
-/** Enqueue \a closure for its eventual execution of \a f(arg) on a separate
- * thread */
-void grpc_executor_enqueue(grpc_closure *closure, bool success);
-
-/** Shutdown the executor, running all pending work as part of the call */
-void grpc_executor_shutdown();
-
-#endif /* GRPC_CORE_IOMGR_EXECUTOR_H */
diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c
deleted file mode 100644
index 3edafa0..0000000
--- a/src/core/iomgr/fd_posix.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/fd_posix.h"
-
-#include <assert.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/useful.h>
-
-#include "src/core/iomgr/pollset_posix.h"
-
-#define CLOSURE_NOT_READY ((grpc_closure *)0)
-#define CLOSURE_READY ((grpc_closure *)1)
-
-/* 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) {
-  // Note that this function must be called after a release store (or
-  // full-barrier operation) on refst so that prior actions on the fd are
-  // ordered before the fd becomes visible to the freelist
-  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);
-  }
-
-  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;
-  // The last operation on r before returning it should be a release-store
-  // so that all the above fields are globally visible before the value of
-  // r could escape to another thread. Our refcount itself needs a release-store
-  // so use this
-  gpr_atm_rel_store(&r->refst, 1);
-  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);
-  }
-}
-
-void grpc_fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
-
-void grpc_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);
-}
-
-grpc_fd *grpc_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;
-}
-
-int grpc_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);
-  grpc_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 {
-    grpc_remove_fd_from_all_epoll_sets(fd->fd);
-  }
-  grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL);
-}
-
-int grpc_fd_wrapped_fd(grpc_fd *fd) {
-  if (fd->released || fd->closed) {
-    return -1;
-  } else {
-    return fd->fd;
-  }
-}
-
-void grpc_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
-void grpc_fd_ref(grpc_fd *fd, const char *reason, const char *file, int line) {
-  ref_by(fd, 2, reason, file, line);
-}
-
-void grpc_fd_unref(grpc_fd *fd, const char *reason, const char *file,
-                   int line) {
-  unref_by(fd, 2, reason, file, line);
-}
-#else
-void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
-
-void grpc_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 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);
-}
-
-void grpc_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);
-}
-
-void grpc_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);
-}
-
-void grpc_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);
-}
-
-uint32_t grpc_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;
-}
-
-void grpc_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 (grpc_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");
-}
-
-void grpc_fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  set_ready(exec_ctx, fd, &fd->read_closure);
-}
-
-void grpc_fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  set_ready(exec_ctx, fd, &fd->write_closure);
-}
-
-#endif
diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h
deleted file mode 100644
index a5c8ff1..0000000
--- a/src/core/iomgr/fd_posix.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_FD_POSIX_H
-#define GRPC_CORE_IOMGR_FD_POSIX_H
-
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/pollset.h"
-#include <grpc/support/atm.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-typedef struct grpc_fd grpc_fd;
-
-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;
-};
-
-/* Create a wrapped file descriptor.
-   Requires fd is a non-blocking file descriptor.
-   This takes ownership of closing fd. */
-grpc_fd *grpc_fd_create(int fd, const char *name);
-
-/* Return the wrapped fd, or -1 if it has been released or closed. */
-int grpc_fd_wrapped_fd(grpc_fd *fd);
-
-/* Releases fd to be asynchronously destroyed.
-   on_done is called when the underlying file descriptor is definitely close()d.
-   If on_done is NULL, no callback will be made.
-   If release_fd is not NULL, it's set to fd and fd will not be closed.
-   Requires: *fd initialized; no outstanding notify_on_read or
-   notify_on_write.
-   MUST NOT be called with a pollset lock taken */
-void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
-                    int *release_fd, const char *reason);
-
-/* 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 */
-uint32_t grpc_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 grpc_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. */
-void grpc_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 */
-int grpc_fd_is_orphaned(grpc_fd *fd);
-
-/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */
-void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
-
-/* Register read interest, causing read_cb to be called once when fd becomes
-   readable, on deadline specified by deadline, or on shutdown triggered by
-   grpc_fd_shutdown.
-   read_cb will be called with read_cb_arg when *fd becomes readable.
-   read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable,
-   GRPC_CALLBACK_TIMED_OUT if the call timed out,
-   and CANCELLED if the call was cancelled.
-
-   Requires:This method must not be called before the read_cb for any previous
-   call runs. Edge triggered events are used whenever they are supported by the
-   underlying platform. This means that users must drain fd in read_cb before
-   calling notify_on_read again. Users are also expected to handle spurious
-   events, i.e read_cb is called while nothing can be readable from fd  */
-void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                            grpc_closure *closure);
-
-/* Exactly the same semantics as above, except based on writable events.  */
-void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                             grpc_closure *closure);
-
-/* Notification from the poller to an fd that it has become readable or
-   writable.
-   If allow_synchronous_callback is 1, allow running the fd callback inline
-   in this callstack, otherwise register an asynchronous callback and return */
-void grpc_fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
-void grpc_fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
-
-/* Reference counting for fds */
-/*#define GRPC_FD_REF_COUNT_DEBUG*/
-#ifdef GRPC_FD_REF_COUNT_DEBUG
-void grpc_fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
-void grpc_fd_unref(grpc_fd *fd, const char *reason, const char *file, int line);
-#define GRPC_FD_REF(fd, reason) grpc_fd_ref(fd, reason, __FILE__, __LINE__)
-#define GRPC_FD_UNREF(fd, reason) grpc_fd_unref(fd, reason, __FILE__, __LINE__)
-#else
-void grpc_fd_ref(grpc_fd *fd);
-void grpc_fd_unref(grpc_fd *fd);
-#define GRPC_FD_REF(fd, reason) grpc_fd_ref(fd)
-#define GRPC_FD_UNREF(fd, reason) grpc_fd_unref(fd)
-#endif
-
-void grpc_fd_global_init(void);
-void grpc_fd_global_shutdown(void);
-
-#endif /* GRPC_CORE_IOMGR_FD_POSIX_H */
diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c
deleted file mode 100644
index fa87e52..0000000
--- a/src/core/iomgr/iocp_windows.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WINSOCK_SOCKET
-
-#include <winsock2.h>
-
-#include <grpc/support/log.h>
-#include <grpc/support/log_win32.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/thd.h>
-
-#include "src/core/iomgr/timer.h"
-#include "src/core/iomgr/iocp_windows.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/socket_windows.h"
-
-static ULONG g_iocp_kick_token;
-static OVERLAPPED g_iocp_custom_overlap;
-
-static gpr_atm g_custom_events = 0;
-
-static HANDLE g_iocp;
-
-static DWORD 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 INFINITE;
-  }
-  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 (DWORD)gpr_time_to_millis(gpr_time_add(
-      timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
-}
-
-grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
-                                     gpr_timespec deadline) {
-  BOOL success;
-  DWORD bytes = 0;
-  DWORD flags = 0;
-  ULONG_PTR completion_key;
-  LPOVERLAPPED overlapped;
-  grpc_winsocket *socket;
-  grpc_winsocket_callback_info *info;
-  grpc_closure *closure = NULL;
-  success = GetQueuedCompletionStatus(
-      g_iocp, &bytes, &completion_key, &overlapped,
-      deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type)));
-  if (success == 0 && overlapped == NULL) {
-    return GRPC_IOCP_WORK_TIMEOUT;
-  }
-  GPR_ASSERT(completion_key && overlapped);
-  if (overlapped == &g_iocp_custom_overlap) {
-    gpr_atm_full_fetch_add(&g_custom_events, -1);
-    if (completion_key == (ULONG_PTR)&g_iocp_kick_token) {
-      /* We were awoken from a kick. */
-      return GRPC_IOCP_WORK_KICK;
-    }
-    gpr_log(GPR_ERROR, "Unknown custom completion key.");
-    abort();
-  }
-
-  socket = (grpc_winsocket *)completion_key;
-  if (overlapped == &socket->write_info.overlapped) {
-    info = &socket->write_info;
-  } else if (overlapped == &socket->read_info.overlapped) {
-    info = &socket->read_info;
-  } else {
-    gpr_log(GPR_ERROR, "Unknown IOCP operation");
-    abort();
-  }
-  success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
-                                   FALSE, &flags);
-  info->bytes_transfered = bytes;
-  info->wsa_error = success ? 0 : WSAGetLastError();
-  GPR_ASSERT(overlapped == &info->overlapped);
-  GPR_ASSERT(!info->has_pending_iocp);
-  gpr_mu_lock(&socket->state_mu);
-  if (info->closure) {
-    closure = info->closure;
-    info->closure = NULL;
-  } else {
-    info->has_pending_iocp = 1;
-  }
-  gpr_mu_unlock(&socket->state_mu);
-  grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
-  return GRPC_IOCP_WORK_WORK;
-}
-
-void grpc_iocp_init(void) {
-  g_iocp =
-      CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0);
-  GPR_ASSERT(g_iocp);
-}
-
-void grpc_iocp_kick(void) {
-  BOOL success;
-
-  gpr_atm_full_fetch_add(&g_custom_events, 1);
-  success = PostQueuedCompletionStatus(g_iocp, 0, (ULONG_PTR)&g_iocp_kick_token,
-                                       &g_iocp_custom_overlap);
-  GPR_ASSERT(success);
-}
-
-void grpc_iocp_flush(void) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_iocp_work_status work_status;
-
-  do {
-    work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
-  } while (work_status == GRPC_IOCP_WORK_KICK ||
-           grpc_exec_ctx_flush(&exec_ctx));
-}
-
-void grpc_iocp_shutdown(void) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  while (gpr_atm_acq_load(&g_custom_events)) {
-    grpc_iocp_work(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC));
-    grpc_exec_ctx_flush(&exec_ctx);
-  }
-  grpc_exec_ctx_finish(&exec_ctx);
-  GPR_ASSERT(CloseHandle(g_iocp));
-}
-
-void grpc_iocp_add_socket(grpc_winsocket *socket) {
-  HANDLE ret;
-  if (socket->added_to_iocp) return;
-  ret = CreateIoCompletionPort((HANDLE)socket->socket, g_iocp,
-                               (uintptr_t)socket, 0);
-  if (!ret) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "Unable to add socket to iocp: %s", utf8_message);
-    gpr_free(utf8_message);
-    __debugbreak();
-    abort();
-  }
-  socket->added_to_iocp = 1;
-  GPR_ASSERT(ret == g_iocp);
-}
-
-/* Calling notify_on_read or write means either of two things:
-   -) The IOCP already completed in the background, and we need to call
-   the callback now.
-   -) The IOCP hasn't completed yet, and we're queuing it for later. */
-static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx,
-                                  grpc_winsocket *socket, grpc_closure *closure,
-                                  grpc_winsocket_callback_info *info) {
-  GPR_ASSERT(info->closure == NULL);
-  gpr_mu_lock(&socket->state_mu);
-  if (info->has_pending_iocp) {
-    info->has_pending_iocp = 0;
-    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
-  } else {
-    info->closure = closure;
-  }
-  gpr_mu_unlock(&socket->state_mu);
-}
-
-void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
-                                 grpc_winsocket *socket,
-                                 grpc_closure *closure) {
-  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info);
-}
-
-void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
-                                grpc_closure *closure) {
-  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info);
-}
-
-#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/iocp_windows.h b/src/core/iomgr/iocp_windows.h
deleted file mode 100644
index 570b892..0000000
--- a/src/core/iomgr/iocp_windows.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_IOCP_WINDOWS_H
-#define GRPC_CORE_IOMGR_IOCP_WINDOWS_H
-
-#include <grpc/support/sync.h>
-
-#include "src/core/iomgr/socket_windows.h"
-
-typedef enum {
-  GRPC_IOCP_WORK_WORK,
-  GRPC_IOCP_WORK_TIMEOUT,
-  GRPC_IOCP_WORK_KICK
-} grpc_iocp_work_status;
-
-grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
-                                     gpr_timespec deadline);
-void grpc_iocp_init(void);
-void grpc_iocp_kick(void);
-void grpc_iocp_flush(void);
-void grpc_iocp_shutdown(void);
-void grpc_iocp_add_socket(grpc_winsocket *);
-
-void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
-                                 grpc_winsocket *winsocket,
-                                 grpc_closure *closure);
-
-void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx,
-                                grpc_winsocket *winsocket,
-                                grpc_closure *closure);
-
-#endif /* GRPC_CORE_IOMGR_IOCP_WINDOWS_H */
diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c
deleted file mode 100644
index 3ab4430..0000000
--- a/src/core/iomgr/iomgr.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *
- * 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/iomgr/iomgr.h"
-
-#include <stdlib.h>
-#include <string.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/thd.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/iomgr/exec_ctx.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/timer.h"
-#include "src/core/support/env.h"
-#include "src/core/support/string.h"
-
-static gpr_mu g_mu;
-static gpr_cv g_rcv;
-static int g_shutdown;
-static grpc_iomgr_object g_root_object;
-
-void grpc_iomgr_init(void) {
-  g_shutdown = 0;
-  gpr_mu_init(&g_mu);
-  gpr_cv_init(&g_rcv);
-  grpc_exec_ctx_global_init();
-  grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC));
-  g_root_object.next = g_root_object.prev = &g_root_object;
-  g_root_object.name = "root";
-  grpc_iomgr_platform_init();
-  grpc_pollset_global_init();
-}
-
-static size_t count_objects(void) {
-  grpc_iomgr_object *obj;
-  size_t n = 0;
-  for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
-    n++;
-  }
-  return n;
-}
-
-static void dump_objects(const char *kind) {
-  grpc_iomgr_object *obj;
-  for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
-    gpr_log(GPR_DEBUG, "%s OBJECT: %s %p", kind, obj->name, obj);
-  }
-}
-
-void grpc_iomgr_shutdown(void) {
-  gpr_timespec shutdown_deadline = gpr_time_add(
-      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN));
-  gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  grpc_iomgr_platform_flush();
-
-  gpr_mu_lock(&g_mu);
-  g_shutdown = 1;
-  while (g_root_object.next != &g_root_object) {
-    if (gpr_time_cmp(
-            gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time),
-            gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
-      if (g_root_object.next != &g_root_object) {
-        gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed",
-                count_objects());
-      }
-      last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
-    }
-    if (grpc_timer_check(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC),
-                         NULL)) {
-      gpr_mu_unlock(&g_mu);
-      grpc_exec_ctx_flush(&exec_ctx);
-      gpr_mu_lock(&g_mu);
-      continue;
-    }
-    if (g_root_object.next != &g_root_object) {
-      gpr_timespec short_deadline = gpr_time_add(
-          gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN));
-      if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) {
-        if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) {
-          if (g_root_object.next != &g_root_object) {
-            gpr_log(GPR_DEBUG,
-                    "Failed to free %d iomgr objects before shutdown deadline: "
-                    "memory leaks are likely",
-                    count_objects());
-            dump_objects("LEAKED");
-            if (grpc_iomgr_abort_on_leaks()) {
-              abort();
-            }
-          }
-          break;
-        }
-      }
-    }
-  }
-  gpr_mu_unlock(&g_mu);
-
-  grpc_timer_list_shutdown(&exec_ctx);
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  /* ensure all threads have left g_mu */
-  gpr_mu_lock(&g_mu);
-  gpr_mu_unlock(&g_mu);
-
-  grpc_pollset_global_shutdown();
-  grpc_iomgr_platform_shutdown();
-  grpc_exec_ctx_global_shutdown();
-  gpr_mu_destroy(&g_mu);
-  gpr_cv_destroy(&g_rcv);
-}
-
-void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) {
-  obj->name = gpr_strdup(name);
-  gpr_mu_lock(&g_mu);
-  obj->next = &g_root_object;
-  obj->prev = g_root_object.prev;
-  obj->next->prev = obj->prev->next = obj;
-  gpr_mu_unlock(&g_mu);
-}
-
-void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
-  gpr_mu_lock(&g_mu);
-  obj->next->prev = obj->prev;
-  obj->prev->next = obj->next;
-  gpr_cv_signal(&g_rcv);
-  gpr_mu_unlock(&g_mu);
-  gpr_free(obj->name);
-}
-
-bool grpc_iomgr_abort_on_leaks(void) {
-  char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
-  if (env == NULL) return false;
-  static const char *truthy[] = {"yes",  "Yes",  "YES", "true",
-                                 "True", "TRUE", "1"};
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
-    if (0 == strcmp(env, truthy[i])) return true;
-  }
-  return false;
-}
diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h
deleted file mode 100644
index e1237a4..0000000
--- a/src/core/iomgr/iomgr.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_IOMGR_H
-#define GRPC_CORE_IOMGR_IOMGR_H
-
-/** Initializes the iomgr. */
-void grpc_iomgr_init(void);
-
-/** Signals the intention to shutdown the iomgr. */
-void grpc_iomgr_shutdown(void);
-
-#endif /* GRPC_CORE_IOMGR_IOMGR_H */
diff --git a/src/core/iomgr/iomgr_internal.h b/src/core/iomgr/iomgr_internal.h
deleted file mode 100644
index d06b068..0000000
--- a/src/core/iomgr/iomgr_internal.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_IOMGR_INTERNAL_H
-#define GRPC_CORE_IOMGR_IOMGR_INTERNAL_H
-
-#include <stdbool.h>
-
-#include "src/core/iomgr/iomgr.h"
-#include <grpc/support/sync.h>
-
-typedef struct grpc_iomgr_object {
-  char *name;
-  struct grpc_iomgr_object *next;
-  struct grpc_iomgr_object *prev;
-} grpc_iomgr_object;
-
-void grpc_pollset_global_init(void);
-void grpc_pollset_global_shutdown(void);
-
-void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name);
-void grpc_iomgr_unregister_object(grpc_iomgr_object *obj);
-
-void grpc_iomgr_platform_init(void);
-/** flush any globally queued work from iomgr */
-void grpc_iomgr_platform_flush(void);
-/** tear down all platform specific global iomgr structures */
-void grpc_iomgr_platform_shutdown(void);
-
-bool grpc_iomgr_abort_on_leaks(void);
-
-#endif /* GRPC_CORE_IOMGR_IOMGR_INTERNAL_H */
diff --git a/src/core/iomgr/iomgr_posix.c b/src/core/iomgr/iomgr_posix.c
deleted file mode 100644
index fecb7b9..0000000
--- a/src/core/iomgr/iomgr_posix.c
+++ /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.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/iomgr_posix.h"
-#include "src/core/debug/trace.h"
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/tcp_posix.h"
-
-void grpc_iomgr_platform_init(void) {
-  grpc_fd_global_init();
-  grpc_register_tracer("tcp", &grpc_tcp_trace);
-}
-
-void grpc_iomgr_platform_flush(void) {}
-
-void grpc_iomgr_platform_shutdown(void) { grpc_fd_global_shutdown(); }
-
-#endif /* GRPC_POSIX_SOCKET */
diff --git a/src/core/iomgr/iomgr_posix.h b/src/core/iomgr/iomgr_posix.h
deleted file mode 100644
index 698fb6a..0000000
--- a/src/core/iomgr/iomgr_posix.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_IOMGR_POSIX_H
-#define GRPC_CORE_IOMGR_IOMGR_POSIX_H
-
-#include "src/core/iomgr/iomgr_internal.h"
-
-#endif /* GRPC_CORE_IOMGR_IOMGR_POSIX_H */
diff --git a/src/core/iomgr/iomgr_windows.c b/src/core/iomgr/iomgr_windows.c
deleted file mode 100644
index 1477551..0000000
--- a/src/core/iomgr/iomgr_windows.c
+++ /dev/null
@@ -1,73 +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_WINSOCK_SOCKET
-
-#include "src/core/iomgr/sockaddr_win32.h"
-
-#include <grpc/support/log.h>
-
-#include "src/core/iomgr/socket_windows.h"
-#include "src/core/iomgr/iocp_windows.h"
-#include "src/core/iomgr/iomgr.h"
-
-/* Windows' io manager is going to be fully designed using IO completion
-   ports. All of what we're doing here is basically make sure that
-   Windows sockets are initialized in and out. */
-
-static void winsock_init(void) {
-  WSADATA wsaData;
-  int status = WSAStartup(MAKEWORD(2, 0), &wsaData);
-  GPR_ASSERT(status == 0);
-}
-
-static void winsock_shutdown(void) {
-  int status = WSACleanup();
-  GPR_ASSERT(status == 0);
-}
-
-void grpc_iomgr_platform_init(void) {
-  winsock_init();
-  grpc_iocp_init();
-}
-
-void grpc_iomgr_platform_flush(void) { grpc_iocp_flush(); }
-
-void grpc_iomgr_platform_shutdown(void) {
-  grpc_iocp_shutdown();
-  winsock_shutdown();
-}
-
-#endif /* GRPC_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h
deleted file mode 100644
index 9500b1a..0000000
--- a/src/core/iomgr/pollset.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_POLLSET_H
-#define GRPC_CORE_IOMGR_POLLSET_H
-
-#include <grpc/support/port_platform.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-#include "src/core/iomgr/exec_ctx.h"
-
-#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1)
-
-/* A grpc_pollset is a set of file descriptors that a higher level item is
-   interested in. For example:
-    - a server will typically keep a pollset containing all connected channels,
-      so that it can find new calls to service
-    - a completion queue might keep a pollset with an entry for each transport
-      that is servicing a call that it's tracking */
-
-typedef struct grpc_pollset grpc_pollset;
-typedef struct grpc_pollset_worker grpc_pollset_worker;
-
-size_t grpc_pollset_size(void);
-void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
-/* Begin shutting down the pollset, and call closure when done.
- * pollset's mutex must be held */
-void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                           grpc_closure *closure);
-/** Reset the pollset to its initial state (perhaps with some cached objects);
- *  must have been previously shutdown */
-void grpc_pollset_reset(grpc_pollset *pollset);
-void grpc_pollset_destroy(grpc_pollset *pollset);
-
-/* Do some work on a pollset.
-   May involve invoking asynchronous callbacks, or actually polling file
-   descriptors.
-   Requires pollset's mutex locked.
-   May unlock its mutex during its execution.
-
-   worker is a (platform-specific) handle that can be used to wake up
-   from grpc_pollset_work before any events are received and before the timeout
-   has expired. It is both initialized and destroyed by grpc_pollset_work.
-   Initialization of worker is guaranteed to occur BEFORE the
-   pollset's mutex is released for the first time by grpc_pollset_work
-   and it is guaranteed that it will not be released by grpc_pollset_work
-   AFTER worker has been destroyed.
-
-   Tries not to block past deadline.
-   May call grpc_closure_list_run on grpc_closure_list, without holding the
-   pollset
-   lock */
-void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker **worker, gpr_timespec now,
-                       gpr_timespec deadline);
-
-/* Break one polling thread out of polling work for this pollset.
-   If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers.
-   Otherwise, if specific_worker is non-NULL, then kick that worker. */
-void grpc_pollset_kick(grpc_pollset *pollset,
-                       grpc_pollset_worker *specific_worker);
-
-#endif /* GRPC_CORE_IOMGR_POLLSET_H */
diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c
deleted file mode 100644
index 2e0f27f..0000000
--- a/src/core/iomgr/pollset_multipoller_with_epoll.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#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/iomgr/fd_posix.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/block_annotate.h"
-
-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);
-}
-
-void grpc_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; } pollset_hdr;
-
-static void finally_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                           grpc_fd *fd) {
-  pollset_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(grpc_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));
-      }
-    }
-  }
-  grpc_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 (!grpc_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;
-  pollset_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 = grpc_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) {
-                grpc_fd_become_readable(exec_ctx, fd);
-              }
-              if (write_ev || cancel) {
-                grpc_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) {
-  pollset_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;
-  pollset_hdr *h = gpr_malloc(sizeof(pollset_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);
-  }
-}
-
-grpc_platform_become_multipoller_type grpc_platform_become_multipoller =
-    epoll_become_multipoller;
-
-#else /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */
-
-void grpc_remove_fd_from_all_epoll_sets(int fd) {}
-
-#endif /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */
diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
deleted file mode 100644
index 92d6fb7..0000000
--- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/pollset_posix.h"
-
-#include <errno.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/support/block_annotate.h"
-
-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;
-} pollset_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;
-  pollset_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;
-  pollset_hdr *h;
-  /* TODO(ctiller): inline some elements to avoid an allocation */
-  grpc_fd_watcher *watchers;
-  struct pollfd *pfds;
-
-  h = pollset->data.ptr;
-  timeout = grpc_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 = grpc_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)grpc_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++) {
-      grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0);
-    }
-  } else if (r == 0) {
-    for (i = 2; i < pfd_count; i++) {
-      grpc_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) {
-        grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0);
-        continue;
-      }
-      grpc_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;
-  pollset_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) {
-  pollset_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};
-
-void grpc_poll_become_multipoller(grpc_exec_ctx *exec_ctx,
-                                  grpc_pollset *pollset, grpc_fd **fds,
-                                  size_t nfds) {
-  size_t i;
-  pollset_hdr *h = gpr_malloc(sizeof(pollset_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_POSIX_SOCKET */
-
-#ifdef GPR_POSIX_MULTIPOLL_WITH_POLL
-grpc_platform_become_multipoller_type grpc_platform_become_multipoller =
-    grpc_poll_become_multipoller;
-#endif
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
deleted file mode 100644
index e895a77..0000000
--- a/src/core/iomgr/pollset_posix.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/pollset_posix.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/tls.h>
-#include <grpc/support/useful.h>
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/socket_utils_posix.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/block_annotate.h"
-
-GPR_TLS_DECL(g_current_thread_poller);
-GPR_TLS_DECL(g_current_thread_worker);
-
-/** Default poll() function - a pointer so that it can be overridden by some
- *  tests */
-grpc_poll_function_type grpc_poll_function = poll;
-
-/** 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;
-}
-
-int grpc_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 (grpc_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;
-}
-
-size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); }
-
-void grpc_pollset_kick_ext(grpc_pollset *p,
-                           grpc_pollset_worker *specific_worker,
-                           uint32_t flags) {
-  GPR_TIMER_BEGIN("grpc_pollset_kick_ext", 0);
-
-  /* pollset->mu already held */
-  if (specific_worker != NULL) {
-    if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
-      GPR_TIMER_BEGIN("grpc_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("grpc_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("grpc_pollset_kick_ext", 0);
-}
-
-void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
-  grpc_pollset_kick_ext(p, specific_worker, 0);
-}
-
-/* global state management */
-
-void grpc_pollset_global_init(void) {
-  gpr_tls_init(&g_current_thread_poller);
-  gpr_tls_init(&g_current_thread_worker);
-  grpc_wakeup_fd_global_init();
-  grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
-}
-
-void grpc_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);
-  grpc_wakeup_fd_global_destroy();
-}
-
-void grpc_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);
-
-void grpc_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);
-}
-
-void grpc_pollset_destroy(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->in_flight_cbs == 0);
-  GPR_ASSERT(!grpc_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;
-  }
-}
-
-void grpc_pollset_reset(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(pollset->in_flight_cbs == 0);
-  GPR_ASSERT(!grpc_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);
-}
-
-void grpc_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);
-}
-
-void grpc_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("grpc_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 (!grpc_pollset_has_workers(pollset) &&
-      !grpc_closure_list_empty(pollset->idle_jobs)) {
-    GPR_TIMER_MARK("grpc_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("grpc_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("grpc_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("grpc_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 grpc_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 (grpc_pollset_has_workers(pollset)) {
-      grpc_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
-       * grpc_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("grpc_pollset_work", 0);
-}
-
-void grpc_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;
-  grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
-  if (!grpc_pollset_has_workers(pollset)) {
-    grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
-  }
-  if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 &&
-      !grpc_pollset_has_workers(pollset)) {
-    pollset->called_shutdown = 1;
-    finish_shutdown(exec_ctx, pollset);
-  }
-}
-
-int grpc_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(!grpc_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 (grpc_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] && !grpc_fd_is_orphaned(fds[0])) {
-      grpc_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 (!grpc_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 (!grpc_fd_is_orphaned(fds[0])) {
-      grpc_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);
-  grpc_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 && grpc_fd_is_orphaned(fd)) {
-    GRPC_FD_UNREF(fd, "basicpoll");
-    fd = pollset->data.ptr = NULL;
-  }
-  timeout = grpc_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)grpc_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) {
-      grpc_fd_end_poll(exec_ctx, &fd_watcher, 0, 0);
-    }
-  } else if (r == 0) {
-    if (fd) {
-      grpc_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) {
-      grpc_fd_end_poll(exec_ctx, &fd_watcher, pfd[2].revents & POLLIN_CHECK,
-                       pfd[2].revents & POLLOUT_CHECK);
-    } else if (fd) {
-      grpc_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");
-  }
-}
-
-#endif /* GPR_POSIX_POLLSET */
diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h
deleted file mode 100644
index e0cfc44..0000000
--- a/src/core/iomgr/pollset_posix.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_POLLSET_POSIX_H
-#define GRPC_CORE_IOMGR_POLLSET_POSIX_H
-
-#include <poll.h>
-
-#include <grpc/support/sync.h>
-
-#include "src/core/iomgr/exec_ctx.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/pollset.h"
-#include "src/core/iomgr/wakeup_fd_posix.h"
-
-typedef struct grpc_pollset_vtable grpc_pollset_vtable;
-
-/* forward declare only in this file to avoid leaking impl details via
-   pollset.h; real users of grpc_fd should always include 'fd_posix.h' and not
-   use the struct tag */
-struct grpc_fd;
-
-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 */
-void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                         struct grpc_fd *fd);
-
-/* Returns the fd to listen on for kicks */
-int grpc_kick_read_fd(grpc_pollset *p);
-/* Call after polling has been kicked to leave the kicked state */
-void grpc_kick_drain(grpc_pollset *p);
-
-/* 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 */
-int grpc_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 grpc_pollset_kick, with an extended set of flags (defined above)
-   -- mostly for fd_posix's use. */
-void grpc_pollset_kick_ext(grpc_pollset *p,
-                           grpc_pollset_worker *specific_worker,
-                           uint32_t flags);
-
-/* turn a pollset into a multipoller: platform specific */
-typedef void (*grpc_platform_become_multipoller_type)(grpc_exec_ctx *exec_ctx,
-                                                      grpc_pollset *pollset,
-                                                      struct grpc_fd **fds,
-                                                      size_t fd_count);
-extern grpc_platform_become_multipoller_type grpc_platform_become_multipoller;
-
-void grpc_poll_become_multipoller(grpc_exec_ctx *exec_ctx,
-                                  grpc_pollset *pollset, struct grpc_fd **fds,
-                                  size_t fd_count);
-
-/* Return 1 if the pollset has active threads in grpc_pollset_work (pollset must
- * be locked) */
-int grpc_pollset_has_workers(grpc_pollset *pollset);
-
-void grpc_remove_fd_from_all_epoll_sets(int fd);
-
-/* override to allow tests to hook poll() usage */
-/* NOTE: Any changes to grpc_poll_function must take place when the gRPC
-   is certainly not doing any polling anywhere.
-   Otherwise, there might be a race between changing the variable and actually
-   doing a polling operation */
-typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int);
-extern grpc_poll_function_type grpc_poll_function;
-extern grpc_wakeup_fd grpc_global_wakeup_fd;
-
-#endif /* GRPC_CORE_IOMGR_POLLSET_POSIX_H */
diff --git a/src/core/iomgr/pollset_set.h b/src/core/iomgr/pollset_set.h
deleted file mode 100644
index 204c625..0000000
--- a/src/core/iomgr/pollset_set.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_POLLSET_SET_H
-#define GRPC_CORE_IOMGR_POLLSET_SET_H
-
-#include "src/core/iomgr/pollset.h"
-
-/* A grpc_pollset_set is a set of pollsets that are interested in an
-   action. Adding a pollset to a pollset_set automatically adds any
-   fd's (etc) that have been registered with the set_set to that pollset.
-   Registering fd's automatically adds them to all current pollsets. */
-
-typedef struct grpc_pollset_set grpc_pollset_set;
-
-grpc_pollset_set *grpc_pollset_set_create(void);
-void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set);
-void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
-                                  grpc_pollset_set *pollset_set,
-                                  grpc_pollset *pollset);
-void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
-                                  grpc_pollset_set *pollset_set,
-                                  grpc_pollset *pollset);
-void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
-                                      grpc_pollset_set *bag,
-                                      grpc_pollset_set *item);
-void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
-                                      grpc_pollset_set *bag,
-                                      grpc_pollset_set *item);
-
-#endif /* GRPC_CORE_IOMGR_POLLSET_SET_H */
diff --git a/src/core/iomgr/pollset_set_posix.c b/src/core/iomgr/pollset_set_posix.c
deleted file mode 100644
index 9dc9aff..0000000
--- a/src/core/iomgr/pollset_set_posix.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/iomgr/pollset_set_posix.h"
-
-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;
-};
-
-grpc_pollset_set *grpc_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;
-}
-
-void grpc_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);
-}
-
-void grpc_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 (grpc_fd_is_orphaned(pollset_set->fds[i])) {
-      GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
-    } else {
-      grpc_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);
-}
-
-void grpc_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);
-}
-
-void grpc_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 (grpc_fd_is_orphaned(bag->fds[i])) {
-      GRPC_FD_UNREF(bag->fds[i], "pollset_set");
-    } else {
-      grpc_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);
-}
-
-void grpc_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);
-}
-
-void grpc_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++) {
-    grpc_pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd);
-  }
-  for (i = 0; i < pollset_set->pollset_set_count; i++) {
-    grpc_pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd);
-  }
-  gpr_mu_unlock(&pollset_set->mu);
-}
-
-void grpc_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++) {
-    grpc_pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd);
-  }
-  gpr_mu_unlock(&pollset_set->mu);
-}
-
-#endif /* GPR_POSIX_SOCKET */
diff --git a/src/core/iomgr/pollset_set_posix.h b/src/core/iomgr/pollset_set_posix.h
deleted file mode 100644
index 80f4877..0000000
--- a/src/core/iomgr/pollset_set_posix.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_POLLSET_SET_POSIX_H
-#define GRPC_CORE_IOMGR_POLLSET_SET_POSIX_H
-
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/pollset_set.h"
-
-void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
-                             grpc_pollset_set *pollset_set, grpc_fd *fd);
-void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
-                             grpc_pollset_set *pollset_set, grpc_fd *fd);
-
-#endif /* GRPC_CORE_IOMGR_POLLSET_SET_POSIX_H */
diff --git a/src/core/iomgr/pollset_set_windows.c b/src/core/iomgr/pollset_set_windows.c
deleted file mode 100644
index 3b8eca2..0000000
--- a/src/core/iomgr/pollset_set_windows.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WINSOCK_SOCKET
-
-#include "src/core/iomgr/pollset_set_windows.h"
-
-grpc_pollset_set* grpc_pollset_set_create(pollset_set) { return NULL; }
-
-void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
-
-void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
-                                  grpc_pollset_set* pollset_set,
-                                  grpc_pollset* pollset) {}
-
-void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx,
-                                  grpc_pollset_set* pollset_set,
-                                  grpc_pollset* pollset) {}
-
-void grpc_pollset_set_add_pollset_set(grpc_exec_ctx* exec_ctx,
-                                      grpc_pollset_set* bag,
-                                      grpc_pollset_set* item) {}
-
-void grpc_pollset_set_del_pollset_set(grpc_exec_ctx* exec_ctx,
-                                      grpc_pollset_set* bag,
-                                      grpc_pollset_set* item) {}
-
-#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/pollset_set_windows.h b/src/core/iomgr/pollset_set_windows.h
deleted file mode 100644
index 0f040fe..0000000
--- a/src/core/iomgr/pollset_set_windows.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_POLLSET_SET_WINDOWS_H
-#define GRPC_CORE_IOMGR_POLLSET_SET_WINDOWS_H
-
-#include "src/core/iomgr/pollset_set.h"
-
-#endif /* GRPC_CORE_IOMGR_POLLSET_SET_WINDOWS_H */
diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c
deleted file mode 100644
index c7f30f4..0000000
--- a/src/core/iomgr/pollset_windows.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WINSOCK_SOCKET
-
-#include <grpc/support/log.h>
-#include <grpc/support/thd.h>
-
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/iocp_windows.h"
-#include "src/core/iomgr/pollset.h"
-#include "src/core/iomgr/pollset_windows.h"
-
-gpr_mu grpc_polling_mu;
-static grpc_pollset_worker *g_active_poller;
-static grpc_pollset_worker g_global_root_worker;
-
-void grpc_pollset_global_init() {
-  gpr_mu_init(&grpc_polling_mu);
-  g_active_poller = NULL;
-  g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next =
-      g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev =
-          &g_global_root_worker;
-}
-
-void grpc_pollset_global_shutdown() { gpr_mu_destroy(&grpc_polling_mu); }
-
-static void remove_worker(grpc_pollset_worker *worker,
-                          grpc_pollset_worker_link_type type) {
-  worker->links[type].prev->links[type].next = worker->links[type].next;
-  worker->links[type].next->links[type].prev = worker->links[type].prev;
-  worker->links[type].next = worker->links[type].prev = worker;
-}
-
-static int has_workers(grpc_pollset_worker *root,
-                       grpc_pollset_worker_link_type type) {
-  return root->links[type].next != root;
-}
-
-static grpc_pollset_worker *pop_front_worker(
-    grpc_pollset_worker *root, grpc_pollset_worker_link_type type) {
-  if (has_workers(root, type)) {
-    grpc_pollset_worker *w = root->links[type].next;
-    remove_worker(w, type);
-    return w;
-  } else {
-    return NULL;
-  }
-}
-
-static void push_front_worker(grpc_pollset_worker *root,
-                              grpc_pollset_worker_link_type type,
-                              grpc_pollset_worker *worker) {
-  worker->links[type].prev = root;
-  worker->links[type].next = worker->links[type].prev->links[type].next;
-  worker->links[type].prev->links[type].next =
-      worker->links[type].next->links[type].prev = worker;
-}
-
-size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); }
-
-/* There isn't really any such thing as a pollset under Windows, due to the
-   nature of the IO completion ports. We're still going to provide a minimal
-   set of features for the sake of the rest of grpc. But grpc_pollset_work
-   won't actually do any polling, and return as quickly as possible. */
-
-void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
-  *mu = &grpc_polling_mu;
-  memset(pollset, 0, sizeof(*pollset));
-  pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
-      pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
-          &pollset->root_worker;
-}
-
-void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                           grpc_closure *closure) {
-  pollset->shutting_down = 1;
-  grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
-  if (!pollset->is_iocp_worker) {
-    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
-  } else {
-    pollset->on_shutdown = closure;
-  }
-}
-
-void grpc_pollset_destroy(grpc_pollset *pollset) {}
-
-void grpc_pollset_reset(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(
-      !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
-  pollset->shutting_down = 0;
-  pollset->is_iocp_worker = 0;
-  pollset->kicked_without_pollers = 0;
-  pollset->on_shutdown = NULL;
-}
-
-void grpc_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;
-
-  int added_worker = 0;
-  worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
-      worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
-          worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next =
-              worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = NULL;
-  worker.kicked = 0;
-  worker.pollset = pollset;
-  gpr_cv_init(&worker.cv);
-  if (!pollset->kicked_without_pollers && !pollset->shutting_down) {
-    if (g_active_poller == NULL) {
-      grpc_pollset_worker *next_worker;
-      /* become poller */
-      pollset->is_iocp_worker = 1;
-      g_active_poller = &worker;
-      gpr_mu_unlock(&grpc_polling_mu);
-      grpc_iocp_work(exec_ctx, deadline);
-      grpc_exec_ctx_flush(exec_ctx);
-      gpr_mu_lock(&grpc_polling_mu);
-      pollset->is_iocp_worker = 0;
-      g_active_poller = NULL;
-      /* try to get a worker from this pollsets worker list */
-      next_worker = pop_front_worker(&pollset->root_worker,
-                                     GRPC_POLLSET_WORKER_LINK_POLLSET);
-      if (next_worker == NULL) {
-        /* try to get a worker from the global list */
-        next_worker = pop_front_worker(&g_global_root_worker,
-                                       GRPC_POLLSET_WORKER_LINK_GLOBAL);
-      }
-      if (next_worker != NULL) {
-        next_worker->kicked = 1;
-        gpr_cv_signal(&next_worker->cv);
-      }
-
-      if (pollset->shutting_down && pollset->on_shutdown != NULL) {
-        grpc_exec_ctx_enqueue(exec_ctx, pollset->on_shutdown, true, NULL);
-        pollset->on_shutdown = NULL;
-      }
-      goto done;
-    }
-    push_front_worker(&g_global_root_worker, GRPC_POLLSET_WORKER_LINK_GLOBAL,
-                      &worker);
-    push_front_worker(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET,
-                      &worker);
-    added_worker = 1;
-    while (!worker.kicked) {
-      if (gpr_cv_wait(&worker.cv, &grpc_polling_mu, deadline)) {
-        break;
-      }
-    }
-  } else {
-    pollset->kicked_without_pollers = 0;
-  }
-done:
-  if (!grpc_closure_list_empty(exec_ctx->closure_list)) {
-    gpr_mu_unlock(&grpc_polling_mu);
-    grpc_exec_ctx_flush(exec_ctx);
-    gpr_mu_lock(&grpc_polling_mu);
-  }
-  if (added_worker) {
-    remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_GLOBAL);
-    remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_POLLSET);
-  }
-  gpr_cv_destroy(&worker.cv);
-  *worker_hdl = NULL;
-}
-
-void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
-  if (specific_worker != NULL) {
-    if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
-      for (specific_worker =
-               p->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next;
-           specific_worker != &p->root_worker;
-           specific_worker =
-               specific_worker->links[GRPC_POLLSET_WORKER_LINK_POLLSET].next) {
-        specific_worker->kicked = 1;
-        gpr_cv_signal(&specific_worker->cv);
-      }
-      p->kicked_without_pollers = 1;
-      if (p->is_iocp_worker) {
-        grpc_iocp_kick();
-      }
-    } else {
-      if (p->is_iocp_worker && g_active_poller == specific_worker) {
-        grpc_iocp_kick();
-      } else {
-        specific_worker->kicked = 1;
-        gpr_cv_signal(&specific_worker->cv);
-      }
-    }
-  } else {
-    specific_worker =
-        pop_front_worker(&p->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET);
-    if (specific_worker != NULL) {
-      grpc_pollset_kick(p, specific_worker);
-    } else if (p->is_iocp_worker) {
-      grpc_iocp_kick();
-    } else {
-      p->kicked_without_pollers = 1;
-    }
-  }
-}
-
-void grpc_kick_poller(void) { grpc_iocp_kick(); }
-
-#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/pollset_windows.h b/src/core/iomgr/pollset_windows.h
deleted file mode 100644
index f1d1585..0000000
--- a/src/core/iomgr/pollset_windows.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_POLLSET_WINDOWS_H
-#define GRPC_CORE_IOMGR_POLLSET_WINDOWS_H
-
-#include <grpc/support/sync.h>
-
-#include "src/core/iomgr/socket_windows.h"
-
-/* There isn't really any such thing as a pollset under Windows, due to the
-   nature of the IO completion ports. A Windows "pollset" is merely a mutex
-   used to synchronize with the IOCP, and workers are condition variables
-   used to block threads until work is ready. */
-
-typedef enum {
-  GRPC_POLLSET_WORKER_LINK_POLLSET = 0,
-  GRPC_POLLSET_WORKER_LINK_GLOBAL,
-  GRPC_POLLSET_WORKER_LINK_TYPES
-} grpc_pollset_worker_link_type;
-
-typedef struct grpc_pollset_worker_link {
-  struct grpc_pollset_worker *next;
-  struct grpc_pollset_worker *prev;
-} grpc_pollset_worker_link;
-
-struct grpc_pollset;
-typedef struct grpc_pollset grpc_pollset;
-
-typedef struct grpc_pollset_worker {
-  gpr_cv cv;
-  int kicked;
-  struct grpc_pollset *pollset;
-  grpc_pollset_worker_link links[GRPC_POLLSET_WORKER_LINK_TYPES];
-} grpc_pollset_worker;
-
-struct grpc_pollset {
-  int shutting_down;
-  int kicked_without_pollers;
-  int is_iocp_worker;
-  grpc_pollset_worker root_worker;
-  grpc_closure *on_shutdown;
-};
-
-#endif /* GRPC_CORE_IOMGR_POLLSET_WINDOWS_H */
diff --git a/src/core/iomgr/resolve_address.h b/src/core/iomgr/resolve_address.h
deleted file mode 100644
index aa0d7d1..0000000
--- a/src/core/iomgr/resolve_address.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_RESOLVE_ADDRESS_H
-#define GRPC_CORE_IOMGR_RESOLVE_ADDRESS_H
-
-#include <stddef.h>
-#include "src/core/iomgr/exec_ctx.h"
-#include "src/core/iomgr/iomgr.h"
-
-#define GRPC_MAX_SOCKADDR_SIZE 128
-
-typedef struct {
-  char addr[GRPC_MAX_SOCKADDR_SIZE];
-  size_t len;
-} grpc_resolved_address;
-
-typedef struct {
-  size_t naddrs;
-  grpc_resolved_address *addrs;
-} grpc_resolved_addresses;
-
-/* Async result callback:
-   On success: addresses is the result, and the callee must call
-   grpc_resolved_addresses_destroy when it's done with them
-   On failure: addresses is NULL */
-typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg,
-                                grpc_resolved_addresses *addresses);
-/* Asynchronously resolve addr. Use default_port if a port isn't designated
-   in addr, otherwise use the port in addr. */
-/* TODO(ctiller): add a timeout here */
-void grpc_resolve_address(const char *addr, const char *default_port,
-                          grpc_resolve_cb cb, void *arg);
-/* Destroy resolved addresses */
-void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
-
-/* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
-   result must be freed with grpc_resolved_addresses_destroy. */
-extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
-    const char *name, const char *default_port);
-
-#endif /* GRPC_CORE_IOMGR_RESOLVE_ADDRESS_H */
diff --git a/src/core/iomgr/resolve_address_posix.c b/src/core/iomgr/resolve_address_posix.c
deleted file mode 100644
index a6c9893..0000000
--- a/src/core/iomgr/resolve_address_posix.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/sockaddr.h"
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/time.h>
-#include <grpc/support/useful.h>
-#include "src/core/iomgr/executor.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/support/block_annotate.h"
-#include "src/core/support/string.h"
-
-typedef struct {
-  char *name;
-  char *default_port;
-  grpc_resolve_cb cb;
-  grpc_closure request_closure;
-  void *arg;
-} request;
-
-static grpc_resolved_addresses *blocking_resolve_address_impl(
-    const char *name, const char *default_port) {
-  struct addrinfo hints;
-  struct addrinfo *result = NULL, *resp;
-  char *host;
-  char *port;
-  int s;
-  size_t i;
-  grpc_resolved_addresses *addrs = NULL;
-  struct sockaddr_un *un;
-
-  if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
-      name[4] == ':' && name[5] != 0) {
-    addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-    addrs->naddrs = 1;
-    addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address));
-    un = (struct sockaddr_un *)addrs->addrs->addr;
-    un->sun_family = AF_UNIX;
-    strcpy(un->sun_path, name + 5);
-    addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
-    return addrs;
-  }
-
-  /* parse name, splitting it into host and port parts */
-  gpr_split_host_port(name, &host, &port);
-  if (host == NULL) {
-    gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
-    goto done;
-  }
-  if (port == NULL) {
-    if (default_port == NULL) {
-      gpr_log(GPR_ERROR, "no port in name '%s'", name);
-      goto done;
-    }
-    port = gpr_strdup(default_port);
-  }
-
-  /* Call getaddrinfo */
-  memset(&hints, 0, sizeof(hints));
-  hints.ai_family = AF_UNSPEC;     /* ipv4 or ipv6 */
-  hints.ai_socktype = SOCK_STREAM; /* stream socket */
-  hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */
-
-  GRPC_SCHEDULING_START_BLOCKING_REGION;
-  s = getaddrinfo(host, port, &hints, &result);
-  GRPC_SCHEDULING_END_BLOCKING_REGION;
-
-  if (s != 0) {
-    /* Retry if well-known service name is recognized */
-    char *svc[][2] = {{"http", "80"}, {"https", "443"}};
-    for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) {
-      if (strcmp(port, svc[i][0]) == 0) {
-        GRPC_SCHEDULING_START_BLOCKING_REGION;
-        s = getaddrinfo(host, svc[i][1], &hints, &result);
-        GRPC_SCHEDULING_END_BLOCKING_REGION;
-        break;
-      }
-    }
-  }
-
-  if (s != 0) {
-    gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
-    goto done;
-  }
-
-  /* Success path: set addrs non-NULL, fill it in */
-  addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-  addrs->naddrs = 0;
-  for (resp = result; resp != NULL; resp = resp->ai_next) {
-    addrs->naddrs++;
-  }
-  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
-  i = 0;
-  for (resp = result; resp != NULL; resp = resp->ai_next) {
-    memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
-    addrs->addrs[i].len = resp->ai_addrlen;
-    i++;
-  }
-
-done:
-  gpr_free(host);
-  gpr_free(port);
-  if (result) {
-    freeaddrinfo(result);
-  }
-  return addrs;
-}
-
-grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
-    const char *name, const char *default_port) = blocking_resolve_address_impl;
-
-/* Callback to be passed to grpc_executor to asynch-ify
- * grpc_blocking_resolve_address */
-static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
-  request *r = rp;
-  grpc_resolved_addresses *resolved =
-      grpc_blocking_resolve_address(r->name, r->default_port);
-  void *arg = r->arg;
-  grpc_resolve_cb cb = r->cb;
-  gpr_free(r->name);
-  gpr_free(r->default_port);
-  cb(exec_ctx, arg, resolved);
-  gpr_free(r);
-}
-
-void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
-  gpr_free(addrs->addrs);
-  gpr_free(addrs);
-}
-
-void grpc_resolve_address(const char *name, const char *default_port,
-                          grpc_resolve_cb cb, void *arg) {
-  request *r = gpr_malloc(sizeof(request));
-  grpc_closure_init(&r->request_closure, do_request_thread, r);
-  r->name = gpr_strdup(name);
-  r->default_port = gpr_strdup(default_port);
-  r->cb = cb;
-  r->arg = arg;
-  grpc_executor_enqueue(&r->request_closure, 1);
-}
-
-#endif
diff --git a/src/core/iomgr/resolve_address_windows.c b/src/core/iomgr/resolve_address_windows.c
deleted file mode 100644
index 472e797..0000000
--- a/src/core/iomgr/resolve_address_windows.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-#ifdef GPR_WINSOCK_SOCKET
-
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/sockaddr.h"
-
-#include <string.h>
-#include <sys/types.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/log_win32.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/time.h>
-#include "src/core/iomgr/executor.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/support/block_annotate.h"
-#include "src/core/support/string.h"
-
-typedef struct {
-  char *name;
-  char *default_port;
-  grpc_resolve_cb cb;
-  grpc_closure request_closure;
-  void *arg;
-} request;
-
-static grpc_resolved_addresses *blocking_resolve_address_impl(
-    const char *name, const char *default_port) {
-  struct addrinfo hints;
-  struct addrinfo *result = NULL, *resp;
-  char *host;
-  char *port;
-  int s;
-  size_t i;
-  grpc_resolved_addresses *addrs = NULL;
-
-  /* parse name, splitting it into host and port parts */
-  gpr_split_host_port(name, &host, &port);
-  if (host == NULL) {
-    gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
-    goto done;
-  }
-  if (port == NULL) {
-    if (default_port == NULL) {
-      gpr_log(GPR_ERROR, "no port in name '%s'", name);
-      goto done;
-    }
-    port = gpr_strdup(default_port);
-  }
-
-  /* Call getaddrinfo */
-  memset(&hints, 0, sizeof(hints));
-  hints.ai_family = AF_UNSPEC;     /* ipv4 or ipv6 */
-  hints.ai_socktype = SOCK_STREAM; /* stream socket */
-  hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */
-
-  GRPC_SCHEDULING_START_BLOCKING_REGION;
-  s = getaddrinfo(host, port, &hints, &result);
-  GRPC_SCHEDULING_END_BLOCKING_REGION;
-  if (s != 0) {
-    char *error_message = gpr_format_message(s);
-    gpr_log(GPR_ERROR, "getaddrinfo: %s", error_message);
-    gpr_free(error_message);
-    goto done;
-  }
-
-  /* Success path: set addrs non-NULL, fill it in */
-  addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-  addrs->naddrs = 0;
-  for (resp = result; resp != NULL; resp = resp->ai_next) {
-    addrs->naddrs++;
-  }
-  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
-  i = 0;
-  for (resp = result; resp != NULL; resp = resp->ai_next) {
-    memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
-    addrs->addrs[i].len = resp->ai_addrlen;
-    i++;
-  }
-
-  {
-    for (i = 0; i < addrs->naddrs; i++) {
-      char *buf;
-      grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr,
-                              0);
-      gpr_free(buf);
-    }
-  }
-
-done:
-  gpr_free(host);
-  gpr_free(port);
-  if (result) {
-    freeaddrinfo(result);
-  }
-  return addrs;
-}
-
-grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
-    const char *name, const char *default_port) = blocking_resolve_address_impl;
-
-/* Callback to be passed to grpc_executor to asynch-ify
- * grpc_blocking_resolve_address */
-static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
-  request *r = rp;
-  grpc_resolved_addresses *resolved =
-      grpc_blocking_resolve_address(r->name, r->default_port);
-  void *arg = r->arg;
-  grpc_resolve_cb cb = r->cb;
-  gpr_free(r->name);
-  gpr_free(r->default_port);
-  cb(exec_ctx, arg, resolved);
-  gpr_free(r);
-}
-
-void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
-  gpr_free(addrs->addrs);
-  gpr_free(addrs);
-}
-
-void grpc_resolve_address(const char *name, const char *default_port,
-                          grpc_resolve_cb cb, void *arg) {
-  request *r = gpr_malloc(sizeof(request));
-  grpc_closure_init(&r->request_closure, do_request_thread, r);
-  r->name = gpr_strdup(name);
-  r->default_port = gpr_strdup(default_port);
-  r->cb = cb;
-  r->arg = arg;
-  grpc_executor_enqueue(&r->request_closure, 1);
-}
-
-#endif
diff --git a/src/core/iomgr/sockaddr.h b/src/core/iomgr/sockaddr.h
deleted file mode 100644
index 68241bd..0000000
--- a/src/core/iomgr/sockaddr.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_SOCKADDR_H
-#define GRPC_CORE_IOMGR_SOCKADDR_H
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-#include "src/core/iomgr/sockaddr_win32.h"
-#endif
-
-#ifdef GPR_POSIX_SOCKETADDR
-#include "src/core/iomgr/sockaddr_posix.h"
-#endif
-
-#endif /* GRPC_CORE_IOMGR_SOCKADDR_H */
diff --git a/src/core/iomgr/sockaddr_posix.h b/src/core/iomgr/sockaddr_posix.h
deleted file mode 100644
index e4425ed..0000000
--- a/src/core/iomgr/sockaddr_posix.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_SOCKADDR_POSIX_H
-#define GRPC_CORE_IOMGR_SOCKADDR_POSIX_H
-
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <unistd.h>
-
-#endif /* GRPC_CORE_IOMGR_SOCKADDR_POSIX_H */
diff --git a/src/core/iomgr/sockaddr_utils.c b/src/core/iomgr/sockaddr_utils.c
deleted file mode 100644
index 61006d7..0000000
--- a/src/core/iomgr/sockaddr_utils.c
+++ /dev/null
@@ -1,234 +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/iomgr/sockaddr_utils.h"
-
-#include <errno.h>
-#include <string.h>
-
-#ifdef GPR_POSIX_SOCKET
-#include <sys/un.h>
-#endif
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/support/string.h"
-
-static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0,    0,
-                                          0, 0, 0, 0, 0xff, 0xff};
-
-int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in *addr4_out) {
-  GPR_ASSERT(addr != (struct sockaddr *)addr4_out);
-  if (addr->sa_family == AF_INET6) {
-    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
-    if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
-               sizeof(kV4MappedPrefix)) == 0) {
-      if (addr4_out != NULL) {
-        /* Normalize ::ffff:0.0.0.0/96 to IPv4. */
-        memset(addr4_out, 0, sizeof(*addr4_out));
-        addr4_out->sin_family = AF_INET;
-        /* s6_addr32 would be nice, but it's non-standard. */
-        memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
-        addr4_out->sin_port = addr6->sin6_port;
-      }
-      return 1;
-    }
-  }
-  return 0;
-}
-
-int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in6 *addr6_out) {
-  GPR_ASSERT(addr != (struct sockaddr *)addr6_out);
-  if (addr->sa_family == AF_INET) {
-    const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
-    memset(addr6_out, 0, sizeof(*addr6_out));
-    addr6_out->sin6_family = AF_INET6;
-    memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
-    memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
-    addr6_out->sin6_port = addr4->sin_port;
-    return 1;
-  }
-  return 0;
-}
-
-int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out) {
-  struct sockaddr_in addr4_normalized;
-  if (grpc_sockaddr_is_v4mapped(addr, &addr4_normalized)) {
-    addr = (struct sockaddr *)&addr4_normalized;
-  }
-  if (addr->sa_family == AF_INET) {
-    /* Check for 0.0.0.0 */
-    const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
-    if (addr4->sin_addr.s_addr != 0) {
-      return 0;
-    }
-    *port_out = ntohs(addr4->sin_port);
-    return 1;
-  } else if (addr->sa_family == AF_INET6) {
-    /* Check for :: */
-    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
-    int i;
-    for (i = 0; i < 16; i++) {
-      if (addr6->sin6_addr.s6_addr[i] != 0) {
-        return 0;
-      }
-    }
-    *port_out = ntohs(addr6->sin6_port);
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
-                                  struct sockaddr_in6 *wild6_out) {
-  grpc_sockaddr_make_wildcard4(port, wild4_out);
-  grpc_sockaddr_make_wildcard6(port, wild6_out);
-}
-
-void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out) {
-  GPR_ASSERT(port >= 0 && port < 65536);
-  memset(wild_out, 0, sizeof(*wild_out));
-  wild_out->sin_family = AF_INET;
-  wild_out->sin_port = htons((uint16_t)port);
-}
-
-void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out) {
-  GPR_ASSERT(port >= 0 && port < 65536);
-  memset(wild_out, 0, sizeof(*wild_out));
-  wild_out->sin6_family = AF_INET6;
-  wild_out->sin6_port = htons((uint16_t)port);
-}
-
-int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
-                            int normalize) {
-  const int save_errno = errno;
-  struct sockaddr_in addr_normalized;
-  char ntop_buf[INET6_ADDRSTRLEN];
-  const void *ip = NULL;
-  int port;
-  int ret;
-
-  *out = NULL;
-  if (normalize && grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
-    addr = (const struct sockaddr *)&addr_normalized;
-  }
-  if (addr->sa_family == AF_INET) {
-    const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
-    ip = &addr4->sin_addr;
-    port = ntohs(addr4->sin_port);
-  } else if (addr->sa_family == AF_INET6) {
-    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
-    ip = &addr6->sin6_addr;
-    port = ntohs(addr6->sin6_port);
-  }
-  /* Windows inet_ntop wants a mutable ip pointer */
-  if (ip != NULL &&
-      inet_ntop(addr->sa_family, (void *)ip, ntop_buf, sizeof(ntop_buf)) !=
-          NULL) {
-    ret = gpr_join_host_port(out, ntop_buf, port);
-  } else {
-    ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
-  }
-  /* This is probably redundant, but we wouldn't want to log the wrong error. */
-  errno = save_errno;
-  return ret;
-}
-
-char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
-  char *temp;
-  char *result;
-  struct sockaddr_in addr_normalized;
-
-  if (grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
-    addr = (const struct sockaddr *)&addr_normalized;
-  }
-
-  switch (addr->sa_family) {
-    case AF_INET:
-      grpc_sockaddr_to_string(&temp, addr, 0);
-      gpr_asprintf(&result, "ipv4:%s", temp);
-      gpr_free(temp);
-      return result;
-    case AF_INET6:
-      grpc_sockaddr_to_string(&temp, addr, 0);
-      gpr_asprintf(&result, "ipv6:%s", temp);
-      gpr_free(temp);
-      return result;
-#ifdef GPR_POSIX_SOCKET
-    case AF_UNIX:
-      gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path);
-      return result;
-#endif
-  }
-
-  return NULL;
-}
-
-int grpc_sockaddr_get_port(const struct sockaddr *addr) {
-  switch (addr->sa_family) {
-    case AF_INET:
-      return ntohs(((struct sockaddr_in *)addr)->sin_port);
-    case AF_INET6:
-      return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
-    case AF_UNIX:
-      return 1;
-    default:
-      gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
-              addr->sa_family);
-      return 0;
-  }
-}
-
-int grpc_sockaddr_set_port(const struct sockaddr *addr, int port) {
-  switch (addr->sa_family) {
-    case AF_INET:
-      GPR_ASSERT(port >= 0 && port < 65536);
-      ((struct sockaddr_in *)addr)->sin_port = htons((uint16_t)port);
-      return 1;
-    case AF_INET6:
-      GPR_ASSERT(port >= 0 && port < 65536);
-      ((struct sockaddr_in6 *)addr)->sin6_port = htons((uint16_t)port);
-      return 1;
-    default:
-      gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
-              addr->sa_family);
-      return 0;
-  }
-}
diff --git a/src/core/iomgr/sockaddr_utils.h b/src/core/iomgr/sockaddr_utils.h
deleted file mode 100644
index 43dc7a4..0000000
--- a/src/core/iomgr/sockaddr_utils.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_SOCKADDR_UTILS_H
-#define GRPC_CORE_IOMGR_SOCKADDR_UTILS_H
-
-#include "src/core/iomgr/sockaddr.h"
-
-/* Returns true if addr is an IPv4-mapped IPv6 address within the
-   ::ffff:0.0.0.0/96 range, or false otherwise.
-
-   If addr4_out is non-NULL, the inner IPv4 address will be copied here when
-   returning true. */
-int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in *addr4_out);
-
-/* If addr is an AF_INET address, writes the corresponding ::ffff:0.0.0.0/96
-   address to addr6_out and returns true.  Otherwise returns false. */
-int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in6 *addr6_out);
-
-/* If addr is ::, 0.0.0.0, or ::ffff:0.0.0.0, writes the port number to
-   *port_out (if not NULL) and returns true, otherwise returns false. */
-int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out);
-
-/* Writes 0.0.0.0:port and [::]:port to separate sockaddrs. */
-void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
-                                  struct sockaddr_in6 *wild6_out);
-
-/* Writes 0.0.0.0:port. */
-void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out);
-
-/* Writes [::]:port. */
-void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out);
-
-/* Return the IP port number of a sockaddr */
-int grpc_sockaddr_get_port(const struct sockaddr *addr);
-
-/* Set IP port number of a sockaddr */
-int grpc_sockaddr_set_port(const struct sockaddr *addr, int port);
-
-/* Converts a sockaddr into a newly-allocated human-readable string.
-
-   Currently, only the AF_INET and AF_INET6 families are recognized.
-   If the normalize flag is enabled, ::ffff:0.0.0.0/96 IPv6 addresses are
-   displayed as plain IPv4.
-
-   Usage is similar to gpr_asprintf: returns the number of bytes written
-   (excluding the final '\0'), and *out points to a string which must later be
-   destroyed using gpr_free().
-
-   In the unlikely event of an error, returns -1 and sets *out to NULL.
-   The existing value of errno is always preserved. */
-int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
-                            int normalize);
-
-char *grpc_sockaddr_to_uri(const struct sockaddr *addr);
-
-#endif /* GRPC_CORE_IOMGR_SOCKADDR_UTILS_H */
diff --git a/src/core/iomgr/sockaddr_win32.h b/src/core/iomgr/sockaddr_win32.h
deleted file mode 100644
index 7acb8f7..0000000
--- a/src/core/iomgr/sockaddr_win32.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_SOCKADDR_WIN32_H
-#define GRPC_CORE_IOMGR_SOCKADDR_WIN32_H
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <mswsock.h>
-
-#endif /* GRPC_CORE_IOMGR_SOCKADDR_WIN32_H */
diff --git a/src/core/iomgr/socket_utils_common_posix.c b/src/core/iomgr/socket_utils_common_posix.c
deleted file mode 100644
index a9af594..0000000
--- a/src/core/iomgr/socket_utils_common_posix.c
+++ /dev/null
@@ -1,208 +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_SOCKET
-
-#include "src/core/iomgr/socket_utils_posix.h"
-
-#include <arpa/inet.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/support/string.h"
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/sync.h>
-
-/* set a socket to non blocking mode */
-int grpc_set_socket_nonblocking(int fd, int non_blocking) {
-  int oldflags = fcntl(fd, F_GETFL, 0);
-  if (oldflags < 0) {
-    return 0;
-  }
-
-  if (non_blocking) {
-    oldflags |= O_NONBLOCK;
-  } else {
-    oldflags &= ~O_NONBLOCK;
-  }
-
-  if (fcntl(fd, F_SETFL, oldflags) != 0) {
-    return 0;
-  }
-
-  return 1;
-}
-
-int grpc_set_socket_no_sigpipe_if_possible(int fd) {
-#ifdef GPR_HAVE_SO_NOSIGPIPE
-  int val = 1;
-  int newval;
-  socklen_t intlen = sizeof(newval);
-  return 0 == setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val)) &&
-         0 == getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen) &&
-         (newval != 0) == val;
-#else
-  return 1;
-#endif
-}
-
-/* set a socket to close on exec */
-int grpc_set_socket_cloexec(int fd, int close_on_exec) {
-  int oldflags = fcntl(fd, F_GETFD, 0);
-  if (oldflags < 0) {
-    return 0;
-  }
-
-  if (close_on_exec) {
-    oldflags |= FD_CLOEXEC;
-  } else {
-    oldflags &= ~FD_CLOEXEC;
-  }
-
-  if (fcntl(fd, F_SETFD, oldflags) != 0) {
-    return 0;
-  }
-
-  return 1;
-}
-
-/* set a socket to reuse old addresses */
-int grpc_set_socket_reuse_addr(int fd, int reuse) {
-  int val = (reuse != 0);
-  int newval;
-  socklen_t intlen = sizeof(newval);
-  return 0 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) &&
-         0 == getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen) &&
-         (newval != 0) == val;
-}
-
-/* disable nagle */
-int grpc_set_socket_low_latency(int fd, int low_latency) {
-  int val = (low_latency != 0);
-  int newval;
-  socklen_t intlen = sizeof(newval);
-  return 0 == setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) &&
-         0 == getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen) &&
-         (newval != 0) == val;
-}
-
-static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
-static int g_ipv6_loopback_available;
-
-static void probe_ipv6_once(void) {
-  int fd = socket(AF_INET6, SOCK_STREAM, 0);
-  g_ipv6_loopback_available = 0;
-  if (fd < 0) {
-    gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed.");
-  } else {
-    struct sockaddr_in6 addr;
-    memset(&addr, 0, sizeof(addr));
-    addr.sin6_family = AF_INET6;
-    addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */
-    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
-      g_ipv6_loopback_available = 1;
-    } else {
-      gpr_log(GPR_INFO,
-              "Disabling AF_INET6 sockets because ::1 is not available.");
-    }
-    close(fd);
-  }
-}
-
-int grpc_ipv6_loopback_available(void) {
-  gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once);
-  return g_ipv6_loopback_available;
-}
-
-/* This should be 0 in production, but it may be enabled for testing or
-   debugging purposes, to simulate an environment where IPv6 sockets can't
-   also speak IPv4. */
-int grpc_forbid_dualstack_sockets_for_testing = 0;
-
-static int set_socket_dualstack(int fd) {
-  if (!grpc_forbid_dualstack_sockets_for_testing) {
-    const int off = 0;
-    return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off));
-  } else {
-    /* Force an IPv6-only socket, for testing purposes. */
-    const int on = 1;
-    setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
-    return 0;
-  }
-}
-
-int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
-                                 int protocol, grpc_dualstack_mode *dsmode) {
-  int family = addr->sa_family;
-  if (family == AF_INET6) {
-    int fd;
-    if (grpc_ipv6_loopback_available()) {
-      fd = socket(family, type, protocol);
-    } else {
-      fd = -1;
-      errno = EAFNOSUPPORT;
-    }
-    /* Check if we've got a valid dualstack socket. */
-    if (fd >= 0 && set_socket_dualstack(fd)) {
-      *dsmode = GRPC_DSMODE_DUALSTACK;
-      return fd;
-    }
-    /* If this isn't an IPv4 address, then return whatever we've got. */
-    if (!grpc_sockaddr_is_v4mapped(addr, NULL)) {
-      *dsmode = GRPC_DSMODE_IPV6;
-      return fd;
-    }
-    /* Fall back to AF_INET. */
-    if (fd >= 0) {
-      close(fd);
-    }
-    family = AF_INET;
-  }
-  *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
-  return socket(family, type, protocol);
-}
-
-#endif
diff --git a/src/core/iomgr/socket_utils_linux.c b/src/core/iomgr/socket_utils_linux.c
deleted file mode 100644
index a876252..0000000
--- a/src/core/iomgr/socket_utils_linux.c
+++ /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.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_LINUX_SOCKETUTILS
-
-#include "src/core/iomgr/socket_utils_posix.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
-                 int nonblock, int cloexec) {
-  int flags = 0;
-  flags |= nonblock ? SOCK_NONBLOCK : 0;
-  flags |= cloexec ? SOCK_CLOEXEC : 0;
-  return accept4(sockfd, addr, addrlen, flags);
-}
-
-#endif
diff --git a/src/core/iomgr/socket_utils_posix.c b/src/core/iomgr/socket_utils_posix.c
deleted file mode 100644
index 3c56b46..0000000
--- a/src/core/iomgr/socket_utils_posix.c
+++ /dev/null
@@ -1,70 +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_SOCKETUTILS
-
-#include "src/core/iomgr/socket_utils_posix.h"
-
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include <grpc/support/log.h>
-
-int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
-                 int nonblock, int cloexec) {
-  int fd, flags;
-
-  fd = accept(sockfd, addr, addrlen);
-  if (fd >= 0) {
-    if (nonblock) {
-      flags = fcntl(fd, F_GETFL, 0);
-      if (flags < 0) goto close_and_error;
-      if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) goto close_and_error;
-    }
-    if (cloexec) {
-      flags = fcntl(fd, F_GETFD, 0);
-      if (flags < 0) goto close_and_error;
-      if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != 0) goto close_and_error;
-    }
-  }
-  return fd;
-
-close_and_error:
-  close(fd);
-  return -1;
-}
-
-#endif /* GPR_POSIX_SOCKETUTILS */
diff --git a/src/core/iomgr/socket_utils_posix.h b/src/core/iomgr/socket_utils_posix.h
deleted file mode 100644
index b01e28b..0000000
--- a/src/core/iomgr/socket_utils_posix.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_SOCKET_UTILS_POSIX_H
-#define GRPC_CORE_IOMGR_SOCKET_UTILS_POSIX_H
-
-#include <unistd.h>
-#include <sys/socket.h>
-
-/* a wrapper for accept or accept4 */
-int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
-                 int nonblock, int cloexec);
-
-/* set a socket to non blocking mode */
-int grpc_set_socket_nonblocking(int fd, int non_blocking);
-
-/* set a socket to close on exec */
-int grpc_set_socket_cloexec(int fd, int close_on_exec);
-
-/* set a socket to reuse old addresses */
-int grpc_set_socket_reuse_addr(int fd, int reuse);
-
-/* disable nagle */
-int grpc_set_socket_low_latency(int fd, int low_latency);
-
-/* Returns true if this system can create AF_INET6 sockets bound to ::1.
-   The value is probed once, and cached for the life of the process.
-
-   This is more restrictive than checking for socket(AF_INET6) to succeed,
-   because Linux with "net.ipv6.conf.all.disable_ipv6 = 1" is able to create
-   and bind IPv6 sockets, but cannot connect to a getsockname() of [::]:port
-   without a valid loopback interface.  Rather than expose this half-broken
-   state to library users, we turn off IPv6 sockets. */
-int grpc_ipv6_loopback_available(void);
-
-/* Tries to set SO_NOSIGPIPE if available on this platform.
-   Returns 1 on success, 0 on failure.
-   If SO_NO_SIGPIPE is not available, returns 1. */
-int grpc_set_socket_no_sigpipe_if_possible(int fd);
-
-/* An enum to keep track of IPv4/IPv6 socket modes.
-
-   Currently, this information is only used when a socket is first created, but
-   in the future we may wish to store it alongside the fd.  This would let calls
-   like sendto() know which family to use without asking the kernel first. */
-typedef enum grpc_dualstack_mode {
-  /* Uninitialized, or a non-IP socket. */
-  GRPC_DSMODE_NONE,
-  /* AF_INET only. */
-  GRPC_DSMODE_IPV4,
-  /* AF_INET6 only, because IPV6_V6ONLY could not be cleared. */
-  GRPC_DSMODE_IPV6,
-  /* AF_INET6, which also supports ::ffff-mapped IPv4 addresses. */
-  GRPC_DSMODE_DUALSTACK
-} grpc_dualstack_mode;
-
-/* Only tests should use this flag. */
-extern int grpc_forbid_dualstack_sockets_for_testing;
-
-/* Creates a new socket for connecting to (or listening on) an address.
-
-   If addr is AF_INET6, this creates an IPv6 socket first.  If that fails,
-   and addr is within ::ffff:0.0.0.0/96, then it automatically falls back to
-   an IPv4 socket.
-
-   If addr is AF_INET, AF_UNIX, or anything else, then this is similar to
-   calling socket() directly.
-
-   Returns an fd on success, otherwise returns -1 with errno set to the result
-   of a failed socket() call.
-
-   The *dsmode output indicates which address family was actually created.
-   The recommended way to use this is:
-   - First convert to IPv6 using grpc_sockaddr_to_v4mapped().
-   - Create the socket.
-   - If *dsmode is IPV4, use grpc_sockaddr_is_v4mapped() to convert back to
-     IPv4, so that bind() or connect() see the correct family.
-   Also, it's important to distinguish between DUALSTACK and IPV6 when
-   listening on the [::] wildcard address. */
-int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
-                                 int protocol, grpc_dualstack_mode *dsmode);
-
-#endif /* GRPC_CORE_IOMGR_SOCKET_UTILS_POSIX_H */
diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c
deleted file mode 100644
index fafb7b6..0000000
--- a/src/core/iomgr/socket_windows.c
+++ /dev/null
@@ -1,98 +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_WINSOCK_SOCKET
-
-#include <winsock2.h>
-#include <mswsock.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/log_win32.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/iomgr/iocp_windows.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/pollset.h"
-#include "src/core/iomgr/pollset_windows.h"
-#include "src/core/iomgr/socket_windows.h"
-
-grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) {
-  char *final_name;
-  grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket));
-  memset(r, 0, sizeof(grpc_winsocket));
-  r->socket = socket;
-  gpr_mu_init(&r->state_mu);
-  gpr_asprintf(&final_name, "%s:socket=0x%p", name, r);
-  grpc_iomgr_register_object(&r->iomgr_object, final_name);
-  gpr_free(final_name);
-  grpc_iocp_add_socket(r);
-  return r;
-}
-
-/* Schedule a shutdown of the socket operations. Will call the pending
-   operations to abort them. We need to do that this way because of the
-   various callsites of that function, which happens to be in various
-   mutex hold states, and that'd be unsafe to call them directly. */
-void grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
-  /* Grab the function pointer for DisconnectEx for that specific socket.
-     It may change depending on the interface. */
-  int status;
-  GUID guid = WSAID_DISCONNECTEX;
-  LPFN_DISCONNECTEX DisconnectEx;
-  DWORD ioctl_num_bytes;
-
-  status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
-                    &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx),
-                    &ioctl_num_bytes, NULL, NULL);
-
-  if (status == 0) {
-    DisconnectEx(winsocket->socket, NULL, 0, 0);
-  } else {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "Unable to retrieve DisconnectEx pointer : %s",
-            utf8_message);
-    gpr_free(utf8_message);
-  }
-  closesocket(winsocket->socket);
-}
-
-void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
-  grpc_iomgr_unregister_object(&winsocket->iomgr_object);
-  gpr_mu_destroy(&winsocket->state_mu);
-  gpr_free(winsocket);
-}
-
-#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/socket_windows.h b/src/core/iomgr/socket_windows.h
deleted file mode 100644
index 8e50e7a..0000000
--- a/src/core/iomgr/socket_windows.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_SOCKET_WINDOWS_H
-#define GRPC_CORE_IOMGR_SOCKET_WINDOWS_H
-
-#include <grpc/support/port_platform.h>
-#include <winsock2.h>
-
-#include <grpc/support/sync.h>
-#include <grpc/support/atm.h>
-
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/exec_ctx.h"
-
-/* This holds the data for an outstanding read or write on a socket.
-   The mutex to protect the concurrent access to that data is the one
-   inside the winsocket wrapper. */
-typedef struct grpc_winsocket_callback_info {
-  /* This is supposed to be a WSAOVERLAPPED, but in order to get that
-     definition, we need to include ws2tcpip.h, which needs to be included
-     from the top, otherwise it'll clash with a previous inclusion of
-     windows.h that in turns includes winsock.h. If anyone knows a way
-     to do it properly, feel free to send a patch. */
-  OVERLAPPED overlapped;
-  /* The callback information for the pending operation. May be empty if the
-     caller hasn't registered a callback yet. */
-  grpc_closure *closure;
-  /* A boolean to describe if the IO Completion Port got a notification for
-     that operation. This will happen if the operation completed before the
-     called had time to register a callback. We could avoid that behavior
-     altogether by forcing the caller to always register its callback before
-     proceeding queue an operation, but it is frequent for an IO Completion
-     Port to trigger quickly. This way we avoid a context switch for calling
-     the callback. We also simplify the read / write operations to avoid having
-     to hold a mutex for a long amount of time. */
-  int has_pending_iocp;
-  /* The results of the overlapped operation. */
-  DWORD bytes_transfered;
-  int wsa_error;
-} grpc_winsocket_callback_info;
-
-/* This is a wrapper to a Windows socket. A socket can have one outstanding
-   read, and one outstanding write. Doing an asynchronous accept means waiting
-   for a read operation. Doing an asynchronous connect means waiting for a
-   write operation. These are completely arbitrary ties between the operation
-   and the kind of event, because we can have one overlapped per pending
-   operation, whichever its nature is. So we could have more dedicated pending
-   operation callbacks for connect and listen. But given the scope of listen
-   and accept, we don't need to go to that extent and waste memory. Also, this
-   is closer to what happens in posix world. */
-typedef struct grpc_winsocket {
-  SOCKET socket;
-
-  grpc_winsocket_callback_info write_info;
-  grpc_winsocket_callback_info read_info;
-
-  gpr_mu state_mu;
-
-  /* You can't add the same socket twice to the same IO Completion Port.
-     This prevents that. */
-  int added_to_iocp;
-
-  grpc_closure shutdown_closure;
-
-  /* A label for iomgr to track outstanding objects */
-  grpc_iomgr_object iomgr_object;
-} grpc_winsocket;
-
-/* Create a wrapped windows handle. This takes ownership of it, meaning that
-   it will be responsible for closing it. */
-grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name);
-
-/* Initiate an asynchronous shutdown of the socket. Will call off any pending
-   operation to cancel them. */
-void grpc_winsocket_shutdown(grpc_winsocket *socket);
-
-/* Destroy a socket. Should only be called if there's no pending operation. */
-void grpc_winsocket_destroy(grpc_winsocket *socket);
-
-#endif /* GRPC_CORE_IOMGR_SOCKET_WINDOWS_H */
diff --git a/src/core/iomgr/tcp_client.h b/src/core/iomgr/tcp_client.h
deleted file mode 100644
index 2e29833..0000000
--- a/src/core/iomgr/tcp_client.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_TCP_CLIENT_H
-#define GRPC_CORE_IOMGR_TCP_CLIENT_H
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/pollset_set.h"
-#include "src/core/iomgr/sockaddr.h"
-#include <grpc/support/time.h>
-
-/* Asynchronously connect to an address (specified as (addr, len)), and call
-   cb with arg and the completed connection when done (or call cb with arg and
-   NULL on failure).
-   interested_parties points to a set of pollsets that would be interested
-   in this connection being established (in order to continue their work) */
-void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_connect,
-                             grpc_endpoint **endpoint,
-                             grpc_pollset_set *interested_parties,
-                             const struct sockaddr *addr, size_t addr_len,
-                             gpr_timespec deadline);
-
-#endif /* GRPC_CORE_IOMGR_TCP_CLIENT_H */
diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c
deleted file mode 100644
index 1572785..0000000
--- a/src/core/iomgr/tcp_client_posix.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/tcp_client.h"
-
-#include <errno.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/time.h>
-
-#include "src/core/iomgr/iomgr_posix.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/iomgr/pollset_set_posix.h"
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/iomgr/socket_utils_posix.h"
-#include "src/core/iomgr/tcp_posix.h"
-#include "src/core/iomgr/timer.h"
-#include "src/core/support/string.h"
-
-extern int grpc_tcp_trace;
-
-typedef struct {
-  gpr_mu mu;
-  grpc_fd *fd;
-  gpr_timespec deadline;
-  grpc_timer alarm;
-  int refs;
-  grpc_closure write_closure;
-  grpc_pollset_set *interested_parties;
-  char *addr_str;
-  grpc_endpoint **ep;
-  grpc_closure *closure;
-} async_connect;
-
-static int prepare_socket(const struct sockaddr *addr, int fd) {
-  if (fd < 0) {
-    goto error;
-  }
-
-  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
-      (addr->sa_family != AF_UNIX && !grpc_set_socket_low_latency(fd, 1)) ||
-      !grpc_set_socket_no_sigpipe_if_possible(fd)) {
-    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
-            strerror(errno));
-    goto error;
-  }
-
-  return 1;
-
-error:
-  if (fd >= 0) {
-    close(fd);
-  }
-  return 0;
-}
-
-static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
-  int done;
-  async_connect *ac = acp;
-  if (grpc_tcp_trace) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: success=%d", ac->addr_str,
-            success);
-  }
-  gpr_mu_lock(&ac->mu);
-  if (ac->fd != NULL) {
-    grpc_fd_shutdown(exec_ctx, ac->fd);
-  }
-  done = (--ac->refs == 0);
-  gpr_mu_unlock(&ac->mu);
-  if (done) {
-    gpr_mu_destroy(&ac->mu);
-    gpr_free(ac->addr_str);
-    gpr_free(ac);
-  }
-}
-
-static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
-  async_connect *ac = acp;
-  int so_error = 0;
-  socklen_t so_error_size;
-  int err;
-  int done;
-  grpc_endpoint **ep = ac->ep;
-  grpc_closure *closure = ac->closure;
-  grpc_fd *fd;
-
-  if (grpc_tcp_trace) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: success=%d",
-            ac->addr_str, success);
-  }
-
-  gpr_mu_lock(&ac->mu);
-  GPR_ASSERT(ac->fd);
-  fd = ac->fd;
-  ac->fd = NULL;
-  gpr_mu_unlock(&ac->mu);
-
-  grpc_timer_cancel(exec_ctx, &ac->alarm);
-
-  gpr_mu_lock(&ac->mu);
-  if (success) {
-    do {
-      so_error_size = sizeof(so_error);
-      err = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size);
-    } while (err < 0 && errno == EINTR);
-    if (err < 0) {
-      gpr_log(GPR_ERROR, "failed to connect to '%s': getsockopt(ERROR): %s",
-              ac->addr_str, strerror(errno));
-      goto finish;
-    } else if (so_error != 0) {
-      if (so_error == ENOBUFS) {
-        /* We will get one of these errors if we have run out of
-           memory in the kernel for the data structures allocated
-           when you connect a socket.  If this happens it is very
-           likely that if we wait a little bit then try again the
-           connection will work (since other programs or this
-           program will close their network connections and free up
-           memory).  This does _not_ indicate that there is anything
-           wrong with the server we are connecting to, this is a
-           local problem.
-
-           If you are looking at this code, then chances are that
-           your program or another program on the same computer
-           opened too many network connections.  The "easy" fix:
-           don't do that! */
-        gpr_log(GPR_ERROR, "kernel out of buffers");
-        gpr_mu_unlock(&ac->mu);
-        grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure);
-        return;
-      } else {
-        switch (so_error) {
-          case ECONNREFUSED:
-            gpr_log(
-                GPR_ERROR,
-                "failed to connect to '%s': socket error: connection refused",
-                ac->addr_str);
-            break;
-          default:
-            gpr_log(GPR_ERROR, "failed to connect to '%s': socket error: %d",
-                    ac->addr_str, so_error);
-            break;
-        }
-        goto finish;
-      }
-    } else {
-      grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
-      *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
-      fd = NULL;
-      goto finish;
-    }
-  } else {
-    gpr_log(GPR_ERROR, "failed to connect to '%s': timeout occurred",
-            ac->addr_str);
-    goto finish;
-  }
-
-  GPR_UNREACHABLE_CODE(return );
-
-finish:
-  if (fd != NULL) {
-    grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
-    grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
-    fd = NULL;
-  }
-  done = (--ac->refs == 0);
-  gpr_mu_unlock(&ac->mu);
-  if (done) {
-    gpr_mu_destroy(&ac->mu);
-    gpr_free(ac->addr_str);
-    gpr_free(ac);
-  }
-  grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL);
-}
-
-void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
-                             grpc_endpoint **ep,
-                             grpc_pollset_set *interested_parties,
-                             const struct sockaddr *addr, size_t addr_len,
-                             gpr_timespec deadline) {
-  int fd;
-  grpc_dualstack_mode dsmode;
-  int err;
-  async_connect *ac;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in addr4_copy;
-  grpc_fd *fdobj;
-  char *name;
-  char *addr_str;
-
-  *ep = NULL;
-
-  /* Use dualstack sockets where available. */
-  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
-  }
-
-  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-  if (fd < 0) {
-    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
-  }
-  if (dsmode == GRPC_DSMODE_IPV4) {
-    /* If we got an AF_INET socket, map the address back to IPv4. */
-    GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
-    addr = (struct sockaddr *)&addr4_copy;
-    addr_len = sizeof(addr4_copy);
-  }
-  if (!prepare_socket(addr, fd)) {
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
-    return;
-  }
-
-  do {
-    GPR_ASSERT(addr_len < ~(socklen_t)0);
-    err = connect(fd, addr, (socklen_t)addr_len);
-  } while (err < 0 && errno == EINTR);
-
-  addr_str = grpc_sockaddr_to_uri(addr);
-  gpr_asprintf(&name, "tcp-client:%s", addr_str);
-
-  fdobj = grpc_fd_create(fd, name);
-
-  if (err >= 0) {
-    *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
-    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
-    goto done;
-  }
-
-  if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
-    gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
-    grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
-    goto done;
-  }
-
-  grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);
-
-  ac = gpr_malloc(sizeof(async_connect));
-  ac->closure = closure;
-  ac->ep = ep;
-  ac->fd = fdobj;
-  ac->interested_parties = interested_parties;
-  ac->addr_str = addr_str;
-  addr_str = NULL;
-  gpr_mu_init(&ac->mu);
-  ac->refs = 2;
-  ac->write_closure.cb = on_writable;
-  ac->write_closure.cb_arg = ac;
-
-  if (grpc_tcp_trace) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
-            ac->addr_str);
-  }
-
-  gpr_mu_lock(&ac->mu);
-  grpc_timer_init(exec_ctx, &ac->alarm,
-                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
-                  tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
-  grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
-  gpr_mu_unlock(&ac->mu);
-
-done:
-  gpr_free(name);
-  gpr_free(addr_str);
-}
-
-#endif
diff --git a/src/core/iomgr/tcp_client_windows.c b/src/core/iomgr/tcp_client_windows.c
deleted file mode 100644
index 689c6f7..0000000
--- a/src/core/iomgr/tcp_client_windows.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WINSOCK_SOCKET
-
-#include "src/core/iomgr/sockaddr_win32.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/log_win32.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/iomgr/timer.h"
-#include "src/core/iomgr/iocp_windows.h"
-#include "src/core/iomgr/tcp_client.h"
-#include "src/core/iomgr/tcp_windows.h"
-#include "src/core/iomgr/sockaddr.h"
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/iomgr/socket_windows.h"
-
-typedef struct {
-  grpc_closure *on_done;
-  gpr_mu mu;
-  grpc_winsocket *socket;
-  gpr_timespec deadline;
-  grpc_timer alarm;
-  char *addr_name;
-  int refs;
-  grpc_closure on_connect;
-  grpc_endpoint **endpoint;
-} async_connect;
-
-static void async_connect_unlock_and_cleanup(async_connect *ac) {
-  int done = (--ac->refs == 0);
-  gpr_mu_unlock(&ac->mu);
-  if (done) {
-    if (ac->socket != NULL) grpc_winsocket_destroy(ac->socket);
-    gpr_mu_destroy(&ac->mu);
-    gpr_free(ac->addr_name);
-    gpr_free(ac);
-  }
-}
-
-static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool occured) {
-  async_connect *ac = acp;
-  gpr_mu_lock(&ac->mu);
-  /* If the alarm didn't occur, it got cancelled. */
-  if (ac->socket != NULL && occured) {
-    grpc_winsocket_shutdown(ac->socket);
-  }
-  async_connect_unlock_and_cleanup(ac);
-}
-
-static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, bool from_iocp) {
-  async_connect *ac = acp;
-  SOCKET sock = ac->socket->socket;
-  grpc_endpoint **ep = ac->endpoint;
-  grpc_winsocket_callback_info *info = &ac->socket->write_info;
-  grpc_closure *on_done = ac->on_done;
-
-  grpc_timer_cancel(exec_ctx, &ac->alarm);
-
-  gpr_mu_lock(&ac->mu);
-
-  if (from_iocp) {
-    DWORD transfered_bytes = 0;
-    DWORD flags;
-    BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
-                                              &transfered_bytes, FALSE, &flags);
-    GPR_ASSERT(transfered_bytes == 0);
-    if (!wsa_success) {
-      char *utf8_message = gpr_format_message(WSAGetLastError());
-      gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
-      gpr_free(utf8_message);
-    } else {
-      *ep = grpc_tcp_create(ac->socket, ac->addr_name);
-      ac->socket = NULL;
-    }
-  }
-
-  async_connect_unlock_and_cleanup(ac);
-  /* If the connection was aborted, the callback was already called when
-     the deadline was met. */
-  on_done->cb(exec_ctx, on_done->cb_arg, *ep != NULL);
-}
-
-/* Tries to issue one async connection, then schedules both an IOCP
-   notification request for the connection, and one timeout alert. */
-void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
-                             grpc_endpoint **endpoint,
-                             grpc_pollset_set *interested_parties,
-                             const struct sockaddr *addr, size_t addr_len,
-                             gpr_timespec deadline) {
-  SOCKET sock = INVALID_SOCKET;
-  BOOL success;
-  int status;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in6 local_address;
-  async_connect *ac;
-  grpc_winsocket *socket = NULL;
-  LPFN_CONNECTEX ConnectEx;
-  GUID guid = WSAID_CONNECTEX;
-  DWORD ioctl_num_bytes;
-  const char *message = NULL;
-  char *utf8_message;
-  grpc_winsocket_callback_info *info;
-
-  *endpoint = NULL;
-
-  /* Use dualstack sockets where available. */
-  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
-  }
-
-  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
-                   WSA_FLAG_OVERLAPPED);
-  if (sock == INVALID_SOCKET) {
-    message = "Unable to create socket: %s";
-    goto failure;
-  }
-
-  if (!grpc_tcp_prepare_socket(sock)) {
-    message = "Unable to set socket options: %s";
-    goto failure;
-  }
-
-  /* Grab the function pointer for ConnectEx for that specific socket.
-     It may change depending on the interface. */
-  status =
-      WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
-               &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, NULL, NULL);
-
-  if (status != 0) {
-    message = "Unable to retrieve ConnectEx pointer: %s";
-    goto failure;
-  }
-
-  grpc_sockaddr_make_wildcard6(0, &local_address);
-
-  status = bind(sock, (struct sockaddr *)&local_address, sizeof(local_address));
-  if (status != 0) {
-    message = "Unable to bind socket: %s";
-    goto failure;
-  }
-
-  socket = grpc_winsocket_create(sock, "client");
-  info = &socket->write_info;
-  success =
-      ConnectEx(sock, addr, (int)addr_len, NULL, 0, NULL, &info->overlapped);
-
-  /* It wouldn't be unusual to get a success immediately. But we'll still get
-     an IOCP notification, so let's ignore it. */
-  if (!success) {
-    int error = WSAGetLastError();
-    if (error != ERROR_IO_PENDING) {
-      message = "ConnectEx failed: %s";
-      goto failure;
-    }
-  }
-
-  ac = gpr_malloc(sizeof(async_connect));
-  ac->on_done = on_done;
-  ac->socket = socket;
-  gpr_mu_init(&ac->mu);
-  ac->refs = 2;
-  ac->addr_name = grpc_sockaddr_to_uri(addr);
-  ac->endpoint = endpoint;
-  grpc_closure_init(&ac->on_connect, on_connect, ac);
-
-  grpc_timer_init(exec_ctx, &ac->alarm, deadline, on_alarm, ac,
-                  gpr_now(GPR_CLOCK_MONOTONIC));
-  grpc_socket_notify_on_write(exec_ctx, socket, &ac->on_connect);
-  return;
-
-failure:
-  utf8_message = gpr_format_message(WSAGetLastError());
-  gpr_log(GPR_ERROR, message, utf8_message);
-  gpr_free(utf8_message);
-  if (socket != NULL) {
-    grpc_winsocket_destroy(socket);
-  } else if (sock != INVALID_SOCKET) {
-    closesocket(sock);
-  }
-  grpc_exec_ctx_enqueue(exec_ctx, on_done, false, NULL);
-}
-
-#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c
deleted file mode 100644
index f74eb3f..0000000
--- a/src/core/iomgr/tcp_posix.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/tcp_posix.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-#include "src/core/debug/trace.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/iomgr/pollset_set_posix.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-
-#ifdef GPR_HAVE_MSG_NOSIGNAL
-#define SENDMSG_FLAGS MSG_NOSIGNAL
-#else
-#define SENDMSG_FLAGS 0
-#endif
-
-#ifdef GPR_MSG_IOVLEN_TYPE
-typedef GPR_MSG_IOVLEN_TYPE msg_iovlen_type;
-#else
-typedef size_t msg_iovlen_type;
-#endif
-
-int grpc_tcp_trace = 0;
-
-typedef struct {
-  grpc_endpoint base;
-  grpc_fd *em_fd;
-  int fd;
-  int finished_edge;
-  msg_iovlen_type iov_size; /* Number of slices to allocate per read attempt */
-  size_t slice_size;
-  gpr_refcount refcount;
-
-  /* garbage after the last read */
-  gpr_slice_buffer last_read_buffer;
-
-  gpr_slice_buffer *incoming_buffer;
-  gpr_slice_buffer *outgoing_buffer;
-  /** slice within outgoing_buffer to write next */
-  size_t outgoing_slice_idx;
-  /** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */
-  size_t outgoing_byte_idx;
-
-  grpc_closure *read_cb;
-  grpc_closure *write_cb;
-  grpc_closure *release_fd_cb;
-  int *release_fd;
-
-  grpc_closure read_closure;
-  grpc_closure write_closure;
-
-  char *peer_string;
-} grpc_tcp;
-
-static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                            bool success);
-static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                             bool success);
-
-static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  grpc_fd_shutdown(exec_ctx, tcp->em_fd);
-}
-
-static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
-  grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd,
-                 "tcp_unref_orphan");
-  gpr_slice_buffer_destroy(&tcp->last_read_buffer);
-  gpr_free(tcp->peer_string);
-  gpr_free(tcp);
-}
-
-/*#define GRPC_TCP_REFCOUNT_DEBUG*/
-#ifdef GRPC_TCP_REFCOUNT_DEBUG
-#define TCP_UNREF(cl, tcp, reason) \
-  tcp_unref((cl), (tcp), (reason), __FILE__, __LINE__)
-#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
-static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
-                      const char *reason, const char *file, int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
-          reason, tcp->refcount.count, tcp->refcount.count - 1);
-  if (gpr_unref(&tcp->refcount)) {
-    tcp_free(exec_ctx, tcp);
-  }
-}
-
-static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
-                    int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP   ref %p : %s %d -> %d", tcp,
-          reason, tcp->refcount.count, tcp->refcount.count + 1);
-  gpr_ref(&tcp->refcount);
-}
-#else
-#define TCP_UNREF(cl, tcp, reason) tcp_unref((cl), (tcp))
-#define TCP_REF(tcp, reason) tcp_ref((tcp))
-static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
-  if (gpr_unref(&tcp->refcount)) {
-    tcp_free(exec_ctx, tcp);
-  }
-}
-
-static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
-#endif
-
-static void tcp_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  TCP_UNREF(exec_ctx, tcp, "destroy");
-}
-
-static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, int success) {
-  grpc_closure *cb = tcp->read_cb;
-
-  if (grpc_tcp_trace) {
-    size_t i;
-    gpr_log(GPR_DEBUG, "read: success=%d", success);
-    for (i = 0; i < tcp->incoming_buffer->count; i++) {
-      char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i],
-                                  GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump);
-      gpr_free(dump);
-    }
-  }
-
-  tcp->read_cb = NULL;
-  tcp->incoming_buffer = NULL;
-  cb->cb(exec_ctx, cb->cb_arg, success);
-}
-
-#define MAX_READ_IOVEC 4
-static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
-  struct msghdr msg;
-  struct iovec iov[MAX_READ_IOVEC];
-  ssize_t read_bytes;
-  size_t i;
-
-  GPR_ASSERT(!tcp->finished_edge);
-  GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC);
-  GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC);
-  GPR_TIMER_BEGIN("tcp_continue_read", 0);
-
-  while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) {
-    gpr_slice_buffer_add_indexed(tcp->incoming_buffer,
-                                 gpr_slice_malloc(tcp->slice_size));
-  }
-  for (i = 0; i < tcp->incoming_buffer->count; i++) {
-    iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]);
-    iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]);
-  }
-
-  msg.msg_name = NULL;
-  msg.msg_namelen = 0;
-  msg.msg_iov = iov;
-  msg.msg_iovlen = tcp->iov_size;
-  msg.msg_control = NULL;
-  msg.msg_controllen = 0;
-  msg.msg_flags = 0;
-
-  GPR_TIMER_BEGIN("recvmsg", 1);
-  do {
-    read_bytes = recvmsg(tcp->fd, &msg, 0);
-  } while (read_bytes < 0 && errno == EINTR);
-  GPR_TIMER_END("recvmsg", 0);
-
-  if (read_bytes < 0) {
-    /* NB: After calling call_read_cb a parallel call of the read handler may
-     * be running. */
-    if (errno == EAGAIN) {
-      if (tcp->iov_size > 1) {
-        tcp->iov_size /= 2;
-      }
-      /* We've consumed the edge, request a new one */
-      grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
-    } else {
-      /* TODO(klempner): Log interesting errors */
-      gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
-      call_read_cb(exec_ctx, tcp, 0);
-      TCP_UNREF(exec_ctx, tcp, "read");
-    }
-  } else if (read_bytes == 0) {
-    /* 0 read size ==> end of stream */
-    gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
-    call_read_cb(exec_ctx, tcp, 0);
-    TCP_UNREF(exec_ctx, tcp, "read");
-  } else {
-    GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length);
-    if ((size_t)read_bytes < tcp->incoming_buffer->length) {
-      gpr_slice_buffer_trim_end(
-          tcp->incoming_buffer,
-          tcp->incoming_buffer->length - (size_t)read_bytes,
-          &tcp->last_read_buffer);
-    } else if (tcp->iov_size < MAX_READ_IOVEC) {
-      ++tcp->iov_size;
-    }
-    GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length);
-    call_read_cb(exec_ctx, tcp, 1);
-    TCP_UNREF(exec_ctx, tcp, "read");
-  }
-
-  GPR_TIMER_END("tcp_continue_read", 0);
-}
-
-static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                            bool success) {
-  grpc_tcp *tcp = (grpc_tcp *)arg;
-  GPR_ASSERT(!tcp->finished_edge);
-
-  if (!success) {
-    gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
-    call_read_cb(exec_ctx, tcp, 0);
-    TCP_UNREF(exec_ctx, tcp, "read");
-  } else {
-    tcp_continue_read(exec_ctx, tcp);
-  }
-}
-
-static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                     gpr_slice_buffer *incoming_buffer, grpc_closure *cb) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  GPR_ASSERT(tcp->read_cb == NULL);
-  tcp->read_cb = cb;
-  tcp->incoming_buffer = incoming_buffer;
-  gpr_slice_buffer_reset_and_unref(incoming_buffer);
-  gpr_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer);
-  TCP_REF(tcp, "read");
-  if (tcp->finished_edge) {
-    tcp->finished_edge = 0;
-    grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
-  } else {
-    grpc_exec_ctx_enqueue(exec_ctx, &tcp->read_closure, true, NULL);
-  }
-}
-
-typedef enum { FLUSH_DONE, FLUSH_PENDING, FLUSH_ERROR } flush_result;
-
-#define MAX_WRITE_IOVEC 16
-static flush_result tcp_flush(grpc_tcp *tcp) {
-  struct msghdr msg;
-  struct iovec iov[MAX_WRITE_IOVEC];
-  msg_iovlen_type iov_size;
-  ssize_t sent_length;
-  size_t sending_length;
-  size_t trailing;
-  size_t unwind_slice_idx;
-  size_t unwind_byte_idx;
-
-  for (;;) {
-    sending_length = 0;
-    unwind_slice_idx = tcp->outgoing_slice_idx;
-    unwind_byte_idx = tcp->outgoing_byte_idx;
-    for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count &&
-                           iov_size != MAX_WRITE_IOVEC;
-         iov_size++) {
-      iov[iov_size].iov_base =
-          GPR_SLICE_START_PTR(
-              tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) +
-          tcp->outgoing_byte_idx;
-      iov[iov_size].iov_len =
-          GPR_SLICE_LENGTH(
-              tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) -
-          tcp->outgoing_byte_idx;
-      sending_length += iov[iov_size].iov_len;
-      tcp->outgoing_slice_idx++;
-      tcp->outgoing_byte_idx = 0;
-    }
-    GPR_ASSERT(iov_size > 0);
-
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
-    msg.msg_iov = iov;
-    msg.msg_iovlen = iov_size;
-    msg.msg_control = NULL;
-    msg.msg_controllen = 0;
-    msg.msg_flags = 0;
-
-    GPR_TIMER_BEGIN("sendmsg", 1);
-    do {
-      /* TODO(klempner): Cork if this is a partial write */
-      sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS);
-    } while (sent_length < 0 && errno == EINTR);
-    GPR_TIMER_END("sendmsg", 0);
-
-    if (sent_length < 0) {
-      if (errno == EAGAIN) {
-        tcp->outgoing_slice_idx = unwind_slice_idx;
-        tcp->outgoing_byte_idx = unwind_byte_idx;
-        return FLUSH_PENDING;
-      } else {
-        /* TODO(klempner): Log some of these */
-        return FLUSH_ERROR;
-      }
-    }
-
-    GPR_ASSERT(tcp->outgoing_byte_idx == 0);
-    trailing = sending_length - (size_t)sent_length;
-    while (trailing > 0) {
-      size_t slice_length;
-
-      tcp->outgoing_slice_idx--;
-      slice_length = GPR_SLICE_LENGTH(
-          tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]);
-      if (slice_length > trailing) {
-        tcp->outgoing_byte_idx = slice_length - trailing;
-        break;
-      } else {
-        trailing -= slice_length;
-      }
-    }
-
-    if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) {
-      return FLUSH_DONE;
-    }
-  };
-}
-
-static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                             bool success) {
-  grpc_tcp *tcp = (grpc_tcp *)arg;
-  flush_result status;
-  grpc_closure *cb;
-
-  if (!success) {
-    cb = tcp->write_cb;
-    tcp->write_cb = NULL;
-    cb->cb(exec_ctx, cb->cb_arg, 0);
-    TCP_UNREF(exec_ctx, tcp, "write");
-    return;
-  }
-
-  status = tcp_flush(tcp);
-  if (status == FLUSH_PENDING) {
-    grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
-  } else {
-    cb = tcp->write_cb;
-    tcp->write_cb = NULL;
-    GPR_TIMER_BEGIN("tcp_handle_write.cb", 0);
-    cb->cb(exec_ctx, cb->cb_arg, status == FLUSH_DONE);
-    GPR_TIMER_END("tcp_handle_write.cb", 0);
-    TCP_UNREF(exec_ctx, tcp, "write");
-  }
-}
-
-static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                      gpr_slice_buffer *buf, grpc_closure *cb) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  flush_result status;
-
-  if (grpc_tcp_trace) {
-    size_t i;
-
-    for (i = 0; i < buf->count; i++) {
-      char *data =
-          gpr_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data);
-      gpr_free(data);
-    }
-  }
-
-  GPR_TIMER_BEGIN("tcp_write", 0);
-  GPR_ASSERT(tcp->write_cb == NULL);
-
-  if (buf->length == 0) {
-    GPR_TIMER_END("tcp_write", 0);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
-    return;
-  }
-  tcp->outgoing_buffer = buf;
-  tcp->outgoing_slice_idx = 0;
-  tcp->outgoing_byte_idx = 0;
-
-  status = tcp_flush(tcp);
-  if (status == FLUSH_PENDING) {
-    TCP_REF(tcp, "write");
-    tcp->write_cb = cb;
-    grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
-  } else {
-    grpc_exec_ctx_enqueue(exec_ctx, cb, status == FLUSH_DONE, NULL);
-  }
-
-  GPR_TIMER_END("tcp_write", 0);
-}
-
-static void tcp_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                               grpc_pollset *pollset) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  grpc_pollset_add_fd(exec_ctx, pollset, tcp->em_fd);
-}
-
-static void tcp_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                                   grpc_pollset_set *pollset_set) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  grpc_pollset_set_add_fd(exec_ctx, pollset_set, tcp->em_fd);
-}
-
-static char *tcp_get_peer(grpc_endpoint *ep) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  return gpr_strdup(tcp->peer_string);
-}
-
-static const grpc_endpoint_vtable vtable = {
-    tcp_read, tcp_write, tcp_add_to_pollset, tcp_add_to_pollset_set,
-    tcp_shutdown, tcp_destroy, tcp_get_peer};
-
-grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
-                               const char *peer_string) {
-  grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
-  tcp->base.vtable = &vtable;
-  tcp->peer_string = gpr_strdup(peer_string);
-  tcp->fd = em_fd->fd;
-  tcp->read_cb = NULL;
-  tcp->write_cb = NULL;
-  tcp->release_fd_cb = NULL;
-  tcp->release_fd = NULL;
-  tcp->incoming_buffer = NULL;
-  tcp->slice_size = slice_size;
-  tcp->iov_size = 1;
-  tcp->finished_edge = 1;
-  /* paired with unref in grpc_tcp_destroy */
-  gpr_ref_init(&tcp->refcount, 1);
-  tcp->em_fd = em_fd;
-  tcp->read_closure.cb = tcp_handle_read;
-  tcp->read_closure.cb_arg = tcp;
-  tcp->write_closure.cb = tcp_handle_write;
-  tcp->write_closure.cb_arg = tcp;
-  gpr_slice_buffer_init(&tcp->last_read_buffer);
-
-  return &tcp->base;
-}
-
-int grpc_tcp_fd(grpc_endpoint *ep) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  GPR_ASSERT(ep->vtable == &vtable);
-  return grpc_fd_wrapped_fd(tcp->em_fd);
-}
-
-void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                                     int *fd, grpc_closure *done) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  GPR_ASSERT(ep->vtable == &vtable);
-  tcp->release_fd = fd;
-  tcp->release_fd_cb = done;
-  TCP_UNREF(exec_ctx, tcp, "destroy");
-}
-
-#endif
diff --git a/src/core/iomgr/tcp_posix.h b/src/core/iomgr/tcp_posix.h
deleted file mode 100644
index d846ec5..0000000
--- a/src/core/iomgr/tcp_posix.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_TCP_POSIX_H
-#define GRPC_CORE_IOMGR_TCP_POSIX_H
-/*
-   Low level TCP "bottom half" implementation, for use by transports built on
-   top of a TCP connection.
-
-   Note that this file does not (yet) include APIs for creating the socket in
-   the first place.
-
-   All calls passing slice transfer ownership of a slice refcount unless
-   otherwise specified.
-*/
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/fd_posix.h"
-
-#define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192
-
-extern int grpc_tcp_trace;
-
-/* Create a tcp endpoint given a file desciptor and a read slice size.
-   Takes ownership of fd. */
-grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size,
-                               const char *peer_string);
-
-/* Return the tcp endpoint's fd, or -1 if this is not available. Does not
-   release the fd.
-   Requires: ep must be a tcp endpoint.
- */
-int grpc_tcp_fd(grpc_endpoint *ep);
-
-/* Destroy the tcp endpoint without closing its fd. *fd will be set and done
- * will be called when the endpoint is destroyed.
- * Requires: ep must be a tcp endpoint and fd must not be NULL. */
-void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                                     int *fd, grpc_closure *done);
-
-#endif /* GRPC_CORE_IOMGR_TCP_POSIX_H */
diff --git a/src/core/iomgr/tcp_server.h b/src/core/iomgr/tcp_server.h
deleted file mode 100644
index 93247e9..0000000
--- a/src/core/iomgr/tcp_server.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_TCP_SERVER_H
-#define GRPC_CORE_IOMGR_TCP_SERVER_H
-
-#include "src/core/iomgr/closure.h"
-#include "src/core/iomgr/endpoint.h"
-
-/* Forward decl of grpc_tcp_server */
-typedef struct grpc_tcp_server grpc_tcp_server;
-
-typedef struct grpc_tcp_server_acceptor {
-  /* grpc_tcp_server_cb functions share a ref on from_server that is valid
-     until the function returns. */
-  grpc_tcp_server *from_server;
-  /* Indices that may be passed to grpc_tcp_server_port_fd(). */
-  unsigned port_index;
-  unsigned fd_index;
-} grpc_tcp_server_acceptor;
-
-/* Called for newly connected TCP connections. */
-typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg,
-                                   grpc_endpoint *ep,
-                                   grpc_tcp_server_acceptor *acceptor);
-
-/* Create a server, initially not bound to any ports. The caller owns one ref.
-   If shutdown_complete is not NULL, it will be used by
-   grpc_tcp_server_unref() when the ref count reaches zero. */
-grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete);
-
-/* Start listening to bound ports */
-void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
-                           grpc_pollset **pollsets, size_t pollset_count,
-                           grpc_tcp_server_cb on_accept_cb, void *cb_arg);
-
-/* Add a port to the server, returning the newly allocated port on success, or
-   -1 on failure.
-
-   The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
-   both IPv4 and IPv6 connections, but :: is the preferred style.  This usually
-   creates one socket, but possibly two on systems which support IPv6,
-   but not dualstack sockets. */
-/* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
-                  all of the multiple socket port matching logic in one place */
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len);
-
-/* Number of fds at the given port_index, or 0 if port_index is out of
-   bounds. */
-unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, unsigned port_index);
-
-/* Returns the file descriptor of the Mth (fd_index) listening socket of the Nth
-   (port_index) call to add_port() on this server, or -1 if the indices are out
-   of bounds. The file descriptor remains owned by the server, and will be
-   cleaned up when the ref count reaches zero. */
-int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
-                            unsigned fd_index);
-
-/* Ref s and return s. */
-grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s);
-
-/* shutdown_starting is called when ref count has reached zero and the server is
-   about to be destroyed. The server will be deleted after it returns. Calling
-   grpc_tcp_server_ref() from it has no effect. */
-void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
-                                           grpc_closure *shutdown_starting);
-
-/* If the refcount drops to zero, delete s, and call (exec_ctx==NULL) or enqueue
-   a call (exec_ctx!=NULL) to shutdown_complete. */
-void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s);
-
-#endif /* GRPC_CORE_IOMGR_TCP_SERVER_H */
diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c
deleted file mode 100644
index 5e07f82..0000000
--- a/src/core/iomgr/tcp_server_posix.c
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/tcp_server.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/iomgr/socket_utils_posix.h"
-#include "src/core/iomgr/tcp_posix.h"
-#include "src/core/support/string.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>
-
-#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
-
-static gpr_once s_init_max_accept_queue_size;
-static int s_max_accept_queue_size;
-
-/* one listening port */
-typedef struct grpc_tcp_listener grpc_tcp_listener;
-struct grpc_tcp_listener {
-  int fd;
-  grpc_fd *emfd;
-  grpc_tcp_server *server;
-  union {
-    uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE];
-    struct sockaddr sockaddr;
-    struct sockaddr_un un;
-  } addr;
-  size_t addr_len;
-  int port;
-  unsigned port_index;
-  unsigned fd_index;
-  grpc_closure read_closure;
-  grpc_closure destroyed_closure;
-  struct grpc_tcp_listener *next;
-  /* When we add a listener, more than one can be created, mainly because of
-     IPv6. A sibling will still be in the normal list, but will be flagged
-     as such. Any action, such as ref or unref, will affect all of the
-     siblings in the list. */
-  struct grpc_tcp_listener *sibling;
-  int is_sibling;
-};
-
-static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
-  struct stat st;
-
-  if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
-    unlink(un->sun_path);
-  }
-}
-
-/* the overall server */
-struct grpc_tcp_server {
-  gpr_refcount refs;
-  /* Called whenever accept() succeeds on a server port. */
-  grpc_tcp_server_cb on_accept_cb;
-  void *on_accept_cb_arg;
-
-  gpr_mu mu;
-
-  /* active port count: how many ports are actually still listening */
-  size_t active_ports;
-  /* destroyed port count: how many ports are completely destroyed */
-  size_t destroyed_ports;
-
-  /* is this server shutting down? (boolean) */
-  int shutdown;
-
-  /* linked list of server ports */
-  grpc_tcp_listener *head;
-  grpc_tcp_listener *tail;
-  unsigned nports;
-
-  /* List of closures passed to shutdown_starting_add(). */
-  grpc_closure_list shutdown_starting;
-
-  /* shutdown callback */
-  grpc_closure *shutdown_complete;
-
-  /* all pollsets interested in new connections */
-  grpc_pollset **pollsets;
-  /* number of pollsets in the pollsets array */
-  size_t pollset_count;
-};
-
-grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
-  grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
-  gpr_ref_init(&s->refs, 1);
-  gpr_mu_init(&s->mu);
-  s->active_ports = 0;
-  s->destroyed_ports = 0;
-  s->shutdown = 0;
-  s->shutdown_starting.head = NULL;
-  s->shutdown_starting.tail = NULL;
-  s->shutdown_complete = shutdown_complete;
-  s->on_accept_cb = NULL;
-  s->on_accept_cb_arg = NULL;
-  s->head = NULL;
-  s->tail = NULL;
-  s->nports = 0;
-  return s;
-}
-
-static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  if (s->shutdown_complete != NULL) {
-    grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL);
-  }
-
-  gpr_mu_destroy(&s->mu);
-
-  while (s->head) {
-    grpc_tcp_listener *sp = s->head;
-    s->head = sp->next;
-    gpr_free(sp);
-  }
-
-  gpr_free(s);
-}
-
-static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
-                           bool success) {
-  grpc_tcp_server *s = server;
-  gpr_mu_lock(&s->mu);
-  s->destroyed_ports++;
-  if (s->destroyed_ports == s->nports) {
-    gpr_mu_unlock(&s->mu);
-    finish_shutdown(exec_ctx, s);
-  } else {
-    GPR_ASSERT(s->destroyed_ports < s->nports);
-    gpr_mu_unlock(&s->mu);
-  }
-}
-
-/* called when all listening endpoints have been shutdown, so no further
-   events will be received on them - at this point it's safe to destroy
-   things */
-static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  /* delete ALL the things */
-  gpr_mu_lock(&s->mu);
-
-  if (!s->shutdown) {
-    gpr_mu_unlock(&s->mu);
-    return;
-  }
-
-  if (s->head) {
-    grpc_tcp_listener *sp;
-    for (sp = s->head; sp; sp = sp->next) {
-      if (sp->addr.sockaddr.sa_family == AF_UNIX) {
-        unlink_if_unix_domain_socket(&sp->addr.un);
-      }
-      sp->destroyed_closure.cb = destroyed_port;
-      sp->destroyed_closure.cb_arg = s;
-      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
-                     "tcp_listener_shutdown");
-    }
-    gpr_mu_unlock(&s->mu);
-  } else {
-    gpr_mu_unlock(&s->mu);
-    finish_shutdown(exec_ctx, s);
-  }
-}
-
-static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  gpr_mu_lock(&s->mu);
-
-  GPR_ASSERT(!s->shutdown);
-  s->shutdown = 1;
-
-  /* shutdown all fd's */
-  if (s->active_ports) {
-    grpc_tcp_listener *sp;
-    for (sp = s->head; sp; sp = sp->next) {
-      grpc_fd_shutdown(exec_ctx, sp->emfd);
-    }
-    gpr_mu_unlock(&s->mu);
-  } else {
-    gpr_mu_unlock(&s->mu);
-    deactivated_all_ports(exec_ctx, s);
-  }
-}
-
-/* get max listen queue size on linux */
-static void init_max_accept_queue_size(void) {
-  int n = SOMAXCONN;
-  char buf[64];
-  FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
-  if (fp == NULL) {
-    /* 2.4 kernel. */
-    s_max_accept_queue_size = SOMAXCONN;
-    return;
-  }
-  if (fgets(buf, sizeof buf, fp)) {
-    char *end;
-    long i = strtol(buf, &end, 10);
-    if (i > 0 && i <= INT_MAX && end && *end == 0) {
-      n = (int)i;
-    }
-  }
-  fclose(fp);
-  s_max_accept_queue_size = n;
-
-  if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
-    gpr_log(GPR_INFO,
-            "Suspiciously small accept queue (%d) will probably lead to "
-            "connection drops",
-            s_max_accept_queue_size);
-  }
-}
-
-static int get_max_accept_queue_size(void) {
-  gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
-  return s_max_accept_queue_size;
-}
-
-/* Prepare a recently-created socket for listening. */
-static int prepare_socket(int fd, const struct sockaddr *addr,
-                          size_t addr_len) {
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
-
-  if (fd < 0) {
-    goto error;
-  }
-
-  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
-      (addr->sa_family != AF_UNIX && (!grpc_set_socket_low_latency(fd, 1) ||
-                                      !grpc_set_socket_reuse_addr(fd, 1))) ||
-      !grpc_set_socket_no_sigpipe_if_possible(fd)) {
-    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
-            strerror(errno));
-    goto error;
-  }
-
-  GPR_ASSERT(addr_len < ~(socklen_t)0);
-  if (bind(fd, addr, (socklen_t)addr_len) < 0) {
-    char *addr_str;
-    grpc_sockaddr_to_string(&addr_str, addr, 0);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
-    gpr_free(addr_str);
-    goto error;
-  }
-
-  if (listen(fd, get_max_accept_queue_size()) < 0) {
-    gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
-    goto error;
-  }
-
-  sockname_len = sizeof(sockname_temp);
-  if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
-    goto error;
-  }
-
-  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
-
-error:
-  if (fd >= 0) {
-    close(fd);
-  }
-  return -1;
-}
-
-/* event manager callback when reads are ready */
-static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  grpc_tcp_listener *sp = arg;
-  grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index,
-                                       sp->fd_index};
-  grpc_fd *fdobj;
-  size_t i;
-
-  if (!success) {
-    goto error;
-  }
-
-  /* loop until accept4 returns EAGAIN, and then re-arm notification */
-  for (;;) {
-    struct sockaddr_storage addr;
-    socklen_t addrlen = sizeof(addr);
-    char *addr_str;
-    char *name;
-    /* Note: If we ever decide to return this address to the user, remember to
-       strip off the ::ffff:0.0.0.0/96 prefix first. */
-    int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
-    if (fd < 0) {
-      switch (errno) {
-        case EINTR:
-          continue;
-        case EAGAIN:
-          grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
-          return;
-        default:
-          gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
-          goto error;
-      }
-    }
-
-    grpc_set_socket_no_sigpipe_if_possible(fd);
-
-    addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
-    gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
-
-    if (grpc_tcp_trace) {
-      gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
-    }
-
-    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);
-    }
-    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);
-
-    gpr_free(name);
-    gpr_free(addr_str);
-  }
-
-  GPR_UNREACHABLE_CODE(return );
-
-error:
-  gpr_mu_lock(&sp->server->mu);
-  if (0 == --sp->server->active_ports) {
-    gpr_mu_unlock(&sp->server->mu);
-    deactivated_all_ports(exec_ctx, sp->server);
-  } else {
-    gpr_mu_unlock(&sp->server->mu);
-  }
-}
-
-static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
-                                               const struct sockaddr *addr,
-                                               size_t addr_len,
-                                               unsigned port_index,
-                                               unsigned fd_index) {
-  grpc_tcp_listener *sp = NULL;
-  int port;
-  char *addr_str;
-  char *name;
-
-  port = prepare_socket(fd, addr, addr_len);
-  if (port >= 0) {
-    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
-    gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
-    gpr_mu_lock(&s->mu);
-    s->nports++;
-    GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
-    sp = gpr_malloc(sizeof(grpc_tcp_listener));
-    sp->next = NULL;
-    if (s->head == NULL) {
-      s->head = sp;
-    } else {
-      s->tail->next = sp;
-    }
-    s->tail = sp;
-    sp->server = s;
-    sp->fd = fd;
-    sp->emfd = grpc_fd_create(fd, name);
-    memcpy(sp->addr.untyped, addr, addr_len);
-    sp->addr_len = addr_len;
-    sp->port = port;
-    sp->port_index = port_index;
-    sp->fd_index = fd_index;
-    sp->is_sibling = 0;
-    sp->sibling = NULL;
-    GPR_ASSERT(sp->emfd);
-    gpr_mu_unlock(&s->mu);
-    gpr_free(addr_str);
-    gpr_free(name);
-  }
-
-  return sp;
-}
-
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len) {
-  grpc_tcp_listener *sp;
-  grpc_tcp_listener *sp2 = NULL;
-  int fd;
-  grpc_dualstack_mode dsmode;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in wild4;
-  struct sockaddr_in6 wild6;
-  struct sockaddr_in addr4_copy;
-  struct sockaddr *allocated_addr = NULL;
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
-  int port;
-  unsigned port_index = 0;
-  unsigned fd_index = 0;
-  if (s->tail != NULL) {
-    port_index = s->tail->port_index + 1;
-  }
-  if (((struct sockaddr *)addr)->sa_family == AF_UNIX) {
-    unlink_if_unix_domain_socket(addr);
-  }
-
-  /* Check if this is a wildcard port, and if so, try to keep the port the same
-     as some previously created listener. */
-  if (grpc_sockaddr_get_port(addr) == 0) {
-    for (sp = s->head; sp; sp = sp->next) {
-      sockname_len = sizeof(sockname_temp);
-      if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
-                           &sockname_len)) {
-        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
-        if (port > 0) {
-          allocated_addr = malloc(addr_len);
-          memcpy(allocated_addr, addr, addr_len);
-          grpc_sockaddr_set_port(allocated_addr, port);
-          addr = allocated_addr;
-          break;
-        }
-      }
-    }
-  }
-
-  sp = NULL;
-
-  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
-  }
-
-  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
-  if (grpc_sockaddr_is_wildcard(addr, &port)) {
-    grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
-
-    /* Try listening on IPv6 first. */
-    addr = (struct sockaddr *)&wild6;
-    addr_len = sizeof(wild6);
-    fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-    sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
-    if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
-      goto done;
-    }
-    if (sp != NULL) {
-      ++fd_index;
-    }
-    /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-    if (port == 0 && sp != NULL) {
-      grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
-      sp2 = sp;
-    }
-    addr = (struct sockaddr *)&wild4;
-    addr_len = sizeof(wild4);
-  }
-
-  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-  if (fd < 0) {
-    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
-  }
-  if (dsmode == GRPC_DSMODE_IPV4 &&
-      grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
-    addr = (struct sockaddr *)&addr4_copy;
-    addr_len = sizeof(addr4_copy);
-  }
-  sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
-  if (sp2 != NULL && sp != NULL) {
-    sp2->sibling = sp;
-    sp->is_sibling = 1;
-  }
-
-done:
-  gpr_free(allocated_addr);
-  if (sp != NULL) {
-    return sp->port;
-  } else {
-    return -1;
-  }
-}
-
-unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
-                                       unsigned port_index) {
-  unsigned num_fds = 0;
-  grpc_tcp_listener *sp;
-  for (sp = s->head; sp && port_index != 0; sp = sp->next) {
-    if (!sp->is_sibling) {
-      --port_index;
-    }
-  }
-  for (; sp; sp = sp->sibling, ++num_fds)
-    ;
-  return num_fds;
-}
-
-int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
-                            unsigned fd_index) {
-  grpc_tcp_listener *sp;
-  for (sp = s->head; sp && port_index != 0; sp = sp->next) {
-    if (!sp->is_sibling) {
-      --port_index;
-    }
-  }
-  for (; sp && fd_index != 0; sp = sp->sibling, --fd_index)
-    ;
-  if (sp) {
-    return sp->fd;
-  } else {
-    return -1;
-  }
-}
-
-void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
-                           grpc_pollset **pollsets, size_t pollset_count,
-                           grpc_tcp_server_cb on_accept_cb,
-                           void *on_accept_cb_arg) {
-  size_t i;
-  grpc_tcp_listener *sp;
-  GPR_ASSERT(on_accept_cb);
-  gpr_mu_lock(&s->mu);
-  GPR_ASSERT(!s->on_accept_cb);
-  GPR_ASSERT(s->active_ports == 0);
-  s->on_accept_cb = on_accept_cb;
-  s->on_accept_cb_arg = on_accept_cb_arg;
-  s->pollsets = pollsets;
-  s->pollset_count = pollset_count;
-  for (sp = s->head; sp; sp = sp->next) {
-    for (i = 0; i < pollset_count; i++) {
-      grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
-    }
-    sp->read_closure.cb = on_read;
-    sp->read_closure.cb_arg = sp;
-    grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
-    s->active_ports++;
-  }
-  gpr_mu_unlock(&s->mu);
-}
-
-grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
-  gpr_ref(&s->refs);
-  return s;
-}
-
-void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
-                                           grpc_closure *shutdown_starting) {
-  gpr_mu_lock(&s->mu);
-  grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1);
-  gpr_mu_unlock(&s->mu);
-}
-
-void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  if (gpr_unref(&s->refs)) {
-    /* Complete shutdown_starting work before destroying. */
-    grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT;
-    gpr_mu_lock(&s->mu);
-    grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL);
-    gpr_mu_unlock(&s->mu);
-    if (exec_ctx == NULL) {
-      grpc_exec_ctx_flush(&local_exec_ctx);
-      tcp_server_destroy(&local_exec_ctx, s);
-      grpc_exec_ctx_finish(&local_exec_ctx);
-    } else {
-      grpc_exec_ctx_finish(&local_exec_ctx);
-      tcp_server_destroy(exec_ctx, s);
-    }
-  }
-}
-
-#endif
diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c
deleted file mode 100644
index a4abc5b..0000000
--- a/src/core/iomgr/tcp_server_windows.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WINSOCK_SOCKET
-
-#include <io.h>
-
-#include "src/core/iomgr/sockaddr_utils.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/log_win32.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-#include "src/core/iomgr/iocp_windows.h"
-#include "src/core/iomgr/pollset_windows.h"
-#include "src/core/iomgr/socket_windows.h"
-#include "src/core/iomgr/tcp_server.h"
-#include "src/core/iomgr/tcp_windows.h"
-
-#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
-
-/* one listening port */
-typedef struct grpc_tcp_listener grpc_tcp_listener;
-struct grpc_tcp_listener {
-  /* This seemingly magic number comes from AcceptEx's documentation. each
-     address buffer needs to have at least 16 more bytes at their end. */
-  uint8_t addresses[(sizeof(struct sockaddr_in6) + 16) * 2];
-  /* This will hold the socket for the next accept. */
-  SOCKET new_socket;
-  /* The listener winsocket. */
-  grpc_winsocket *socket;
-  /* The actual TCP port number. */
-  int port;
-  unsigned port_index;
-  grpc_tcp_server *server;
-  /* The cached AcceptEx for that port. */
-  LPFN_ACCEPTEX AcceptEx;
-  int shutting_down;
-  /* closure for socket notification of accept being ready */
-  grpc_closure on_accept;
-  /* linked list */
-  struct grpc_tcp_listener *next;
-};
-
-/* the overall server */
-struct grpc_tcp_server {
-  gpr_refcount refs;
-  /* Called whenever accept() succeeds on a server port. */
-  grpc_tcp_server_cb on_accept_cb;
-  void *on_accept_cb_arg;
-
-  gpr_mu mu;
-
-  /* active port count: how many ports are actually still listening */
-  int active_ports;
-
-  /* linked list of server ports */
-  grpc_tcp_listener *head;
-  grpc_tcp_listener *tail;
-
-  /* List of closures passed to shutdown_starting_add(). */
-  grpc_closure_list shutdown_starting;
-
-  /* shutdown callback */
-  grpc_closure *shutdown_complete;
-};
-
-/* Public function. Allocates the proper data structures to hold a
-   grpc_tcp_server. */
-grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
-  grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
-  gpr_ref_init(&s->refs, 1);
-  gpr_mu_init(&s->mu);
-  s->active_ports = 0;
-  s->on_accept_cb = NULL;
-  s->on_accept_cb_arg = NULL;
-  s->head = NULL;
-  s->tail = NULL;
-  s->shutdown_starting.head = NULL;
-  s->shutdown_starting.tail = NULL;
-  s->shutdown_complete = shutdown_complete;
-  return s;
-}
-
-static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  if (s->shutdown_complete != NULL) {
-    grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL);
-  }
-
-  /* Now that the accepts have been aborted, we can destroy the sockets.
-     The IOCP won't get notified on these, so we can flag them as already
-     closed by the system. */
-  while (s->head) {
-    grpc_tcp_listener *sp = s->head;
-    s->head = sp->next;
-    sp->next = NULL;
-    grpc_winsocket_destroy(sp->socket);
-    gpr_free(sp);
-  }
-  gpr_free(s);
-}
-
-grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
-  gpr_ref(&s->refs);
-  return s;
-}
-
-void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
-                                           grpc_closure *shutdown_starting) {
-  gpr_mu_lock(&s->mu);
-  grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1);
-  gpr_mu_unlock(&s->mu);
-}
-
-static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  int immediately_done = 0;
-  grpc_tcp_listener *sp;
-  gpr_mu_lock(&s->mu);
-
-  /* First, shutdown all fd's. This will queue abortion calls for all
-     of the pending accepts due to the normal operation mechanism. */
-  if (s->active_ports == 0) {
-    immediately_done = 1;
-  }
-  for (sp = s->head; sp; sp = sp->next) {
-    sp->shutting_down = 1;
-    grpc_winsocket_shutdown(sp->socket);
-  }
-  gpr_mu_unlock(&s->mu);
-
-  if (immediately_done) {
-    finish_shutdown(exec_ctx, s);
-  }
-}
-
-void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  if (gpr_unref(&s->refs)) {
-    /* Complete shutdown_starting work before destroying. */
-    grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT;
-    gpr_mu_lock(&s->mu);
-    grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL);
-    gpr_mu_unlock(&s->mu);
-    if (exec_ctx == NULL) {
-      grpc_exec_ctx_flush(&local_exec_ctx);
-      tcp_server_destroy(&local_exec_ctx, s);
-      grpc_exec_ctx_finish(&local_exec_ctx);
-    } else {
-      grpc_exec_ctx_finish(&local_exec_ctx);
-      tcp_server_destroy(exec_ctx, s);
-    }
-  }
-}
-
-/* Prepare (bind) a recently-created socket for listening. */
-static int prepare_socket(SOCKET sock, const struct sockaddr *addr,
-                          size_t addr_len) {
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
-
-  if (sock == INVALID_SOCKET) goto error;
-
-  if (!grpc_tcp_prepare_socket(sock)) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "Unable to prepare socket: %s", utf8_message);
-    gpr_free(utf8_message);
-    goto error;
-  }
-
-  if (bind(sock, addr, (int)addr_len) == SOCKET_ERROR) {
-    char *addr_str;
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    grpc_sockaddr_to_string(&addr_str, addr, 0);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, utf8_message);
-    gpr_free(utf8_message);
-    gpr_free(addr_str);
-    goto error;
-  }
-
-  if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "listen: %s", utf8_message);
-    gpr_free(utf8_message);
-    goto error;
-  }
-
-  sockname_len = sizeof(sockname_temp);
-  if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) ==
-      SOCKET_ERROR) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "getsockname: %s", utf8_message);
-    gpr_free(utf8_message);
-    goto error;
-  }
-
-  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
-
-error:
-  if (sock != INVALID_SOCKET) closesocket(sock);
-  return -1;
-}
-
-static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
-                                              grpc_tcp_listener *sp) {
-  int notify = 0;
-  sp->shutting_down = 0;
-  gpr_mu_lock(&sp->server->mu);
-  GPR_ASSERT(sp->server->active_ports > 0);
-  if (0 == --sp->server->active_ports) {
-    notify = 1;
-  }
-  gpr_mu_unlock(&sp->server->mu);
-  if (notify) {
-    finish_shutdown(exec_ctx, sp->server);
-  }
-}
-
-/* In order to do an async accept, we need to create a socket first which
-   will be the one assigned to the new incoming connection. */
-static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) {
-  SOCKET sock = INVALID_SOCKET;
-  char *message;
-  char *utf8_message;
-  BOOL success;
-  DWORD addrlen = sizeof(struct sockaddr_in6) + 16;
-  DWORD bytes_received = 0;
-
-  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
-                   WSA_FLAG_OVERLAPPED);
-
-  if (sock == INVALID_SOCKET) {
-    message = "Unable to create socket: %s";
-    goto failure;
-  }
-
-  if (!grpc_tcp_prepare_socket(sock)) {
-    message = "Unable to prepare socket: %s";
-    goto failure;
-  }
-
-  /* Start the "accept" asynchronously. */
-  success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0,
-                           addrlen, addrlen, &bytes_received,
-                           &port->socket->read_info.overlapped);
-
-  /* It is possible to get an accept immediately without delay. However, we
-     will still get an IOCP notification for it. So let's just ignore it. */
-  if (!success) {
-    int error = WSAGetLastError();
-    if (error != ERROR_IO_PENDING) {
-      message = "AcceptEx failed: %s";
-      goto failure;
-    }
-  }
-
-  /* We're ready to do the accept. Calling grpc_socket_notify_on_read may
-     immediately process an accept that happened in the meantime. */
-  port->new_socket = sock;
-  grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
-  return;
-
-failure:
-  if (port->shutting_down) {
-    /* We are abandoning the listener port, take that into account to prevent
-       occasional hangs on shutdown. The hang happens when sp->shutting_down
-       change is not seen by on_accept and we proceed to trying new accept,
-       but we fail there because the listening port has been closed in the
-       meantime. */
-    decrement_active_ports_and_notify(exec_ctx, port);
-    return;
-  }
-  utf8_message = gpr_format_message(WSAGetLastError());
-  gpr_log(GPR_ERROR, message, utf8_message);
-  gpr_free(utf8_message);
-  if (sock != INVALID_SOCKET) closesocket(sock);
-}
-
-/* Event manager callback when reads are ready. */
-static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, bool from_iocp) {
-  grpc_tcp_listener *sp = arg;
-  grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0};
-  SOCKET sock = sp->new_socket;
-  grpc_winsocket_callback_info *info = &sp->socket->read_info;
-  grpc_endpoint *ep = NULL;
-  struct sockaddr_storage peer_name;
-  char *peer_name_string;
-  char *fd_name;
-  int peer_name_len = sizeof(peer_name);
-  DWORD transfered_bytes;
-  DWORD flags;
-  BOOL wsa_success;
-  int err;
-
-  /* The general mechanism for shutting down is to queue abortion calls. While
-     this is necessary in the read/write case, it's useless for the accept
-     case. We only need to adjust the pending callback count */
-  if (!from_iocp) {
-    return;
-  }
-
-  /* The IOCP notified us of a completed operation. Let's grab the results,
-     and act accordingly. */
-  transfered_bytes = 0;
-  wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
-                                       &transfered_bytes, FALSE, &flags);
-  if (!wsa_success) {
-    if (sp->shutting_down) {
-      /* During the shutdown case, we ARE expecting an error. So that's well,
-         and we can wake up the shutdown thread. */
-      decrement_active_ports_and_notify(exec_ctx, sp);
-      return;
-    } else {
-      char *utf8_message = gpr_format_message(WSAGetLastError());
-      gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
-      gpr_free(utf8_message);
-      closesocket(sock);
-    }
-  } else {
-    if (!sp->shutting_down) {
-      peer_name_string = NULL;
-      err = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
-                       (char *)&sp->socket->socket, sizeof(sp->socket->socket));
-      if (err) {
-        char *utf8_message = gpr_format_message(WSAGetLastError());
-        gpr_log(GPR_ERROR, "setsockopt error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-      err = getpeername(sock, (struct sockaddr *)&peer_name, &peer_name_len);
-      if (!err) {
-        peer_name_string = grpc_sockaddr_to_uri((struct sockaddr *)&peer_name);
-      } else {
-        char *utf8_message = gpr_format_message(WSAGetLastError());
-        gpr_log(GPR_ERROR, "getpeername error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-      gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string);
-      ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name),
-                           peer_name_string);
-      gpr_free(fd_name);
-      gpr_free(peer_name_string);
-    } else {
-      closesocket(sock);
-    }
-  }
-
-  /* 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,
-                             &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
-     connection. */
-  start_accept(exec_ctx, sp);
-}
-
-static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
-                                               const struct sockaddr *addr,
-                                               size_t addr_len,
-                                               unsigned port_index) {
-  grpc_tcp_listener *sp = NULL;
-  int port;
-  int status;
-  GUID guid = WSAID_ACCEPTEX;
-  DWORD ioctl_num_bytes;
-  LPFN_ACCEPTEX AcceptEx;
-
-  if (sock == INVALID_SOCKET) return NULL;
-
-  /* We need to grab the AcceptEx pointer for that port, as it may be
-     interface-dependent. We'll cache it to avoid doing that again. */
-  status =
-      WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
-               &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL);
-
-  if (status != 0) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
-    gpr_free(utf8_message);
-    closesocket(sock);
-    return NULL;
-  }
-
-  port = prepare_socket(sock, addr, addr_len);
-  if (port >= 0) {
-    gpr_mu_lock(&s->mu);
-    GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
-    sp = gpr_malloc(sizeof(grpc_tcp_listener));
-    sp->next = NULL;
-    if (s->head == NULL) {
-      s->head = sp;
-    } else {
-      s->tail->next = sp;
-    }
-    s->tail = sp;
-    sp->server = s;
-    sp->socket = grpc_winsocket_create(sock, "listener");
-    sp->shutting_down = 0;
-    sp->AcceptEx = AcceptEx;
-    sp->new_socket = INVALID_SOCKET;
-    sp->port = port;
-    sp->port_index = port_index;
-    grpc_closure_init(&sp->on_accept, on_accept, sp);
-    GPR_ASSERT(sp->socket);
-    gpr_mu_unlock(&s->mu);
-  }
-
-  return sp;
-}
-
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len) {
-  grpc_tcp_listener *sp;
-  SOCKET sock;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in6 wildcard;
-  struct sockaddr *allocated_addr = NULL;
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
-  int port;
-  unsigned port_index = 0;
-  if (s->tail != NULL) {
-    port_index = s->tail->port_index + 1;
-  }
-
-  /* Check if this is a wildcard port, and if so, try to keep the port the same
-     as some previously created listener. */
-  if (grpc_sockaddr_get_port(addr) == 0) {
-    for (sp = s->head; sp; sp = sp->next) {
-      sockname_len = sizeof(sockname_temp);
-      if (0 == getsockname(sp->socket->socket,
-                           (struct sockaddr *)&sockname_temp, &sockname_len)) {
-        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
-        if (port > 0) {
-          allocated_addr = malloc(addr_len);
-          memcpy(allocated_addr, addr, addr_len);
-          grpc_sockaddr_set_port(allocated_addr, port);
-          addr = allocated_addr;
-          break;
-        }
-      }
-    }
-  }
-
-  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
-  }
-
-  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
-  if (grpc_sockaddr_is_wildcard(addr, &port)) {
-    grpc_sockaddr_make_wildcard6(port, &wildcard);
-
-    addr = (struct sockaddr *)&wildcard;
-    addr_len = sizeof(wildcard);
-  }
-
-  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
-                   WSA_FLAG_OVERLAPPED);
-  if (sock == INVALID_SOCKET) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "unable to create socket: %s", utf8_message);
-    gpr_free(utf8_message);
-  }
-
-  sp = add_socket_to_server(s, sock, addr, addr_len, port_index);
-  gpr_free(allocated_addr);
-
-  if (sp) {
-    return sp->port;
-  } else {
-    return -1;
-  }
-}
-
-unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
-                                       unsigned port_index) {
-  grpc_tcp_listener *sp;
-  for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
-    ;
-  if (sp) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
-                            unsigned fd_index) {
-  grpc_tcp_listener *sp;
-  if (fd_index != 0) {
-    /* Windows implementation has only one fd per port_index. */
-    return -1;
-  }
-  for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
-    ;
-  if (sp) {
-    return _open_osfhandle((intptr_t)sp->socket->socket, 0);
-  } else {
-    return -1;
-  }
-}
-
-void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
-                           grpc_pollset **pollset, size_t pollset_count,
-                           grpc_tcp_server_cb on_accept_cb,
-                           void *on_accept_cb_arg) {
-  grpc_tcp_listener *sp;
-  GPR_ASSERT(on_accept_cb);
-  gpr_mu_lock(&s->mu);
-  GPR_ASSERT(!s->on_accept_cb);
-  GPR_ASSERT(s->active_ports == 0);
-  s->on_accept_cb = on_accept_cb;
-  s->on_accept_cb_arg = on_accept_cb_arg;
-  for (sp = s->head; sp; sp = sp->next) {
-    start_accept(exec_ctx, sp);
-    s->active_ports++;
-  }
-  gpr_mu_unlock(&s->mu);
-}
-
-#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c
deleted file mode 100644
index 038e415..0000000
--- a/src/core/iomgr/tcp_windows.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WINSOCK_SOCKET
-
-#include "src/core/iomgr/sockaddr_win32.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/log_win32.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/iomgr/timer.h"
-#include "src/core/iomgr/iocp_windows.h"
-#include "src/core/iomgr/sockaddr.h"
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/iomgr/socket_windows.h"
-#include "src/core/iomgr/tcp_client.h"
-
-static int set_non_block(SOCKET sock) {
-  int status;
-  unsigned long param = 1;
-  DWORD ret;
-  status =
-      WSAIoctl(sock, FIONBIO, &param, sizeof(param), NULL, 0, &ret, NULL, NULL);
-  return status == 0;
-}
-
-static int set_dualstack(SOCKET sock) {
-  int status;
-  unsigned long param = 0;
-  status = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&param,
-                      sizeof(param));
-  return status == 0;
-}
-
-int grpc_tcp_prepare_socket(SOCKET sock) {
-  if (!set_non_block(sock)) return 0;
-  if (!set_dualstack(sock)) return 0;
-  return 1;
-}
-
-typedef struct grpc_tcp {
-  /* This is our C++ class derivation emulation. */
-  grpc_endpoint base;
-  /* The one socket this endpoint is using. */
-  grpc_winsocket *socket;
-  /* Refcounting how many operations are in progress. */
-  gpr_refcount refcount;
-
-  grpc_closure on_read;
-  grpc_closure on_write;
-
-  grpc_closure *read_cb;
-  grpc_closure *write_cb;
-  gpr_slice read_slice;
-  gpr_slice_buffer *write_slices;
-  gpr_slice_buffer *read_slices;
-
-  /* The IO Completion Port runs from another thread. We need some mechanism
-     to protect ourselves when requesting a shutdown. */
-  gpr_mu mu;
-  int shutting_down;
-
-  char *peer_string;
-} grpc_tcp;
-
-static void tcp_free(grpc_tcp *tcp) {
-  grpc_winsocket_destroy(tcp->socket);
-  gpr_mu_destroy(&tcp->mu);
-  gpr_free(tcp->peer_string);
-  gpr_free(tcp);
-}
-
-/*#define GRPC_TCP_REFCOUNT_DEBUG*/
-#ifdef GRPC_TCP_REFCOUNT_DEBUG
-#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__)
-#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
-static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file,
-                      int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
-          reason, tcp->refcount.count, tcp->refcount.count - 1);
-  if (gpr_unref(&tcp->refcount)) {
-    tcp_free(tcp);
-  }
-}
-
-static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
-                    int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP   ref %p : %s %d -> %d", tcp,
-          reason, tcp->refcount.count, tcp->refcount.count + 1);
-  gpr_ref(&tcp->refcount);
-}
-#else
-#define TCP_UNREF(tcp, reason) tcp_unref((tcp))
-#define TCP_REF(tcp, reason) tcp_ref((tcp))
-static void tcp_unref(grpc_tcp *tcp) {
-  if (gpr_unref(&tcp->refcount)) {
-    tcp_free(tcp);
-  }
-}
-
-static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
-#endif
-
-/* Asynchronous callback from the IOCP, or the background thread. */
-static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) {
-  grpc_tcp *tcp = tcpp;
-  grpc_closure *cb = tcp->read_cb;
-  grpc_winsocket *socket = tcp->socket;
-  gpr_slice sub;
-  grpc_winsocket_callback_info *info = &socket->read_info;
-
-  if (success) {
-    if (socket->read_info.wsa_error != 0 && !tcp->shutting_down) {
-      if (socket->read_info.wsa_error != WSAECONNRESET) {
-        char *utf8_message = gpr_format_message(info->wsa_error);
-        gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-      success = 0;
-      gpr_slice_unref(tcp->read_slice);
-    } else {
-      if (info->bytes_transfered != 0 && !tcp->shutting_down) {
-        sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
-        gpr_slice_buffer_add(tcp->read_slices, sub);
-        success = 1;
-      } else {
-        gpr_slice_unref(tcp->read_slice);
-        success = 0;
-      }
-    }
-  }
-
-  tcp->read_cb = NULL;
-  TCP_UNREF(tcp, "read");
-  if (cb) {
-    cb->cb(exec_ctx, cb->cb_arg, success);
-  }
-}
-
-static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                     gpr_slice_buffer *read_slices, grpc_closure *cb) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  grpc_winsocket *handle = tcp->socket;
-  grpc_winsocket_callback_info *info = &handle->read_info;
-  int status;
-  DWORD bytes_read = 0;
-  DWORD flags = 0;
-  WSABUF buffer;
-
-  if (tcp->shutting_down) {
-    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
-    return;
-  }
-
-  tcp->read_cb = cb;
-  tcp->read_slices = read_slices;
-  gpr_slice_buffer_reset_and_unref(read_slices);
-
-  tcp->read_slice = gpr_slice_malloc(8192);
-
-  buffer.len = (ULONG)GPR_SLICE_LENGTH(
-      tcp->read_slice);  // we know slice size fits in 32bit.
-  buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice);
-
-  TCP_REF(tcp, "read");
-
-  /* First let's try a synchronous, non-blocking read. */
-  status =
-      WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL);
-  info->wsa_error = status == 0 ? 0 : WSAGetLastError();
-
-  /* Did we get data immediately ? Yay. */
-  if (info->wsa_error != WSAEWOULDBLOCK) {
-    info->bytes_transfered = bytes_read;
-    grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, true, NULL);
-    return;
-  }
-
-  /* Otherwise, let's retry, by queuing a read. */
-  memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED));
-  status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags,
-                   &info->overlapped, NULL);
-
-  if (status != 0) {
-    int wsa_error = WSAGetLastError();
-    if (wsa_error != WSA_IO_PENDING) {
-      info->wsa_error = wsa_error;
-      grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, false, NULL);
-      return;
-    }
-  }
-
-  grpc_socket_notify_on_read(exec_ctx, tcp->socket, &tcp->on_read);
-}
-
-/* Asynchronous callback from the IOCP, or the background thread. */
-static void on_write(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) {
-  grpc_tcp *tcp = (grpc_tcp *)tcpp;
-  grpc_winsocket *handle = tcp->socket;
-  grpc_winsocket_callback_info *info = &handle->write_info;
-  grpc_closure *cb;
-
-  gpr_mu_lock(&tcp->mu);
-  cb = tcp->write_cb;
-  tcp->write_cb = NULL;
-  gpr_mu_unlock(&tcp->mu);
-
-  if (success) {
-    if (info->wsa_error != 0) {
-      if (info->wsa_error != WSAECONNRESET) {
-        char *utf8_message = gpr_format_message(info->wsa_error);
-        gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-      success = 0;
-    } else {
-      GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length);
-    }
-  }
-
-  TCP_UNREF(tcp, "write");
-  cb->cb(exec_ctx, cb->cb_arg, success);
-}
-
-/* Initiates a write. */
-static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                      gpr_slice_buffer *slices, grpc_closure *cb) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  grpc_winsocket *socket = tcp->socket;
-  grpc_winsocket_callback_info *info = &socket->write_info;
-  unsigned i;
-  DWORD bytes_sent;
-  int status;
-  WSABUF local_buffers[16];
-  WSABUF *allocated = NULL;
-  WSABUF *buffers = local_buffers;
-  size_t len;
-
-  if (tcp->shutting_down) {
-    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
-    return;
-  }
-
-  tcp->write_cb = cb;
-  tcp->write_slices = slices;
-  GPR_ASSERT(tcp->write_slices->count <= UINT_MAX);
-  if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) {
-    buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count);
-    allocated = buffers;
-  }
-
-  for (i = 0; i < tcp->write_slices->count; i++) {
-    len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]);
-    GPR_ASSERT(len <= ULONG_MAX);
-    buffers[i].len = (ULONG)len;
-    buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]);
-  }
-
-  /* First, let's try a synchronous, non-blocking write. */
-  status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
-                   &bytes_sent, 0, NULL, NULL);
-  info->wsa_error = status == 0 ? 0 : WSAGetLastError();
-
-  /* We would kind of expect to get a WSAEWOULDBLOCK here, especially on a busy
-     connection that has its send queue filled up. But if we don't, then we can
-     avoid doing an async write operation at all. */
-  if (info->wsa_error != WSAEWOULDBLOCK) {
-    bool ok = false;
-    if (status == 0) {
-      ok = true;
-      GPR_ASSERT(bytes_sent == tcp->write_slices->length);
-    } else {
-      if (socket->read_info.wsa_error != WSAECONNRESET) {
-        char *utf8_message = gpr_format_message(info->wsa_error);
-        gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-    }
-    if (allocated) gpr_free(allocated);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, ok, NULL);
-    return;
-  }
-
-  TCP_REF(tcp, "write");
-
-  /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same
-     operation, this time asynchronously. */
-  memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED));
-  status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
-                   &bytes_sent, 0, &socket->write_info.overlapped, NULL);
-  if (allocated) gpr_free(allocated);
-
-  if (status != 0) {
-    int wsa_error = WSAGetLastError();
-    if (wsa_error != WSA_IO_PENDING) {
-      TCP_UNREF(tcp, "write");
-      grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
-      return;
-    }
-  }
-
-  /* As all is now setup, we can now ask for the IOCP notification. It may
-     trigger the callback immediately however, but no matter. */
-  grpc_socket_notify_on_write(exec_ctx, socket, &tcp->on_write);
-}
-
-static void win_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                               grpc_pollset *ps) {
-  grpc_tcp *tcp;
-  (void)ps;
-  tcp = (grpc_tcp *)ep;
-  grpc_iocp_add_socket(tcp->socket);
-}
-
-static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
-                                   grpc_pollset_set *pss) {
-  grpc_tcp *tcp;
-  (void)pss;
-  tcp = (grpc_tcp *)ep;
-  grpc_iocp_add_socket(tcp->socket);
-}
-
-/* Initiates a shutdown of the TCP endpoint. This will queue abort callbacks
-   for the potential read and write operations. It is up to the caller to
-   guarantee this isn't called in parallel to a read or write request, so
-   we're not going to protect against these. However the IO Completion Port
-   callback will happen from another thread, so we need to protect against
-   concurrent access of the data structure in that regard. */
-static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  gpr_mu_lock(&tcp->mu);
-  /* At that point, what may happen is that we're already inside the IOCP
-     callback. See the comments in on_read and on_write. */
-  tcp->shutting_down = 1;
-  grpc_winsocket_shutdown(tcp->socket);
-  gpr_mu_unlock(&tcp->mu);
-}
-
-static void win_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  TCP_UNREF(tcp, "destroy");
-}
-
-static char *win_get_peer(grpc_endpoint *ep) {
-  grpc_tcp *tcp = (grpc_tcp *)ep;
-  return gpr_strdup(tcp->peer_string);
-}
-
-static grpc_endpoint_vtable vtable = {win_read, win_write, win_add_to_pollset,
-                                      win_add_to_pollset_set, win_shutdown,
-                                      win_destroy, win_get_peer};
-
-grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) {
-  grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
-  memset(tcp, 0, sizeof(grpc_tcp));
-  tcp->base.vtable = &vtable;
-  tcp->socket = socket;
-  gpr_mu_init(&tcp->mu);
-  gpr_ref_init(&tcp->refcount, 1);
-  grpc_closure_init(&tcp->on_read, on_read, tcp);
-  grpc_closure_init(&tcp->on_write, on_write, tcp);
-  tcp->peer_string = gpr_strdup(peer_string);
-  return &tcp->base;
-}
-
-#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/iomgr/tcp_windows.h b/src/core/iomgr/tcp_windows.h
deleted file mode 100644
index 78bc133..0000000
--- a/src/core/iomgr/tcp_windows.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_TCP_WINDOWS_H
-#define GRPC_CORE_IOMGR_TCP_WINDOWS_H
-/*
-   Low level TCP "bottom half" implementation, for use by transports built on
-   top of a TCP connection.
-
-   Note that this file does not (yet) include APIs for creating the socket in
-   the first place.
-
-   All calls passing slice transfer ownership of a slice refcount unless
-   otherwise specified.
-*/
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/socket_windows.h"
-
-/* Create a tcp endpoint given a winsock handle.
- * Takes ownership of the handle.
- */
-grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string);
-
-int grpc_tcp_prepare_socket(SOCKET sock);
-
-#endif /* GRPC_CORE_IOMGR_TCP_WINDOWS_H */
diff --git a/src/core/iomgr/time_averaged_stats.c b/src/core/iomgr/time_averaged_stats.c
deleted file mode 100644
index e075db4..0000000
--- a/src/core/iomgr/time_averaged_stats.c
+++ /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 "src/core/iomgr/time_averaged_stats.h"
-
-void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats,
-                                   double init_avg, double regress_weight,
-                                   double persistence_factor) {
-  stats->init_avg = init_avg;
-  stats->regress_weight = regress_weight;
-  stats->persistence_factor = persistence_factor;
-  stats->batch_total_value = 0;
-  stats->batch_num_samples = 0;
-  stats->aggregate_total_weight = 0;
-  stats->aggregate_weighted_avg = init_avg;
-}
-
-void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats,
-                                         double value) {
-  stats->batch_total_value += value;
-  ++stats->batch_num_samples;
-}
-
-double grpc_time_averaged_stats_update_average(
-    grpc_time_averaged_stats* stats) {
-  /* Start with the current batch: */
-  double weighted_sum = stats->batch_total_value;
-  double total_weight = stats->batch_num_samples;
-  if (stats->regress_weight > 0) {
-    /* Add in the regression towards init_avg_: */
-    weighted_sum += stats->regress_weight * stats->init_avg;
-    total_weight += stats->regress_weight;
-  }
-  if (stats->persistence_factor > 0) {
-    /* Add in the persistence: */
-    const double prev_sample_weight =
-        stats->persistence_factor * stats->aggregate_total_weight;
-    weighted_sum += prev_sample_weight * stats->aggregate_weighted_avg;
-    total_weight += prev_sample_weight;
-  }
-  stats->aggregate_weighted_avg =
-      (total_weight > 0) ? (weighted_sum / total_weight) : stats->init_avg;
-  stats->aggregate_total_weight = total_weight;
-  stats->batch_num_samples = 0;
-  stats->batch_total_value = 0;
-  return stats->aggregate_weighted_avg;
-}
diff --git a/src/core/iomgr/time_averaged_stats.h b/src/core/iomgr/time_averaged_stats.h
deleted file mode 100644
index 048e244..0000000
--- a/src/core/iomgr/time_averaged_stats.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_TIME_AVERAGED_STATS_H
-#define GRPC_CORE_IOMGR_TIME_AVERAGED_STATS_H
-
-/* This tracks a time-decaying weighted average.  It works by collecting
-   batches of samples and then mixing their average into a time-decaying
-   weighted mean.  It is designed for batch operations where we do many adds
-   before updating the average. */
-
-typedef struct {
-  /* The initial average value.  This is the reported average until the first
-     grpc_time_averaged_stats_update_average call.  If a positive regress_weight
-     is used, we also regress towards this value on each update. */
-  double init_avg;
-  /* The sample weight of "init_avg" that is mixed in with each call to
-     grpc_time_averaged_stats_update_average.  If the calls to
-     grpc_time_averaged_stats_add_sample stop, this will cause the average to
-     regress back to the mean.  This should be non-negative.  Set it to 0 to
-     disable the bias.  A value of 1 has the effect of adding in 1 bonus sample
-     with value init_avg to each sample period. */
-  double regress_weight;
-  /* This determines the rate of decay of the time-averaging from one period
-     to the next by scaling the aggregate_total_weight of samples from prior
-     periods when combining with the latest period.  It should be in the range
-     [0,1].  A higher value adapts more slowly.  With a value of 0.5, if the
-     batches each have k samples, the samples_in_avg_ will grow to 2 k, so the
-     weighting of the time average will eventually be 1/3 new batch and 2/3
-     old average. */
-  double persistence_factor;
-
-  /* The total value of samples since the last UpdateAverage(). */
-  double batch_total_value;
-  /* The number of samples since the last UpdateAverage(). */
-  double batch_num_samples;
-  /* The time-decayed sum of batch_num_samples_ over previous batches.  This is
-     the "weight" of the old aggregate_weighted_avg_ when updating the
-     average. */
-  double aggregate_total_weight;
-  /* A time-decayed average of the (batch_total_value_ / batch_num_samples_),
-     computed by decaying the samples_in_avg_ weight in the weighted average. */
-  double aggregate_weighted_avg;
-} grpc_time_averaged_stats;
-
-/* See the comments on the members above for an explanation of init_avg,
-   regress_weight, and persistence_factor. */
-void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats,
-                                   double init_avg, double regress_weight,
-                                   double persistence_factor);
-/* Add a sample to the current batch. */
-void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats,
-                                         double value);
-/* Complete a batch and compute the new estimate of the average sample
-   value. */
-double grpc_time_averaged_stats_update_average(grpc_time_averaged_stats* stats);
-
-#endif /* GRPC_CORE_IOMGR_TIME_AVERAGED_STATS_H */
diff --git a/src/core/iomgr/timer.c b/src/core/iomgr/timer.c
deleted file mode 100644
index f444643..0000000
--- a/src/core/iomgr/timer.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- *
- * 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/iomgr/timer.h"
-
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/useful.h>
-#include "src/core/iomgr/time_averaged_stats.h"
-#include "src/core/iomgr/timer_heap.h"
-
-#define INVALID_HEAP_INDEX 0xffffffffu
-
-#define LOG2_NUM_SHARDS 5
-#define NUM_SHARDS (1 << LOG2_NUM_SHARDS)
-#define ADD_DEADLINE_SCALE 0.33
-#define MIN_QUEUE_WINDOW_DURATION 0.01
-#define MAX_QUEUE_WINDOW_DURATION 1
-
-typedef struct {
-  gpr_mu mu;
-  grpc_time_averaged_stats stats;
-  /* All and only timers with deadlines <= this will be in the heap. */
-  gpr_timespec queue_deadline_cap;
-  gpr_timespec min_deadline;
-  /* Index in the g_shard_queue */
-  uint32_t shard_queue_index;
-  /* This holds all timers with deadlines < queue_deadline_cap. Timers in this
-     list have the top bit of their deadline set to 0. */
-  grpc_timer_heap heap;
-  /* This holds timers whose deadline is >= queue_deadline_cap. */
-  grpc_timer list;
-} shard_type;
-
-/* Protects g_shard_queue */
-static gpr_mu g_mu;
-/* Allow only one run_some_expired_timers at once */
-static gpr_mu g_checker_mu;
-static gpr_clock_type g_clock_type;
-static shard_type g_shards[NUM_SHARDS];
-/* Protected by g_mu */
-static shard_type *g_shard_queue[NUM_SHARDS];
-
-static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
-                                   gpr_timespec *next, int success);
-
-static gpr_timespec compute_min_deadline(shard_type *shard) {
-  return grpc_timer_heap_is_empty(&shard->heap)
-             ? shard->queue_deadline_cap
-             : grpc_timer_heap_top(&shard->heap)->deadline;
-}
-
-void grpc_timer_list_init(gpr_timespec now) {
-  uint32_t i;
-
-  gpr_mu_init(&g_mu);
-  gpr_mu_init(&g_checker_mu);
-  g_clock_type = now.clock_type;
-
-  for (i = 0; i < NUM_SHARDS; i++) {
-    shard_type *shard = &g_shards[i];
-    gpr_mu_init(&shard->mu);
-    grpc_time_averaged_stats_init(&shard->stats, 1.0 / ADD_DEADLINE_SCALE, 0.1,
-                                  0.5);
-    shard->queue_deadline_cap = now;
-    shard->shard_queue_index = i;
-    grpc_timer_heap_init(&shard->heap);
-    shard->list.next = shard->list.prev = &shard->list;
-    shard->min_deadline = compute_min_deadline(shard);
-    g_shard_queue[i] = shard;
-  }
-}
-
-void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {
-  int i;
-  run_some_expired_timers(exec_ctx, gpr_inf_future(g_clock_type), NULL, 0);
-  for (i = 0; i < NUM_SHARDS; i++) {
-    shard_type *shard = &g_shards[i];
-    gpr_mu_destroy(&shard->mu);
-    grpc_timer_heap_destroy(&shard->heap);
-  }
-  gpr_mu_destroy(&g_mu);
-  gpr_mu_destroy(&g_checker_mu);
-}
-
-/* This is a cheap, but good enough, pointer hash for sharding the tasks: */
-static size_t shard_idx(const grpc_timer *info) {
-  size_t x = (size_t)info;
-  return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (NUM_SHARDS - 1);
-}
-
-static double ts_to_dbl(gpr_timespec ts) {
-  return (double)ts.tv_sec + 1e-9 * ts.tv_nsec;
-}
-
-static gpr_timespec dbl_to_ts(double d) {
-  gpr_timespec ts;
-  ts.tv_sec = (int64_t)d;
-  ts.tv_nsec = (int32_t)(1e9 * (d - (double)ts.tv_sec));
-  ts.clock_type = GPR_TIMESPAN;
-  return ts;
-}
-
-static void list_join(grpc_timer *head, grpc_timer *timer) {
-  timer->next = head;
-  timer->prev = head->prev;
-  timer->next->prev = timer->prev->next = timer;
-}
-
-static void list_remove(grpc_timer *timer) {
-  timer->next->prev = timer->prev;
-  timer->prev->next = timer->next;
-}
-
-static void swap_adjacent_shards_in_queue(uint32_t first_shard_queue_index) {
-  shard_type *temp;
-  temp = g_shard_queue[first_shard_queue_index];
-  g_shard_queue[first_shard_queue_index] =
-      g_shard_queue[first_shard_queue_index + 1];
-  g_shard_queue[first_shard_queue_index + 1] = temp;
-  g_shard_queue[first_shard_queue_index]->shard_queue_index =
-      first_shard_queue_index;
-  g_shard_queue[first_shard_queue_index + 1]->shard_queue_index =
-      first_shard_queue_index + 1;
-}
-
-static void note_deadline_change(shard_type *shard) {
-  while (shard->shard_queue_index > 0 &&
-         gpr_time_cmp(
-             shard->min_deadline,
-             g_shard_queue[shard->shard_queue_index - 1]->min_deadline) < 0) {
-    swap_adjacent_shards_in_queue(shard->shard_queue_index - 1);
-  }
-  while (shard->shard_queue_index < NUM_SHARDS - 1 &&
-         gpr_time_cmp(
-             shard->min_deadline,
-             g_shard_queue[shard->shard_queue_index + 1]->min_deadline) > 0) {
-    swap_adjacent_shards_in_queue(shard->shard_queue_index);
-  }
-}
-
-void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
-                     gpr_timespec deadline, grpc_iomgr_cb_func timer_cb,
-                     void *timer_cb_arg, gpr_timespec now) {
-  int is_first_timer = 0;
-  shard_type *shard = &g_shards[shard_idx(timer)];
-  GPR_ASSERT(deadline.clock_type == g_clock_type);
-  GPR_ASSERT(now.clock_type == g_clock_type);
-  grpc_closure_init(&timer->closure, timer_cb, timer_cb_arg);
-  timer->deadline = deadline;
-  timer->triggered = 0;
-
-  /* TODO(ctiller): check deadline expired */
-
-  gpr_mu_lock(&shard->mu);
-  grpc_time_averaged_stats_add_sample(&shard->stats,
-                                      ts_to_dbl(gpr_time_sub(deadline, now)));
-  if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) {
-    is_first_timer = grpc_timer_heap_add(&shard->heap, timer);
-  } else {
-    timer->heap_index = INVALID_HEAP_INDEX;
-    list_join(&shard->list, timer);
-  }
-  gpr_mu_unlock(&shard->mu);
-
-  /* Deadline may have decreased, we need to adjust the master queue.  Note
-     that there is a potential racy unlocked region here.  There could be a
-     reordering of multiple grpc_timer_init calls, at this point, but the < test
-     below should ensure that we err on the side of caution.  There could
-     also be a race with grpc_timer_check, which might beat us to the lock.  In
-     that case, it is possible that the timer that we added will have already
-     run by the time we hold the lock, but that too is a safe error.
-     Finally, it's possible that the grpc_timer_check that intervened failed to
-     trigger the new timer because the min_deadline hadn't yet been reduced.
-     In that case, the timer will simply have to wait for the next
-     grpc_timer_check. */
-  if (is_first_timer) {
-    gpr_mu_lock(&g_mu);
-    if (gpr_time_cmp(deadline, shard->min_deadline) < 0) {
-      gpr_timespec old_min_deadline = g_shard_queue[0]->min_deadline;
-      shard->min_deadline = deadline;
-      note_deadline_change(shard);
-      if (shard->shard_queue_index == 0 &&
-          gpr_time_cmp(deadline, old_min_deadline) < 0) {
-        grpc_kick_poller();
-      }
-    }
-    gpr_mu_unlock(&g_mu);
-  }
-}
-
-void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
-  shard_type *shard = &g_shards[shard_idx(timer)];
-  gpr_mu_lock(&shard->mu);
-  if (!timer->triggered) {
-    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, false, NULL);
-    timer->triggered = 1;
-    if (timer->heap_index == INVALID_HEAP_INDEX) {
-      list_remove(timer);
-    } else {
-      grpc_timer_heap_remove(&shard->heap, timer);
-    }
-  }
-  gpr_mu_unlock(&shard->mu);
-}
-
-/* This is called when the queue is empty and "now" has reached the
-   queue_deadline_cap.  We compute a new queue deadline and then scan the map
-   for timers that fall at or under it.  Returns true if the queue is no
-   longer empty.
-   REQUIRES: shard->mu locked */
-static int refill_queue(shard_type *shard, gpr_timespec now) {
-  /* Compute the new queue window width and bound by the limits: */
-  double computed_deadline_delta =
-      grpc_time_averaged_stats_update_average(&shard->stats) *
-      ADD_DEADLINE_SCALE;
-  double deadline_delta =
-      GPR_CLAMP(computed_deadline_delta, MIN_QUEUE_WINDOW_DURATION,
-                MAX_QUEUE_WINDOW_DURATION);
-  grpc_timer *timer, *next;
-
-  /* Compute the new cap and put all timers under it into the queue: */
-  shard->queue_deadline_cap = gpr_time_add(
-      gpr_time_max(now, shard->queue_deadline_cap), dbl_to_ts(deadline_delta));
-  for (timer = shard->list.next; timer != &shard->list; timer = next) {
-    next = timer->next;
-
-    if (gpr_time_cmp(timer->deadline, shard->queue_deadline_cap) < 0) {
-      list_remove(timer);
-      grpc_timer_heap_add(&shard->heap, timer);
-    }
-  }
-  return !grpc_timer_heap_is_empty(&shard->heap);
-}
-
-/* This pops the next non-cancelled timer with deadline <= now from the queue,
-   or returns NULL if there isn't one.
-   REQUIRES: shard->mu locked */
-static grpc_timer *pop_one(shard_type *shard, gpr_timespec now) {
-  grpc_timer *timer;
-  for (;;) {
-    if (grpc_timer_heap_is_empty(&shard->heap)) {
-      if (gpr_time_cmp(now, shard->queue_deadline_cap) < 0) return NULL;
-      if (!refill_queue(shard, now)) return NULL;
-    }
-    timer = grpc_timer_heap_top(&shard->heap);
-    if (gpr_time_cmp(timer->deadline, now) > 0) return NULL;
-    timer->triggered = 1;
-    grpc_timer_heap_pop(&shard->heap);
-    return timer;
-  }
-}
-
-/* REQUIRES: shard->mu unlocked */
-static size_t pop_timers(grpc_exec_ctx *exec_ctx, shard_type *shard,
-                         gpr_timespec now, gpr_timespec *new_min_deadline,
-                         int success) {
-  size_t n = 0;
-  grpc_timer *timer;
-  gpr_mu_lock(&shard->mu);
-  while ((timer = pop_one(shard, now))) {
-    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, success, NULL);
-    n++;
-  }
-  *new_min_deadline = compute_min_deadline(shard);
-  gpr_mu_unlock(&shard->mu);
-  return n;
-}
-
-static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
-                                   gpr_timespec *next, int success) {
-  size_t n = 0;
-
-  /* TODO(ctiller): verify that there are any timers (atomically) here */
-
-  if (gpr_mu_trylock(&g_checker_mu)) {
-    gpr_mu_lock(&g_mu);
-
-    while (gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) {
-      gpr_timespec new_min_deadline;
-
-      /* For efficiency, we pop as many available timers as we can from the
-         shard.  This may violate perfect timer deadline ordering, but that
-         shouldn't be a big deal because we don't make ordering guarantees. */
-      n += pop_timers(exec_ctx, g_shard_queue[0], now, &new_min_deadline,
-                      success);
-
-      /* An grpc_timer_init() on the shard could intervene here, adding a new
-         timer that is earlier than new_min_deadline.  However,
-         grpc_timer_init() will block on the master_lock before it can call
-         set_min_deadline, so this one will complete first and then the Addtimer
-         will reduce the min_deadline (perhaps unnecessarily). */
-      g_shard_queue[0]->min_deadline = new_min_deadline;
-      note_deadline_change(g_shard_queue[0]);
-    }
-
-    if (next) {
-      *next = gpr_time_min(*next, g_shard_queue[0]->min_deadline);
-    }
-
-    gpr_mu_unlock(&g_mu);
-    gpr_mu_unlock(&g_checker_mu);
-  } else if (next != NULL) {
-    /* TODO(ctiller): this forces calling code to do an short poll, and
-       then retry the timer check (because this time through the timer list was
-       contended).
-
-       We could reduce the cost here dramatically by keeping a count of how many
-       currently active pollers got through the uncontended case above
-       successfully, and waking up other pollers IFF that count drops to zero.
-
-       Once that count is in place, this entire else branch could disappear. */
-    *next = gpr_time_min(
-        *next, gpr_time_add(now, gpr_time_from_millis(1, GPR_TIMESPAN)));
-  }
-
-  return (int)n;
-}
-
-bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
-                      gpr_timespec *next) {
-  GPR_ASSERT(now.clock_type == g_clock_type);
-  return run_some_expired_timers(
-      exec_ctx, now, next,
-      gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0);
-}
diff --git a/src/core/iomgr/timer.h b/src/core/iomgr/timer.h
deleted file mode 100644
index 63505df..0000000
--- a/src/core/iomgr/timer.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_TIMER_H
-#define GRPC_CORE_IOMGR_TIMER_H
-
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/exec_ctx.h"
-#include <grpc/support/port_platform.h>
-#include <grpc/support/time.h>
-
-typedef struct grpc_timer {
-  gpr_timespec deadline;
-  uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */
-  int triggered;
-  struct grpc_timer *next;
-  struct grpc_timer *prev;
-  grpc_closure closure;
-} grpc_timer;
-
-/* Initialize *timer. When expired or canceled, timer_cb will be called with
-   *timer_cb_arg and status to indicate if it expired (SUCCESS) or was
-   canceled (CANCELLED). timer_cb is guaranteed to be called exactly once,
-   and application code should check the status to determine how it was
-   invoked. The application callback is also responsible for maintaining
-   information about when to free up any user-level state. */
-void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
-                     gpr_timespec deadline, grpc_iomgr_cb_func timer_cb,
-                     void *timer_cb_arg, gpr_timespec now);
-
-/* Note that there is no timer destroy function. This is because the
-   timer is a one-time occurrence with a guarantee that the callback will
-   be called exactly once, either at expiration or cancellation. Thus, all
-   the internal timer event management state is destroyed just before
-   that callback is invoked. If the user has additional state associated with
-   the timer, the user is responsible for determining when it is safe to
-   destroy that state. */
-
-/* Cancel an *timer.
-   There are three cases:
-   1. We normally cancel the timer
-   2. The timer has already run
-   3. We can't cancel the timer because it is "in flight".
-
-   In all of these cases, the cancellation is still considered successful.
-   They are essentially distinguished in that the timer_cb will be run
-   exactly once from either the cancellation (with status CANCELLED)
-   or from the activation (with status SUCCESS)
-
-   Note carefully that the callback function MAY occur in the same callstack
-   as grpc_timer_cancel. It's expected that most timers will be cancelled (their
-   primary use is to implement deadlines), and so this code is optimized such
-   that cancellation costs as little as possible. Making callbacks run inline
-   matches this aim.
-
-   Requires:  cancel() must happen after add() on a given timer */
-void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer);
-
-/* iomgr internal api for dealing with timers */
-
-/* Check for timers to be run, and run them.
-   Return true if timer callbacks were executed.
-   Drops drop_mu if it is non-null before executing callbacks.
-   If next is non-null, TRY to update *next with the next running timer
-   IF that timer occurs before *next current value.
-   *next is never guaranteed to be updated on any given execution; however,
-   with high probability at least one thread in the system will see an update
-   at any time slice. */
-bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
-                      gpr_timespec *next);
-void grpc_timer_list_init(gpr_timespec now);
-void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx);
-
-/* the following must be implemented by each iomgr implementation */
-
-void grpc_kick_poller(void);
-
-#endif /* GRPC_CORE_IOMGR_TIMER_H */
diff --git a/src/core/iomgr/timer_heap.c b/src/core/iomgr/timer_heap.c
deleted file mode 100644
index b5df566..0000000
--- a/src/core/iomgr/timer_heap.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- *
- * 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/iomgr/timer_heap.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/useful.h>
-
-/* Adjusts a heap so as to move a hole at position i closer to the root,
-   until a suitable position is found for element t. Then, copies t into that
-   position. This functor is called each time immediately after modifying a
-   value in the underlying container, with the offset of the modified element as
-   its argument. */
-static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) {
-  while (i > 0) {
-    uint32_t parent = (uint32_t)(((int)i - 1) / 2);
-    if (gpr_time_cmp(first[parent]->deadline, t->deadline) <= 0) break;
-    first[i] = first[parent];
-    first[i]->heap_index = i;
-    i = parent;
-  }
-  first[i] = t;
-  t->heap_index = i;
-}
-
-/* Adjusts a heap so as to move a hole at position i farther away from the root,
-   until a suitable position is found for element t.  Then, copies t into that
-   position. */
-static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length,
-                             grpc_timer *t) {
-  for (;;) {
-    uint32_t left_child = 1u + 2u * i;
-    if (left_child >= length) break;
-    uint32_t right_child = left_child + 1;
-    uint32_t next_i = right_child < length &&
-                              gpr_time_cmp(first[left_child]->deadline,
-                                           first[right_child]->deadline) > 0
-                          ? right_child
-                          : left_child;
-    if (gpr_time_cmp(t->deadline, first[next_i]->deadline) <= 0) break;
-    first[i] = first[next_i];
-    first[i]->heap_index = i;
-    i = next_i;
-  }
-  first[i] = t;
-  t->heap_index = i;
-}
-
-#define SHRINK_MIN_ELEMS 8
-#define SHRINK_FULLNESS_FACTOR 2
-
-static void maybe_shrink(grpc_timer_heap *heap) {
-  if (heap->timer_count >= 8 &&
-      heap->timer_count <= heap->timer_capacity / SHRINK_FULLNESS_FACTOR / 2) {
-    heap->timer_capacity = heap->timer_count * SHRINK_FULLNESS_FACTOR;
-    heap->timers =
-        gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *));
-  }
-}
-
-static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) {
-  uint32_t i = timer->heap_index;
-  uint32_t parent = (uint32_t)(((int)i - 1) / 2);
-  if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) > 0) {
-    adjust_upwards(heap->timers, i, timer);
-  } else {
-    adjust_downwards(heap->timers, i, heap->timer_count, timer);
-  }
-}
-
-void grpc_timer_heap_init(grpc_timer_heap *heap) {
-  memset(heap, 0, sizeof(*heap));
-}
-
-void grpc_timer_heap_destroy(grpc_timer_heap *heap) { gpr_free(heap->timers); }
-
-int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer) {
-  if (heap->timer_count == heap->timer_capacity) {
-    heap->timer_capacity =
-        GPR_MAX(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2);
-    heap->timers =
-        gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *));
-  }
-  timer->heap_index = heap->timer_count;
-  adjust_upwards(heap->timers, heap->timer_count, timer);
-  heap->timer_count++;
-  return timer->heap_index == 0;
-}
-
-void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer) {
-  uint32_t i = timer->heap_index;
-  if (i == heap->timer_count - 1) {
-    heap->timer_count--;
-    maybe_shrink(heap);
-    return;
-  }
-  heap->timers[i] = heap->timers[heap->timer_count - 1];
-  heap->timers[i]->heap_index = i;
-  heap->timer_count--;
-  maybe_shrink(heap);
-  note_changed_priority(heap, heap->timers[i]);
-}
-
-int grpc_timer_heap_is_empty(grpc_timer_heap *heap) {
-  return heap->timer_count == 0;
-}
-
-grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap) {
-  return heap->timers[0];
-}
-
-void grpc_timer_heap_pop(grpc_timer_heap *heap) {
-  grpc_timer_heap_remove(heap, grpc_timer_heap_top(heap));
-}
diff --git a/src/core/iomgr/timer_heap.h b/src/core/iomgr/timer_heap.h
deleted file mode 100644
index c2912ef..0000000
--- a/src/core/iomgr/timer_heap.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_TIMER_HEAP_H
-#define GRPC_CORE_IOMGR_TIMER_HEAP_H
-
-#include "src/core/iomgr/timer.h"
-
-typedef struct {
-  grpc_timer **timers;
-  uint32_t timer_count;
-  uint32_t timer_capacity;
-} grpc_timer_heap;
-
-/* return 1 if the new timer is the first timer in the heap */
-int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer);
-
-void grpc_timer_heap_init(grpc_timer_heap *heap);
-void grpc_timer_heap_destroy(grpc_timer_heap *heap);
-
-void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer);
-grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap);
-void grpc_timer_heap_pop(grpc_timer_heap *heap);
-
-int grpc_timer_heap_is_empty(grpc_timer_heap *heap);
-
-#endif /* GRPC_CORE_IOMGR_TIMER_HEAP_H */
diff --git a/src/core/iomgr/udp_server.c b/src/core/iomgr/udp_server.c
deleted file mode 100644
index ef548cf..0000000
--- a/src/core/iomgr/udp_server.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GRPC_NEED_UDP
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/udp_server.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/sockaddr_utils.h"
-#include "src/core/iomgr/socket_utils_posix.h"
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/time.h>
-
-#define INIT_PORT_CAP 2
-
-/* one listening port */
-typedef struct {
-  int fd;
-  grpc_fd *emfd;
-  grpc_udp_server *server;
-  union {
-    uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE];
-    struct sockaddr sockaddr;
-    struct sockaddr_un un;
-  } addr;
-  size_t addr_len;
-  grpc_closure read_closure;
-  grpc_closure destroyed_closure;
-  grpc_udp_server_read_cb read_cb;
-} server_port;
-
-static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
-  struct stat st;
-
-  if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
-    unlink(un->sun_path);
-  }
-}
-
-/* the overall server */
-struct grpc_udp_server {
-  gpr_mu mu;
-  gpr_cv cv;
-
-  /* active port count: how many ports are actually still listening */
-  size_t active_ports;
-  /* destroyed port count: how many ports are completely destroyed */
-  size_t destroyed_ports;
-
-  /* is this server shutting down? (boolean) */
-  int shutdown;
-
-  /* all listening ports */
-  server_port *ports;
-  size_t nports;
-  size_t port_capacity;
-
-  /* shutdown callback */
-  grpc_closure *shutdown_complete;
-
-  /* all pollsets interested in new connections */
-  grpc_pollset **pollsets;
-  /* number of pollsets in the pollsets array */
-  size_t pollset_count;
-  /* The parent grpc server */
-  grpc_server *grpc_server;
-};
-
-grpc_udp_server *grpc_udp_server_create(void) {
-  grpc_udp_server *s = gpr_malloc(sizeof(grpc_udp_server));
-  gpr_mu_init(&s->mu);
-  gpr_cv_init(&s->cv);
-  s->active_ports = 0;
-  s->destroyed_ports = 0;
-  s->shutdown = 0;
-  s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
-  s->nports = 0;
-  s->port_capacity = INIT_PORT_CAP;
-
-  return s;
-}
-
-static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
-  grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1, NULL);
-
-  gpr_mu_destroy(&s->mu);
-  gpr_cv_destroy(&s->cv);
-
-  gpr_free(s->ports);
-  gpr_free(s);
-}
-
-static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
-                           bool success) {
-  grpc_udp_server *s = server;
-  gpr_mu_lock(&s->mu);
-  s->destroyed_ports++;
-  if (s->destroyed_ports == s->nports) {
-    gpr_mu_unlock(&s->mu);
-    finish_shutdown(exec_ctx, s);
-  } else {
-    gpr_mu_unlock(&s->mu);
-  }
-}
-
-/* called when all listening endpoints have been shutdown, so no further
-   events will be received on them - at this point it's safe to destroy
-   things */
-static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
-  size_t i;
-
-  /* delete ALL the things */
-  gpr_mu_lock(&s->mu);
-
-  if (!s->shutdown) {
-    gpr_mu_unlock(&s->mu);
-    return;
-  }
-
-  if (s->nports) {
-    for (i = 0; i < s->nports; i++) {
-      server_port *sp = &s->ports[i];
-      if (sp->addr.sockaddr.sa_family == AF_UNIX) {
-        unlink_if_unix_domain_socket(&sp->addr.un);
-      }
-      sp->destroyed_closure.cb = destroyed_port;
-      sp->destroyed_closure.cb_arg = s;
-      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
-                     "udp_listener_shutdown");
-    }
-    gpr_mu_unlock(&s->mu);
-  } else {
-    gpr_mu_unlock(&s->mu);
-    finish_shutdown(exec_ctx, s);
-  }
-}
-
-void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
-                             grpc_closure *on_done) {
-  size_t i;
-  gpr_mu_lock(&s->mu);
-
-  GPR_ASSERT(!s->shutdown);
-  s->shutdown = 1;
-
-  s->shutdown_complete = on_done;
-
-  /* shutdown all fd's */
-  if (s->active_ports) {
-    for (i = 0; i < s->nports; i++) {
-      grpc_fd_shutdown(exec_ctx, s->ports[i].emfd);
-    }
-    gpr_mu_unlock(&s->mu);
-  } else {
-    gpr_mu_unlock(&s->mu);
-    deactivated_all_ports(exec_ctx, s);
-  }
-}
-
-/* Prepare a recently-created socket for listening. */
-static int prepare_socket(int fd, const struct sockaddr *addr,
-                          size_t addr_len) {
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
-  int get_local_ip;
-  int rc;
-
-  if (fd < 0) {
-    goto error;
-  }
-
-  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1)) {
-    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
-            strerror(errno));
-  }
-
-  get_local_ip = 1;
-  rc = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
-                  sizeof(get_local_ip));
-  if (rc == 0 && addr->sa_family == AF_INET6) {
-#if !defined(__APPLE__)
-    rc = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
-                    sizeof(get_local_ip));
-#endif
-  }
-
-  GPR_ASSERT(addr_len < ~(socklen_t)0);
-  if (bind(fd, addr, (socklen_t)addr_len) < 0) {
-    char *addr_str;
-    grpc_sockaddr_to_string(&addr_str, addr, 0);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
-    gpr_free(addr_str);
-    goto error;
-  }
-
-  sockname_len = sizeof(sockname_temp);
-  if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
-    goto error;
-  }
-
-  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
-
-error:
-  if (fd >= 0) {
-    close(fd);
-  }
-  return -1;
-}
-
-/* event manager callback when reads are ready */
-static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  server_port *sp = arg;
-
-  if (!success) {
-    gpr_mu_lock(&sp->server->mu);
-    if (0 == --sp->server->active_ports) {
-      gpr_mu_unlock(&sp->server->mu);
-      deactivated_all_ports(exec_ctx, sp->server);
-    } else {
-      gpr_mu_unlock(&sp->server->mu);
-    }
-    return;
-  }
-
-  /* Tell the registered callback that data is available to read. */
-  GPR_ASSERT(sp->read_cb);
-  sp->read_cb(exec_ctx, sp->emfd, sp->server->grpc_server);
-
-  /* Re-arm the notification event so we get another chance to read. */
-  grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
-}
-
-static int add_socket_to_server(grpc_udp_server *s, int fd,
-                                const struct sockaddr *addr, size_t addr_len,
-                                grpc_udp_server_read_cb read_cb) {
-  server_port *sp;
-  int port;
-  char *addr_str;
-  char *name;
-
-  port = prepare_socket(fd, addr, addr_len);
-  if (port >= 0) {
-    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
-    gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
-    gpr_free(addr_str);
-    gpr_mu_lock(&s->mu);
-    /* append it to the list under a lock */
-    if (s->nports == s->port_capacity) {
-      s->port_capacity *= 2;
-      s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
-    }
-    sp = &s->ports[s->nports++];
-    sp->server = s;
-    sp->fd = fd;
-    sp->emfd = grpc_fd_create(fd, name);
-    memcpy(sp->addr.untyped, addr, addr_len);
-    sp->addr_len = addr_len;
-    sp->read_cb = read_cb;
-    GPR_ASSERT(sp->emfd);
-    gpr_mu_unlock(&s->mu);
-    gpr_free(name);
-  }
-
-  return port;
-}
-
-int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
-                             size_t addr_len, grpc_udp_server_read_cb read_cb) {
-  int allocated_port1 = -1;
-  int allocated_port2 = -1;
-  unsigned i;
-  int fd;
-  grpc_dualstack_mode dsmode;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in wild4;
-  struct sockaddr_in6 wild6;
-  struct sockaddr_in addr4_copy;
-  struct sockaddr *allocated_addr = NULL;
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
-  int port;
-
-  if (((struct sockaddr *)addr)->sa_family == AF_UNIX) {
-    unlink_if_unix_domain_socket(addr);
-  }
-
-  /* Check if this is a wildcard port, and if so, try to keep the port the same
-     as some previously created listener. */
-  if (grpc_sockaddr_get_port(addr) == 0) {
-    for (i = 0; i < s->nports; i++) {
-      sockname_len = sizeof(sockname_temp);
-      if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
-                           &sockname_len)) {
-        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
-        if (port > 0) {
-          allocated_addr = malloc(addr_len);
-          memcpy(allocated_addr, addr, addr_len);
-          grpc_sockaddr_set_port(allocated_addr, port);
-          addr = allocated_addr;
-          break;
-        }
-      }
-    }
-  }
-
-  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
-  }
-
-  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
-  if (grpc_sockaddr_is_wildcard(addr, &port)) {
-    grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
-
-    /* Try listening on IPv6 first. */
-    addr = (struct sockaddr *)&wild6;
-    addr_len = sizeof(wild6);
-    fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode);
-    allocated_port1 = add_socket_to_server(s, fd, addr, addr_len, read_cb);
-    if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
-      goto done;
-    }
-
-    /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-    if (port == 0 && allocated_port1 > 0) {
-      grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
-    }
-    addr = (struct sockaddr *)&wild4;
-    addr_len = sizeof(wild4);
-  }
-
-  fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode);
-  if (fd < 0) {
-    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
-  }
-  if (dsmode == GRPC_DSMODE_IPV4 &&
-      grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
-    addr = (struct sockaddr *)&addr4_copy;
-    addr_len = sizeof(addr4_copy);
-  }
-  allocated_port2 = add_socket_to_server(s, fd, addr, addr_len, read_cb);
-
-done:
-  gpr_free(allocated_addr);
-  return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
-}
-
-int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index) {
-  return (port_index < s->nports) ? s->ports[port_index].fd : -1;
-}
-
-void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
-                           grpc_pollset **pollsets, size_t pollset_count,
-                           grpc_server *server) {
-  size_t i, j;
-  gpr_mu_lock(&s->mu);
-  GPR_ASSERT(s->active_ports == 0);
-  s->pollsets = pollsets;
-  s->grpc_server = server;
-  for (i = 0; i < s->nports; i++) {
-    for (j = 0; j < pollset_count; j++) {
-      grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd);
-    }
-    s->ports[i].read_closure.cb = on_read;
-    s->ports[i].read_closure.cb_arg = &s->ports[i];
-    grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd,
-                           &s->ports[i].read_closure);
-    s->active_ports++;
-  }
-  gpr_mu_unlock(&s->mu);
-}
-
-#endif
-#endif
diff --git a/src/core/iomgr/udp_server.h b/src/core/iomgr/udp_server.h
deleted file mode 100644
index 148c04f..0000000
--- a/src/core/iomgr/udp_server.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_UDP_SERVER_H
-#define GRPC_CORE_IOMGR_UDP_SERVER_H
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/fd_posix.h"
-
-/* Forward decl of struct grpc_server */
-/* This is not typedef'ed to avoid a typedef-redefinition error */
-struct grpc_server;
-
-/* Forward decl of grpc_udp_server */
-typedef struct grpc_udp_server grpc_udp_server;
-
-/* Called when data is available to read from the socket. */
-typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
-                                        struct grpc_server *server);
-
-/* Create a server, initially not bound to any ports */
-grpc_udp_server *grpc_udp_server_create(void);
-
-/* Start listening to bound ports */
-void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server,
-                           grpc_pollset **pollsets, size_t pollset_count,
-                           struct grpc_server *server);
-
-int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index);
-
-/* Add a port to the server, returning port number on success, or negative
-   on failure.
-
-   The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
-   both IPv4 and IPv6 connections, but :: is the preferred style.  This usually
-   creates one socket, but possibly two on systems which support IPv6,
-   but not dualstack sockets. */
-
-/* TODO(ctiller): deprecate this, and make grpc_udp_server_add_ports to handle
-                  all of the multiple socket port matching logic in one place */
-int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
-                             size_t addr_len, grpc_udp_server_read_cb read_cb);
-
-void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server,
-                             grpc_closure *on_done);
-
-#endif /* GRPC_CORE_IOMGR_UDP_SERVER_H */
diff --git a/src/core/iomgr/wakeup_fd_eventfd.c b/src/core/iomgr/wakeup_fd_eventfd.c
deleted file mode 100644
index f67379e..0000000
--- a/src/core/iomgr/wakeup_fd_eventfd.c
+++ /dev/null
@@ -1,85 +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_LINUX_EVENTFD
-
-#include <errno.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-
-#include <grpc/support/log.h>
-
-#include "src/core/iomgr/wakeup_fd_posix.h"
-#include "src/core/profiling/timers.h"
-
-static void eventfd_create(grpc_wakeup_fd* fd_info) {
-  int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
-  /* TODO(klempner): Handle failure more gracefully */
-  GPR_ASSERT(efd >= 0);
-  fd_info->read_fd = efd;
-  fd_info->write_fd = -1;
-}
-
-static void eventfd_consume(grpc_wakeup_fd* fd_info) {
-  eventfd_t value;
-  int err;
-  do {
-    err = eventfd_read(fd_info->read_fd, &value);
-  } while (err < 0 && errno == EINTR);
-}
-
-static void eventfd_wakeup(grpc_wakeup_fd* fd_info) {
-  int err;
-  GPR_TIMER_BEGIN("eventfd_wakeup", 0);
-  do {
-    err = eventfd_write(fd_info->read_fd, 1);
-  } while (err < 0 && errno == EINTR);
-  GPR_TIMER_END("eventfd_wakeup", 0);
-}
-
-static void eventfd_destroy(grpc_wakeup_fd* fd_info) {
-  if (fd_info->read_fd != 0) close(fd_info->read_fd);
-}
-
-static int eventfd_check_availability(void) {
-  /* TODO(klempner): Actually check if eventfd is available */
-  return 1;
-}
-
-const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = {
-    eventfd_create, eventfd_consume, eventfd_wakeup, eventfd_destroy,
-    eventfd_check_availability};
-
-#endif /* GPR_LINUX_EVENTFD */
diff --git a/src/core/iomgr/wakeup_fd_nospecial.c b/src/core/iomgr/wakeup_fd_nospecial.c
deleted file mode 100644
index 78d763c..0000000
--- a/src/core/iomgr/wakeup_fd_nospecial.c
+++ /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.
- *
- */
-
-/*
- * This is a dummy file to provide an invalid specialized_wakeup_fd_vtable on
- * systems without anything better than pipe.
- */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_NO_SPECIAL_WAKEUP_FD
-
-#include "src/core/iomgr/wakeup_fd_posix.h"
-#include <stddef.h>
-
-static int check_availability_invalid(void) { return 0; }
-
-const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = {
-    NULL, NULL, NULL, NULL, check_availability_invalid};
-
-#endif /* GPR_POSIX_NO_SPECIAL_WAKEUP_FD */
diff --git a/src/core/iomgr/wakeup_fd_pipe.c b/src/core/iomgr/wakeup_fd_pipe.c
deleted file mode 100644
index dd2fd1f..0000000
--- a/src/core/iomgr/wakeup_fd_pipe.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_WAKEUP_FD
-
-#include "src/core/iomgr/wakeup_fd_posix.h"
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <grpc/support/log.h>
-
-#include "src/core/iomgr/socket_utils_posix.h"
-
-static void pipe_init(grpc_wakeup_fd* fd_info) {
-  int pipefd[2];
-  /* TODO(klempner): Make this nonfatal */
-  int r = pipe(pipefd);
-  if (0 != r) {
-    gpr_log(GPR_ERROR, "pipe creation failed (%d): %s", errno, strerror(errno));
-    abort();
-  }
-  GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[0], 1));
-  GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[1], 1));
-  fd_info->read_fd = pipefd[0];
-  fd_info->write_fd = pipefd[1];
-}
-
-static void pipe_consume(grpc_wakeup_fd* fd_info) {
-  char buf[128];
-  ssize_t r;
-
-  for (;;) {
-    r = read(fd_info->read_fd, buf, sizeof(buf));
-    if (r > 0) continue;
-    if (r == 0) return;
-    switch (errno) {
-      case EAGAIN:
-        return;
-      case EINTR:
-        continue;
-      default:
-        gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno));
-        return;
-    }
-  }
-}
-
-static void pipe_wakeup(grpc_wakeup_fd* fd_info) {
-  char c = 0;
-  while (write(fd_info->write_fd, &c, 1) != 1 && errno == EINTR)
-    ;
-}
-
-static void pipe_destroy(grpc_wakeup_fd* fd_info) {
-  if (fd_info->read_fd != 0) close(fd_info->read_fd);
-  if (fd_info->write_fd != 0) close(fd_info->write_fd);
-}
-
-static int pipe_check_availability(void) {
-  /* Assume that pipes are always available. */
-  return 1;
-}
-
-const grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable = {
-    pipe_init, pipe_consume, pipe_wakeup, pipe_destroy,
-    pipe_check_availability};
-
-#endif /* GPR_POSIX_WAKUP_FD */
diff --git a/src/core/iomgr/wakeup_fd_pipe.h b/src/core/iomgr/wakeup_fd_pipe.h
deleted file mode 100644
index eb3e02b..0000000
--- a/src/core/iomgr/wakeup_fd_pipe.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_WAKEUP_FD_PIPE_H
-#define GRPC_CORE_IOMGR_WAKEUP_FD_PIPE_H
-
-#include "src/core/iomgr/wakeup_fd_posix.h"
-
-extern grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable;
-
-#endif /* GRPC_CORE_IOMGR_WAKEUP_FD_PIPE_H */
diff --git a/src/core/iomgr/wakeup_fd_posix.c b/src/core/iomgr/wakeup_fd_posix.c
deleted file mode 100644
index f40be08..0000000
--- a/src/core/iomgr/wakeup_fd_posix.c
+++ /dev/null
@@ -1,72 +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_WAKEUP_FD
-
-#include "src/core/iomgr/wakeup_fd_posix.h"
-#include "src/core/iomgr/wakeup_fd_pipe.h"
-#include <stddef.h>
-
-static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL;
-int grpc_allow_specialized_wakeup_fd = 1;
-
-void grpc_wakeup_fd_global_init(void) {
-  if (grpc_allow_specialized_wakeup_fd &&
-      grpc_specialized_wakeup_fd_vtable.check_availability()) {
-    wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable;
-  } else {
-    wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable;
-  }
-}
-
-void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; }
-
-void grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) {
-  wakeup_fd_vtable->init(fd_info);
-}
-
-void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) {
-  wakeup_fd_vtable->consume(fd_info);
-}
-
-void grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) {
-  wakeup_fd_vtable->wakeup(fd_info);
-}
-
-void grpc_wakeup_fd_destroy(grpc_wakeup_fd *fd_info) {
-  wakeup_fd_vtable->destroy(fd_info);
-}
-
-#endif /* GPR_POSIX_WAKEUP_FD */
diff --git a/src/core/iomgr/wakeup_fd_posix.h b/src/core/iomgr/wakeup_fd_posix.h
deleted file mode 100644
index d7e3cf4..0000000
--- a/src/core/iomgr/wakeup_fd_posix.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/*
- * wakeup_fd abstracts the concept of a file descriptor for the purpose of
- * waking up a thread in select()/poll()/epoll_wait()/etc.
-
- * The poll() family of system calls provide a way for a thread to block until
- * there is activity on one (or more) of a set of file descriptors. An
- * application may wish to wake up this thread to do non file related work. The
- * typical way to do this is to add a pipe to the set of file descriptors, then
- * write to the pipe to wake up the thread in poll().
- *
- * Linux has a lighter weight eventfd specifically designed for this purpose.
- * wakeup_fd abstracts the difference between the two.
- *
- * Setup:
- * 1. Before calling anything, call global_init() at least once.
- * 1. Call grpc_wakeup_fd_create() to get a wakeup_fd.
- * 2. Add the result of GRPC_WAKEUP_FD_FD to the set of monitored file
- *    descriptors for the poll() style API you are using. Monitor the file
- *    descriptor for readability.
- * 3. To tear down, call grpc_wakeup_fd_destroy(). This closes the underlying
- *    file descriptor.
- *
- * Usage:
- * 1. To wake up a polling thread, call grpc_wakeup_fd_wakeup() on a wakeup_fd
- *    it is monitoring.
- * 2. If the polling thread was awakened by a wakeup_fd event, call
- *    grpc_wakeup_fd_consume_wakeup() on it.
- */
-#ifndef GRPC_CORE_IOMGR_WAKEUP_FD_POSIX_H
-#define GRPC_CORE_IOMGR_WAKEUP_FD_POSIX_H
-
-void grpc_wakeup_fd_global_init(void);
-void grpc_wakeup_fd_global_destroy(void);
-
-/* Force using the fallback implementation. This is intended for testing
- * purposes only.*/
-void grpc_wakeup_fd_global_init_force_fallback(void);
-
-typedef struct grpc_wakeup_fd grpc_wakeup_fd;
-
-typedef struct grpc_wakeup_fd_vtable {
-  void (*init)(grpc_wakeup_fd* fd_info);
-  void (*consume)(grpc_wakeup_fd* fd_info);
-  void (*wakeup)(grpc_wakeup_fd* fd_info);
-  void (*destroy)(grpc_wakeup_fd* fd_info);
-  /* Must be called before calling any other functions */
-  int (*check_availability)(void);
-} grpc_wakeup_fd_vtable;
-
-struct grpc_wakeup_fd {
-  int read_fd;
-  int write_fd;
-};
-
-extern int grpc_allow_specialized_wakeup_fd;
-
-#define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd)
-
-void grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info);
-void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info);
-void grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info);
-void grpc_wakeup_fd_destroy(grpc_wakeup_fd* fd_info);
-
-/* Defined in some specialized implementation's .c file, or by
- * wakeup_fd_nospecial.c if no such implementation exists. */
-extern const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable;
-
-#endif /* GRPC_CORE_IOMGR_WAKEUP_FD_POSIX_H */
diff --git a/src/core/iomgr/workqueue.h b/src/core/iomgr/workqueue.h
deleted file mode 100644
index 2ba1e5d..0000000
--- a/src/core/iomgr/workqueue.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_WORKQUEUE_H
-#define GRPC_CORE_IOMGR_WORKQUEUE_H
-
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/pollset.h"
-#include "src/core/iomgr/closure.h"
-#include "src/core/iomgr/exec_ctx.h"
-
-#ifdef GPR_POSIX_SOCKET
-#include "src/core/iomgr/workqueue_posix.h"
-#endif
-
-#ifdef GPR_WIN32
-#include "src/core/iomgr/workqueue_windows.h"
-#endif
-
-/* grpc_workqueue is forward declared in exec_ctx.h */
-
-/** Create a work queue */
-grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx);
-
-void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue);
-
-#define GRPC_WORKQUEUE_REFCOUNT_DEBUG
-#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG
-#define GRPC_WORKQUEUE_REF(p, r) \
-  grpc_workqueue_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_WORKQUEUE_UNREF(cl, p, r) \
-  grpc_workqueue_unref((cl), (p), __FILE__, __LINE__, (r))
-void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line,
-                        const char *reason);
-void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue,
-                          const char *file, int line, const char *reason);
-#else
-#define GRPC_WORKQUEUE_REF(p, r) grpc_workqueue_ref((p))
-#define GRPC_WORKQUEUE_UNREF(cl, p, r) grpc_workqueue_unref((cl), (p))
-void grpc_workqueue_ref(grpc_workqueue *workqueue);
-void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue);
-#endif
-
-/** Bind this workqueue to a pollset */
-void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx,
-                                   grpc_workqueue *workqueue,
-                                   grpc_pollset *pollset);
-
-/** Add a work item to a workqueue */
-void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure,
-                         int success);
-
-#endif /* GRPC_CORE_IOMGR_WORKQUEUE_H */
diff --git a/src/core/iomgr/workqueue_posix.c b/src/core/iomgr/workqueue_posix.c
deleted file mode 100644
index 2b42e6d..0000000
--- a/src/core/iomgr/workqueue_posix.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/iomgr/workqueue.h"
-
-#include <stdio.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/pollset_posix.h"
-
-static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success);
-
-grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx) {
-  char name[32];
-  grpc_workqueue *workqueue = gpr_malloc(sizeof(grpc_workqueue));
-  gpr_ref_init(&workqueue->refs, 1);
-  gpr_mu_init(&workqueue->mu);
-  workqueue->closure_list.head = workqueue->closure_list.tail = NULL;
-  grpc_wakeup_fd_init(&workqueue->wakeup_fd);
-  sprintf(name, "workqueue:%p", (void *)workqueue);
-  workqueue->wakeup_read_fd =
-      grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&workqueue->wakeup_fd), name);
-  grpc_closure_init(&workqueue->read_closure, on_readable, workqueue);
-  grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,
-                         &workqueue->read_closure);
-  return workqueue;
-}
-
-static void workqueue_destroy(grpc_exec_ctx *exec_ctx,
-                              grpc_workqueue *workqueue) {
-  GPR_ASSERT(grpc_closure_list_empty(workqueue->closure_list));
-  grpc_fd_shutdown(exec_ctx, workqueue->wakeup_read_fd);
-}
-
-#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG
-void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line,
-                        const char *reason) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p   ref %d -> %d %s",
-          workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count + 1,
-          reason);
-#else
-void grpc_workqueue_ref(grpc_workqueue *workqueue) {
-#endif
-  gpr_ref(&workqueue->refs);
-}
-
-#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG
-void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue,
-                          const char *file, int line, const char *reason) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p unref %d -> %d %s",
-          workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count - 1,
-          reason);
-#else
-void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
-#endif
-  if (gpr_unref(&workqueue->refs)) {
-    workqueue_destroy(exec_ctx, workqueue);
-  }
-}
-
-void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx,
-                                   grpc_workqueue *workqueue,
-                                   grpc_pollset *pollset) {
-  grpc_pollset_add_fd(exec_ctx, pollset, workqueue->wakeup_read_fd);
-}
-
-void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
-  gpr_mu_lock(&workqueue->mu);
-  if (grpc_closure_list_empty(workqueue->closure_list)) {
-    grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
-  }
-  grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
-  gpr_mu_unlock(&workqueue->mu);
-}
-
-static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  grpc_workqueue *workqueue = arg;
-
-  if (!success) {
-    gpr_mu_destroy(&workqueue->mu);
-    /* HACK: let wakeup_fd code know that we stole the fd */
-    workqueue->wakeup_fd.read_fd = 0;
-    grpc_wakeup_fd_destroy(&workqueue->wakeup_fd);
-    grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy");
-    gpr_free(workqueue);
-  } else {
-    gpr_mu_lock(&workqueue->mu);
-    grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
-    grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd);
-    gpr_mu_unlock(&workqueue->mu);
-    grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,
-                           &workqueue->read_closure);
-  }
-}
-
-void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure,
-                         int success) {
-  gpr_mu_lock(&workqueue->mu);
-  if (grpc_closure_list_empty(workqueue->closure_list)) {
-    grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
-  }
-  grpc_closure_list_add(&workqueue->closure_list, closure, success);
-  gpr_mu_unlock(&workqueue->mu);
-}
-
-#endif /* GPR_POSIX_SOCKET */
diff --git a/src/core/iomgr/workqueue_posix.h b/src/core/iomgr/workqueue_posix.h
deleted file mode 100644
index 89937b1..0000000
--- a/src/core/iomgr/workqueue_posix.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_WORKQUEUE_POSIX_H
-#define GRPC_CORE_IOMGR_WORKQUEUE_POSIX_H
-
-#include "src/core/iomgr/wakeup_fd_posix.h"
-
-struct grpc_fd;
-
-struct grpc_workqueue {
-  gpr_refcount refs;
-
-  gpr_mu mu;
-  grpc_closure_list closure_list;
-
-  grpc_wakeup_fd wakeup_fd;
-  struct grpc_fd *wakeup_read_fd;
-
-  grpc_closure read_closure;
-};
-
-#endif /* GRPC_CORE_IOMGR_WORKQUEUE_POSIX_H */
diff --git a/src/core/iomgr/workqueue_windows.c b/src/core/iomgr/workqueue_windows.c
deleted file mode 100644
index f9ca575..0000000
--- a/src/core/iomgr/workqueue_windows.c
+++ /dev/null
@@ -1,40 +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/iomgr/workqueue.h"
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/iomgr/workqueue_windows.h b/src/core/iomgr/workqueue_windows.h
deleted file mode 100644
index 7e81869..0000000
--- a/src/core/iomgr/workqueue_windows.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_IOMGR_WORKQUEUE_WINDOWS_H
-#define GRPC_CORE_IOMGR_WORKQUEUE_WINDOWS_H
-
-#endif /* GRPC_CORE_IOMGR_WORKQUEUE_WINDOWS_H */
diff --git a/src/core/json/json.c b/src/core/json/json.c
deleted file mode 100644
index 96e11ee..0000000
--- a/src/core/json/json.c
+++ /dev/null
@@ -1,64 +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 <grpc/support/alloc.h>
-
-#include "src/core/json/json.h"
-
-grpc_json *grpc_json_create(grpc_json_type type) {
-  grpc_json *json = gpr_malloc(sizeof(*json));
-  memset(json, 0, sizeof(*json));
-  json->type = type;
-
-  return json;
-}
-
-void grpc_json_destroy(grpc_json *json) {
-  while (json->child) {
-    grpc_json_destroy(json->child);
-  }
-
-  if (json->next) {
-    json->next->prev = json->prev;
-  }
-
-  if (json->prev) {
-    json->prev->next = json->next;
-  } else if (json->parent) {
-    json->parent->child = json->next;
-  }
-
-  gpr_free(json);
-}
diff --git a/src/core/json/json.h b/src/core/json/json.h
deleted file mode 100644
index aea9d5d..0000000
--- a/src/core/json/json.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_JSON_JSON_H
-#define GRPC_CORE_JSON_JSON_H
-
-#include <stdlib.h>
-
-#include "src/core/json/json_common.h"
-
-/* A tree-like structure to hold json values. The key and value pointers
- * are not owned by it.
- */
-typedef struct grpc_json {
-  struct grpc_json *next;
-  struct grpc_json *prev;
-  struct grpc_json *child;
-  struct grpc_json *parent;
-
-  grpc_json_type type;
-  const char *key;
-  const char *value;
-} grpc_json;
-
-/* The next two functions are going to parse the input string, and
- * modify it in the process, in order to use its space to store
- * all of the keys and values for the returned object tree.
- *
- * They assume UTF-8 input stream, and will output UTF-8 encoded
- * strings in the tree. The input stream's UTF-8 isn't validated,
- * as in, what you input is what you get as an output.
- *
- * All the keys and values in the grpc_json objects will be strings
- * pointing at your input buffer.
- *
- * Delete the allocated tree afterward using grpc_json_destroy().
- */
-grpc_json *grpc_json_parse_string_with_len(char *input, size_t size);
-grpc_json *grpc_json_parse_string(char *input);
-
-/* This function will create a new string using gpr_realloc, and will
- * deserialize the grpc_json tree into it. It'll be zero-terminated,
- * but will be allocated in chunks of 256 bytes.
- *
- * The indent parameter controls the way the output is formatted.
- * If indent is 0, then newlines will be suppressed as well, and the
- * output will be condensed at its maximum.
- */
-char *grpc_json_dump_to_string(grpc_json *json, int indent);
-
-/* Use these to create or delete a grpc_json object.
- * Deletion is recursive. We will not attempt to free any of the strings
- * in any of the objects of that tree.
- */
-grpc_json *grpc_json_create(grpc_json_type type);
-void grpc_json_destroy(grpc_json *json);
-
-#endif /* GRPC_CORE_JSON_JSON_H */
diff --git a/src/core/json/json_common.h b/src/core/json/json_common.h
deleted file mode 100644
index 7205a94..0000000
--- a/src/core/json/json_common.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_JSON_JSON_COMMON_H
-#define GRPC_CORE_JSON_JSON_COMMON_H
-
-/* The various json types. */
-typedef enum {
-  GRPC_JSON_OBJECT,
-  GRPC_JSON_ARRAY,
-  GRPC_JSON_STRING,
-  GRPC_JSON_NUMBER,
-  GRPC_JSON_TRUE,
-  GRPC_JSON_FALSE,
-  GRPC_JSON_NULL,
-  GRPC_JSON_TOP_LEVEL
-} grpc_json_type;
-
-#endif /* GRPC_CORE_JSON_JSON_COMMON_H */
diff --git a/src/core/json/json_reader.c b/src/core/json/json_reader.c
deleted file mode 100644
index 30da6f2..0000000
--- a/src/core/json/json_reader.c
+++ /dev/null
@@ -1,659 +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 <grpc/support/port_platform.h>
-
-#include <grpc/support/log.h>
-
-#include "src/core/json/json_reader.h"
-
-static void json_reader_string_clear(grpc_json_reader *reader) {
-  reader->vtable->string_clear(reader->userdata);
-}
-
-static void json_reader_string_add_char(grpc_json_reader *reader, uint32_t c) {
-  reader->vtable->string_add_char(reader->userdata, c);
-}
-
-static void json_reader_string_add_utf32(grpc_json_reader *reader,
-                                         uint32_t utf32) {
-  reader->vtable->string_add_utf32(reader->userdata, utf32);
-}
-
-static uint32_t grpc_json_reader_read_char(grpc_json_reader *reader) {
-  return reader->vtable->read_char(reader->userdata);
-}
-
-static void json_reader_container_begins(grpc_json_reader *reader,
-                                         grpc_json_type type) {
-  reader->vtable->container_begins(reader->userdata, type);
-}
-
-static grpc_json_type grpc_json_reader_container_ends(
-    grpc_json_reader *reader) {
-  return reader->vtable->container_ends(reader->userdata);
-}
-
-static void json_reader_set_key(grpc_json_reader *reader) {
-  reader->vtable->set_key(reader->userdata);
-}
-
-static void json_reader_set_string(grpc_json_reader *reader) {
-  reader->vtable->set_string(reader->userdata);
-}
-
-static int json_reader_set_number(grpc_json_reader *reader) {
-  return reader->vtable->set_number(reader->userdata);
-}
-
-static void json_reader_set_true(grpc_json_reader *reader) {
-  reader->vtable->set_true(reader->userdata);
-}
-
-static void json_reader_set_false(grpc_json_reader *reader) {
-  reader->vtable->set_false(reader->userdata);
-}
-
-static void json_reader_set_null(grpc_json_reader *reader) {
-  reader->vtable->set_null(reader->userdata);
-}
-
-/* Call this function to initialize the reader structure. */
-void grpc_json_reader_init(grpc_json_reader *reader,
-                           grpc_json_reader_vtable *vtable, void *userdata) {
-  memset(reader, 0, sizeof(*reader));
-  reader->vtable = vtable;
-  reader->userdata = userdata;
-  json_reader_string_clear(reader);
-  reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
-}
-
-int grpc_json_reader_is_complete(grpc_json_reader *reader) {
-  return ((reader->depth == 0) &&
-          ((reader->state == GRPC_JSON_STATE_END) ||
-           (reader->state == GRPC_JSON_STATE_VALUE_END)));
-}
-
-grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
-  uint32_t c, success;
-
-  /* This state-machine is a strict implementation of ECMA-404 */
-  for (;;) {
-    c = grpc_json_reader_read_char(reader);
-    switch (c) {
-      /* Let's process the error cases first. */
-      case GRPC_JSON_READ_CHAR_ERROR:
-        return GRPC_JSON_READ_ERROR;
-
-      case GRPC_JSON_READ_CHAR_EAGAIN:
-        return GRPC_JSON_EAGAIN;
-
-      case GRPC_JSON_READ_CHAR_EOF:
-        if (grpc_json_reader_is_complete(reader)) {
-          return GRPC_JSON_DONE;
-        } else {
-          return GRPC_JSON_PARSE_ERROR;
-        }
-        break;
-
-      /* Processing whitespaces. */
-      case ' ':
-      case '\t':
-      case '\n':
-      case '\r':
-        switch (reader->state) {
-          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
-          case GRPC_JSON_STATE_OBJECT_KEY_END:
-          case GRPC_JSON_STATE_VALUE_BEGIN:
-          case GRPC_JSON_STATE_VALUE_END:
-          case GRPC_JSON_STATE_END:
-            break;
-
-          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
-          case GRPC_JSON_STATE_VALUE_STRING:
-            if (c != ' ') return GRPC_JSON_PARSE_ERROR;
-            if (reader->unicode_high_surrogate != 0)
-              return GRPC_JSON_PARSE_ERROR;
-            json_reader_string_add_char(reader, c);
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER:
-          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
-          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
-          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
-            success = (uint32_t)json_reader_set_number(reader);
-            if (!success) return GRPC_JSON_PARSE_ERROR;
-            json_reader_string_clear(reader);
-            reader->state = GRPC_JSON_STATE_VALUE_END;
-            break;
-
-          default:
-            return GRPC_JSON_PARSE_ERROR;
-        }
-        break;
-
-      /* Value, object or array terminations. */
-      case ',':
-      case '}':
-      case ']':
-        switch (reader->state) {
-          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
-          case GRPC_JSON_STATE_VALUE_STRING:
-            if (reader->unicode_high_surrogate != 0)
-              return GRPC_JSON_PARSE_ERROR;
-            json_reader_string_add_char(reader, c);
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER:
-          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
-          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
-          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
-            success = (uint32_t)json_reader_set_number(reader);
-            if (!success) return GRPC_JSON_PARSE_ERROR;
-            json_reader_string_clear(reader);
-            reader->state = GRPC_JSON_STATE_VALUE_END;
-          /* The missing break here is intentional. */
-
-          case GRPC_JSON_STATE_VALUE_END:
-          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
-          case GRPC_JSON_STATE_VALUE_BEGIN:
-            if (c == ',') {
-              if (reader->state != GRPC_JSON_STATE_VALUE_END) {
-                return GRPC_JSON_PARSE_ERROR;
-              }
-              if (reader->in_object) {
-                reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
-              } else {
-                reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
-              }
-            } else {
-              if (reader->depth-- == 0) return GRPC_JSON_PARSE_ERROR;
-              if ((c == '}') && !reader->in_object) {
-                return GRPC_JSON_PARSE_ERROR;
-              }
-              if ((c == '}') &&
-                  (reader->state == GRPC_JSON_STATE_OBJECT_KEY_BEGIN) &&
-                  !reader->container_just_begun) {
-                return GRPC_JSON_PARSE_ERROR;
-              }
-              if ((c == ']') && !reader->in_array) return GRPC_JSON_PARSE_ERROR;
-              if ((c == ']') &&
-                  (reader->state == GRPC_JSON_STATE_VALUE_BEGIN) &&
-                  !reader->container_just_begun) {
-                return GRPC_JSON_PARSE_ERROR;
-              }
-              reader->state = GRPC_JSON_STATE_VALUE_END;
-              switch (grpc_json_reader_container_ends(reader)) {
-                case GRPC_JSON_OBJECT:
-                  reader->in_object = 1;
-                  reader->in_array = 0;
-                  break;
-                case GRPC_JSON_ARRAY:
-                  reader->in_object = 0;
-                  reader->in_array = 1;
-                  break;
-                case GRPC_JSON_TOP_LEVEL:
-                  GPR_ASSERT(reader->depth == 0);
-                  reader->in_object = 0;
-                  reader->in_array = 0;
-                  reader->state = GRPC_JSON_STATE_END;
-                  break;
-                default:
-                  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
-              }
-            }
-            break;
-
-          default:
-            return GRPC_JSON_PARSE_ERROR;
-        }
-        break;
-
-      /* In-string escaping. */
-      case '\\':
-        switch (reader->state) {
-          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
-            reader->escaped_string_was_key = 1;
-            reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_STRING:
-            reader->escaped_string_was_key = 0;
-            reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
-            break;
-
-          /* This is the \\ case. */
-          case GRPC_JSON_STATE_STRING_ESCAPE:
-            if (reader->unicode_high_surrogate != 0)
-              return GRPC_JSON_PARSE_ERROR;
-            json_reader_string_add_char(reader, '\\');
-            if (reader->escaped_string_was_key) {
-              reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
-            } else {
-              reader->state = GRPC_JSON_STATE_VALUE_STRING;
-            }
-            break;
-
-          default:
-            return GRPC_JSON_PARSE_ERROR;
-        }
-        break;
-
-      default:
-        reader->container_just_begun = 0;
-        switch (reader->state) {
-          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
-            if (c != '"') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
-            break;
-
-          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
-            GPR_ASSERT(reader->unicode_high_surrogate == 0);
-            if (c == '"') {
-              reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
-              json_reader_set_key(reader);
-              json_reader_string_clear(reader);
-            } else {
-              if (c <= 0x001f) return GRPC_JSON_PARSE_ERROR;
-              json_reader_string_add_char(reader, c);
-            }
-            break;
-
-          case GRPC_JSON_STATE_VALUE_STRING:
-            if (reader->unicode_high_surrogate != 0)
-              return GRPC_JSON_PARSE_ERROR;
-            if (c == '"') {
-              reader->state = GRPC_JSON_STATE_VALUE_END;
-              json_reader_set_string(reader);
-              json_reader_string_clear(reader);
-            } else {
-              if (c < 32) return GRPC_JSON_PARSE_ERROR;
-              json_reader_string_add_char(reader, c);
-            }
-            break;
-
-          case GRPC_JSON_STATE_OBJECT_KEY_END:
-            if (c != ':') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_BEGIN:
-            switch (c) {
-              case 't':
-                reader->state = GRPC_JSON_STATE_VALUE_TRUE_R;
-                break;
-
-              case 'f':
-                reader->state = GRPC_JSON_STATE_VALUE_FALSE_A;
-                break;
-
-              case 'n':
-                reader->state = GRPC_JSON_STATE_VALUE_NULL_U;
-                break;
-
-              case '"':
-                reader->state = GRPC_JSON_STATE_VALUE_STRING;
-                break;
-
-              case '0':
-                json_reader_string_add_char(reader, c);
-                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_ZERO;
-                break;
-
-              case '1':
-              case '2':
-              case '3':
-              case '4':
-              case '5':
-              case '6':
-              case '7':
-              case '8':
-              case '9':
-              case '-':
-                json_reader_string_add_char(reader, c);
-                reader->state = GRPC_JSON_STATE_VALUE_NUMBER;
-                break;
-
-              case '{':
-                reader->container_just_begun = 1;
-                json_reader_container_begins(reader, GRPC_JSON_OBJECT);
-                reader->depth++;
-                reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
-                reader->in_object = 1;
-                reader->in_array = 0;
-                break;
-
-              case '[':
-                reader->container_just_begun = 1;
-                json_reader_container_begins(reader, GRPC_JSON_ARRAY);
-                reader->depth++;
-                reader->in_object = 0;
-                reader->in_array = 1;
-                break;
-            }
-            break;
-
-          case GRPC_JSON_STATE_STRING_ESCAPE:
-            if (reader->escaped_string_was_key) {
-              reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
-            } else {
-              reader->state = GRPC_JSON_STATE_VALUE_STRING;
-            }
-            if (reader->unicode_high_surrogate && c != 'u')
-              return GRPC_JSON_PARSE_ERROR;
-            switch (c) {
-              case '"':
-              case '/':
-                json_reader_string_add_char(reader, c);
-                break;
-              case 'b':
-                json_reader_string_add_char(reader, '\b');
-                break;
-              case 'f':
-                json_reader_string_add_char(reader, '\f');
-                break;
-              case 'n':
-                json_reader_string_add_char(reader, '\n');
-                break;
-              case 'r':
-                json_reader_string_add_char(reader, '\r');
-                break;
-              case 't':
-                json_reader_string_add_char(reader, '\t');
-                break;
-              case 'u':
-                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U1;
-                reader->unicode_char = 0;
-                break;
-              default:
-                return GRPC_JSON_PARSE_ERROR;
-            }
-            break;
-
-          case GRPC_JSON_STATE_STRING_ESCAPE_U1:
-          case GRPC_JSON_STATE_STRING_ESCAPE_U2:
-          case GRPC_JSON_STATE_STRING_ESCAPE_U3:
-          case GRPC_JSON_STATE_STRING_ESCAPE_U4:
-            if ((c >= '0') && (c <= '9')) {
-              c -= '0';
-            } else if ((c >= 'A') && (c <= 'F')) {
-              c -= 'A' - 10;
-            } else if ((c >= 'a') && (c <= 'f')) {
-              c -= 'a' - 10;
-            } else {
-              return GRPC_JSON_PARSE_ERROR;
-            }
-            reader->unicode_char = (uint16_t)(reader->unicode_char << 4);
-            reader->unicode_char = (uint16_t)(reader->unicode_char | c);
-
-            switch (reader->state) {
-              case GRPC_JSON_STATE_STRING_ESCAPE_U1:
-                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U2;
-                break;
-              case GRPC_JSON_STATE_STRING_ESCAPE_U2:
-                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U3;
-                break;
-              case GRPC_JSON_STATE_STRING_ESCAPE_U3:
-                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U4;
-                break;
-              case GRPC_JSON_STATE_STRING_ESCAPE_U4:
-                /* See grpc_json_writer_escape_string to have a description
-                 * of what's going on here.
-                 */
-                if ((reader->unicode_char & 0xfc00) == 0xd800) {
-                  /* high surrogate utf-16 */
-                  if (reader->unicode_high_surrogate != 0)
-                    return GRPC_JSON_PARSE_ERROR;
-                  reader->unicode_high_surrogate = reader->unicode_char;
-                } else if ((reader->unicode_char & 0xfc00) == 0xdc00) {
-                  /* low surrogate utf-16 */
-                  uint32_t utf32;
-                  if (reader->unicode_high_surrogate == 0)
-                    return GRPC_JSON_PARSE_ERROR;
-                  utf32 = 0x10000;
-                  utf32 += (uint32_t)(
-                      (reader->unicode_high_surrogate - 0xd800) * 0x400);
-                  utf32 += (uint32_t)(reader->unicode_char - 0xdc00);
-                  json_reader_string_add_utf32(reader, utf32);
-                  reader->unicode_high_surrogate = 0;
-                } else {
-                  /* anything else */
-                  if (reader->unicode_high_surrogate != 0)
-                    return GRPC_JSON_PARSE_ERROR;
-                  json_reader_string_add_utf32(reader, reader->unicode_char);
-                }
-                if (reader->escaped_string_was_key) {
-                  reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
-                } else {
-                  reader->state = GRPC_JSON_STATE_VALUE_STRING;
-                }
-                break;
-              default:
-                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
-            }
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER:
-            json_reader_string_add_char(reader, c);
-            switch (c) {
-              case '0':
-              case '1':
-              case '2':
-              case '3':
-              case '4':
-              case '5':
-              case '6':
-              case '7':
-              case '8':
-              case '9':
-                break;
-              case 'e':
-              case 'E':
-                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
-                break;
-              case '.':
-                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
-                break;
-              default:
-                return GRPC_JSON_PARSE_ERROR;
-            }
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
-            json_reader_string_add_char(reader, c);
-            switch (c) {
-              case '0':
-              case '1':
-              case '2':
-              case '3':
-              case '4':
-              case '5':
-              case '6':
-              case '7':
-              case '8':
-              case '9':
-                break;
-              case 'e':
-              case 'E':
-                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
-                break;
-              default:
-                return GRPC_JSON_PARSE_ERROR;
-            }
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
-            if (c != '.') return GRPC_JSON_PARSE_ERROR;
-            json_reader_string_add_char(reader, c);
-            reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER_DOT:
-            json_reader_string_add_char(reader, c);
-            switch (c) {
-              case '0':
-              case '1':
-              case '2':
-              case '3':
-              case '4':
-              case '5':
-              case '6':
-              case '7':
-              case '8':
-              case '9':
-                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL;
-                break;
-              default:
-                return GRPC_JSON_PARSE_ERROR;
-            }
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER_E:
-            json_reader_string_add_char(reader, c);
-            switch (c) {
-              case '0':
-              case '1':
-              case '2':
-              case '3':
-              case '4':
-              case '5':
-              case '6':
-              case '7':
-              case '8':
-              case '9':
-              case '+':
-              case '-':
-                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_EPM;
-                break;
-              default:
-                return GRPC_JSON_PARSE_ERROR;
-            }
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
-            json_reader_string_add_char(reader, c);
-            switch (c) {
-              case '0':
-              case '1':
-              case '2':
-              case '3':
-              case '4':
-              case '5':
-              case '6':
-              case '7':
-              case '8':
-              case '9':
-                break;
-              default:
-                return GRPC_JSON_PARSE_ERROR;
-            }
-            break;
-
-          case GRPC_JSON_STATE_VALUE_TRUE_R:
-            if (c != 'r') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_TRUE_U;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_TRUE_U:
-            if (c != 'u') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_TRUE_E;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_TRUE_E:
-            if (c != 'e') return GRPC_JSON_PARSE_ERROR;
-            json_reader_set_true(reader);
-            reader->state = GRPC_JSON_STATE_VALUE_END;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_FALSE_A:
-            if (c != 'a') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_FALSE_L;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_FALSE_L:
-            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_FALSE_S;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_FALSE_S:
-            if (c != 's') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_FALSE_E;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_FALSE_E:
-            if (c != 'e') return GRPC_JSON_PARSE_ERROR;
-            json_reader_set_false(reader);
-            reader->state = GRPC_JSON_STATE_VALUE_END;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NULL_U:
-            if (c != 'u') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_NULL_L1;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NULL_L1:
-            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
-            reader->state = GRPC_JSON_STATE_VALUE_NULL_L2;
-            break;
-
-          case GRPC_JSON_STATE_VALUE_NULL_L2:
-            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
-            json_reader_set_null(reader);
-            reader->state = GRPC_JSON_STATE_VALUE_END;
-            break;
-
-          /* All of the VALUE_END cases are handled in the specialized case
-           * above. */
-          case GRPC_JSON_STATE_VALUE_END:
-            switch (c) {
-              case ',':
-              case '}':
-              case ']':
-                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
-                break;
-
-              default:
-                return GRPC_JSON_PARSE_ERROR;
-            }
-            break;
-
-          case GRPC_JSON_STATE_END:
-            return GRPC_JSON_PARSE_ERROR;
-        }
-    }
-  }
-
-  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
-}
diff --git a/src/core/json/json_reader.h b/src/core/json/json_reader.h
deleted file mode 100644
index f25f44b..0000000
--- a/src/core/json/json_reader.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_JSON_JSON_READER_H
-#define GRPC_CORE_JSON_JSON_READER_H
-
-#include <grpc/support/port_platform.h>
-#include "src/core/json/json_common.h"
-
-typedef enum {
-  GRPC_JSON_STATE_OBJECT_KEY_BEGIN,
-  GRPC_JSON_STATE_OBJECT_KEY_STRING,
-  GRPC_JSON_STATE_OBJECT_KEY_END,
-  GRPC_JSON_STATE_VALUE_BEGIN,
-  GRPC_JSON_STATE_VALUE_STRING,
-  GRPC_JSON_STATE_STRING_ESCAPE,
-  GRPC_JSON_STATE_STRING_ESCAPE_U1,
-  GRPC_JSON_STATE_STRING_ESCAPE_U2,
-  GRPC_JSON_STATE_STRING_ESCAPE_U3,
-  GRPC_JSON_STATE_STRING_ESCAPE_U4,
-  GRPC_JSON_STATE_VALUE_NUMBER,
-  GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL,
-  GRPC_JSON_STATE_VALUE_NUMBER_ZERO,
-  GRPC_JSON_STATE_VALUE_NUMBER_DOT,
-  GRPC_JSON_STATE_VALUE_NUMBER_E,
-  GRPC_JSON_STATE_VALUE_NUMBER_EPM,
-  GRPC_JSON_STATE_VALUE_TRUE_R,
-  GRPC_JSON_STATE_VALUE_TRUE_U,
-  GRPC_JSON_STATE_VALUE_TRUE_E,
-  GRPC_JSON_STATE_VALUE_FALSE_A,
-  GRPC_JSON_STATE_VALUE_FALSE_L,
-  GRPC_JSON_STATE_VALUE_FALSE_S,
-  GRPC_JSON_STATE_VALUE_FALSE_E,
-  GRPC_JSON_STATE_VALUE_NULL_U,
-  GRPC_JSON_STATE_VALUE_NULL_L1,
-  GRPC_JSON_STATE_VALUE_NULL_L2,
-  GRPC_JSON_STATE_VALUE_END,
-  GRPC_JSON_STATE_END
-} grpc_json_reader_state;
-
-enum {
-  /* The first non-unicode value is 0x110000. But let's pick
-   * a value high enough to start our error codes from. These
-   * values are safe to return from the read_char function.
-   */
-  GRPC_JSON_READ_CHAR_EOF = 0x7ffffff0,
-  GRPC_JSON_READ_CHAR_EAGAIN,
-  GRPC_JSON_READ_CHAR_ERROR
-};
-
-struct grpc_json_reader;
-
-typedef struct grpc_json_reader_vtable {
-  /* Clears your internal string scratchpad. */
-  void (*string_clear)(void *userdata);
-  /* Adds a char to the string scratchpad. */
-  void (*string_add_char)(void *userdata, uint32_t c);
-  /* Adds a utf32 char to the string scratchpad. */
-  void (*string_add_utf32)(void *userdata, uint32_t c);
-  /* Reads a character from your input. May be utf-8, 16 or 32. */
-  uint32_t (*read_char)(void *userdata);
-  /* Starts a container of type GRPC_JSON_ARRAY or GRPC_JSON_OBJECT. */
-  void (*container_begins)(void *userdata, grpc_json_type type);
-  /* Ends the current container. Must return the type of its parent. */
-  grpc_json_type (*container_ends)(void *userdata);
-  /* Your internal string scratchpad is an object's key. */
-  void (*set_key)(void *userdata);
-  /* Your internal string scratchpad is a string value. */
-  void (*set_string)(void *userdata);
-  /* Your internal string scratchpad is a numerical value. Return 1 if valid. */
-  int (*set_number)(void *userdata);
-  /* Sets the values true, false or null. */
-  void (*set_true)(void *userdata);
-  void (*set_false)(void *userdata);
-  void (*set_null)(void *userdata);
-} grpc_json_reader_vtable;
-
-typedef struct grpc_json_reader {
-  /* That structure is fully private, and initialized by grpc_json_reader_init.
-   * The definition is public so you can put it on your stack.
-   */
-
-  void *userdata;
-  grpc_json_reader_vtable *vtable;
-  int depth;
-  int in_object;
-  int in_array;
-  int escaped_string_was_key;
-  int container_just_begun;
-  uint16_t unicode_char, unicode_high_surrogate;
-  grpc_json_reader_state state;
-} grpc_json_reader;
-
-/* The return type of the parser. */
-typedef enum {
-  GRPC_JSON_DONE,          /* The parser finished successfully. */
-  GRPC_JSON_EAGAIN,        /* The parser yields to get more data. */
-  GRPC_JSON_READ_ERROR,    /* The parser passes through a read error. */
-  GRPC_JSON_PARSE_ERROR,   /* The parser found an error in the json stream. */
-  GRPC_JSON_INTERNAL_ERROR /* The parser got an internal error. */
-} grpc_json_reader_status;
-
-/* Call this function to start parsing the input. It will return the following:
- *    . GRPC_JSON_DONE if the input got eof, and the parsing finished
- *      successfully.
- *    . GRPC_JSON_EAGAIN if the read_char function returned again. Call the
- *      parser again as needed. It is okay to call the parser in polling mode,
- *      although a bit dull.
- *    . GRPC_JSON_READ_ERROR if the read_char function returned an error. The
- *      state isn't broken however, and the function can be called again if the
- *      error has been corrected. But please use the EAGAIN feature instead for
- *      consistency.
- *    . GRPC_JSON_PARSE_ERROR if the input was somehow invalid.
- *    . GRPC_JSON_INTERNAL_ERROR if the parser somehow ended into an invalid
- *      internal state.
- */
-grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader);
-
-/* Call this function to initialize the reader structure. */
-void grpc_json_reader_init(grpc_json_reader *reader,
-                           grpc_json_reader_vtable *vtable, void *userdata);
-
-/* You may call this from the read_char callback if you don't know where is the
- * end of your input stream, and you'd like the json reader to hint you that it
- * has completed reading its input, so you can return an EOF to it. Note that
- * there might still be trailing whitespaces after that point.
- */
-int grpc_json_reader_is_complete(grpc_json_reader *reader);
-
-#endif /* GRPC_CORE_JSON_JSON_READER_H */
diff --git a/src/core/json/json_string.c b/src/core/json/json_string.c
deleted file mode 100644
index 2bc0b51..0000000
--- a/src/core/json/json_string.c
+++ /dev/null
@@ -1,379 +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 <stdlib.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/json/json.h"
-#include "src/core/json/json_reader.h"
-#include "src/core/json/json_writer.h"
-
-/* The json reader will construct a bunch of grpc_json objects and
- * link them all up together in a tree-like structure that will represent
- * the json data in memory.
- *
- * It also uses its own input as a scratchpad to store all of the decoded,
- * unescaped strings. So we need to keep track of all these pointers in
- * that opaque structure the reader will carry for us.
- *
- * Note that this works because the act of parsing json always reduces its
- * input size, and never expands it.
- */
-typedef struct {
-  grpc_json *top;
-  grpc_json *current_container;
-  grpc_json *current_value;
-  uint8_t *input;
-  uint8_t *key;
-  uint8_t *string;
-  uint8_t *string_ptr;
-  size_t remaining_input;
-} json_reader_userdata;
-
-/* This json writer will put everything in a big string.
- * The point is that we allocate that string in chunks of 256 bytes.
- */
-typedef struct {
-  char *output;
-  size_t free_space;
-  size_t string_len;
-  size_t allocated;
-} json_writer_userdata;
-
-/* This function checks if there's enough space left in the output buffer,
- * and will enlarge it if necessary. We're only allocating chunks of 256
- * bytes at a time (or multiples thereof).
- */
-static void json_writer_output_check(void *userdata, size_t needed) {
-  json_writer_userdata *state = userdata;
-  if (state->free_space >= needed) return;
-  needed -= state->free_space;
-  /* Round up by 256 bytes. */
-  needed = (needed + 0xff) & ~0xffU;
-  state->output = gpr_realloc(state->output, state->allocated + needed);
-  state->free_space += needed;
-  state->allocated += needed;
-}
-
-/* These are needed by the writer's implementation. */
-static void json_writer_output_char(void *userdata, char c) {
-  json_writer_userdata *state = userdata;
-  json_writer_output_check(userdata, 1);
-  state->output[state->string_len++] = c;
-  state->free_space--;
-}
-
-static void json_writer_output_string_with_len(void *userdata, const char *str,
-                                               size_t len) {
-  json_writer_userdata *state = userdata;
-  json_writer_output_check(userdata, len);
-  memcpy(state->output + state->string_len, str, len);
-  state->string_len += len;
-  state->free_space -= len;
-}
-
-static void json_writer_output_string(void *userdata, const char *str) {
-  size_t len = strlen(str);
-  json_writer_output_string_with_len(userdata, str, len);
-}
-
-/* The reader asks us to clear our scratchpad. In our case, we'll simply mark
- * the end of the current string, and advance our output pointer.
- */
-static void json_reader_string_clear(void *userdata) {
-  json_reader_userdata *state = userdata;
-  if (state->string) {
-    GPR_ASSERT(state->string_ptr < state->input);
-    *state->string_ptr++ = 0;
-  }
-  state->string = state->string_ptr;
-}
-
-static void json_reader_string_add_char(void *userdata, uint32_t c) {
-  json_reader_userdata *state = userdata;
-  GPR_ASSERT(state->string_ptr < state->input);
-  GPR_ASSERT(c <= 0xff);
-  *state->string_ptr++ = (uint8_t)c;
-}
-
-/* We are converting a UTF-32 character into UTF-8 here,
- * as described by RFC3629.
- */
-static void json_reader_string_add_utf32(void *userdata, uint32_t c) {
-  if (c <= 0x7f) {
-    json_reader_string_add_char(userdata, c);
-  } else if (c <= 0x7ff) {
-    uint32_t b1 = 0xc0 | ((c >> 6) & 0x1f);
-    uint32_t b2 = 0x80 | (c & 0x3f);
-    json_reader_string_add_char(userdata, b1);
-    json_reader_string_add_char(userdata, b2);
-  } else if (c <= 0xffff) {
-    uint32_t b1 = 0xe0 | ((c >> 12) & 0x0f);
-    uint32_t b2 = 0x80 | ((c >> 6) & 0x3f);
-    uint32_t b3 = 0x80 | (c & 0x3f);
-    json_reader_string_add_char(userdata, b1);
-    json_reader_string_add_char(userdata, b2);
-    json_reader_string_add_char(userdata, b3);
-  } else if (c <= 0x1fffff) {
-    uint32_t b1 = 0xf0 | ((c >> 18) & 0x07);
-    uint32_t b2 = 0x80 | ((c >> 12) & 0x3f);
-    uint32_t b3 = 0x80 | ((c >> 6) & 0x3f);
-    uint32_t b4 = 0x80 | (c & 0x3f);
-    json_reader_string_add_char(userdata, b1);
-    json_reader_string_add_char(userdata, b2);
-    json_reader_string_add_char(userdata, b3);
-    json_reader_string_add_char(userdata, b4);
-  }
-}
-
-/* We consider that the input may be a zero-terminated string. So we
- * can end up hitting eof before the end of the alleged string length.
- */
-static uint32_t json_reader_read_char(void *userdata) {
-  uint32_t r;
-  json_reader_userdata *state = userdata;
-
-  if (state->remaining_input == 0) return GRPC_JSON_READ_CHAR_EOF;
-
-  r = *state->input++;
-  state->remaining_input--;
-
-  if (r == 0) {
-    state->remaining_input = 0;
-    return GRPC_JSON_READ_CHAR_EOF;
-  }
-
-  return r;
-}
-
-/* Helper function to create a new grpc_json object and link it into
- * our tree-in-progress inside our opaque structure.
- */
-static grpc_json *json_create_and_link(void *userdata, grpc_json_type type) {
-  json_reader_userdata *state = userdata;
-  grpc_json *json = grpc_json_create(type);
-
-  json->parent = state->current_container;
-  json->prev = state->current_value;
-  state->current_value = json;
-
-  if (json->prev) {
-    json->prev->next = json;
-  }
-  if (json->parent) {
-    if (!json->parent->child) {
-      json->parent->child = json;
-    }
-    if (json->parent->type == GRPC_JSON_OBJECT) {
-      json->key = (char *)state->key;
-    }
-  }
-  if (!state->top) {
-    state->top = json;
-  }
-
-  return json;
-}
-
-static void json_reader_container_begins(void *userdata, grpc_json_type type) {
-  json_reader_userdata *state = userdata;
-  grpc_json *container;
-
-  GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT);
-
-  container = json_create_and_link(userdata, type);
-  state->current_container = container;
-  state->current_value = NULL;
-}
-
-/* It's important to remember that the reader is mostly stateless, so it
- * isn't trying to remember what the container was prior the one that just
- * ends. Since we're keeping track of these for our own purpose, we are
- * able to return that information back, which is useful for it to validate
- * the input json stream.
- *
- * Also note that if we're at the top of the tree, and the last container
- * ends, we have to return GRPC_JSON_TOP_LEVEL.
- */
-static grpc_json_type json_reader_container_ends(void *userdata) {
-  grpc_json_type container_type = GRPC_JSON_TOP_LEVEL;
-  json_reader_userdata *state = userdata;
-
-  GPR_ASSERT(state->current_container);
-
-  state->current_value = state->current_container;
-  state->current_container = state->current_container->parent;
-
-  if (state->current_container) {
-    container_type = state->current_container->type;
-  }
-
-  return container_type;
-}
-
-/* The next 3 functions basically are the reader asking us to use our string
- * scratchpad for one of these 3 purposes.
- *
- * Note that in the set_number case, we're not going to try interpreting it.
- * We'll keep it as a string, and leave it to the caller to evaluate it.
- */
-static void json_reader_set_key(void *userdata) {
-  json_reader_userdata *state = userdata;
-  state->key = state->string;
-}
-
-static void json_reader_set_string(void *userdata) {
-  json_reader_userdata *state = userdata;
-  grpc_json *json = json_create_and_link(userdata, GRPC_JSON_STRING);
-  json->value = (char *)state->string;
-}
-
-static int json_reader_set_number(void *userdata) {
-  json_reader_userdata *state = userdata;
-  grpc_json *json = json_create_and_link(userdata, GRPC_JSON_NUMBER);
-  json->value = (char *)state->string;
-  return 1;
-}
-
-/* The object types true, false and null are self-sufficient, and don't need
- * any more information beside their type.
- */
-static void json_reader_set_true(void *userdata) {
-  json_create_and_link(userdata, GRPC_JSON_TRUE);
-}
-
-static void json_reader_set_false(void *userdata) {
-  json_create_and_link(userdata, GRPC_JSON_FALSE);
-}
-
-static void json_reader_set_null(void *userdata) {
-  json_create_and_link(userdata, GRPC_JSON_NULL);
-}
-
-static grpc_json_reader_vtable reader_vtable = {
-    json_reader_string_clear,     json_reader_string_add_char,
-    json_reader_string_add_utf32, json_reader_read_char,
-    json_reader_container_begins, json_reader_container_ends,
-    json_reader_set_key,          json_reader_set_string,
-    json_reader_set_number,       json_reader_set_true,
-    json_reader_set_false,        json_reader_set_null};
-
-/* And finally, let's define our public API. */
-grpc_json *grpc_json_parse_string_with_len(char *input, size_t size) {
-  grpc_json_reader reader;
-  json_reader_userdata state;
-  grpc_json *json = NULL;
-  grpc_json_reader_status status;
-
-  if (!input) return NULL;
-
-  state.top = state.current_container = state.current_value = NULL;
-  state.string = state.key = NULL;
-  state.string_ptr = state.input = (uint8_t *)input;
-  state.remaining_input = size;
-  grpc_json_reader_init(&reader, &reader_vtable, &state);
-
-  status = grpc_json_reader_run(&reader);
-  json = state.top;
-
-  if ((status != GRPC_JSON_DONE) && json) {
-    grpc_json_destroy(json);
-    json = NULL;
-  }
-
-  return json;
-}
-
-#define UNBOUND_JSON_STRING_LENGTH 0x7fffffff
-
-grpc_json *grpc_json_parse_string(char *input) {
-  return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH);
-}
-
-static void json_dump_recursive(grpc_json_writer *writer, grpc_json *json,
-                                int in_object) {
-  while (json) {
-    if (in_object) grpc_json_writer_object_key(writer, json->key);
-
-    switch (json->type) {
-      case GRPC_JSON_OBJECT:
-      case GRPC_JSON_ARRAY:
-        grpc_json_writer_container_begins(writer, json->type);
-        if (json->child)
-          json_dump_recursive(writer, json->child,
-                              json->type == GRPC_JSON_OBJECT);
-        grpc_json_writer_container_ends(writer, json->type);
-        break;
-      case GRPC_JSON_STRING:
-        grpc_json_writer_value_string(writer, json->value);
-        break;
-      case GRPC_JSON_NUMBER:
-        grpc_json_writer_value_raw(writer, json->value);
-        break;
-      case GRPC_JSON_TRUE:
-        grpc_json_writer_value_raw_with_len(writer, "true", 4);
-        break;
-      case GRPC_JSON_FALSE:
-        grpc_json_writer_value_raw_with_len(writer, "false", 5);
-        break;
-      case GRPC_JSON_NULL:
-        grpc_json_writer_value_raw_with_len(writer, "null", 4);
-        break;
-      default:
-        GPR_UNREACHABLE_CODE(abort());
-    }
-    json = json->next;
-  }
-}
-
-static grpc_json_writer_vtable writer_vtable = {
-    json_writer_output_char, json_writer_output_string,
-    json_writer_output_string_with_len};
-
-char *grpc_json_dump_to_string(grpc_json *json, int indent) {
-  grpc_json_writer writer;
-  json_writer_userdata state;
-
-  state.output = NULL;
-  state.free_space = state.string_len = state.allocated = 0;
-  grpc_json_writer_init(&writer, indent, &writer_vtable, &state);
-
-  json_dump_recursive(&writer, json, 0);
-
-  json_writer_output_char(&state, 0);
-
-  return state.output;
-}
diff --git a/src/core/json/json_writer.c b/src/core/json/json_writer.c
deleted file mode 100644
index 326ec2d..0000000
--- a/src/core/json/json_writer.c
+++ /dev/null
@@ -1,258 +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 <grpc/support/port_platform.h>
-
-#include "src/core/json/json_writer.h"
-
-static void json_writer_output_char(grpc_json_writer *writer, char c) {
-  writer->vtable->output_char(writer->userdata, c);
-}
-
-static void json_writer_output_string(grpc_json_writer *writer,
-                                      const char *str) {
-  writer->vtable->output_string(writer->userdata, str);
-}
-
-static void json_writer_output_string_with_len(grpc_json_writer *writer,
-                                               const char *str, size_t len) {
-  writer->vtable->output_string_with_len(writer->userdata, str, len);
-}
-
-void grpc_json_writer_init(grpc_json_writer *writer, int indent,
-                           grpc_json_writer_vtable *vtable, void *userdata) {
-  memset(writer, 0, sizeof(*writer));
-  writer->container_empty = 1;
-  writer->indent = indent;
-  writer->vtable = vtable;
-  writer->userdata = userdata;
-}
-
-static void json_writer_output_indent(grpc_json_writer *writer) {
-  static const char spacesstr[] =
-      "                "
-      "                "
-      "                "
-      "                ";
-
-  unsigned spaces = (unsigned)(writer->depth * writer->indent);
-
-  if (writer->indent == 0) return;
-
-  if (writer->got_key) {
-    json_writer_output_char(writer, ' ');
-    return;
-  }
-
-  while (spaces >= (sizeof(spacesstr) - 1)) {
-    json_writer_output_string_with_len(writer, spacesstr,
-                                       sizeof(spacesstr) - 1);
-    spaces -= (unsigned)(sizeof(spacesstr) - 1);
-  }
-
-  if (spaces == 0) return;
-
-  json_writer_output_string_with_len(
-      writer, spacesstr + sizeof(spacesstr) - 1 - spaces, spaces);
-}
-
-static void json_writer_value_end(grpc_json_writer *writer) {
-  if (writer->container_empty) {
-    writer->container_empty = 0;
-    if ((writer->indent == 0) || (writer->depth == 0)) return;
-    json_writer_output_char(writer, '\n');
-  } else {
-    json_writer_output_char(writer, ',');
-    if (writer->indent == 0) return;
-    json_writer_output_char(writer, '\n');
-  }
-}
-
-static void json_writer_escape_utf16(grpc_json_writer *writer, uint16_t utf16) {
-  static const char hex[] = "0123456789abcdef";
-
-  json_writer_output_string_with_len(writer, "\\u", 2);
-  json_writer_output_char(writer, hex[(utf16 >> 12) & 0x0f]);
-  json_writer_output_char(writer, hex[(utf16 >> 8) & 0x0f]);
-  json_writer_output_char(writer, hex[(utf16 >> 4) & 0x0f]);
-  json_writer_output_char(writer, hex[(utf16)&0x0f]);
-}
-
-static void json_writer_escape_string(grpc_json_writer *writer,
-                                      const char *string) {
-  json_writer_output_char(writer, '"');
-
-  for (;;) {
-    uint8_t c = (uint8_t)*string++;
-    if (c == 0) {
-      break;
-    } else if ((c >= 32) && (c <= 126)) {
-      if ((c == '\\') || (c == '"')) json_writer_output_char(writer, '\\');
-      json_writer_output_char(writer, (char)c);
-    } else if ((c < 32) || (c == 127)) {
-      switch (c) {
-        case '\b':
-          json_writer_output_string_with_len(writer, "\\b", 2);
-          break;
-        case '\f':
-          json_writer_output_string_with_len(writer, "\\f", 2);
-          break;
-        case '\n':
-          json_writer_output_string_with_len(writer, "\\n", 2);
-          break;
-        case '\r':
-          json_writer_output_string_with_len(writer, "\\r", 2);
-          break;
-        case '\t':
-          json_writer_output_string_with_len(writer, "\\t", 2);
-          break;
-        default:
-          json_writer_escape_utf16(writer, c);
-          break;
-      }
-    } else {
-      uint32_t utf32 = 0;
-      int extra = 0;
-      int i;
-      int valid = 1;
-      if ((c & 0xe0) == 0xc0) {
-        utf32 = c & 0x1f;
-        extra = 1;
-      } else if ((c & 0xf0) == 0xe0) {
-        utf32 = c & 0x0f;
-        extra = 2;
-      } else if ((c & 0xf8) == 0xf0) {
-        utf32 = c & 0x07;
-        extra = 3;
-      } else {
-        break;
-      }
-      for (i = 0; i < extra; i++) {
-        utf32 <<= 6;
-        c = (uint8_t)(*string++);
-        /* Breaks out and bail on any invalid UTF-8 sequence, including \0. */
-        if ((c & 0xc0) != 0x80) {
-          valid = 0;
-          break;
-        }
-        utf32 |= c & 0x3f;
-      }
-      if (!valid) break;
-      /* The range 0xd800 - 0xdfff is reserved by the surrogates ad vitam.
-       * Any other range is technically reserved for future usage, so if we
-       * don't want the software to break in the future, we have to allow
-       * anything else. The first non-unicode character is 0x110000. */
-      if (((utf32 >= 0xd800) && (utf32 <= 0xdfff)) || (utf32 >= 0x110000))
-        break;
-      if (utf32 >= 0x10000) {
-        /* If utf32 contains a character that is above 0xffff, it needs to be
-         * broken down into a utf-16 surrogate pair. A surrogate pair is first
-         * a high surrogate, followed by a low surrogate. Each surrogate holds
-         * 10 bits of usable data, thus allowing a total of 20 bits of data.
-         * The high surrogate marker is 0xd800, while the low surrogate marker
-         * is 0xdc00. The low 10 bits of each will be the usable data.
-         *
-         * After re-combining the 20 bits of data, one has to add 0x10000 to
-         * the resulting value, in order to obtain the original character.
-         * This is obviously because the range 0x0000 - 0xffff can be written
-         * without any special trick.
-         *
-         * Since 0x10ffff is the highest allowed character, we're working in
-         * the range 0x00000 - 0xfffff after we decrement it by 0x10000.
-         * That range is exactly 20 bits.
-         */
-        utf32 -= 0x10000;
-        json_writer_escape_utf16(writer, (uint16_t)(0xd800 | (utf32 >> 10)));
-        json_writer_escape_utf16(writer, (uint16_t)(0xdc00 | (utf32 & 0x3ff)));
-      } else {
-        json_writer_escape_utf16(writer, (uint16_t)utf32);
-      }
-    }
-  }
-
-  json_writer_output_char(writer, '"');
-}
-
-void grpc_json_writer_container_begins(grpc_json_writer *writer,
-                                       grpc_json_type type) {
-  if (!writer->got_key) json_writer_value_end(writer);
-  json_writer_output_indent(writer);
-  json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '[');
-  writer->container_empty = 1;
-  writer->got_key = 0;
-  writer->depth++;
-}
-
-void grpc_json_writer_container_ends(grpc_json_writer *writer,
-                                     grpc_json_type type) {
-  if (writer->indent && !writer->container_empty)
-    json_writer_output_char(writer, '\n');
-  writer->depth--;
-  if (!writer->container_empty) json_writer_output_indent(writer);
-  json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '}' : ']');
-  writer->container_empty = 0;
-  writer->got_key = 0;
-}
-
-void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string) {
-  json_writer_value_end(writer);
-  json_writer_output_indent(writer);
-  json_writer_escape_string(writer, string);
-  json_writer_output_char(writer, ':');
-  writer->got_key = 1;
-}
-
-void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string) {
-  if (!writer->got_key) json_writer_value_end(writer);
-  json_writer_output_indent(writer);
-  json_writer_output_string(writer, string);
-  writer->got_key = 0;
-}
-
-void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer,
-                                         const char *string, size_t len) {
-  if (!writer->got_key) json_writer_value_end(writer);
-  json_writer_output_indent(writer);
-  json_writer_output_string_with_len(writer, string, len);
-  writer->got_key = 0;
-}
-
-void grpc_json_writer_value_string(grpc_json_writer *writer,
-                                   const char *string) {
-  if (!writer->got_key) json_writer_value_end(writer);
-  json_writer_output_indent(writer);
-  json_writer_escape_string(writer, string);
-  writer->got_key = 0;
-}
diff --git a/src/core/json/json_writer.h b/src/core/json/json_writer.h
deleted file mode 100644
index c392126..0000000
--- a/src/core/json/json_writer.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* The idea of the writer is basically symmetrical of the reader. While the
- * reader emits various calls to your code, the writer takes basically the
- * same calls and emit json out of it. It doesn't try to make any check on
- * the order of the calls you do on it. Meaning you can theorically force
- * it to generate invalid json.
- *
- * Also, unlike the reader, the writer expects UTF-8 encoded input strings.
- * These strings will be UTF-8 validated, and any invalid character will
- * cut the conversion short, before any invalid UTF-8 sequence, thus forming
- * a valid UTF-8 string overall.
- */
-
-#ifndef GRPC_CORE_JSON_JSON_WRITER_H
-#define GRPC_CORE_JSON_JSON_WRITER_H
-
-#include <stdlib.h>
-
-#include "src/core/json/json_common.h"
-
-typedef struct grpc_json_writer_vtable {
-  /* Adds a character to the output stream. */
-  void (*output_char)(void *userdata, char);
-  /* Adds a zero-terminated string to the output stream. */
-  void (*output_string)(void *userdata, const char *str);
-  /* Adds a fixed-length string to the output stream. */
-  void (*output_string_with_len)(void *userdata, const char *str, size_t len);
-
-} grpc_json_writer_vtable;
-
-typedef struct grpc_json_writer {
-  void *userdata;
-  grpc_json_writer_vtable *vtable;
-  int indent;
-  int depth;
-  int container_empty;
-  int got_key;
-} grpc_json_writer;
-
-/* Call this to initialize your writer structure. The indent parameter is
- * specifying the number of spaces to use for indenting the output. If you
- * use indent=0, then the output will not have any newlines either, thus
- * emitting a condensed json output.
- */
-void grpc_json_writer_init(grpc_json_writer *writer, int indent,
-                           grpc_json_writer_vtable *vtable, void *userdata);
-
-/* Signals the beginning of a container. */
-void grpc_json_writer_container_begins(grpc_json_writer *writer,
-                                       grpc_json_type type);
-/* Signals the end of a container. */
-void grpc_json_writer_container_ends(grpc_json_writer *writer,
-                                     grpc_json_type type);
-/* Writes down an object key for the next value. */
-void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string);
-/* Sets a raw value. Useful for numbers. */
-void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string);
-/* Sets a raw value with its length. Useful for values like true or false. */
-void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer,
-                                         const char *string, size_t len);
-/* Sets a string value. It'll be escaped, and utf-8 validated. */
-void grpc_json_writer_value_string(grpc_json_writer *writer,
-                                   const char *string);
-
-#endif /* GRPC_CORE_JSON_JSON_WRITER_H */
diff --git a/src/core/lib/channel/channel_args.c b/src/core/lib/channel/channel_args.c
new file mode 100644
index 0000000..28d2d78
--- /dev/null
+++ b/src/core/lib/channel/channel_args.c
@@ -0,0 +1,259 @@
+/*
+ *
+ * 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/channel/channel_args.h"
+#include <grpc/grpc.h>
+#include "src/core/lib/support/string.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include <string.h>
+
+static grpc_arg copy_arg(const grpc_arg *src) {
+  grpc_arg dst;
+  dst.type = src->type;
+  dst.key = gpr_strdup(src->key);
+  switch (dst.type) {
+    case GRPC_ARG_STRING:
+      dst.value.string = gpr_strdup(src->value.string);
+      break;
+    case GRPC_ARG_INTEGER:
+      dst.value.integer = src->value.integer;
+      break;
+    case GRPC_ARG_POINTER:
+      dst.value.pointer = src->value.pointer;
+      dst.value.pointer.p =
+          src->value.pointer.vtable->copy(src->value.pointer.p);
+      break;
+  }
+  return dst;
+}
+
+grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
+                                                  const grpc_arg *to_add,
+                                                  size_t num_to_add) {
+  grpc_channel_args *dst = gpr_malloc(sizeof(grpc_channel_args));
+  size_t i;
+  size_t src_num_args = (src == NULL) ? 0 : src->num_args;
+  if (!src && !to_add) {
+    dst->num_args = 0;
+    dst->args = NULL;
+    return dst;
+  }
+  dst->num_args = src_num_args + num_to_add;
+  dst->args = gpr_malloc(sizeof(grpc_arg) * dst->num_args);
+  for (i = 0; i < src_num_args; i++) {
+    dst->args[i] = copy_arg(&src->args[i]);
+  }
+  for (i = 0; i < num_to_add; i++) {
+    dst->args[i + src_num_args] = copy_arg(&to_add[i]);
+  }
+  return dst;
+}
+
+grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src) {
+  return grpc_channel_args_copy_and_add(src, NULL, 0);
+}
+
+grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a,
+                                           const grpc_channel_args *b) {
+  return grpc_channel_args_copy_and_add(a, b->args, b->num_args);
+}
+
+static int cmp_arg(const grpc_arg *a, const grpc_arg *b) {
+  int c = GPR_ICMP(a->type, b->type);
+  if (c != 0) return c;
+  c = strcmp(a->key, b->key);
+  if (c != 0) return c;
+  switch (a->type) {
+    case GRPC_ARG_STRING:
+      return strcmp(a->value.string, b->value.string);
+    case GRPC_ARG_INTEGER:
+      return GPR_ICMP(a->value.integer, b->value.integer);
+    case GRPC_ARG_POINTER:
+      c = GPR_ICMP(a->value.pointer.p, b->value.pointer.p);
+      if (c != 0) {
+        c = GPR_ICMP(a->value.pointer.vtable, b->value.pointer.vtable);
+        if (c == 0) {
+          c = a->value.pointer.vtable->cmp(a->value.pointer.p,
+                                           b->value.pointer.p);
+        }
+      }
+      return c;
+  }
+  GPR_UNREACHABLE_CODE(return 0);
+}
+
+/* stabilizing comparison function: since channel_args ordering matters for
+ * keys with the same name, we need to preserve that ordering */
+static int cmp_key_stable(const void *ap, const void *bp) {
+  const grpc_arg *const *a = ap;
+  const grpc_arg *const *b = bp;
+  int c = strcmp((*a)->key, (*b)->key);
+  if (c == 0) c = GPR_ICMP(*a, *b);
+  return c;
+}
+
+grpc_channel_args *grpc_channel_args_normalize(const grpc_channel_args *a) {
+  grpc_arg **args = gpr_malloc(sizeof(grpc_arg *) * a->num_args);
+  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);
+
+  grpc_channel_args *b = gpr_malloc(sizeof(grpc_channel_args));
+  b->num_args = a->num_args;
+  b->args = gpr_malloc(sizeof(grpc_arg) * b->num_args);
+  for (size_t i = 0; i < a->num_args; i++) {
+    b->args[i] = copy_arg(args[i]);
+  }
+
+  gpr_free(args);
+  return b;
+}
+
+void grpc_channel_args_destroy(grpc_channel_args *a) {
+  size_t i;
+  for (i = 0; i < a->num_args; i++) {
+    switch (a->args[i].type) {
+      case GRPC_ARG_STRING:
+        gpr_free(a->args[i].value.string);
+        break;
+      case GRPC_ARG_INTEGER:
+        break;
+      case GRPC_ARG_POINTER:
+        a->args[i].value.pointer.vtable->destroy(a->args[i].value.pointer.p);
+        break;
+    }
+    gpr_free(a->args[i].key);
+  }
+  gpr_free(a->args);
+  gpr_free(a);
+}
+
+grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
+    const grpc_channel_args *a) {
+  size_t i;
+  if (a == NULL) return 0;
+  for (i = 0; i < a->num_args; ++i) {
+    if (a->args[i].type == GRPC_ARG_INTEGER &&
+        !strcmp(GRPC_COMPRESSION_ALGORITHM_ARG, a->args[i].key)) {
+      return (grpc_compression_algorithm)a->args[i].value.integer;
+      break;
+    }
+  }
+  return GRPC_COMPRESS_NONE;
+}
+
+grpc_channel_args *grpc_channel_args_set_compression_algorithm(
+    grpc_channel_args *a, grpc_compression_algorithm algorithm) {
+  grpc_arg tmp;
+  tmp.type = GRPC_ARG_INTEGER;
+  tmp.key = GRPC_COMPRESSION_ALGORITHM_ARG;
+  tmp.value.integer = algorithm;
+  return grpc_channel_args_copy_and_add(a, &tmp, 1);
+}
+
+/** Returns 1 if the argument for compression algorithm's enabled states bitset
+ * was found in \a a, returning the arg's value in \a states. Otherwise, returns
+ * 0. */
+static int find_compression_algorithm_states_bitset(const grpc_channel_args *a,
+                                                    int **states_arg) {
+  if (a != NULL) {
+    size_t i;
+    for (i = 0; i < a->num_args; ++i) {
+      if (a->args[i].type == GRPC_ARG_INTEGER &&
+          !strcmp(GRPC_COMPRESSION_ALGORITHM_STATE_ARG, a->args[i].key)) {
+        *states_arg = &a->args[i].value.integer;
+        return 1; /* GPR_TRUE */
+      }
+    }
+  }
+  return 0; /* GPR_FALSE */
+}
+
+grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
+    grpc_channel_args **a, grpc_compression_algorithm algorithm, int state) {
+  int *states_arg;
+  grpc_channel_args *result = *a;
+  const int states_arg_found =
+      find_compression_algorithm_states_bitset(*a, &states_arg);
+
+  if (states_arg_found) {
+    if (state != 0) {
+      GPR_BITSET((unsigned *)states_arg, algorithm);
+    } else {
+      GPR_BITCLEAR((unsigned *)states_arg, algorithm);
+    }
+  } else {
+    /* create a new arg */
+    grpc_arg tmp;
+    tmp.type = GRPC_ARG_INTEGER;
+    tmp.key = GRPC_COMPRESSION_ALGORITHM_STATE_ARG;
+    /* all enabled by default */
+    tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
+    if (state != 0) {
+      GPR_BITSET((unsigned *)&tmp.value.integer, algorithm);
+    } else {
+      GPR_BITCLEAR((unsigned *)&tmp.value.integer, algorithm);
+    }
+    result = grpc_channel_args_copy_and_add(*a, &tmp, 1);
+    grpc_channel_args_destroy(*a);
+    *a = result;
+  }
+  return result;
+}
+
+int grpc_channel_args_compression_algorithm_get_states(
+    const grpc_channel_args *a) {
+  int *states_arg;
+  if (find_compression_algorithm_states_bitset(a, &states_arg)) {
+    return *states_arg;
+  } else {
+    return (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; /* All algs. enabled */
+  }
+}
+
+int grpc_channel_args_compare(const grpc_channel_args *a,
+                              const grpc_channel_args *b) {
+  int c = GPR_ICMP(a->num_args, b->num_args);
+  if (c != 0) return c;
+  for (size_t i = 0; i < a->num_args; i++) {
+    c = cmp_arg(&a->args[i], &b->args[i]);
+    if (c != 0) return c;
+  }
+  return 0;
+}
diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h
new file mode 100644
index 0000000..0a51780
--- /dev/null
+++ b/src/core/lib/channel/channel_args.h
@@ -0,0 +1,94 @@
+/*
+ *
+ * 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_CHANNEL_CHANNEL_ARGS_H
+#define GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H
+
+#include <grpc/compression.h>
+#include <grpc/grpc.h>
+
+/** Copy the arguments in \a src into a new instance */
+grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src);
+
+/** Copy the arguments in \a src into a new instance, stably sorting keys */
+grpc_channel_args *grpc_channel_args_normalize(const grpc_channel_args *src);
+
+/** Copy the arguments in \a src and append \a to_add. If \a to_add is NULL, it
+ * is equivalent to calling \a grpc_channel_args_copy. */
+grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
+                                                  const grpc_arg *to_add,
+                                                  size_t num_to_add);
+
+/** Concatenate args from \a a and \a b into a new instance */
+grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a,
+                                           const grpc_channel_args *b);
+
+/** Destroy arguments created by \a grpc_channel_args_copy */
+void grpc_channel_args_destroy(grpc_channel_args *a);
+
+/** Reads census_enabled settings from channel args. Returns 1 if census_enabled
+ * is specified in channel args, otherwise returns 0. */
+int grpc_channel_args_is_census_enabled(const grpc_channel_args *a);
+
+/** Returns the compression algorithm set in \a a. */
+grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
+    const grpc_channel_args *a);
+
+/** Returns a channel arg instance with compression enabled. If \a a is
+ * non-NULL, its args are copied. N.B. GRPC_COMPRESS_NONE disables compression
+ * for the channel. */
+grpc_channel_args *grpc_channel_args_set_compression_algorithm(
+    grpc_channel_args *a, grpc_compression_algorithm algorithm);
+
+/** Sets the support for the given compression algorithm. By default, all
+ * compression algorithms are enabled. It's an error to disable an algorithm set
+ * by grpc_channel_args_set_compression_algorithm.
+ *
+ * Returns an instance with the updated algorithm states. The \a a pointer is
+ * modified to point to the returned instance (which may be different from the
+ * input value of \a a). */
+grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
+    grpc_channel_args **a, grpc_compression_algorithm algorithm, int enabled);
+
+/** Returns the bitset representing the support state (true for enabled, false
+ * for disabled) for compression algorithms.
+ *
+ * The i-th bit of the returned bitset corresponds to the i-th entry in the
+ * grpc_compression_algorithm enum. */
+int grpc_channel_args_compression_algorithm_get_states(
+    const grpc_channel_args *a);
+
+int grpc_channel_args_compare(const grpc_channel_args *a,
+                              const grpc_channel_args *b);
+
+#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
new file mode 100644
index 0000000..e36066d
--- /dev/null
+++ b/src/core/lib/channel/channel_stack.c
@@ -0,0 +1,262 @@
+/*
+ *
+ * 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/channel/channel_stack.h"
+#include <grpc/support/log.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+int grpc_trace_channel = 0;
+
+/* Memory layouts.
+
+   Channel stack is laid out as: {
+     grpc_channel_stack stk;
+     padding to GPR_MAX_ALIGNMENT
+     grpc_channel_element[stk.count];
+     per-filter memory, aligned to GPR_MAX_ALIGNMENT
+   }
+
+   Call stack is laid out as: {
+     grpc_call_stack stk;
+     padding to GPR_MAX_ALIGNMENT
+     grpc_call_element[stk.count];
+     per-filter memory, aligned to GPR_MAX_ALIGNMENT
+   } */
+
+/* Given a size, round up to the next multiple of sizeof(void*) */
+#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
+  (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
+
+size_t grpc_channel_stack_size(const grpc_channel_filter **filters,
+                               size_t filter_count) {
+  /* always need the header, and size for the channel elements */
+  size_t size =
+      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
+      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
+  size_t i;
+
+  GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
+             "GPR_MAX_ALIGNMENT must be a power of two");
+
+  /* add the size for each filter */
+  for (i = 0; i < filter_count; i++) {
+    size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
+  }
+
+  return size;
+}
+
+#define CHANNEL_ELEMS_FROM_STACK(stk)                                   \
+  ((grpc_channel_element *)((char *)(stk) + ROUND_UP_TO_ALIGNMENT_SIZE( \
+                                                sizeof(grpc_channel_stack))))
+
+#define CALL_ELEMS_FROM_STACK(stk)       \
+  ((grpc_call_element *)((char *)(stk) + \
+                         ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack))))
+
+grpc_channel_element *grpc_channel_stack_element(
+    grpc_channel_stack *channel_stack, size_t index) {
+  return CHANNEL_ELEMS_FROM_STACK(channel_stack) + index;
+}
+
+grpc_channel_element *grpc_channel_stack_last_element(
+    grpc_channel_stack *channel_stack) {
+  return grpc_channel_stack_element(channel_stack, channel_stack->count - 1);
+}
+
+grpc_call_element *grpc_call_stack_element(grpc_call_stack *call_stack,
+                                           size_t index) {
+  return CALL_ELEMS_FROM_STACK(call_stack) + index;
+}
+
+void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
+                             grpc_iomgr_cb_func destroy, void *destroy_arg,
+                             const grpc_channel_filter **filters,
+                             size_t filter_count,
+                             const grpc_channel_args *channel_args,
+                             const char *name, grpc_channel_stack *stack) {
+  size_t call_size =
+      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
+      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
+  grpc_channel_element *elems;
+  grpc_channel_element_args args;
+  char *user_data;
+  size_t i;
+
+  stack->count = filter_count;
+  GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg,
+                       name);
+  elems = CHANNEL_ELEMS_FROM_STACK(stack);
+  user_data =
+      ((char *)elems) +
+      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
+
+  /* init per-filter data */
+  for (i = 0; i < filter_count; i++) {
+    args.channel_stack = stack;
+    args.channel_args = channel_args;
+    args.is_first = i == 0;
+    args.is_last = i == (filter_count - 1);
+    elems[i].filter = filters[i];
+    elems[i].channel_data = user_data;
+    elems[i].filter->init_channel_elem(exec_ctx, &elems[i], &args);
+    user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
+    call_size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
+  }
+
+  GPR_ASSERT(user_data > (char *)stack);
+  GPR_ASSERT((uintptr_t)(user_data - (char *)stack) ==
+             grpc_channel_stack_size(filters, filter_count));
+
+  stack->call_stack_size = call_size;
+}
+
+void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
+                                grpc_channel_stack *stack) {
+  grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(stack);
+  size_t count = stack->count;
+  size_t i;
+
+  /* destroy per-filter data */
+  for (i = 0; i < count; i++) {
+    channel_elems[i].filter->destroy_channel_elem(exec_ctx, &channel_elems[i]);
+  }
+}
+
+void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
+                          grpc_channel_stack *channel_stack, int initial_refs,
+                          grpc_iomgr_cb_func destroy, void *destroy_arg,
+                          grpc_call_context_element *context,
+                          const void *transport_server_data,
+                          grpc_call_stack *call_stack) {
+  grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
+  grpc_call_element_args args;
+  size_t count = channel_stack->count;
+  grpc_call_element *call_elems;
+  char *user_data;
+  size_t i;
+
+  call_stack->count = count;
+  GRPC_STREAM_REF_INIT(&call_stack->refcount, initial_refs, destroy,
+                       destroy_arg, "CALL_STACK");
+  call_elems = CALL_ELEMS_FROM_STACK(call_stack);
+  user_data = ((char *)call_elems) +
+              ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
+
+  /* init per-filter data */
+  for (i = 0; i < count; i++) {
+    args.call_stack = call_stack;
+    args.server_transport_data = transport_server_data;
+    args.context = context;
+    call_elems[i].filter = channel_elems[i].filter;
+    call_elems[i].channel_data = channel_elems[i].channel_data;
+    call_elems[i].call_data = user_data;
+    call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args);
+    user_data +=
+        ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
+  }
+}
+
+void grpc_call_stack_set_pollset(grpc_exec_ctx *exec_ctx,
+                                 grpc_call_stack *call_stack,
+                                 grpc_pollset *pollset) {
+  size_t count = call_stack->count;
+  grpc_call_element *call_elems;
+  char *user_data;
+  size_t i;
+
+  call_elems = CALL_ELEMS_FROM_STACK(call_stack);
+  user_data = ((char *)call_elems) +
+              ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
+
+  /* init per-filter data */
+  for (i = 0; i < count; i++) {
+    call_elems[i].filter->set_pollset(exec_ctx, &call_elems[i], pollset);
+    user_data +=
+        ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
+  }
+}
+
+void grpc_call_stack_ignore_set_pollset(grpc_exec_ctx *exec_ctx,
+                                        grpc_call_element *elem,
+                                        grpc_pollset *pollset) {}
+
+void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack) {
+  grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack);
+  size_t count = stack->count;
+  size_t i;
+
+  /* destroy per-filter data */
+  for (i = 0; i < count; i++) {
+    elems[i].filter->destroy_call_elem(exec_ctx, &elems[i]);
+  }
+}
+
+void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                       grpc_transport_stream_op *op) {
+  grpc_call_element *next_elem = elem + 1;
+  next_elem->filter->start_transport_stream_op(exec_ctx, next_elem, op);
+}
+
+char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {
+  grpc_call_element *next_elem = elem + 1;
+  return next_elem->filter->get_peer(exec_ctx, next_elem);
+}
+
+void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
+                          grpc_transport_op *op) {
+  grpc_channel_element *next_elem = elem + 1;
+  next_elem->filter->start_transport_op(exec_ctx, next_elem, op);
+}
+
+grpc_channel_stack *grpc_channel_stack_from_top_element(
+    grpc_channel_element *elem) {
+  return (grpc_channel_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
+      sizeof(grpc_channel_stack)));
+}
+
+grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) {
+  return (grpc_call_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
+      sizeof(grpc_call_stack)));
+}
+
+void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
+                                   grpc_call_element *cur_elem) {
+  grpc_transport_stream_op op;
+  memset(&op, 0, sizeof(op));
+  op.cancel_with_status = GRPC_STATUS_CANCELLED;
+  grpc_call_next_op(exec_ctx, cur_elem, &op);
+}
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
new file mode 100644
index 0000000..9e3a25a
--- /dev/null
+++ b/src/core/lib/channel/channel_stack.h
@@ -0,0 +1,260 @@
+/*
+ *
+ * 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_CHANNEL_CHANNEL_STACK_H
+#define GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H
+
+/* A channel filter defines how operations on a channel are implemented.
+   Channel filters are chained together to create full channels, and if those
+   chains are linear, then channel stacks provide a mechanism to minimize
+   allocations for that chain.
+   Call stacks are created by channel stacks and represent the per-call data
+   for that stack. */
+
+#include <stddef.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/transport/transport.h"
+
+typedef struct grpc_channel_element grpc_channel_element;
+typedef struct grpc_call_element grpc_call_element;
+
+typedef struct grpc_channel_stack grpc_channel_stack;
+typedef struct grpc_call_stack grpc_call_stack;
+
+typedef struct {
+  grpc_channel_stack *channel_stack;
+  const grpc_channel_args *channel_args;
+  int is_first;
+  int is_last;
+} grpc_channel_element_args;
+
+typedef struct {
+  grpc_call_stack *call_stack;
+  const void *server_transport_data;
+  grpc_call_context_element *context;
+} grpc_call_element_args;
+
+/* Channel filters specify:
+   1. the amount of memory needed in the channel & call (via the sizeof_XXX
+      members)
+   2. functions to initialize and destroy channel & call data
+      (init_XXX, destroy_XXX)
+   3. functions to implement call operations and channel operations (call_op,
+      channel_op)
+   4. a name, which is useful when debugging
+
+   Members are laid out in approximate frequency of use order. */
+typedef struct {
+  /* Called to eg. send/receive data on a call.
+     See grpc_call_next_op on how to call the next element in the stack */
+  void (*start_transport_stream_op)(grpc_exec_ctx *exec_ctx,
+                                    grpc_call_element *elem,
+                                    grpc_transport_stream_op *op);
+  /* Called to handle channel level operations - e.g. new calls, or transport
+     closure.
+     See grpc_channel_next_op on how to call the next element in the stack */
+  void (*start_transport_op)(grpc_exec_ctx *exec_ctx,
+                             grpc_channel_element *elem, grpc_transport_op *op);
+
+  /* sizeof(per call data) */
+  size_t sizeof_call_data;
+  /* Initialize per call data.
+     elem is initialized at the start of the call, and elem->call_data is what
+     needs initializing.
+     The filter does not need to do any chaining.
+     server_transport_data is an opaque pointer. If it is NULL, this call is
+     on a client; if it is non-NULL, then it points to memory owned by the
+     transport and is on the server. Most filters want to ignore this
+     argument. */
+  void (*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                         grpc_call_element_args *args);
+  void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                      grpc_pollset *pollset);
+  /* Destroy per call data.
+     The filter does not need to do any chaining */
+  void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
+
+  /* sizeof(per channel data) */
+  size_t sizeof_channel_data;
+  /* Initialize per-channel data.
+     elem is initialized at the start of the call, and elem->channel_data is
+     what needs initializing.
+     is_first, is_last designate this elements position in the stack, and are
+     useful for asserting correct configuration by upper layer code.
+     The filter does not need to do any chaining */
+  void (*init_channel_elem)(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
+                            grpc_channel_element_args *args);
+  /* Destroy per channel data.
+     The filter does not need to do any chaining */
+  void (*destroy_channel_elem)(grpc_exec_ctx *exec_ctx,
+                               grpc_channel_element *elem);
+
+  /* Implement grpc_call_get_peer() */
+  char *(*get_peer)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
+
+  /* The name of this filter */
+  const char *name;
+} grpc_channel_filter;
+
+/* A channel_element tracks its filter and the filter requested memory within
+   a channel allocation */
+struct grpc_channel_element {
+  const grpc_channel_filter *filter;
+  void *channel_data;
+};
+
+/* A call_element tracks its filter, the filter requested memory within
+   a channel allocation, and the filter requested memory within a call
+   allocation */
+struct grpc_call_element {
+  const grpc_channel_filter *filter;
+  void *channel_data;
+  void *call_data;
+};
+
+/* A channel stack tracks a set of related filters for one channel, and
+   guarantees they live within a single malloc() allocation */
+struct grpc_channel_stack {
+  grpc_stream_refcount refcount;
+  size_t count;
+  /* Memory required for a call stack (computed at channel stack
+     initialization) */
+  size_t call_stack_size;
+};
+
+/* A call stack tracks a set of related filters for one call, and guarantees
+   they live within a single malloc() allocation */
+struct grpc_call_stack {
+  /* shared refcount for this channel stack.
+     MUST be the first element: the underlying code calls destroy
+     with the address of the refcount, but higher layers prefer to think
+     about the address of the call stack itself. */
+  grpc_stream_refcount refcount;
+  size_t count;
+};
+
+/* Get a channel element given a channel stack and its index */
+grpc_channel_element *grpc_channel_stack_element(grpc_channel_stack *stack,
+                                                 size_t i);
+/* Get the last channel element in a channel stack */
+grpc_channel_element *grpc_channel_stack_last_element(
+    grpc_channel_stack *stack);
+/* Get a call stack element given a call stack and an index */
+grpc_call_element *grpc_call_stack_element(grpc_call_stack *stack, size_t i);
+
+/* Determine memory required for a channel stack containing a set of filters */
+size_t grpc_channel_stack_size(const grpc_channel_filter **filters,
+                               size_t filter_count);
+/* Initialize a channel stack given some filters */
+void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
+                             grpc_iomgr_cb_func destroy, void *destroy_arg,
+                             const grpc_channel_filter **filters,
+                             size_t filter_count, const grpc_channel_args *args,
+                             const char *name, grpc_channel_stack *stack);
+/* Destroy a channel stack */
+void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
+                                grpc_channel_stack *stack);
+
+/* Initialize a call stack given a channel stack. transport_server_data is
+   expected to be NULL on a client, or an opaque transport owned pointer on the
+   server. */
+void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
+                          grpc_channel_stack *channel_stack, int initial_refs,
+                          grpc_iomgr_cb_func destroy, void *destroy_arg,
+                          grpc_call_context_element *context,
+                          const void *transport_server_data,
+                          grpc_call_stack *call_stack);
+/* Set a pollset for a call stack: must occur before the first op is started */
+void grpc_call_stack_set_pollset(grpc_exec_ctx *exec_ctx,
+                                 grpc_call_stack *call_stack,
+                                 grpc_pollset *pollset);
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+#define GRPC_CALL_STACK_REF(call_stack, reason) \
+  grpc_stream_ref(&(call_stack)->refcount, reason)
+#define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \
+  grpc_stream_unref(exec_ctx, &(call_stack)->refcount, reason)
+#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
+  grpc_stream_ref(&(channel_stack)->refcount, reason)
+#define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \
+  grpc_stream_unref(exec_ctx, &(channel_stack)->refcount, reason)
+#else
+#define GRPC_CALL_STACK_REF(call_stack, reason) \
+  grpc_stream_ref(&(call_stack)->refcount)
+#define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \
+  grpc_stream_unref(exec_ctx, &(call_stack)->refcount)
+#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
+  grpc_stream_ref(&(channel_stack)->refcount)
+#define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \
+  grpc_stream_unref(exec_ctx, &(channel_stack)->refcount)
+#endif
+
+/* Destroy a call stack */
+void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack);
+
+/* Ignore set pollset - used by filters to implement the set_pollset method
+   if they don't care about pollsets at all. Does nothing. */
+void grpc_call_stack_ignore_set_pollset(grpc_exec_ctx *exec_ctx,
+                                        grpc_call_element *elem,
+                                        grpc_pollset *pollset);
+/* Call the next operation in a call stack */
+void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                       grpc_transport_stream_op *op);
+/* Call the next operation (depending on call directionality) in a channel
+   stack */
+void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
+                          grpc_transport_op *op);
+/* Pass through a request to get_peer to the next child element */
+char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
+
+/* Given the top element of a channel stack, get the channel stack itself */
+grpc_channel_stack *grpc_channel_stack_from_top_element(
+    grpc_channel_element *elem);
+/* Given the top element of a call stack, get the call stack itself */
+grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem);
+
+void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
+                      grpc_call_element *elem, grpc_transport_stream_op *op);
+
+void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
+                                   grpc_call_element *cur_elem);
+
+extern int grpc_trace_channel;
+
+#define GRPC_CALL_LOG_OP(sev, elem, op) \
+  if (grpc_trace_channel) grpc_call_log_op(sev, elem, op)
+
+#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H */
diff --git a/src/core/lib/channel/channel_stack_builder.c b/src/core/lib/channel/channel_stack_builder.c
new file mode 100644
index 0000000..a8646c9
--- /dev/null
+++ b/src/core/lib/channel/channel_stack_builder.c
@@ -0,0 +1,277 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/channel/channel_stack_builder.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+int grpc_trace_channel_stack_builder = 0;
+
+typedef struct filter_node {
+  struct filter_node *next;
+  struct filter_node *prev;
+  const grpc_channel_filter *filter;
+  grpc_post_filter_create_init_func init;
+  void *init_arg;
+} filter_node;
+
+struct grpc_channel_stack_builder {
+  // sentinel nodes for filters that have been added
+  filter_node begin;
+  filter_node end;
+  // various set/get-able parameters
+  grpc_channel_args *args;
+  grpc_transport *transport;
+  char *target;
+  const char *name;
+};
+
+struct grpc_channel_stack_builder_iterator {
+  grpc_channel_stack_builder *builder;
+  filter_node *node;
+};
+
+grpc_channel_stack_builder *grpc_channel_stack_builder_create(void) {
+  grpc_channel_stack_builder *b = gpr_malloc(sizeof(*b));
+  memset(b, 0, sizeof(*b));
+
+  b->begin.filter = NULL;
+  b->end.filter = NULL;
+  b->begin.next = &b->end;
+  b->begin.prev = &b->end;
+  b->end.next = &b->begin;
+  b->end.prev = &b->begin;
+
+  return b;
+}
+
+void grpc_channel_stack_builder_set_target(grpc_channel_stack_builder *b,
+                                           const char *target) {
+  gpr_free(b->target);
+  b->target = gpr_strdup(target);
+}
+
+const char *grpc_channel_stack_builder_get_target(
+    grpc_channel_stack_builder *b) {
+  return b->target;
+}
+
+static grpc_channel_stack_builder_iterator *create_iterator_at_filter_node(
+    grpc_channel_stack_builder *builder, filter_node *node) {
+  grpc_channel_stack_builder_iterator *it = gpr_malloc(sizeof(*it));
+  it->builder = builder;
+  it->node = node;
+  return it;
+}
+
+void grpc_channel_stack_builder_iterator_destroy(
+    grpc_channel_stack_builder_iterator *it) {
+  gpr_free(it);
+}
+
+grpc_channel_stack_builder_iterator *
+grpc_channel_stack_builder_create_iterator_at_first(
+    grpc_channel_stack_builder *builder) {
+  return create_iterator_at_filter_node(builder, &builder->begin);
+}
+
+grpc_channel_stack_builder_iterator *
+grpc_channel_stack_builder_create_iterator_at_last(
+    grpc_channel_stack_builder *builder) {
+  return create_iterator_at_filter_node(builder, &builder->end);
+}
+
+bool grpc_channel_stack_builder_move_next(
+    grpc_channel_stack_builder_iterator *iterator) {
+  if (iterator->node == &iterator->builder->end) return false;
+  iterator->node = iterator->node->next;
+  return true;
+}
+
+bool grpc_channel_stack_builder_move_prev(
+    grpc_channel_stack_builder_iterator *iterator) {
+  if (iterator->node == &iterator->builder->begin) return false;
+  iterator->node = iterator->node->prev;
+  return true;
+}
+
+bool grpc_channel_stack_builder_move_prev(
+    grpc_channel_stack_builder_iterator *iterator);
+
+void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder *builder,
+                                         const char *name) {
+  GPR_ASSERT(builder->name == NULL);
+  builder->name = name;
+}
+
+void grpc_channel_stack_builder_set_channel_arguments(
+    grpc_channel_stack_builder *builder, const grpc_channel_args *args) {
+  if (builder->args != NULL) {
+    grpc_channel_args_destroy(builder->args);
+  }
+  builder->args = grpc_channel_args_copy(args);
+}
+
+void grpc_channel_stack_builder_set_transport(
+    grpc_channel_stack_builder *builder, grpc_transport *transport) {
+  GPR_ASSERT(builder->transport == NULL);
+  builder->transport = transport;
+}
+
+grpc_transport *grpc_channel_stack_builder_get_transport(
+    grpc_channel_stack_builder *builder) {
+  return builder->transport;
+}
+
+const grpc_channel_args *grpc_channel_stack_builder_get_channel_arguments(
+    grpc_channel_stack_builder *builder) {
+  return builder->args;
+}
+
+bool grpc_channel_stack_builder_append_filter(
+    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func, void *user_data) {
+  grpc_channel_stack_builder_iterator *it =
+      grpc_channel_stack_builder_create_iterator_at_last(builder);
+  bool ok = grpc_channel_stack_builder_add_filter_before(
+      it, filter, post_init_func, user_data);
+  grpc_channel_stack_builder_iterator_destroy(it);
+  return ok;
+}
+
+bool grpc_channel_stack_builder_prepend_filter(
+    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func, void *user_data) {
+  grpc_channel_stack_builder_iterator *it =
+      grpc_channel_stack_builder_create_iterator_at_first(builder);
+  bool ok = grpc_channel_stack_builder_add_filter_after(
+      it, filter, post_init_func, user_data);
+  grpc_channel_stack_builder_iterator_destroy(it);
+  return ok;
+}
+
+static void add_after(filter_node *before, const grpc_channel_filter *filter,
+                      grpc_post_filter_create_init_func post_init_func,
+                      void *user_data) {
+  filter_node *new = gpr_malloc(sizeof(*new));
+  new->next = before->next;
+  new->prev = before;
+  new->next->prev = new->prev->next = new;
+  new->filter = filter;
+  new->init = post_init_func;
+  new->init_arg = user_data;
+}
+
+bool grpc_channel_stack_builder_add_filter_before(
+    grpc_channel_stack_builder_iterator *iterator,
+    const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func, void *user_data) {
+  if (iterator->node == &iterator->builder->begin) return false;
+  add_after(iterator->node->prev, filter, post_init_func, user_data);
+  return true;
+}
+
+bool grpc_channel_stack_builder_add_filter_after(
+    grpc_channel_stack_builder_iterator *iterator,
+    const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func, void *user_data) {
+  if (iterator->node == &iterator->builder->end) return false;
+  add_after(iterator->node, filter, post_init_func, user_data);
+  return true;
+}
+
+void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder *builder) {
+  filter_node *p = builder->begin.next;
+  while (p != &builder->end) {
+    filter_node *next = p->next;
+    gpr_free(p);
+    p = next;
+  }
+  if (builder->args != NULL) {
+    grpc_channel_args_destroy(builder->args);
+  }
+  gpr_free(builder->target);
+  gpr_free(builder);
+}
+
+void *grpc_channel_stack_builder_finish(grpc_exec_ctx *exec_ctx,
+                                        grpc_channel_stack_builder *builder,
+                                        size_t prefix_bytes, int initial_refs,
+                                        grpc_iomgr_cb_func destroy,
+                                        void *destroy_arg) {
+  // count the number of filters
+  size_t num_filters = 0;
+  for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) {
+    num_filters++;
+  }
+
+  // create an array of filters
+  const grpc_channel_filter **filters =
+      gpr_malloc(sizeof(*filters) * num_filters);
+  size_t i = 0;
+  for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) {
+    filters[i++] = p->filter;
+  }
+
+  // calculate the size of the channel stack
+  size_t channel_stack_size = grpc_channel_stack_size(filters, num_filters);
+
+  // allocate memory, with prefix_bytes followed by channel_stack_size
+  char *result = gpr_malloc(prefix_bytes + channel_stack_size);
+  // fetch a pointer to the channel stack
+  grpc_channel_stack *channel_stack =
+      (grpc_channel_stack *)(result + prefix_bytes);
+  // and initialize it
+  grpc_channel_stack_init(exec_ctx, initial_refs, destroy,
+                          destroy_arg == NULL ? result : destroy_arg, filters,
+                          num_filters, builder->args, builder->name,
+                          channel_stack);
+
+  // run post-initialization functions
+  i = 0;
+  for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) {
+    if (p->init != NULL) {
+      p->init(channel_stack, grpc_channel_stack_element(channel_stack, i),
+              p->init_arg);
+    }
+    i++;
+  }
+
+  grpc_channel_stack_builder_destroy(builder);
+  gpr_free((grpc_channel_filter **)filters);
+
+  return result;
+}
diff --git a/src/core/lib/channel/channel_stack_builder.h b/src/core/lib/channel/channel_stack_builder.h
new file mode 100644
index 0000000..0e6bfd9
--- /dev/null
+++ b/src/core/lib/channel/channel_stack_builder.h
@@ -0,0 +1,161 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H
+#define GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H
+
+#include <stdbool.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/channel_stack.h"
+
+/// grpc_channel_stack_builder offers a programmatic interface to selected
+/// and order channel filters
+typedef struct grpc_channel_stack_builder grpc_channel_stack_builder;
+typedef struct grpc_channel_stack_builder_iterator
+    grpc_channel_stack_builder_iterator;
+
+/// Create a new channel stack builder
+grpc_channel_stack_builder *grpc_channel_stack_builder_create(void);
+
+/// Assign a name to the channel stack: \a name must be statically allocated
+void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder *builder,
+                                         const char *name);
+
+/// Set the target uri
+void grpc_channel_stack_builder_set_target(grpc_channel_stack_builder *b,
+                                           const char *target);
+
+const char *grpc_channel_stack_builder_get_target(
+    grpc_channel_stack_builder *b);
+
+/// Attach \a transport to the builder (does not take ownership)
+void grpc_channel_stack_builder_set_transport(
+    grpc_channel_stack_builder *builder, grpc_transport *transport);
+
+/// Fetch attached transport
+grpc_transport *grpc_channel_stack_builder_get_transport(
+    grpc_channel_stack_builder *builder);
+
+/// Set channel arguments: copies args
+void grpc_channel_stack_builder_set_channel_arguments(
+    grpc_channel_stack_builder *builder, const grpc_channel_args *args);
+
+/// Return a borrowed pointer to the channel arguments
+const grpc_channel_args *grpc_channel_stack_builder_get_channel_arguments(
+    grpc_channel_stack_builder *builder);
+
+/// Begin iterating over already defined filters in the builder at the beginning
+grpc_channel_stack_builder_iterator *
+grpc_channel_stack_builder_create_iterator_at_first(
+    grpc_channel_stack_builder *builder);
+
+/// Begin iterating over already defined filters in the builder at the end
+grpc_channel_stack_builder_iterator *
+grpc_channel_stack_builder_create_iterator_at_last(
+    grpc_channel_stack_builder *builder);
+
+/// Is an iterator at the first element?
+bool grpc_channel_stack_builder_iterator_is_first(
+    grpc_channel_stack_builder_iterator *iterator);
+
+/// Is an iterator at the end?
+bool grpc_channel_stack_builder_iterator_is_end(
+    grpc_channel_stack_builder_iterator *iterator);
+
+/// Move an iterator to the next item
+bool grpc_channel_stack_builder_move_next(
+    grpc_channel_stack_builder_iterator *iterator);
+
+/// Move an iterator to the previous item
+bool grpc_channel_stack_builder_move_prev(
+    grpc_channel_stack_builder_iterator *iterator);
+
+typedef void (*grpc_post_filter_create_init_func)(
+    grpc_channel_stack *channel_stack, grpc_channel_element *elem, void *arg);
+
+/// Add \a filter to the stack, after \a iterator.
+/// Call \a post_init_func(..., \a user_data) once the channel stack is
+/// created.
+bool grpc_channel_stack_builder_add_filter_after(
+    grpc_channel_stack_builder_iterator *iterator,
+    const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func,
+    void *user_data) GRPC_MUST_USE_RESULT;
+
+/// Add \a filter to the stack, before \a iterator.
+/// Call \a post_init_func(..., \a user_data) once the channel stack is
+/// created.
+bool grpc_channel_stack_builder_add_filter_before(
+    grpc_channel_stack_builder_iterator *iterator,
+    const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func,
+    void *user_data) GRPC_MUST_USE_RESULT;
+
+/// Add \a filter to the beginning of the filter list.
+/// Call \a post_init_func(..., \a user_data) once the channel stack is
+/// created.
+bool grpc_channel_stack_builder_prepend_filter(
+    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func,
+    void *user_data) GRPC_MUST_USE_RESULT;
+
+/// Add \a filter to the end of the filter list.
+/// Call \a post_init_func(..., \a user_data) once the channel stack is
+/// created.
+bool grpc_channel_stack_builder_append_filter(
+    grpc_channel_stack_builder *builder, const grpc_channel_filter *filter,
+    grpc_post_filter_create_init_func post_init_func,
+    void *user_data) GRPC_MUST_USE_RESULT;
+
+/// Terminate iteration and destroy \a iterator
+void grpc_channel_stack_builder_iterator_destroy(
+    grpc_channel_stack_builder_iterator *iterator);
+
+/// Destroy the builder, return the freshly minted channel stack
+/// Allocates \a prefix_bytes bytes before the channel stack
+/// Returns the base pointer of the allocated block
+/// \a initial_refs, \a destroy, \a destroy_arg are as per
+/// grpc_channel_stack_init
+void *grpc_channel_stack_builder_finish(grpc_exec_ctx *exec_ctx,
+                                        grpc_channel_stack_builder *builder,
+                                        size_t prefix_bytes, int initial_refs,
+                                        grpc_iomgr_cb_func destroy,
+                                        void *destroy_arg);
+
+/// Destroy the builder without creating a channel stack
+void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder *builder);
+
+extern int grpc_trace_channel_stack_builder;
+
+#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H */
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
new file mode 100644
index 0000000..3d42d0e
--- /dev/null
+++ b/src/core/lib/channel/compress_filter.c
@@ -0,0 +1,310 @@
+/*
+ *
+ * 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 <assert.h>
+#include <string.h>
+
+#include <grpc/compression.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/compression/algorithm_metadata.h"
+#include "src/core/lib/compression/message_compress.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+typedef struct call_data {
+  gpr_slice_buffer slices; /**< Buffers up input slices to be compressed */
+  grpc_linked_mdelem compression_algorithm_storage;
+  grpc_linked_mdelem accept_encoding_storage;
+  uint32_t remaining_slice_bytes;
+  /** Compression algorithm we'll try to use. It may be given by incoming
+   * metadata, or by the channel's default compression settings. */
+  grpc_compression_algorithm compression_algorithm;
+  /** If true, contents of \a compression_algorithm are authoritative */
+  int has_compression_algorithm;
+
+  grpc_transport_stream_op send_op;
+  uint32_t send_length;
+  uint32_t send_flags;
+  gpr_slice incoming_slice;
+  grpc_slice_buffer_stream replacement_stream;
+  grpc_closure *post_send;
+  grpc_closure send_done;
+  grpc_closure got_slice;
+} call_data;
+
+typedef struct channel_data {
+  /** The default, channel-level, compression algorithm */
+  grpc_compression_algorithm default_compression_algorithm;
+  /** Compression options for the channel */
+  grpc_compression_options compression_options;
+  /** Supported compression algorithms */
+  uint32_t supported_compression_algorithms;
+} channel_data;
+
+/** For each \a md element from the incoming metadata, filter out the entry for
+ * "grpc-encoding", using its value to populate the call data's
+ * compression_algorithm field. */
+static grpc_mdelem *compression_md_filter(void *user_data, grpc_mdelem *md) {
+  grpc_call_element *elem = user_data;
+  call_data *calld = elem->call_data;
+  channel_data *channeld = elem->channel_data;
+
+  if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
+    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
+    if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
+                                          &calld->compression_algorithm)) {
+      gpr_log(GPR_ERROR,
+              "Invalid compression algorithm: '%s' (unknown). Ignoring.",
+              md_c_str);
+      calld->compression_algorithm = GRPC_COMPRESS_NONE;
+    }
+    if (grpc_compression_options_is_algorithm_enabled(
+            &channeld->compression_options, calld->compression_algorithm) ==
+        0) {
+      gpr_log(GPR_ERROR,
+              "Invalid compression algorithm: '%s' (previously disabled). "
+              "Ignoring.",
+              md_c_str);
+      calld->compression_algorithm = GRPC_COMPRESS_NONE;
+    }
+    calld->has_compression_algorithm = 1;
+    return NULL;
+  }
+
+  return md;
+}
+
+static int skip_compression(grpc_call_element *elem) {
+  call_data *calld = elem->call_data;
+  channel_data *channeld = elem->channel_data;
+  if (calld->has_compression_algorithm) {
+    if (calld->compression_algorithm == GRPC_COMPRESS_NONE) {
+      return 1;
+    }
+    return 0; /* we have an actual call-specific algorithm */
+  }
+  /* no per-call compression override */
+  return channeld->default_compression_algorithm == GRPC_COMPRESS_NONE;
+}
+
+/** Filter initial metadata */
+static void process_send_initial_metadata(
+    grpc_call_element *elem, grpc_metadata_batch *initial_metadata) {
+  call_data *calld = elem->call_data;
+  channel_data *channeld = elem->channel_data;
+  /* Parse incoming request for compression. If any, it'll be available
+   * at calld->compression_algorithm */
+  grpc_metadata_batch_filter(initial_metadata, compression_md_filter, elem);
+  if (!calld->has_compression_algorithm) {
+    /* If no algorithm was found in the metadata and we aren't
+     * exceptionally skipping compression, fall back to the channel
+     * default */
+    calld->compression_algorithm = channeld->default_compression_algorithm;
+    calld->has_compression_algorithm = 1; /* GPR_TRUE */
+  }
+  /* hint compression algorithm */
+  grpc_metadata_batch_add_tail(
+      initial_metadata, &calld->compression_algorithm_storage,
+      grpc_compression_encoding_mdelem(calld->compression_algorithm));
+
+  /* convey supported compression algorithms */
+  grpc_metadata_batch_add_tail(initial_metadata,
+                               &calld->accept_encoding_storage,
+                               GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
+                                   channeld->supported_compression_algorithms));
+}
+
+static void continue_send_message(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem);
+
+static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
+  grpc_call_element *elem = elemp;
+  call_data *calld = elem->call_data;
+  gpr_slice_buffer_reset_and_unref(&calld->slices);
+  calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, success);
+}
+
+static void finish_send_message(grpc_exec_ctx *exec_ctx,
+                                grpc_call_element *elem) {
+  call_data *calld = elem->call_data;
+  int did_compress;
+  gpr_slice_buffer tmp;
+  gpr_slice_buffer_init(&tmp);
+  did_compress =
+      grpc_msg_compress(calld->compression_algorithm, &calld->slices, &tmp);
+  if (did_compress) {
+    gpr_slice_buffer_swap(&calld->slices, &tmp);
+    calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
+  }
+  gpr_slice_buffer_destroy(&tmp);
+
+  grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
+                                calld->send_flags);
+  calld->send_op.send_message = &calld->replacement_stream.base;
+  calld->post_send = calld->send_op.on_complete;
+  calld->send_op.on_complete = &calld->send_done;
+
+  grpc_call_next_op(exec_ctx, elem, &calld->send_op);
+}
+
+static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
+  grpc_call_element *elem = elemp;
+  call_data *calld = elem->call_data;
+  gpr_slice_buffer_add(&calld->slices, calld->incoming_slice);
+  if (calld->send_length == calld->slices.length) {
+    finish_send_message(exec_ctx, elem);
+  } else {
+    continue_send_message(exec_ctx, elem);
+  }
+}
+
+static void continue_send_message(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem) {
+  call_data *calld = elem->call_data;
+  while (grpc_byte_stream_next(exec_ctx, calld->send_op.send_message,
+                               &calld->incoming_slice, ~(size_t)0,
+                               &calld->got_slice)) {
+    gpr_slice_buffer_add(&calld->slices, calld->incoming_slice);
+    if (calld->send_length == calld->slices.length) {
+      finish_send_message(exec_ctx, elem);
+      break;
+    }
+  }
+}
+
+static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
+                                               grpc_call_element *elem,
+                                               grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+
+  GPR_TIMER_BEGIN("compress_start_transport_stream_op", 0);
+
+  if (op->send_initial_metadata) {
+    process_send_initial_metadata(elem, op->send_initial_metadata);
+  }
+  if (op->send_message != NULL && !skip_compression(elem) &&
+      0 == (op->send_message->flags & GRPC_WRITE_NO_COMPRESS)) {
+    calld->send_op = *op;
+    calld->send_length = op->send_message->length;
+    calld->send_flags = op->send_message->flags;
+    continue_send_message(exec_ctx, elem);
+  } else {
+    /* pass control down the stack */
+    grpc_call_next_op(exec_ctx, elem, op);
+  }
+
+  GPR_TIMER_END("compress_start_transport_stream_op", 0);
+}
+
+/* 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;
+
+  /* initialize members */
+  gpr_slice_buffer_init(&calld->slices);
+  calld->has_compression_algorithm = 0;
+  grpc_closure_init(&calld->got_slice, got_slice, elem);
+  grpc_closure_init(&calld->send_done, send_done, elem);
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {
+  /* grab pointers to our data from the call element */
+  call_data *calld = elem->call_data;
+  gpr_slice_buffer_destroy(&calld->slices);
+}
+
+/* Constructor for channel_data */
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  channel_data *channeld = elem->channel_data;
+  grpc_compression_algorithm algo_idx;
+
+  grpc_compression_options_init(&channeld->compression_options);
+  channeld->compression_options.enabled_algorithms_bitset =
+      (uint32_t)grpc_channel_args_compression_algorithm_get_states(
+          args->channel_args);
+
+  channeld->default_compression_algorithm =
+      grpc_channel_args_get_compression_algorithm(args->channel_args);
+  /* Make sure the default isn't disabled. */
+  if (!grpc_compression_options_is_algorithm_enabled(
+          &channeld->compression_options,
+          channeld->default_compression_algorithm)) {
+    gpr_log(GPR_DEBUG,
+            "compression algorithm %d not enabled: switching to none",
+            channeld->default_compression_algorithm);
+    channeld->default_compression_algorithm = GRPC_COMPRESS_NONE;
+  }
+  channeld->compression_options.default_compression_algorithm =
+      channeld->default_compression_algorithm;
+
+  channeld->supported_compression_algorithms = 0;
+  for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
+    /* skip disabled algorithms */
+    if (grpc_compression_options_is_algorithm_enabled(
+            &channeld->compression_options, algo_idx) == 0) {
+      continue;
+    }
+    channeld->supported_compression_algorithms |= 1u << algo_idx;
+  }
+
+  GPR_ASSERT(!args->is_last);
+}
+
+/* Destructor for channel data */
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {}
+
+const grpc_channel_filter grpc_compress_filter = {
+    compress_start_transport_stream_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "compress"};
diff --git a/src/core/lib/channel/compress_filter.h b/src/core/lib/channel/compress_filter.h
new file mode 100644
index 0000000..0d97332
--- /dev/null
+++ b/src/core/lib/channel/compress_filter.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * 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_CHANNEL_COMPRESS_FILTER_H
+#define GRPC_CORE_LIB_CHANNEL_COMPRESS_FILTER_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+#define GRPC_COMPRESS_REQUEST_ALGORITHM_KEY "grpc-internal-encoding-request"
+
+/** Compression filter for outgoing data.
+ *
+ * See <grpc/compression.h> for the available compression settings.
+ *
+ * Compression settings may come from:
+ *  - Channel configuration, as established at channel creation time.
+ *  - The metadata accompanying the outgoing data to be compressed. This is
+ *    taken as a request only. We may choose not to honor it. The metadata key
+ *    is given by \a GRPC_COMPRESS_REQUEST_ALGORITHM_KEY.
+ *
+ * Compression can be disabled for concrete messages (for instance in order to
+ * prevent CRIME/BEAST type attacks) by having the GRPC_WRITE_NO_COMPRESS set in
+ * the BEGIN_MESSAGE flags.
+ *
+ * The attempted compression mechanism is added to the resulting initial
+ * metadata under the'grpc-encoding' key.
+ *
+ * If compression is actually performed, BEGIN_MESSAGE's flag is modified to
+ * incorporate GRPC_WRITE_INTERNAL_COMPRESS. Otherwise, and regardless of the
+ * aforementioned 'grpc-encoding' metadata value, data will pass through
+ * uncompressed. */
+
+extern const grpc_channel_filter grpc_compress_filter;
+
+#endif /* GRPC_CORE_LIB_CHANNEL_COMPRESS_FILTER_H */
diff --git a/src/core/lib/channel/connected_channel.c b/src/core/lib/channel/connected_channel.c
new file mode 100644
index 0000000..c1debab
--- /dev/null
+++ b/src/core/lib/channel/connected_channel.c
@@ -0,0 +1,176 @@
+/*
+ *
+ * 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/channel/connected_channel.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/transport.h"
+
+#define MAX_BUFFER_LENGTH 8192
+
+typedef struct connected_channel_channel_data {
+  grpc_transport *transport;
+} channel_data;
+
+typedef struct connected_channel_call_data { void *unused; } call_data;
+
+/* We perform a small hack to locate transport data alongside the connected
+   channel data in call allocations, to allow everything to be pulled in minimal
+   cache line requests */
+#define TRANSPORT_STREAM_FROM_CALL_DATA(calld) ((grpc_stream *)((calld) + 1))
+#define CALL_DATA_FROM_TRANSPORT_STREAM(transport_stream) \
+  (((call_data *)(transport_stream)) - 1)
+
+/* Intercept a call operation and either push it directly up or translate it
+   into transport stream operations */
+static void con_start_transport_stream_op(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_CALL_LOG_OP(GPR_INFO, elem, op);
+
+  grpc_transport_perform_stream_op(exec_ctx, chand->transport,
+                                   TRANSPORT_STREAM_FROM_CALL_DATA(calld), op);
+}
+
+static void con_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                   grpc_channel_element *elem,
+                                   grpc_transport_op *op) {
+  channel_data *chand = elem->channel_data;
+  grpc_transport_perform_op(exec_ctx, chand->transport, 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;
+  channel_data *chand = elem->channel_data;
+  int r;
+
+  r = grpc_transport_init_stream(
+      exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld),
+      &args->call_stack->refcount, args->server_transport_data);
+  GPR_ASSERT(r == 0);
+}
+
+static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                        grpc_pollset *pollset) {
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  grpc_transport_set_pollset(exec_ctx, chand->transport,
+                             TRANSPORT_STREAM_FROM_CALL_DATA(calld), pollset);
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  grpc_transport_destroy_stream(exec_ctx, chand->transport,
+                                TRANSPORT_STREAM_FROM_CALL_DATA(calld));
+}
+
+/* Constructor for channel_data */
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  channel_data *cd = (channel_data *)elem->channel_data;
+  GPR_ASSERT(args->is_last);
+  cd->transport = NULL;
+}
+
+/* Destructor for channel_data */
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {
+  channel_data *cd = (channel_data *)elem->channel_data;
+  grpc_transport_destroy(exec_ctx, cd->transport);
+}
+
+static char *con_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+  channel_data *chand = elem->channel_data;
+  return grpc_transport_get_peer(exec_ctx, chand->transport);
+}
+
+static const grpc_channel_filter connected_channel_filter = {
+    con_start_transport_stream_op,
+    con_start_transport_op,
+    sizeof(call_data),
+    init_call_elem,
+    set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    con_get_peer,
+    "connected",
+};
+
+static void bind_transport(grpc_channel_stack *channel_stack,
+                           grpc_channel_element *elem, void *t) {
+  channel_data *cd = (channel_data *)elem->channel_data;
+  GPR_ASSERT(elem->filter == &connected_channel_filter);
+  GPR_ASSERT(cd->transport == NULL);
+  cd->transport = t;
+
+  /* HACK(ctiller): increase call stack size for the channel to make space
+     for channel data. We need a cleaner (but performant) way to do this,
+     and I'm not sure what that is yet.
+     This is only "safe" because call stacks place no additional data after
+     the last call element, and the last call element MUST be the connected
+     channel. */
+  channel_stack->call_stack_size += grpc_transport_stream_size(t);
+}
+
+bool grpc_add_connected_filter(grpc_channel_stack_builder *builder,
+                               void *arg_must_be_null) {
+  GPR_ASSERT(arg_must_be_null == NULL);
+  grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
+  GPR_ASSERT(t != NULL);
+  return grpc_channel_stack_builder_append_filter(
+      builder, &connected_channel_filter, bind_transport, t);
+}
+
+grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem) {
+  call_data *calld = elem->call_data;
+  return TRANSPORT_STREAM_FROM_CALL_DATA(calld);
+}
diff --git a/src/core/lib/channel/connected_channel.h b/src/core/lib/channel/connected_channel.h
new file mode 100644
index 0000000..3142d64
--- /dev/null
+++ b/src/core/lib/channel/connected_channel.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_CHANNEL_CONNECTED_CHANNEL_H
+#define GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H
+
+#include "src/core/lib/channel/channel_stack_builder.h"
+
+bool grpc_add_connected_filter(grpc_channel_stack_builder *builder,
+                               void *arg_must_be_null);
+
+#endif /* GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H */
diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h
new file mode 100644
index 0000000..c50e842
--- /dev/null
+++ b/src/core/lib/channel/context.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_CHANNEL_CONTEXT_H
+#define GRPC_CORE_LIB_CHANNEL_CONTEXT_H
+
+/* Call object context pointers */
+typedef enum {
+  GRPC_CONTEXT_SECURITY = 0,
+  GRPC_CONTEXT_TRACING,
+  GRPC_CONTEXT_COUNT
+} grpc_context_index;
+
+typedef struct {
+  void *value;
+  void (*destroy)(void *);
+} grpc_call_context_element;
+
+#endif /* GRPC_CORE_LIB_CHANNEL_CONTEXT_H */
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
new file mode 100644
index 0000000..211f537
--- /dev/null
+++ b/src/core/lib/channel/http_client_filter.c
@@ -0,0 +1,259 @@
+/*
+ * 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/channel/http_client_filter.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <string.h>
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+typedef struct call_data {
+  grpc_linked_mdelem method;
+  grpc_linked_mdelem scheme;
+  grpc_linked_mdelem authority;
+  grpc_linked_mdelem te_trailers;
+  grpc_linked_mdelem content_type;
+  grpc_linked_mdelem user_agent;
+
+  grpc_metadata_batch *recv_initial_metadata;
+
+  /** Closure to call when finished with the hc_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 hc_on_recv;
+} call_data;
+
+typedef struct channel_data {
+  grpc_mdelem *static_scheme;
+  grpc_mdelem *user_agent;
+} channel_data;
+
+typedef struct {
+  grpc_call_element *elem;
+  grpc_exec_ctx *exec_ctx;
+} client_recv_filter_args;
+
+static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
+  client_recv_filter_args *a = user_data;
+  if (md == GRPC_MDELEM_STATUS_200) {
+    return NULL;
+  } else if (md->key == GRPC_MDSTR_STATUS) {
+    grpc_call_element_send_cancel(a->exec_ctx, a->elem);
+    return NULL;
+  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
+    return NULL;
+  }
+  return md;
+}
+
+static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+  grpc_call_element *elem = user_data;
+  call_data *calld = elem->call_data;
+  client_recv_filter_args a;
+  a.elem = elem;
+  a.exec_ctx = exec_ctx;
+  grpc_metadata_batch_filter(calld->recv_initial_metadata, client_recv_filter,
+                             &a);
+  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+}
+
+static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
+  /* eat the things we'd like to set ourselves */
+  if (md->key == GRPC_MDSTR_METHOD) return NULL;
+  if (md->key == GRPC_MDSTR_SCHEME) return NULL;
+  if (md->key == GRPC_MDSTR_TE) return NULL;
+  if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL;
+  if (md->key == GRPC_MDSTR_USER_AGENT) return NULL;
+  return md;
+}
+
+static void hc_mutate_op(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 *channeld = elem->channel_data;
+  if (op->send_initial_metadata != NULL) {
+    grpc_metadata_batch_filter(op->send_initial_metadata, client_strip_filter,
+                               elem);
+    /* Send : prefixed headers, which have to be before any application
+       layer headers. */
+    grpc_metadata_batch_add_head(
+        op->send_initial_metadata, &calld->method,
+        op->send_initial_metadata_flags &
+                GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
+            ? GRPC_MDELEM_METHOD_PUT
+            : GRPC_MDELEM_METHOD_POST);
+    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme,
+                                 channeld->static_scheme);
+    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers,
+                                 GRPC_MDELEM_TE_TRAILERS);
+    grpc_metadata_batch_add_tail(
+        op->send_initial_metadata, &calld->content_type,
+        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
+    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent,
+                                 GRPC_MDELEM_REF(channeld->user_agent));
+  }
+
+  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->hc_on_recv;
+  }
+}
+
+static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_transport_stream_op *op) {
+  GPR_TIMER_BEGIN("hc_start_transport_op", 0);
+  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
+  hc_mutate_op(elem, op);
+  GPR_TIMER_END("hc_start_transport_op", 0);
+  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;
+  calld->on_done_recv = NULL;
+  grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {}
+
+static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) {
+  unsigned i;
+  size_t j;
+  grpc_mdelem *valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP,
+                                  GRPC_MDELEM_SCHEME_HTTPS};
+  if (args != NULL) {
+    for (i = 0; i < args->num_args; ++i) {
+      if (args->args[i].type == GRPC_ARG_STRING &&
+          strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) {
+        for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) {
+          if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value),
+                          args->args[i].value.string)) {
+            return valid_schemes[j];
+          }
+        }
+      }
+    }
+  }
+  return GRPC_MDELEM_SCHEME_HTTP;
+}
+
+static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args) {
+  gpr_strvec v;
+  size_t i;
+  int is_first = 1;
+  char *tmp;
+  grpc_mdstr *result;
+
+  gpr_strvec_init(&v);
+
+  for (i = 0; args && i < args->num_args; i++) {
+    if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
+      if (args->args[i].type != GRPC_ARG_STRING) {
+        gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
+                GRPC_ARG_PRIMARY_USER_AGENT_STRING);
+      } else {
+        if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
+        is_first = 0;
+        gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
+      }
+    }
+  }
+
+  gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ",
+               grpc_version_string(), GPR_PLATFORM_STRING);
+  is_first = 0;
+  gpr_strvec_add(&v, tmp);
+
+  for (i = 0; args && i < args->num_args; i++) {
+    if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
+      if (args->args[i].type != GRPC_ARG_STRING) {
+        gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
+                GRPC_ARG_SECONDARY_USER_AGENT_STRING);
+      } else {
+        if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
+        is_first = 0;
+        gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
+      }
+    }
+  }
+
+  tmp = gpr_strvec_flatten(&v, NULL);
+  gpr_strvec_destroy(&v);
+  result = grpc_mdstr_from_string(tmp);
+  gpr_free(tmp);
+
+  return result;
+}
+
+/* Constructor for channel_data */
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  channel_data *chand = elem->channel_data;
+  GPR_ASSERT(!args->is_last);
+  chand->static_scheme = scheme_from_args(args->channel_args);
+  chand->user_agent = grpc_mdelem_from_metadata_strings(
+      GRPC_MDSTR_USER_AGENT, user_agent_from_args(args->channel_args));
+}
+
+/* Destructor for channel data */
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {
+  channel_data *chand = elem->channel_data;
+  GRPC_MDELEM_UNREF(chand->user_agent);
+}
+
+const grpc_channel_filter grpc_http_client_filter = {
+    hc_start_transport_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "http-client"};
diff --git a/src/core/lib/channel/http_client_filter.h b/src/core/lib/channel/http_client_filter.h
new file mode 100644
index 0000000..a884b36
--- /dev/null
+++ b/src/core/lib/channel/http_client_filter.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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_CHANNEL_HTTP_CLIENT_FILTER_H
+#define GRPC_CORE_LIB_CHANNEL_HTTP_CLIENT_FILTER_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+/* Processes metadata on the client side for HTTP2 transports */
+extern const grpc_channel_filter grpc_http_client_filter;
+
+#define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme"
+
+#endif /* GRPC_CORE_LIB_CHANNEL_HTTP_CLIENT_FILTER_H */
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
new file mode 100644
index 0000000..c140c61
--- /dev/null
+++ b/src/core/lib/channel/http_server_filter.c
@@ -0,0 +1,248 @@
+/*
+ *
+ * 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/channel/http_server_filter.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <string.h>
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+typedef struct call_data {
+  uint8_t seen_path;
+  uint8_t seen_method;
+  uint8_t sent_status;
+  uint8_t seen_scheme;
+  uint8_t seen_te_trailers;
+  uint8_t seen_authority;
+  grpc_linked_mdelem status;
+  grpc_linked_mdelem content_type;
+
+  grpc_metadata_batch *recv_initial_metadata;
+  bool *recv_idempotent_request;
+  /** Closure to call when finished with the hs_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 hs_on_recv;
+} call_data;
+
+typedef struct channel_data { uint8_t unused; } channel_data;
+
+typedef struct {
+  grpc_call_element *elem;
+  grpc_exec_ctx *exec_ctx;
+} server_filter_args;
+
+static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
+  server_filter_args *a = user_data;
+  grpc_call_element *elem = a->elem;
+  call_data *calld = elem->call_data;
+
+  /* Check if it is one of the headers we care about. */
+  if (md == GRPC_MDELEM_TE_TRAILERS || md == GRPC_MDELEM_METHOD_POST ||
+      md == GRPC_MDELEM_METHOD_PUT || md == GRPC_MDELEM_SCHEME_HTTP ||
+      md == GRPC_MDELEM_SCHEME_HTTPS ||
+      md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
+    /* swallow it */
+    if (md == GRPC_MDELEM_METHOD_POST) {
+      calld->seen_method = 1;
+      *calld->recv_idempotent_request = false;
+    } else if (md == GRPC_MDELEM_METHOD_PUT) {
+      calld->seen_method = 1;
+      *calld->recv_idempotent_request = true;
+    } else if (md->key == GRPC_MDSTR_SCHEME) {
+      calld->seen_scheme = 1;
+    } else if (md == GRPC_MDELEM_TE_TRAILERS) {
+      calld->seen_te_trailers = 1;
+    }
+    /* TODO(klempner): Track that we've seen all the headers we should
+       require */
+    return NULL;
+  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
+    if (strncmp(grpc_mdstr_as_c_string(md->value), "application/grpc+", 17) ==
+        0) {
+      /* Although the C implementation doesn't (currently) generate them,
+         any custom +-suffix is explicitly valid. */
+      /* TODO(klempner): We should consider preallocating common values such
+         as +proto or +json, or at least stashing them if we see them. */
+      /* TODO(klempner): Should we be surfacing this to application code? */
+    } else {
+      /* TODO(klempner): We're currently allowing this, but we shouldn't
+         see it without a proxy so log for now. */
+      gpr_log(GPR_INFO, "Unexpected content-type %s",
+              grpc_mdstr_as_c_string(md->value));
+    }
+    return NULL;
+  } else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD ||
+             md->key == GRPC_MDSTR_SCHEME) {
+    gpr_log(GPR_ERROR, "Invalid %s: header: '%s'",
+            grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value));
+    /* swallow it and error everything out. */
+    /* TODO(klempner): We ought to generate more descriptive error messages
+       on the wire here. */
+    grpc_call_element_send_cancel(a->exec_ctx, elem);
+    return NULL;
+  } else if (md->key == GRPC_MDSTR_PATH) {
+    if (calld->seen_path) {
+      gpr_log(GPR_ERROR, "Received :path twice");
+      return NULL;
+    }
+    calld->seen_path = 1;
+    return md;
+  } else if (md->key == GRPC_MDSTR_AUTHORITY) {
+    calld->seen_authority = 1;
+    return md;
+  } else if (md->key == GRPC_MDSTR_HOST) {
+    /* translate host to :authority since :authority may be
+       omitted */
+    grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
+        GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value));
+    calld->seen_authority = 1;
+    return authority;
+  } else {
+    return md;
+  }
+}
+
+static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+  grpc_call_element *elem = user_data;
+  call_data *calld = elem->call_data;
+  if (success) {
+    server_filter_args a;
+    a.elem = elem;
+    a.exec_ctx = exec_ctx;
+    grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, &a);
+    /* Have we seen the required http2 transport headers?
+       (:method, :scheme, content-type, with :path and :authority covered
+       at the channel level right now) */
+    if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers &&
+        calld->seen_path && calld->seen_authority) {
+      /* do nothing */
+    } else {
+      if (!calld->seen_path) {
+        gpr_log(GPR_ERROR, "Missing :path header");
+      }
+      if (!calld->seen_authority) {
+        gpr_log(GPR_ERROR, "Missing :authority header");
+      }
+      if (!calld->seen_method) {
+        gpr_log(GPR_ERROR, "Missing :method header");
+      }
+      if (!calld->seen_scheme) {
+        gpr_log(GPR_ERROR, "Missing :scheme header");
+      }
+      if (!calld->seen_te_trailers) {
+        gpr_log(GPR_ERROR, "Missing te trailers header");
+      }
+      /* Error this call out */
+      success = 0;
+      grpc_call_element_send_cancel(exec_ctx, elem);
+    }
+  }
+  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+}
+
+static void hs_mutate_op(grpc_call_element *elem,
+                         grpc_transport_stream_op *op) {
+  /* grab pointers to our data from the call element */
+  call_data *calld = elem->call_data;
+
+  if (op->send_initial_metadata != NULL && !calld->sent_status) {
+    calld->sent_status = 1;
+    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->status,
+                                 GRPC_MDELEM_STATUS_200);
+    grpc_metadata_batch_add_tail(
+        op->send_initial_metadata, &calld->content_type,
+        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
+  }
+
+  if (op->recv_initial_metadata) {
+    /* substitute our callback for the higher callback */
+    GPR_ASSERT(op->recv_idempotent_request != NULL);
+    calld->recv_initial_metadata = op->recv_initial_metadata;
+    calld->recv_idempotent_request = op->recv_idempotent_request;
+    calld->on_done_recv = op->recv_initial_metadata_ready;
+    op->recv_initial_metadata_ready = &calld->hs_on_recv;
+  }
+}
+
+static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_transport_stream_op *op) {
+  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
+  GPR_TIMER_BEGIN("hs_start_transport_op", 0);
+  hs_mutate_op(elem, op);
+  grpc_call_next_op(exec_ctx, elem, op);
+  GPR_TIMER_END("hs_start_transport_op", 0);
+}
+
+/* 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;
+  /* initialize members */
+  memset(calld, 0, sizeof(*calld));
+  grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem);
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {}
+
+/* Constructor for channel_data */
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  GPR_ASSERT(!args->is_last);
+}
+
+/* Destructor for channel data */
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {}
+
+const grpc_channel_filter grpc_http_server_filter = {
+    hs_start_transport_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "http-server"};
diff --git a/src/core/lib/channel/http_server_filter.h b/src/core/lib/channel/http_server_filter.h
new file mode 100644
index 0000000..77ba2d2
--- /dev/null
+++ b/src/core/lib/channel/http_server_filter.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_CHANNEL_HTTP_SERVER_FILTER_H
+#define GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+/* Processes metadata on the client side for HTTP2 transports */
+extern const grpc_channel_filter grpc_http_server_filter;
+
+#endif /* GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H */
diff --git a/src/core/lib/compression/algorithm_metadata.h b/src/core/lib/compression/algorithm_metadata.h
new file mode 100644
index 0000000..1f9cc15
--- /dev/null
+++ b/src/core/lib/compression/algorithm_metadata.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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_COMPRESSION_ALGORITHM_METADATA_H
+#define GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H
+
+#include <grpc/compression.h>
+#include "src/core/lib/transport/metadata.h"
+
+/** Return compression algorithm based metadata value */
+grpc_mdstr *grpc_compression_algorithm_mdstr(
+    grpc_compression_algorithm algorithm);
+
+/** Return compression algorithm based metadata element (grpc-encoding: xxx) */
+grpc_mdelem *grpc_compression_encoding_mdelem(
+    grpc_compression_algorithm algorithm);
+
+/** Find compression algorithm based on passed in mdstr - returns
+ * GRPC_COMPRESS_ALGORITHM_COUNT on failure */
+grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
+    grpc_mdstr *str);
+
+#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */
diff --git a/src/core/lib/compression/compression_algorithm.c b/src/core/lib/compression/compression_algorithm.c
new file mode 100644
index 0000000..7039364
--- /dev/null
+++ b/src/core/lib/compression/compression_algorithm.c
@@ -0,0 +1,203 @@
+/*
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <grpc/compression.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/compression/algorithm_metadata.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+int grpc_compression_algorithm_parse(const char *name, size_t name_length,
+                                     grpc_compression_algorithm *algorithm) {
+  /* we use strncmp not only because it's safer (even though in this case it
+   * doesn't matter, given that we are comparing against string literals, but
+   * because this way we needn't have "name" nil-terminated (useful for slice
+   * data, for example) */
+  GRPC_API_TRACE(
+      "grpc_compression_algorithm_parse("
+      "name=%*.*s, name_length=%lu, algorithm=%p)",
+      5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
+          algorithm));
+  if (name_length == 0) {
+    return 0;
+  }
+  if (strncmp(name, "identity", name_length) == 0) {
+    *algorithm = GRPC_COMPRESS_NONE;
+  } else if (strncmp(name, "gzip", name_length) == 0) {
+    *algorithm = GRPC_COMPRESS_GZIP;
+  } else if (strncmp(name, "deflate", name_length) == 0) {
+    *algorithm = GRPC_COMPRESS_DEFLATE;
+  } else {
+    return 0;
+  }
+  return 1;
+}
+
+int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
+                                    char **name) {
+  GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
+                 ((int)algorithm, name));
+  switch (algorithm) {
+    case GRPC_COMPRESS_NONE:
+      *name = "identity";
+      return 1;
+    case GRPC_COMPRESS_DEFLATE:
+      *name = "deflate";
+      return 1;
+    case GRPC_COMPRESS_GZIP:
+      *name = "gzip";
+      return 1;
+    case GRPC_COMPRESS_ALGORITHMS_COUNT:
+      return 0;
+  }
+  return 0;
+}
+
+grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
+    grpc_mdstr *str) {
+  if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
+  if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
+  if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
+  return GRPC_COMPRESS_ALGORITHMS_COUNT;
+}
+
+grpc_mdstr *grpc_compression_algorithm_mdstr(
+    grpc_compression_algorithm algorithm) {
+  switch (algorithm) {
+    case GRPC_COMPRESS_NONE:
+      return GRPC_MDSTR_IDENTITY;
+    case GRPC_COMPRESS_DEFLATE:
+      return GRPC_MDSTR_DEFLATE;
+    case GRPC_COMPRESS_GZIP:
+      return GRPC_MDSTR_GZIP;
+    case GRPC_COMPRESS_ALGORITHMS_COUNT:
+      return NULL;
+  }
+  return NULL;
+}
+
+grpc_mdelem *grpc_compression_encoding_mdelem(
+    grpc_compression_algorithm algorithm) {
+  switch (algorithm) {
+    case GRPC_COMPRESS_NONE:
+      return GRPC_MDELEM_GRPC_ENCODING_IDENTITY;
+    case GRPC_COMPRESS_DEFLATE:
+      return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
+    case GRPC_COMPRESS_GZIP:
+      return GRPC_MDELEM_GRPC_ENCODING_GZIP;
+    default:
+      break;
+  }
+  return NULL;
+}
+
+/* TODO(dgq): Add the ability to specify parameters to the individual
+ * compression algorithms */
+grpc_compression_algorithm grpc_compression_algorithm_for_level(
+    grpc_compression_level level, uint32_t accepted_encodings) {
+  GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1,
+                 ((int)level));
+  if (level > GRPC_COMPRESS_LEVEL_HIGH) {
+    gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
+    abort();
+  }
+
+  const size_t num_supported =
+      GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */
+  if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) {
+    return GRPC_COMPRESS_NONE;
+  }
+
+  GPR_ASSERT(level > 0);
+
+  /* Establish a "ranking" or compression algorithms in increasing order of
+   * compression.
+   * This is simplistic and we will probably want to introduce other dimensions
+   * in the future (cpu/memory cost, etc). */
+  const grpc_compression_algorithm algos_ranking[] = {GRPC_COMPRESS_GZIP,
+                                                      GRPC_COMPRESS_DEFLATE};
+
+  /* intersect algos_ranking with the supported ones keeping the ranked order */
+  grpc_compression_algorithm
+      sorted_supported_algos[GRPC_COMPRESS_ALGORITHMS_COUNT];
+  size_t algos_supported_idx = 0;
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) {
+    const grpc_compression_algorithm alg = algos_ranking[i];
+    for (size_t j = 0; j < num_supported; j++) {
+      if (GPR_BITGET(accepted_encodings, alg) == 1) {
+        /* if \a alg in supported */
+        sorted_supported_algos[algos_supported_idx++] = alg;
+        break;
+      }
+    }
+    if (algos_supported_idx == num_supported) break;
+  }
+
+  switch (level) {
+    case GRPC_COMPRESS_LEVEL_NONE:
+      abort(); /* should have been handled already */
+    case GRPC_COMPRESS_LEVEL_LOW:
+      return sorted_supported_algos[0];
+    case GRPC_COMPRESS_LEVEL_MED:
+      return sorted_supported_algos[num_supported / 2];
+    case GRPC_COMPRESS_LEVEL_HIGH:
+      return sorted_supported_algos[num_supported - 1];
+    default:
+      abort();
+  };
+}
+
+void grpc_compression_options_init(grpc_compression_options *opts) {
+  opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
+  opts->default_compression_algorithm = GRPC_COMPRESS_NONE;
+}
+
+void grpc_compression_options_enable_algorithm(
+    grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
+  GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm);
+}
+
+void grpc_compression_options_disable_algorithm(
+    grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
+  GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm);
+}
+
+int grpc_compression_options_is_algorithm_enabled(
+    const grpc_compression_options *opts,
+    grpc_compression_algorithm algorithm) {
+  return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
+}
diff --git a/src/core/lib/compression/message_compress.c b/src/core/lib/compression/message_compress.c
new file mode 100644
index 0000000..cbe0b5a
--- /dev/null
+++ b/src/core/lib/compression/message_compress.c
@@ -0,0 +1,198 @@
+/*
+ *
+ * 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/compression/message_compress.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include <zlib.h>
+
+#define OUTPUT_BLOCK_SIZE 1024
+
+static int zlib_body(z_stream* zs, gpr_slice_buffer* input,
+                     gpr_slice_buffer* output,
+                     int (*flate)(z_stream* zs, int flush)) {
+  int r;
+  int flush;
+  size_t i;
+  gpr_slice outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE);
+  const uInt uint_max = ~(uInt)0;
+
+  GPR_ASSERT(GPR_SLICE_LENGTH(outbuf) <= uint_max);
+  zs->avail_out = (uInt)GPR_SLICE_LENGTH(outbuf);
+  zs->next_out = GPR_SLICE_START_PTR(outbuf);
+  flush = Z_NO_FLUSH;
+  for (i = 0; i < input->count; i++) {
+    if (i == input->count - 1) flush = Z_FINISH;
+    GPR_ASSERT(GPR_SLICE_LENGTH(input->slices[i]) <= uint_max);
+    zs->avail_in = (uInt)GPR_SLICE_LENGTH(input->slices[i]);
+    zs->next_in = GPR_SLICE_START_PTR(input->slices[i]);
+    do {
+      if (zs->avail_out == 0) {
+        gpr_slice_buffer_add_indexed(output, outbuf);
+        outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE);
+        GPR_ASSERT(GPR_SLICE_LENGTH(outbuf) <= uint_max);
+        zs->avail_out = (uInt)GPR_SLICE_LENGTH(outbuf);
+        zs->next_out = GPR_SLICE_START_PTR(outbuf);
+      }
+      r = flate(zs, flush);
+      if (r < 0 && r != Z_BUF_ERROR /* not fatal */) {
+        gpr_log(GPR_INFO, "zlib error (%d)", r);
+        goto error;
+      }
+    } while (zs->avail_out == 0);
+    if (zs->avail_in) {
+      gpr_log(GPR_INFO, "zlib: not all input consumed");
+      goto error;
+    }
+  }
+
+  GPR_ASSERT(outbuf.refcount);
+  outbuf.data.refcounted.length -= zs->avail_out;
+  gpr_slice_buffer_add_indexed(output, outbuf);
+
+  return 1;
+
+error:
+  gpr_slice_unref(outbuf);
+  return 0;
+}
+
+static void* zalloc_gpr(void* opaque, unsigned int items, unsigned int size) {
+  return gpr_malloc(items * size);
+}
+
+static void zfree_gpr(void* opaque, void* address) { gpr_free(address); }
+
+static int zlib_compress(gpr_slice_buffer* input, gpr_slice_buffer* output,
+                         int gzip) {
+  z_stream zs;
+  int r;
+  size_t i;
+  size_t count_before = output->count;
+  size_t length_before = output->length;
+  memset(&zs, 0, sizeof(zs));
+  zs.zalloc = zalloc_gpr;
+  zs.zfree = zfree_gpr;
+  r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | (gzip ? 16 : 0),
+                   8, Z_DEFAULT_STRATEGY);
+  GPR_ASSERT(r == Z_OK);
+  r = zlib_body(&zs, input, output, deflate) && output->length < input->length;
+  if (!r) {
+    for (i = count_before; i < output->count; i++) {
+      gpr_slice_unref(output->slices[i]);
+    }
+    output->count = count_before;
+    output->length = length_before;
+  }
+  deflateEnd(&zs);
+  return r;
+}
+
+static int zlib_decompress(gpr_slice_buffer* input, gpr_slice_buffer* output,
+                           int gzip) {
+  z_stream zs;
+  int r;
+  size_t i;
+  size_t count_before = output->count;
+  size_t length_before = output->length;
+  memset(&zs, 0, sizeof(zs));
+  zs.zalloc = zalloc_gpr;
+  zs.zfree = zfree_gpr;
+  r = inflateInit2(&zs, 15 | (gzip ? 16 : 0));
+  GPR_ASSERT(r == Z_OK);
+  r = zlib_body(&zs, input, output, inflate);
+  if (!r) {
+    for (i = count_before; i < output->count; i++) {
+      gpr_slice_unref(output->slices[i]);
+    }
+    output->count = count_before;
+    output->length = length_before;
+  }
+  inflateEnd(&zs);
+  return r;
+}
+
+static int copy(gpr_slice_buffer* input, gpr_slice_buffer* output) {
+  size_t i;
+  for (i = 0; i < input->count; i++) {
+    gpr_slice_buffer_add(output, gpr_slice_ref(input->slices[i]));
+  }
+  return 1;
+}
+
+static int compress_inner(grpc_compression_algorithm algorithm,
+                          gpr_slice_buffer* input, gpr_slice_buffer* output) {
+  switch (algorithm) {
+    case GRPC_COMPRESS_NONE:
+      /* the fallback path always needs to be send uncompressed: we simply
+         rely on that here */
+      return 0;
+    case GRPC_COMPRESS_DEFLATE:
+      return zlib_compress(input, output, 0);
+    case GRPC_COMPRESS_GZIP:
+      return zlib_compress(input, output, 1);
+    case GRPC_COMPRESS_ALGORITHMS_COUNT:
+      break;
+  }
+  gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm);
+  return 0;
+}
+
+int grpc_msg_compress(grpc_compression_algorithm algorithm,
+                      gpr_slice_buffer* input, gpr_slice_buffer* output) {
+  if (!compress_inner(algorithm, input, output)) {
+    copy(input, output);
+    return 0;
+  }
+  return 1;
+}
+
+int grpc_msg_decompress(grpc_compression_algorithm algorithm,
+                        gpr_slice_buffer* input, gpr_slice_buffer* output) {
+  switch (algorithm) {
+    case GRPC_COMPRESS_NONE:
+      return copy(input, output);
+    case GRPC_COMPRESS_DEFLATE:
+      return zlib_decompress(input, output, 0);
+    case GRPC_COMPRESS_GZIP:
+      return zlib_decompress(input, output, 1);
+    case GRPC_COMPRESS_ALGORITHMS_COUNT:
+      break;
+  }
+  gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm);
+  return 0;
+}
diff --git a/src/core/lib/compression/message_compress.h b/src/core/lib/compression/message_compress.h
new file mode 100644
index 0000000..c69eaaf
--- /dev/null
+++ b/src/core/lib/compression/message_compress.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_COMPRESSION_MESSAGE_COMPRESS_H
+#define GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H
+
+#include <grpc/compression.h>
+#include <grpc/support/slice_buffer.h>
+
+/* compress 'input' to 'output' using 'algorithm'.
+   On success, appends compressed slices to output and returns 1.
+   On failure, appends uncompressed slices to output and returns 0. */
+int grpc_msg_compress(grpc_compression_algorithm algorithm,
+                      gpr_slice_buffer* input, gpr_slice_buffer* output);
+
+/* decompress 'input' to 'output' using 'algorithm'.
+   On success, appends slices to output and returns 1.
+   On failure, output is unchanged, and returns 0. */
+int grpc_msg_decompress(grpc_compression_algorithm algorithm,
+                        gpr_slice_buffer* input, gpr_slice_buffer* output);
+
+#endif /* GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H */
diff --git a/src/core/lib/debug/trace.c b/src/core/lib/debug/trace.c
new file mode 100644
index 0000000..555f497
--- /dev/null
+++ b/src/core/lib/debug/trace.c
@@ -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.
+ *
+ */
+
+#include "src/core/lib/debug/trace.h"
+
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include "src/core/lib/support/env.h"
+
+typedef struct tracer {
+  const char *name;
+  int *flag;
+  struct tracer *next;
+} tracer;
+static tracer *tracers;
+
+void grpc_register_tracer(const char *name, int *flag) {
+  tracer *t = gpr_malloc(sizeof(*t));
+  t->name = name;
+  t->flag = flag;
+  t->next = tracers;
+  *flag = 0;
+  tracers = t;
+}
+
+static void add(const char *beg, const char *end, char ***ss, size_t *ns) {
+  size_t n = *ns;
+  size_t np = n + 1;
+  char *s;
+  size_t len;
+  GPR_ASSERT(end >= beg);
+  len = (size_t)(end - beg);
+  s = gpr_malloc(len + 1);
+  memcpy(s, beg, len);
+  s[len] = 0;
+  *ss = gpr_realloc(*ss, sizeof(char **) * np);
+  (*ss)[n] = s;
+  *ns = np;
+}
+
+static void split(const char *s, char ***ss, size_t *ns) {
+  const char *c = strchr(s, ',');
+  if (c == NULL) {
+    add(s, s + strlen(s), ss, ns);
+  } else {
+    add(s, c, ss, ns);
+    split(c + 1, ss, ns);
+  }
+}
+
+static void parse(const char *s) {
+  char **strings = NULL;
+  size_t nstrings = 0;
+  size_t i;
+  split(s, &strings, &nstrings);
+
+  for (i = 0; i < nstrings; i++) {
+    grpc_tracer_set_enabled(strings[i], 1);
+  }
+
+  for (i = 0; i < nstrings; i++) {
+    gpr_free(strings[i]);
+  }
+  gpr_free(strings);
+}
+
+void grpc_tracer_init(const char *env_var) {
+  char *e = gpr_getenv(env_var);
+  if (e != NULL) {
+    parse(e);
+    gpr_free(e);
+  }
+}
+
+void grpc_tracer_shutdown(void) {
+  while (tracers) {
+    tracer *t = tracers;
+    tracers = t->next;
+    gpr_free(t);
+  }
+}
+
+int grpc_tracer_set_enabled(const char *name, int enabled) {
+  tracer *t;
+  if (0 == strcmp(name, "all")) {
+    for (t = tracers; t; t = t->next) {
+      *t->flag = 1;
+    }
+  } else {
+    int found = 0;
+    for (t = tracers; t; t = t->next) {
+      if (0 == strcmp(name, t->name)) {
+        *t->flag = enabled;
+        found = 1;
+      }
+    }
+    if (!found) {
+      gpr_log(GPR_ERROR, "Unknown trace var: '%s'", name);
+      return 0; /* early return */
+    }
+  }
+  return 1;
+}
diff --git a/src/core/lib/debug/trace.h b/src/core/lib/debug/trace.h
new file mode 100644
index 0000000..7afc38d
--- /dev/null
+++ b/src/core/lib/debug/trace.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * 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_DEBUG_TRACE_H
+#define GRPC_CORE_LIB_DEBUG_TRACE_H
+
+#include <grpc/support/port_platform.h>
+
+void grpc_register_tracer(const char *name, int *flag);
+void grpc_tracer_init(const char *env_var_name);
+void grpc_tracer_shutdown(void);
+
+#endif /* GRPC_CORE_LIB_DEBUG_TRACE_H */
diff --git a/src/core/lib/http/format_request.c b/src/core/lib/http/format_request.c
new file mode 100644
index 0000000..9240356
--- /dev/null
+++ b/src/core/lib/http/format_request.c
@@ -0,0 +1,120 @@
+/*
+ *
+ * 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/http/format_request.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
+
+static void fill_common_header(const grpc_httpcli_request *request,
+                               gpr_strvec *buf) {
+  size_t i;
+  gpr_strvec_add(buf, gpr_strdup(request->http.path));
+  gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n"));
+  /* just in case some crazy server really expects HTTP/1.1 */
+  gpr_strvec_add(buf, gpr_strdup("Host: "));
+  gpr_strvec_add(buf, gpr_strdup(request->host));
+  gpr_strvec_add(buf, gpr_strdup("\r\n"));
+  gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n"));
+  gpr_strvec_add(buf,
+                 gpr_strdup("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n"));
+  /* user supplied headers */
+  for (i = 0; i < request->http.hdr_count; i++) {
+    gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].key));
+    gpr_strvec_add(buf, gpr_strdup(": "));
+    gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].value));
+    gpr_strvec_add(buf, gpr_strdup("\r\n"));
+  }
+}
+
+gpr_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request) {
+  gpr_strvec out;
+  char *flat;
+  size_t flat_len;
+
+  gpr_strvec_init(&out);
+  gpr_strvec_add(&out, gpr_strdup("GET "));
+  fill_common_header(request, &out);
+  gpr_strvec_add(&out, gpr_strdup("\r\n"));
+
+  flat = gpr_strvec_flatten(&out, &flat_len);
+  gpr_strvec_destroy(&out);
+
+  return gpr_slice_new(flat, flat_len, gpr_free);
+}
+
+gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request,
+                                           const char *body_bytes,
+                                           size_t body_size) {
+  gpr_strvec out;
+  char *tmp;
+  size_t out_len;
+  size_t i;
+
+  gpr_strvec_init(&out);
+
+  gpr_strvec_add(&out, gpr_strdup("POST "));
+  fill_common_header(request, &out);
+  if (body_bytes) {
+    uint8_t has_content_type = 0;
+    for (i = 0; i < request->http.hdr_count; i++) {
+      if (strcmp(request->http.hdrs[i].key, "Content-Type") == 0) {
+        has_content_type = 1;
+        break;
+      }
+    }
+    if (!has_content_type) {
+      gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n"));
+    }
+    gpr_asprintf(&tmp, "Content-Length: %lu\r\n", (unsigned long)body_size);
+    gpr_strvec_add(&out, tmp);
+  }
+  gpr_strvec_add(&out, gpr_strdup("\r\n"));
+  tmp = gpr_strvec_flatten(&out, &out_len);
+  gpr_strvec_destroy(&out);
+
+  if (body_bytes) {
+    tmp = gpr_realloc(tmp, out_len + body_size);
+    memcpy(tmp + out_len, body_bytes, body_size);
+    out_len += body_size;
+  }
+
+  return gpr_slice_new(tmp, out_len, gpr_free);
+}
diff --git a/src/core/lib/http/format_request.h b/src/core/lib/http/format_request.h
new file mode 100644
index 0000000..1543efe
--- /dev/null
+++ b/src/core/lib/http/format_request.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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_HTTP_FORMAT_REQUEST_H
+#define GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H
+
+#include <grpc/support/slice.h>
+#include "src/core/lib/http/httpcli.h"
+
+gpr_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request);
+gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request,
+                                           const char *body_bytes,
+                                           size_t body_size);
+
+#endif /* GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H */
diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c
new file mode 100644
index 0000000..f22721a
--- /dev/null
+++ b/src/core/lib/http/httpcli.c
@@ -0,0 +1,293 @@
+/*
+ *
+ * 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/http/httpcli.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/http/format_request.h"
+#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/tcp_client.h"
+#include "src/core/lib/support/string.h"
+
+typedef struct {
+  gpr_slice request_text;
+  grpc_http_parser parser;
+  grpc_resolved_addresses *addresses;
+  size_t next_address;
+  grpc_endpoint *ep;
+  char *host;
+  char *ssl_host_override;
+  gpr_timespec deadline;
+  int have_read_byte;
+  const grpc_httpcli_handshaker *handshaker;
+  grpc_httpcli_response_cb on_response;
+  void *user_data;
+  grpc_httpcli_context *context;
+  grpc_pollset *pollset;
+  grpc_iomgr_object iomgr_obj;
+  gpr_slice_buffer incoming;
+  gpr_slice_buffer outgoing;
+  grpc_closure on_read;
+  grpc_closure done_write;
+  grpc_closure connected;
+} internal_request;
+
+static grpc_httpcli_get_override g_get_override = NULL;
+static grpc_httpcli_post_override g_post_override = NULL;
+
+static void plaintext_handshake(grpc_exec_ctx *exec_ctx, void *arg,
+                                grpc_endpoint *endpoint, const char *host,
+                                void (*on_done)(grpc_exec_ctx *exec_ctx,
+                                                void *arg,
+                                                grpc_endpoint *endpoint)) {
+  on_done(exec_ctx, arg, endpoint);
+}
+
+const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http",
+                                                        plaintext_handshake};
+
+void grpc_httpcli_context_init(grpc_httpcli_context *context) {
+  context->pollset_set = grpc_pollset_set_create();
+}
+
+void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
+  grpc_pollset_set_destroy(context->pollset_set);
+}
+
+static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
+
+static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
+                   int success) {
+  grpc_pollset_set_del_pollset(exec_ctx, req->context->pollset_set,
+                               req->pollset);
+  req->on_response(exec_ctx, req->user_data,
+                   success ? &req->parser.http.response : NULL);
+  grpc_http_parser_destroy(&req->parser);
+  if (req->addresses != NULL) {
+    grpc_resolved_addresses_destroy(req->addresses);
+  }
+  if (req->ep != NULL) {
+    grpc_endpoint_destroy(exec_ctx, req->ep);
+  }
+  gpr_slice_unref(req->request_text);
+  gpr_free(req->host);
+  gpr_free(req->ssl_host_override);
+  grpc_iomgr_unregister_object(&req->iomgr_obj);
+  gpr_slice_buffer_destroy(&req->incoming);
+  gpr_slice_buffer_destroy(&req->outgoing);
+  gpr_free(req);
+}
+
+static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success);
+
+static void do_read(grpc_exec_ctx *exec_ctx, internal_request *req) {
+  grpc_endpoint_read(exec_ctx, req->ep, &req->incoming, &req->on_read);
+}
+
+static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+  internal_request *req = user_data;
+  size_t i;
+
+  for (i = 0; i < req->incoming.count; i++) {
+    if (GPR_SLICE_LENGTH(req->incoming.slices[i])) {
+      req->have_read_byte = 1;
+      if (!grpc_http_parser_parse(&req->parser, req->incoming.slices[i])) {
+        finish(exec_ctx, req, 0);
+        return;
+      }
+    }
+  }
+
+  if (success) {
+    do_read(exec_ctx, req);
+  } else if (!req->have_read_byte) {
+    next_address(exec_ctx, req);
+  } else {
+    int parse_success = grpc_http_parser_eof(&req->parser);
+    if (parse_success && (req->parser.type != GRPC_HTTP_RESPONSE)) {
+      parse_success = 0;
+    }
+    finish(exec_ctx, req, parse_success);
+  }
+}
+
+static void on_written(grpc_exec_ctx *exec_ctx, internal_request *req) {
+  do_read(exec_ctx, req);
+}
+
+static void done_write(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  internal_request *req = arg;
+  if (success) {
+    on_written(exec_ctx, req);
+  } else {
+    next_address(exec_ctx, req);
+  }
+}
+
+static void start_write(grpc_exec_ctx *exec_ctx, internal_request *req) {
+  gpr_slice_ref(req->request_text);
+  gpr_slice_buffer_add(&req->outgoing, req->request_text);
+  grpc_endpoint_write(exec_ctx, req->ep, &req->outgoing, &req->done_write);
+}
+
+static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
+                              grpc_endpoint *ep) {
+  internal_request *req = arg;
+
+  if (!ep) {
+    next_address(exec_ctx, req);
+    return;
+  }
+
+  req->ep = ep;
+  start_write(exec_ctx, req);
+}
+
+static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  internal_request *req = arg;
+
+  if (!req->ep) {
+    next_address(exec_ctx, req);
+    return;
+  }
+  req->handshaker->handshake(
+      exec_ctx, req, req->ep,
+      req->ssl_host_override ? req->ssl_host_override : req->host,
+      on_handshake_done);
+}
+
+static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
+  grpc_resolved_address *addr;
+  if (req->next_address == req->addresses->naddrs) {
+    finish(exec_ctx, req, 0);
+    return;
+  }
+  addr = &req->addresses->addrs[req->next_address++];
+  grpc_closure_init(&req->connected, on_connected, req);
+  grpc_tcp_client_connect(
+      exec_ctx, &req->connected, &req->ep, req->context->pollset_set,
+      (struct sockaddr *)&addr->addr, addr->len, req->deadline);
+}
+
+static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
+                        grpc_resolved_addresses *addresses) {
+  internal_request *req = arg;
+  if (!addresses) {
+    finish(exec_ctx, req, 0);
+    return;
+  }
+  req->addresses = addresses;
+  req->next_address = 0;
+  next_address(exec_ctx, req);
+}
+
+static void internal_request_begin(
+    grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
+    grpc_pollset *pollset, const grpc_httpcli_request *request,
+    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
+    void *user_data, const char *name, gpr_slice request_text) {
+  internal_request *req = gpr_malloc(sizeof(internal_request));
+  memset(req, 0, sizeof(*req));
+  req->request_text = request_text;
+  grpc_http_parser_init(&req->parser);
+  req->on_response = on_response;
+  req->user_data = user_data;
+  req->deadline = deadline;
+  req->handshaker =
+      request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
+  req->context = context;
+  req->pollset = pollset;
+  grpc_closure_init(&req->on_read, on_read, req);
+  grpc_closure_init(&req->done_write, done_write, req);
+  gpr_slice_buffer_init(&req->incoming);
+  gpr_slice_buffer_init(&req->outgoing);
+  grpc_iomgr_register_object(&req->iomgr_obj, name);
+  req->host = gpr_strdup(request->host);
+  req->ssl_host_override = gpr_strdup(request->ssl_host_override);
+
+  grpc_pollset_set_add_pollset(exec_ctx, req->context->pollset_set,
+                               req->pollset);
+  grpc_resolve_address(exec_ctx, request->host, req->handshaker->default_port,
+                       on_resolved, req);
+}
+
+void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
+                      grpc_pollset *pollset,
+                      const grpc_httpcli_request *request,
+                      gpr_timespec deadline,
+                      grpc_httpcli_response_cb on_response, void *user_data) {
+  char *name;
+  if (g_get_override &&
+      g_get_override(exec_ctx, request, deadline, on_response, user_data)) {
+    return;
+  }
+  gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->http.path);
+  internal_request_begin(exec_ctx, context, pollset, request, deadline,
+                         on_response, user_data, name,
+                         grpc_httpcli_format_get_request(request));
+  gpr_free(name);
+}
+
+void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
+                       grpc_pollset *pollset,
+                       const grpc_httpcli_request *request,
+                       const char *body_bytes, size_t body_size,
+                       gpr_timespec deadline,
+                       grpc_httpcli_response_cb on_response, void *user_data) {
+  char *name;
+  if (g_post_override &&
+      g_post_override(exec_ctx, request, body_bytes, body_size, deadline,
+                      on_response, user_data)) {
+    return;
+  }
+  gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->http.path);
+  internal_request_begin(
+      exec_ctx, context, pollset, request, deadline, on_response, user_data,
+      name, grpc_httpcli_format_post_request(request, body_bytes, body_size));
+  gpr_free(name);
+}
+
+void grpc_httpcli_set_override(grpc_httpcli_get_override get,
+                               grpc_httpcli_post_override post) {
+  g_get_override = get;
+  g_post_override = post;
+}
diff --git a/src/core/lib/http/httpcli.h b/src/core/lib/http/httpcli.h
new file mode 100644
index 0000000..11a32a1
--- /dev/null
+++ b/src/core/lib/http/httpcli.h
@@ -0,0 +1,144 @@
+/*
+ *
+ * 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_HTTP_HTTPCLI_H
+#define GRPC_CORE_LIB_HTTP_HTTPCLI_H
+
+#include <stddef.h>
+
+#include <grpc/support/time.h>
+
+#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/pollset_set.h"
+
+/* User agent this library reports */
+#define GRPC_HTTPCLI_USER_AGENT "grpc-httpcli/0.0"
+
+/* Tracks in-progress http requests
+   TODO(ctiller): allow caching and capturing multiple requests for the
+                  same content and combining them */
+typedef struct grpc_httpcli_context {
+  grpc_pollset_set *pollset_set;
+} grpc_httpcli_context;
+
+typedef struct {
+  const char *default_port;
+  void (*handshake)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint,
+                    const char *host,
+                    void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
+                                    grpc_endpoint *endpoint));
+} grpc_httpcli_handshaker;
+
+extern const grpc_httpcli_handshaker grpc_httpcli_plaintext;
+extern const grpc_httpcli_handshaker grpc_httpcli_ssl;
+
+/* A request */
+typedef struct grpc_httpcli_request {
+  /* The host name to connect to */
+  char *host;
+  /* The host to verify in the SSL handshake (or NULL) */
+  char *ssl_host_override;
+  /* The main part of the request
+     The following headers are supplied automatically and MUST NOT be set here:
+     Host, Connection, User-Agent */
+  grpc_http_request http;
+  /* handshaker to use ssl for the request */
+  const grpc_httpcli_handshaker *handshaker;
+} grpc_httpcli_request;
+
+/* Expose the parser response type as a httpcli response too */
+typedef struct grpc_http_response grpc_httpcli_response;
+
+/* Callback for grpc_httpcli_get and grpc_httpcli_post. */
+typedef void (*grpc_httpcli_response_cb)(grpc_exec_ctx *exec_ctx,
+                                         void *user_data,
+                                         const grpc_http_response *response);
+
+void grpc_httpcli_context_init(grpc_httpcli_context *context);
+void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
+
+/* Asynchronously perform a HTTP GET.
+   'context' specifies the http context under which to do the get
+   'pollset' indicates a grpc_pollset that is interested in the result
+     of the get - work on this pollset may be used to progress the get
+     operation
+   'request' contains request parameters - these are caller owned and can be
+     destroyed once the call returns
+   'deadline' contains a deadline for the request (or gpr_inf_future)
+   'on_response' is a callback to report results to (and 'user_data' is a user
+     supplied pointer to pass to said call) */
+void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
+                      grpc_pollset *pollset,
+                      const grpc_httpcli_request *request,
+                      gpr_timespec deadline,
+                      grpc_httpcli_response_cb on_response, void *user_data);
+
+/* Asynchronously perform a HTTP POST.
+   'context' specifies the http context under which to do the post
+   'pollset' indicates a grpc_pollset that is interested in the result
+     of the post - work on this pollset may be used to progress the post
+     operation
+   'request' contains request parameters - these are caller owned and can be
+     destroyed once the call returns
+   'body_bytes' and 'body_size' specify the payload for the post.
+     When there is no body, pass in NULL as body_bytes.
+   'deadline' contains a deadline for the request (or gpr_inf_future)
+   'em' points to a caller owned event manager that must be alive for the
+     lifetime of the request
+   'on_response' is a callback to report results to (and 'user_data' is a user
+     supplied pointer to pass to said call)
+   Does not support ?var1=val1&var2=val2 in the path. */
+void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
+                       grpc_pollset *pollset,
+                       const grpc_httpcli_request *request,
+                       const char *body_bytes, size_t body_size,
+                       gpr_timespec deadline,
+                       grpc_httpcli_response_cb on_response, void *user_data);
+
+/* override functions return 1 if they handled the request, 0 otherwise */
+typedef int (*grpc_httpcli_get_override)(grpc_exec_ctx *exec_ctx,
+                                         const grpc_httpcli_request *request,
+                                         gpr_timespec deadline,
+                                         grpc_httpcli_response_cb on_response,
+                                         void *user_data);
+typedef int (*grpc_httpcli_post_override)(
+    grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
+    const char *body_bytes, size_t body_size, gpr_timespec deadline,
+    grpc_httpcli_response_cb on_response, void *user_data);
+
+void grpc_httpcli_set_override(grpc_httpcli_get_override get,
+                               grpc_httpcli_post_override post);
+
+#endif /* GRPC_CORE_LIB_HTTP_HTTPCLI_H */
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
new file mode 100644
index 0000000..ea4bff3
--- /dev/null
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -0,0 +1,188 @@
+/*
+ *
+ * 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/http/httpcli.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/handshake.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/tsi/ssl_transport_security.h"
+
+typedef struct {
+  grpc_channel_security_connector base;
+  tsi_ssl_handshaker_factory *handshaker_factory;
+  char *secure_peer_name;
+} grpc_httpcli_ssl_channel_security_connector;
+
+static void httpcli_ssl_destroy(grpc_security_connector *sc) {
+  grpc_httpcli_ssl_channel_security_connector *c =
+      (grpc_httpcli_ssl_channel_security_connector *)sc;
+  if (c->handshaker_factory != NULL) {
+    tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
+  }
+  if (c->secure_peer_name != NULL) gpr_free(c->secure_peer_name);
+  gpr_free(sc);
+}
+
+static void httpcli_ssl_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_httpcli_ssl_channel_security_connector *c =
+      (grpc_httpcli_ssl_channel_security_connector *)sc;
+  tsi_result result = TSI_OK;
+  tsi_handshaker *handshaker;
+  if (c->handshaker_factory == NULL) {
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
+    return;
+  }
+  result = tsi_ssl_handshaker_factory_create_handshaker(
+      c->handshaker_factory, c->secure_peer_name, &handshaker);
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
+            tsi_result_to_string(result));
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
+  } else {
+    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
+                               nonsecure_endpoint, cb, user_data);
+  }
+}
+
+static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,
+                                   grpc_security_connector *sc, tsi_peer peer,
+                                   grpc_security_peer_check_cb cb,
+                                   void *user_data) {
+  grpc_httpcli_ssl_channel_security_connector *c =
+      (grpc_httpcli_ssl_channel_security_connector *)sc;
+  grpc_security_status status = GRPC_SECURITY_OK;
+
+  /* Check the peer name. */
+  if (c->secure_peer_name != NULL &&
+      !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) {
+    gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate",
+            c->secure_peer_name);
+    status = GRPC_SECURITY_ERROR;
+  }
+  cb(exec_ctx, user_data, status, NULL);
+  tsi_peer_destruct(&peer);
+}
+
+static grpc_security_connector_vtable httpcli_ssl_vtable = {
+    httpcli_ssl_destroy, httpcli_ssl_check_peer};
+
+static grpc_security_status httpcli_ssl_channel_security_connector_create(
+    const unsigned char *pem_root_certs, size_t pem_root_certs_size,
+    const char *secure_peer_name, grpc_channel_security_connector **sc) {
+  tsi_result result = TSI_OK;
+  grpc_httpcli_ssl_channel_security_connector *c;
+
+  if (secure_peer_name != NULL && pem_root_certs == NULL) {
+    gpr_log(GPR_ERROR,
+            "Cannot assert a secure peer name without a trust root.");
+    return GRPC_SECURITY_ERROR;
+  }
+
+  c = gpr_malloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
+  memset(c, 0, sizeof(grpc_httpcli_ssl_channel_security_connector));
+
+  gpr_ref_init(&c->base.base.refcount, 1);
+  c->base.base.vtable = &httpcli_ssl_vtable;
+  if (secure_peer_name != NULL) {
+    c->secure_peer_name = gpr_strdup(secure_peer_name);
+  }
+  result = tsi_create_ssl_client_handshaker_factory(
+      NULL, 0, NULL, 0, pem_root_certs, pem_root_certs_size, NULL, NULL, NULL,
+      0, &c->handshaker_factory);
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
+            tsi_result_to_string(result));
+    httpcli_ssl_destroy(&c->base.base);
+    *sc = NULL;
+    return GRPC_SECURITY_ERROR;
+  }
+  c->base.do_handshake = httpcli_ssl_do_handshake;
+  *sc = &c->base;
+  return GRPC_SECURITY_OK;
+}
+
+/* handshaker */
+
+typedef struct {
+  void (*func)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint);
+  void *arg;
+} on_done_closure;
+
+static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
+                                           grpc_security_status status,
+                                           grpc_endpoint *secure_endpoint,
+                                           grpc_auth_context *auth_context) {
+  on_done_closure *c = rp;
+  if (status != GRPC_SECURITY_OK) {
+    gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
+    c->func(exec_ctx, c->arg, NULL);
+  } else {
+    c->func(exec_ctx, c->arg, secure_endpoint);
+  }
+  gpr_free(c);
+}
+
+static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
+                          grpc_endpoint *tcp, const char *host,
+                          void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
+                                          grpc_endpoint *endpoint)) {
+  grpc_channel_security_connector *sc = NULL;
+  const unsigned char *pem_root_certs = NULL;
+  on_done_closure *c = gpr_malloc(sizeof(*c));
+  size_t 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.");
+    on_done(exec_ctx, arg, NULL);
+    gpr_free(c);
+    return;
+  }
+  c->func = on_done;
+  c->arg = arg;
+  GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
+                 pem_root_certs, pem_root_certs_size, host, &sc) ==
+             GRPC_SECURITY_OK);
+  grpc_channel_security_connector_do_handshake(
+      exec_ctx, sc, tcp, on_secure_transport_setup_done, c);
+  GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
+}
+
+const grpc_httpcli_handshaker grpc_httpcli_ssl = {"https", ssl_handshake};
diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c
new file mode 100644
index 0000000..a7efb5e
--- /dev/null
+++ b/src/core/lib/http/parser.c
@@ -0,0 +1,341 @@
+/*
+ *
+ * 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/http/parser.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+int grpc_http1_trace = 0;
+
+static char *buf2str(void *buffer, size_t length) {
+  char *out = gpr_malloc(length + 1);
+  memcpy(out, buffer, length);
+  out[length] = 0;
+  return out;
+}
+
+static int handle_response_line(grpc_http_parser *parser) {
+  uint8_t *beg = parser->cur_line;
+  uint8_t *cur = beg;
+  uint8_t *end = beg + parser->cur_line_length;
+
+  if (cur == end || *cur++ != 'H') goto error;
+  if (cur == end || *cur++ != 'T') goto error;
+  if (cur == end || *cur++ != 'T') goto error;
+  if (cur == end || *cur++ != 'P') goto error;
+  if (cur == end || *cur++ != '/') goto error;
+  if (cur == end || *cur++ != '1') goto error;
+  if (cur == end || *cur++ != '.') goto error;
+  if (cur == end || *cur < '0' || *cur++ > '1') goto error;
+  if (cur == end || *cur++ != ' ') goto error;
+  if (cur == end || *cur < '1' || *cur++ > '9') goto error;
+  if (cur == end || *cur < '0' || *cur++ > '9') goto error;
+  if (cur == end || *cur < '0' || *cur++ > '9') goto error;
+  parser->http.response.status =
+      (cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0');
+  if (cur == end || *cur++ != ' ') goto error;
+
+  /* we don't really care about the status code message */
+
+  return 1;
+
+error:
+  if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing response line");
+  return 0;
+}
+
+static int handle_request_line(grpc_http_parser *parser) {
+  uint8_t *beg = parser->cur_line;
+  uint8_t *cur = beg;
+  uint8_t *end = beg + parser->cur_line_length;
+  uint8_t vers_major = 0;
+  uint8_t vers_minor = 0;
+
+  while (cur != end && *cur++ != ' ')
+    ;
+  if (cur == end) goto error;
+  parser->http.request.method = buf2str(beg, (size_t)(cur - beg - 1));
+
+  beg = cur;
+  while (cur != end && *cur++ != ' ')
+    ;
+  if (cur == end) goto error;
+  parser->http.request.path = buf2str(beg, (size_t)(cur - beg - 1));
+
+  if (cur == end || *cur++ != 'H') goto error;
+  if (cur == end || *cur++ != 'T') goto error;
+  if (cur == end || *cur++ != 'T') goto error;
+  if (cur == end || *cur++ != 'P') goto error;
+  if (cur == end || *cur++ != '/') goto error;
+  vers_major = (uint8_t)(*cur++ - '1' + 1);
+  ++cur;
+  if (cur == end) goto error;
+  vers_minor = (uint8_t)(*cur++ - '1' + 1);
+
+  if (vers_major == 1) {
+    if (vers_minor == 0) {
+      parser->http.request.version = GRPC_HTTP_HTTP10;
+    } else if (vers_minor == 1) {
+      parser->http.request.version = GRPC_HTTP_HTTP11;
+    } else {
+      goto error;
+    }
+  } else if (vers_major == 2) {
+    if (vers_minor == 0) {
+      parser->http.request.version = GRPC_HTTP_HTTP20;
+    } else {
+      goto error;
+    }
+  } else {
+    goto error;
+  }
+
+  return 1;
+
+error:
+  if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing request line");
+  return 0;
+}
+
+static int handle_first_line(grpc_http_parser *parser) {
+  if (parser->cur_line[0] == 'H') {
+    parser->type = GRPC_HTTP_RESPONSE;
+    return handle_response_line(parser);
+  } else {
+    parser->type = GRPC_HTTP_REQUEST;
+    return handle_request_line(parser);
+  }
+}
+
+static int add_header(grpc_http_parser *parser) {
+  uint8_t *beg = parser->cur_line;
+  uint8_t *cur = beg;
+  uint8_t *end = beg + parser->cur_line_length;
+  size_t *hdr_count = NULL;
+  grpc_http_header **hdrs = NULL;
+  grpc_http_header hdr = {NULL, NULL};
+
+  GPR_ASSERT(cur != end);
+
+  if (*cur == ' ' || *cur == '\t') {
+    if (grpc_http1_trace)
+      gpr_log(GPR_ERROR, "Continued header lines not supported yet");
+    goto error;
+  }
+
+  while (cur != end && *cur != ':') {
+    cur++;
+  }
+  if (cur == end) {
+    if (grpc_http1_trace)
+      gpr_log(GPR_ERROR, "Didn't find ':' in header string");
+    goto error;
+  }
+  GPR_ASSERT(cur >= beg);
+  hdr.key = buf2str(beg, (size_t)(cur - beg));
+  cur++; /* skip : */
+
+  while (cur != end && (*cur == ' ' || *cur == '\t')) {
+    cur++;
+  }
+  GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length);
+  hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length);
+
+  if (parser->type == GRPC_HTTP_RESPONSE) {
+    hdr_count = &parser->http.response.hdr_count;
+    hdrs = &parser->http.response.hdrs;
+  } else if (parser->type == GRPC_HTTP_REQUEST) {
+    hdr_count = &parser->http.request.hdr_count;
+    hdrs = &parser->http.request.hdrs;
+  } else {
+    return 0;
+  }
+
+  if (*hdr_count == parser->hdr_capacity) {
+    parser->hdr_capacity =
+        GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2);
+    *hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs));
+  }
+  (*hdrs)[(*hdr_count)++] = hdr;
+  return 1;
+
+error:
+  gpr_free(hdr.key);
+  gpr_free(hdr.value);
+  return 0;
+}
+
+static int finish_line(grpc_http_parser *parser) {
+  switch (parser->state) {
+    case GRPC_HTTP_FIRST_LINE:
+      if (!handle_first_line(parser)) {
+        return 0;
+      }
+      parser->state = GRPC_HTTP_HEADERS;
+      break;
+    case GRPC_HTTP_HEADERS:
+      if (parser->cur_line_length == parser->cur_line_end_length) {
+        parser->state = GRPC_HTTP_BODY;
+        break;
+      }
+      if (!add_header(parser)) {
+        return 0;
+      }
+      break;
+    case GRPC_HTTP_BODY:
+      GPR_UNREACHABLE_CODE(return 0);
+  }
+
+  parser->cur_line_length = 0;
+  return 1;
+}
+
+static int addbyte_body(grpc_http_parser *parser, uint8_t byte) {
+  size_t *body_length = NULL;
+  char **body = NULL;
+
+  if (parser->type == GRPC_HTTP_RESPONSE) {
+    body_length = &parser->http.response.body_length;
+    body = &parser->http.response.body;
+  } else if (parser->type == GRPC_HTTP_REQUEST) {
+    body_length = &parser->http.request.body_length;
+    body = &parser->http.request.body;
+  } else {
+    return 0;
+  }
+
+  if (*body_length == parser->body_capacity) {
+    parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2);
+    *body = gpr_realloc((void *)*body, parser->body_capacity);
+  }
+  (*body)[*body_length] = (char)byte;
+  (*body_length)++;
+
+  return 1;
+}
+
+static int check_line(grpc_http_parser *parser) {
+  if (parser->cur_line_length >= 2 &&
+      parser->cur_line[parser->cur_line_length - 2] == '\r' &&
+      parser->cur_line[parser->cur_line_length - 1] == '\n') {
+    return 1;
+  }
+
+  // HTTP request with \n\r line termiantors.
+  else if (parser->cur_line_length >= 2 &&
+           parser->cur_line[parser->cur_line_length - 2] == '\n' &&
+           parser->cur_line[parser->cur_line_length - 1] == '\r') {
+    return 1;
+  }
+
+  // HTTP request with only \n line terminators.
+  else if (parser->cur_line_length >= 1 &&
+           parser->cur_line[parser->cur_line_length - 1] == '\n') {
+    parser->cur_line_end_length = 1;
+    return 1;
+  }
+
+  return 0;
+}
+
+static int addbyte(grpc_http_parser *parser, uint8_t byte) {
+  switch (parser->state) {
+    case GRPC_HTTP_FIRST_LINE:
+    case GRPC_HTTP_HEADERS:
+      if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) {
+        if (grpc_http1_trace)
+          gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded",
+                  GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
+        return 0;
+      }
+      parser->cur_line[parser->cur_line_length] = byte;
+      parser->cur_line_length++;
+      if (check_line(parser)) {
+        return finish_line(parser);
+      } else {
+        return 1;
+      }
+      GPR_UNREACHABLE_CODE(return 0);
+    case GRPC_HTTP_BODY:
+      return addbyte_body(parser, byte);
+  }
+  GPR_UNREACHABLE_CODE(return 0);
+}
+
+void grpc_http_parser_init(grpc_http_parser *parser) {
+  memset(parser, 0, sizeof(*parser));
+  parser->state = GRPC_HTTP_FIRST_LINE;
+  parser->type = GRPC_HTTP_UNKNOWN;
+  parser->cur_line_end_length = 2;
+}
+
+void grpc_http_parser_destroy(grpc_http_parser *parser) {
+  size_t i;
+  if (parser->type == GRPC_HTTP_RESPONSE) {
+    gpr_free(parser->http.response.body);
+    for (i = 0; i < parser->http.response.hdr_count; i++) {
+      gpr_free(parser->http.response.hdrs[i].key);
+      gpr_free(parser->http.response.hdrs[i].value);
+    }
+    gpr_free(parser->http.response.hdrs);
+  } else if (parser->type == GRPC_HTTP_REQUEST) {
+    gpr_free(parser->http.request.body);
+    for (i = 0; i < parser->http.request.hdr_count; i++) {
+      gpr_free(parser->http.request.hdrs[i].key);
+      gpr_free(parser->http.request.hdrs[i].value);
+    }
+    gpr_free(parser->http.request.hdrs);
+    gpr_free(parser->http.request.method);
+    gpr_free(parser->http.request.path);
+  }
+}
+
+int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
+  size_t i;
+
+  for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) {
+    if (!addbyte(parser, GPR_SLICE_START_PTR(slice)[i])) {
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+int grpc_http_parser_eof(grpc_http_parser *parser) {
+  return parser->state == GRPC_HTTP_BODY;
+}
diff --git a/src/core/lib/http/parser.h b/src/core/lib/http/parser.h
new file mode 100644
index 0000000..536637e
--- /dev/null
+++ b/src/core/lib/http/parser.h
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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_HTTP_PARSER_H
+#define GRPC_CORE_LIB_HTTP_PARSER_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+
+/* Maximum length of a header string of the form 'Key: Value\r\n' */
+#define GRPC_HTTP_PARSER_MAX_HEADER_LENGTH 4096
+
+/* A single header to be passed in a request */
+typedef struct grpc_http_header {
+  char *key;
+  char *value;
+} grpc_http_header;
+
+typedef enum {
+  GRPC_HTTP_FIRST_LINE,
+  GRPC_HTTP_HEADERS,
+  GRPC_HTTP_BODY
+} grpc_http_parser_state;
+
+typedef enum {
+  GRPC_HTTP_HTTP10,
+  GRPC_HTTP_HTTP11,
+  GRPC_HTTP_HTTP20,
+} grpc_http_version;
+
+typedef enum {
+  GRPC_HTTP_RESPONSE,
+  GRPC_HTTP_REQUEST,
+  GRPC_HTTP_UNKNOWN
+} grpc_http_type;
+
+/* A request */
+typedef struct grpc_http_request {
+  /* Method of the request (e.g. GET, POST) */
+  char *method;
+  /* The path of the resource to fetch */
+  char *path;
+  /* HTTP version to use */
+  grpc_http_version version;
+  /* Headers attached to the request */
+  size_t hdr_count;
+  grpc_http_header *hdrs;
+  /* Body: length and contents; contents are NOT null-terminated */
+  size_t body_length;
+  char *body;
+} grpc_http_request;
+
+/* A response */
+typedef struct grpc_http_response {
+  /* HTTP status code */
+  int status;
+  /* Headers: count and key/values */
+  size_t hdr_count;
+  grpc_http_header *hdrs;
+  /* Body: length and contents; contents are NOT null-terminated */
+  size_t body_length;
+  char *body;
+} grpc_http_response;
+
+typedef struct {
+  grpc_http_parser_state state;
+  grpc_http_type type;
+
+  union {
+    grpc_http_response response;
+    grpc_http_request request;
+  } http;
+  size_t body_capacity;
+  size_t hdr_capacity;
+
+  uint8_t cur_line[GRPC_HTTP_PARSER_MAX_HEADER_LENGTH];
+  size_t cur_line_length;
+  size_t cur_line_end_length;
+} grpc_http_parser;
+
+void grpc_http_parser_init(grpc_http_parser *parser);
+void grpc_http_parser_destroy(grpc_http_parser *parser);
+
+int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
+int grpc_http_parser_eof(grpc_http_parser *parser);
+
+extern int grpc_http1_trace;
+
+#endif /* GRPC_CORE_LIB_HTTP_PARSER_H */
diff --git a/src/core/lib/iomgr/closure.c b/src/core/lib/iomgr/closure.c
new file mode 100644
index 0000000..27793c3
--- /dev/null
+++ b/src/core/lib/iomgr/closure.c
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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/iomgr/closure.h"
+
+#include <grpc/support/alloc.h>
+
+void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
+                       void *cb_arg) {
+  closure->cb = cb;
+  closure->cb_arg = cb_arg;
+  closure->final_data = 0;
+}
+
+void grpc_closure_list_add(grpc_closure_list *closure_list,
+                           grpc_closure *closure, bool success) {
+  if (closure == NULL) return;
+  closure->final_data = (success != 0);
+  if (closure_list->head == NULL) {
+    closure_list->head = closure;
+  } else {
+    closure_list->tail->final_data |= (uintptr_t)closure;
+  }
+  closure_list->tail = closure;
+}
+
+void grpc_closure_list_fail_all(grpc_closure_list *list) {
+  for (grpc_closure *c = list->head; c != NULL; c = grpc_closure_next(c)) {
+    c->final_data &= ~(uintptr_t)1;
+  }
+}
+
+bool grpc_closure_list_empty(grpc_closure_list closure_list) {
+  return closure_list.head == NULL;
+}
+
+void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst) {
+  if (src->head == NULL) {
+    return;
+  }
+  if (dst->head == NULL) {
+    *dst = *src;
+  } else {
+    dst->tail->final_data |= (uintptr_t)src->head;
+    dst->tail = src->tail;
+  }
+  src->head = src->tail = NULL;
+}
+
+typedef struct {
+  grpc_iomgr_cb_func cb;
+  void *cb_arg;
+  grpc_closure wrapper;
+} wrapped_closure;
+
+static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  wrapped_closure *wc = arg;
+  grpc_iomgr_cb_func cb = wc->cb;
+  void *cb_arg = wc->cb_arg;
+  gpr_free(wc);
+  cb(exec_ctx, cb_arg, success);
+}
+
+grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg) {
+  wrapped_closure *wc = gpr_malloc(sizeof(*wc));
+  wc->cb = cb;
+  wc->cb_arg = cb_arg;
+  grpc_closure_init(&wc->wrapper, closure_wrapper, wc);
+  return &wc->wrapper;
+}
+
+grpc_closure *grpc_closure_next(grpc_closure *closure) {
+  return (grpc_closure *)(closure->final_data & ~(uintptr_t)1);
+}
diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h
new file mode 100644
index 0000000..fdc2dae
--- /dev/null
+++ b/src/core/lib/iomgr/closure.h
@@ -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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_IOMGR_CLOSURE_H
+#define GRPC_CORE_LIB_IOMGR_CLOSURE_H
+
+#include <grpc/support/port_platform.h>
+#include <stdbool.h>
+
+struct grpc_closure;
+typedef struct grpc_closure grpc_closure;
+
+/* forward declaration for exec_ctx.h */
+struct grpc_exec_ctx;
+typedef struct grpc_exec_ctx grpc_exec_ctx;
+
+typedef struct grpc_closure_list {
+  grpc_closure *head;
+  grpc_closure *tail;
+} grpc_closure_list;
+
+/** gRPC Callback definition.
+ *
+ * \param arg Arbitrary input.
+ * \param success An indication on the state of the iomgr. On false, cleanup
+ * actions should be taken (eg, shutdown). */
+typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg,
+                                   bool success);
+
+/** A closure over a grpc_iomgr_cb_func. */
+struct grpc_closure {
+  /** Bound callback. */
+  grpc_iomgr_cb_func cb;
+
+  /** Arguments to be passed to "cb". */
+  void *cb_arg;
+
+  /** Once enqueued, contains in the lower bit the success of the closure,
+      and in the upper bits the pointer to the next closure in the list.
+      Before enqueing for execution, this is usable for scratch data. */
+  uintptr_t final_data;
+};
+
+/** Initializes \a closure with \a cb and \a cb_arg. */
+void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
+                       void *cb_arg);
+
+/* Create a heap allocated closure: try to avoid except for very rare events */
+grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg);
+
+#define GRPC_CLOSURE_LIST_INIT \
+  { NULL, NULL }
+
+/** add \a closure to the end of \a list and set \a closure's success to \a
+ * success */
+void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure,
+                           bool success);
+
+/** force all success bits in \a list to false */
+void grpc_closure_list_fail_all(grpc_closure_list *list);
+
+/** append all closures from \a src to \a dst and empty \a src. */
+void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst);
+
+/** return whether \a list is empty. */
+bool grpc_closure_list_empty(grpc_closure_list list);
+
+/** return the next pointer for a queued closure list */
+grpc_closure *grpc_closure_next(grpc_closure *closure);
+
+#endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */
diff --git a/src/core/lib/iomgr/endpoint.c b/src/core/lib/iomgr/endpoint.c
new file mode 100644
index 0000000..1ab3733
--- /dev/null
+++ b/src/core/lib/iomgr/endpoint.c
@@ -0,0 +1,67 @@
+/*
+ *
+ * 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/iomgr/endpoint.h"
+
+void grpc_endpoint_read(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
+                        gpr_slice_buffer* slices, grpc_closure* cb) {
+  ep->vtable->read(exec_ctx, ep, slices, cb);
+}
+
+void grpc_endpoint_write(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
+                         gpr_slice_buffer* slices, grpc_closure* cb) {
+  ep->vtable->write(exec_ctx, ep, slices, cb);
+}
+
+void grpc_endpoint_add_to_pollset(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
+                                  grpc_pollset* pollset) {
+  ep->vtable->add_to_pollset(exec_ctx, ep, pollset);
+}
+
+void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx,
+                                      grpc_endpoint* ep,
+                                      grpc_pollset_set* pollset_set) {
+  ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set);
+}
+
+void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
+  ep->vtable->shutdown(exec_ctx, ep);
+}
+
+void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
+  ep->vtable->destroy(exec_ctx, ep);
+}
+
+char* grpc_endpoint_get_peer(grpc_endpoint* ep) {
+  return ep->vtable->get_peer(ep);
+}
diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h
new file mode 100644
index 0000000..3877ceb
--- /dev/null
+++ b/src/core/lib/iomgr/endpoint.h
@@ -0,0 +1,102 @@
+/*
+ *
+ * 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_ENDPOINT_H
+#define GRPC_CORE_LIB_IOMGR_ENDPOINT_H
+
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/pollset_set.h"
+
+/* An endpoint caps a streaming channel between two communicating processes.
+   Examples may be: a tcp socket, <stdin+stdout>, or some shared memory. */
+
+typedef struct grpc_endpoint grpc_endpoint;
+typedef struct grpc_endpoint_vtable grpc_endpoint_vtable;
+
+struct grpc_endpoint_vtable {
+  void (*read)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+               gpr_slice_buffer *slices, grpc_closure *cb);
+  void (*write)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                gpr_slice_buffer *slices, grpc_closure *cb);
+  void (*add_to_pollset)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                         grpc_pollset *pollset);
+  void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                             grpc_pollset_set *pollset);
+  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
+  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
+  char *(*get_peer)(grpc_endpoint *ep);
+};
+
+/* When data is available on the connection, calls the callback with slices.
+   Callback success indicates that the endpoint can accept more reads, failure
+   indicates the endpoint is closed.
+   Valid slices may be placed into \a slices even on callback success == 0. */
+void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                        gpr_slice_buffer *slices, grpc_closure *cb);
+
+char *grpc_endpoint_get_peer(grpc_endpoint *ep);
+
+/* Write slices out to the socket.
+
+   If the connection is ready for more data after the end of the call, it
+   returns GRPC_ENDPOINT_DONE.
+   Otherwise it returns GRPC_ENDPOINT_PENDING and calls cb when the
+   connection is ready for more data.
+   \a slices may be mutated at will by the endpoint until cb is called.
+   No guarantee is made to the content of slices after a write EXCEPT that
+   it is a valid slice buffer.
+   */
+void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                         gpr_slice_buffer *slices, grpc_closure *cb);
+
+/* Causes any pending read/write callbacks to run immediately with
+   success==0 */
+void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
+void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
+
+/* Add an endpoint to a pollset, so that when the pollset is polled, events from
+   this endpoint are considered */
+void grpc_endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                  grpc_pollset *pollset);
+void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx,
+                                      grpc_endpoint *ep,
+                                      grpc_pollset_set *pollset_set);
+
+struct grpc_endpoint {
+  const grpc_endpoint_vtable *vtable;
+};
+
+#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_H */
diff --git a/src/core/lib/iomgr/endpoint_pair.h b/src/core/lib/iomgr/endpoint_pair.h
new file mode 100644
index 0000000..5cd7805
--- /dev/null
+++ b/src/core/lib/iomgr/endpoint_pair.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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_ENDPOINT_PAIR_H
+#define GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H
+
+#include "src/core/lib/iomgr/endpoint.h"
+
+typedef struct {
+  grpc_endpoint *client;
+  grpc_endpoint *server;
+} grpc_endpoint_pair;
+
+grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
+                                                   size_t read_slice_size);
+
+#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H */
diff --git a/src/core/lib/iomgr/endpoint_pair_posix.c b/src/core/lib/iomgr/endpoint_pair_posix.c
new file mode 100644
index 0000000..e0ce47c
--- /dev/null
+++ b/src/core/lib/iomgr/endpoint_pair_posix.c
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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 <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_SOCKET
+
+#include "src/core/lib/iomgr/endpoint_pair.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/iomgr/unix_sockets_posix.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include "src/core/lib/iomgr/tcp_posix.h"
+#include "src/core/lib/support/string.h"
+
+static void create_sockets(int sv[2]) {
+  int flags;
+  grpc_create_socketpair_if_unix(sv);
+  flags = fcntl(sv[0], F_GETFL, 0);
+  GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
+  flags = fcntl(sv[1], F_GETFL, 0);
+  GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]));
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]));
+}
+
+grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
+                                                   size_t read_slice_size) {
+  int sv[2];
+  grpc_endpoint_pair p;
+  char *final_name;
+  create_sockets(sv);
+
+  gpr_asprintf(&final_name, "%s:client", name);
+  p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size,
+                             "socketpair-server");
+  gpr_free(final_name);
+  gpr_asprintf(&final_name, "%s:server", name);
+  p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size,
+                             "socketpair-client");
+  gpr_free(final_name);
+  return p;
+}
+
+#endif
diff --git a/src/core/lib/iomgr/endpoint_pair_windows.c b/src/core/lib/iomgr/endpoint_pair_windows.c
new file mode 100644
index 0000000..582704e
--- /dev/null
+++ b/src/core/lib/iomgr/endpoint_pair_windows.c
@@ -0,0 +1,97 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+#include "src/core/lib/iomgr/endpoint_pair.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <grpc/support/log.h>
+#include "src/core/lib/iomgr/socket_windows.h"
+#include "src/core/lib/iomgr/tcp_windows.h"
+
+static void create_sockets(SOCKET sv[2]) {
+  SOCKET svr_sock = INVALID_SOCKET;
+  SOCKET lst_sock = INVALID_SOCKET;
+  SOCKET cli_sock = INVALID_SOCKET;
+  SOCKADDR_IN addr;
+  int addr_len = sizeof(addr);
+
+  lst_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
+                       WSA_FLAG_OVERLAPPED);
+  GPR_ASSERT(lst_sock != INVALID_SOCKET);
+
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  addr.sin_family = AF_INET;
+  GPR_ASSERT(bind(lst_sock, (struct sockaddr *)&addr, sizeof(addr)) !=
+             SOCKET_ERROR);
+  GPR_ASSERT(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR);
+  GPR_ASSERT(getsockname(lst_sock, (struct sockaddr *)&addr, &addr_len) !=
+             SOCKET_ERROR);
+
+  cli_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
+                       WSA_FLAG_OVERLAPPED);
+  GPR_ASSERT(cli_sock != INVALID_SOCKET);
+
+  GPR_ASSERT(WSAConnect(cli_sock, (struct sockaddr *)&addr, addr_len, NULL,
+                        NULL, NULL, NULL) == 0);
+  svr_sock = accept(lst_sock, (struct sockaddr *)&addr, &addr_len);
+  GPR_ASSERT(svr_sock != INVALID_SOCKET);
+
+  closesocket(lst_sock);
+  grpc_tcp_prepare_socket(cli_sock);
+  grpc_tcp_prepare_socket(svr_sock);
+
+  sv[1] = cli_sock;
+  sv[0] = svr_sock;
+}
+
+grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
+                                                   size_t read_slice_size) {
+  SOCKET sv[2];
+  grpc_endpoint_pair p;
+  create_sockets(sv);
+  p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"),
+                             "endpoint:server");
+  p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"),
+                             "endpoint:client");
+  return p;
+}
+
+#endif
diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c
new file mode 100644
index 0000000..3c8127e
--- /dev/null
+++ b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c
@@ -0,0 +1,1936 @@
+/*
+ *
+ * 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_global_init();
+  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);
+  grpc_wakeup_fd_global_destroy();
+}
+
+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
new file mode 100644
index 0000000..06d6dbf
--- /dev/null
+++ b/src/core/lib/iomgr/ev_poll_and_epoll_posix.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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_posix.c b/src/core/lib/iomgr/ev_posix.c
new file mode 100644
index 0000000..0eb95a2
--- /dev/null
+++ b/src/core/lib/iomgr/ev_posix.c
@@ -0,0 +1,165 @@
+/*
+ *
+ * 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_SOCKET
+
+#include "src/core/lib/iomgr/ev_posix.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h"
+
+static const grpc_event_engine_vtable *g_event_engine;
+
+grpc_poll_function_type grpc_poll_function = poll;
+grpc_wakeup_fd grpc_global_wakeup_fd;
+
+void grpc_event_engine_init(void) {
+  if ((g_event_engine = grpc_init_poll_and_epoll_posix())) {
+    return;
+  }
+  gpr_log(GPR_ERROR, "No event engine could be initialized");
+  abort();
+}
+
+void grpc_event_engine_shutdown(void) { g_event_engine->shutdown_engine(); }
+
+grpc_fd *grpc_fd_create(int fd, const char *name) {
+  return g_event_engine->fd_create(fd, name);
+}
+
+int grpc_fd_wrapped_fd(grpc_fd *fd) {
+  return g_event_engine->fd_wrapped_fd(fd);
+}
+
+void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
+                    int *release_fd, const char *reason) {
+  g_event_engine->fd_orphan(exec_ctx, fd, on_done, release_fd, reason);
+}
+
+void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
+  g_event_engine->fd_shutdown(exec_ctx, fd);
+}
+
+void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
+                            grpc_closure *closure) {
+  g_event_engine->fd_notify_on_read(exec_ctx, fd, closure);
+}
+
+void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
+                             grpc_closure *closure) {
+  g_event_engine->fd_notify_on_write(exec_ctx, fd, closure);
+}
+
+size_t grpc_pollset_size(void) { return g_event_engine->pollset_size; }
+
+void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
+  g_event_engine->pollset_init(pollset, mu);
+}
+
+void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                           grpc_closure *closure) {
+  g_event_engine->pollset_shutdown(exec_ctx, pollset, closure);
+}
+
+void grpc_pollset_reset(grpc_pollset *pollset) {
+  g_event_engine->pollset_reset(pollset);
+}
+
+void grpc_pollset_destroy(grpc_pollset *pollset) {
+  g_event_engine->pollset_destroy(pollset);
+}
+
+void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                       grpc_pollset_worker **worker, gpr_timespec now,
+                       gpr_timespec deadline) {
+  g_event_engine->pollset_work(exec_ctx, pollset, worker, now, deadline);
+}
+
+void grpc_pollset_kick(grpc_pollset *pollset,
+                       grpc_pollset_worker *specific_worker) {
+  g_event_engine->pollset_kick(pollset, specific_worker);
+}
+
+void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                         struct grpc_fd *fd) {
+  g_event_engine->pollset_add_fd(exec_ctx, pollset, fd);
+}
+
+grpc_pollset_set *grpc_pollset_set_create(void) {
+  return g_event_engine->pollset_set_create();
+}
+
+void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
+  g_event_engine->pollset_set_destroy(pollset_set);
+}
+
+void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
+                                  grpc_pollset_set *pollset_set,
+                                  grpc_pollset *pollset) {
+  g_event_engine->pollset_set_add_pollset(exec_ctx, pollset_set, pollset);
+}
+
+void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
+                                  grpc_pollset_set *pollset_set,
+                                  grpc_pollset *pollset) {
+  g_event_engine->pollset_set_del_pollset(exec_ctx, pollset_set, pollset);
+}
+
+void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
+                                      grpc_pollset_set *bag,
+                                      grpc_pollset_set *item) {
+  g_event_engine->pollset_set_add_pollset_set(exec_ctx, bag, item);
+}
+
+void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
+                                      grpc_pollset_set *bag,
+                                      grpc_pollset_set *item) {
+  g_event_engine->pollset_set_del_pollset_set(exec_ctx, bag, item);
+}
+
+void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
+                             grpc_pollset_set *pollset_set, grpc_fd *fd) {
+  g_event_engine->pollset_set_add_fd(exec_ctx, pollset_set, fd);
+}
+
+void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
+                             grpc_pollset_set *pollset_set, grpc_fd *fd) {
+  g_event_engine->pollset_set_del_fd(exec_ctx, pollset_set, fd);
+}
+
+void grpc_kick_poller(void) { g_event_engine->kick_poller(); }
+
+#endif  // GPR_POSIX_SOCKET
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
new file mode 100644
index 0000000..1fa9f5e
--- /dev/null
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -0,0 +1,158 @@
+/*
+ *
+ * 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_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_EV_POSIX_H
+
+#include <poll.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/pollset_set.h"
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+
+typedef struct grpc_fd grpc_fd;
+
+typedef struct grpc_event_engine_vtable {
+  size_t pollset_size;
+
+  grpc_fd *(*fd_create)(int fd, const char *name);
+  int (*fd_wrapped_fd)(grpc_fd *fd);
+  void (*fd_orphan)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
+                    int *release_fd, const char *reason);
+  void (*fd_shutdown)(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
+  void (*fd_notify_on_read)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
+                            grpc_closure *closure);
+  void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
+                             grpc_closure *closure);
+
+  void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu);
+  void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                           grpc_closure *closure);
+  void (*pollset_reset)(grpc_pollset *pollset);
+  void (*pollset_destroy)(grpc_pollset *pollset);
+  void (*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                       grpc_pollset_worker **worker, gpr_timespec now,
+                       gpr_timespec deadline);
+  void (*pollset_kick)(grpc_pollset *pollset,
+                       grpc_pollset_worker *specific_worker);
+  void (*pollset_add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                         struct grpc_fd *fd);
+
+  grpc_pollset_set *(*pollset_set_create)(void);
+  void (*pollset_set_destroy)(grpc_pollset_set *pollset_set);
+  void (*pollset_set_add_pollset)(grpc_exec_ctx *exec_ctx,
+                                  grpc_pollset_set *pollset_set,
+                                  grpc_pollset *pollset);
+  void (*pollset_set_del_pollset)(grpc_exec_ctx *exec_ctx,
+                                  grpc_pollset_set *pollset_set,
+                                  grpc_pollset *pollset);
+  void (*pollset_set_add_pollset_set)(grpc_exec_ctx *exec_ctx,
+                                      grpc_pollset_set *bag,
+                                      grpc_pollset_set *item);
+  void (*pollset_set_del_pollset_set)(grpc_exec_ctx *exec_ctx,
+                                      grpc_pollset_set *bag,
+                                      grpc_pollset_set *item);
+  void (*pollset_set_add_fd)(grpc_exec_ctx *exec_ctx,
+                             grpc_pollset_set *pollset_set, grpc_fd *fd);
+  void (*pollset_set_del_fd)(grpc_exec_ctx *exec_ctx,
+                             grpc_pollset_set *pollset_set, grpc_fd *fd);
+
+  void (*kick_poller)(void);
+
+  void (*shutdown_engine)(void);
+} grpc_event_engine_vtable;
+
+void grpc_event_engine_init(void);
+void grpc_event_engine_shutdown(void);
+
+/* Create a wrapped file descriptor.
+   Requires fd is a non-blocking file descriptor.
+   This takes ownership of closing fd. */
+grpc_fd *grpc_fd_create(int fd, const char *name);
+
+/* Return the wrapped fd, or -1 if it has been released or closed. */
+int grpc_fd_wrapped_fd(grpc_fd *fd);
+
+/* Releases fd to be asynchronously destroyed.
+   on_done is called when the underlying file descriptor is definitely close()d.
+   If on_done is NULL, no callback will be made.
+   If release_fd is not NULL, it's set to fd and fd will not be closed.
+   Requires: *fd initialized; no outstanding notify_on_read or
+   notify_on_write.
+   MUST NOT be called with a pollset lock taken */
+void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
+                    int *release_fd, const char *reason);
+
+/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */
+void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
+
+/* Register read interest, causing read_cb to be called once when fd becomes
+   readable, on deadline specified by deadline, or on shutdown triggered by
+   grpc_fd_shutdown.
+   read_cb will be called with read_cb_arg when *fd becomes readable.
+   read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable,
+   GRPC_CALLBACK_TIMED_OUT if the call timed out,
+   and CANCELLED if the call was cancelled.
+
+   Requires:This method must not be called before the read_cb for any previous
+   call runs. Edge triggered events are used whenever they are supported by the
+   underlying platform. This means that users must drain fd in read_cb before
+   calling notify_on_read again. Users are also expected to handle spurious
+   events, i.e read_cb is called while nothing can be readable from fd  */
+void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
+                            grpc_closure *closure);
+
+/* Exactly the same semantics as above, except based on writable events.  */
+void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
+                             grpc_closure *closure);
+
+/* pollset_posix functions */
+
+/* Add an fd to a pollset */
+void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                         struct grpc_fd *fd);
+
+/* pollset_set_posix functions */
+
+void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
+                             grpc_pollset_set *pollset_set, grpc_fd *fd);
+void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
+                             grpc_pollset_set *pollset_set, grpc_fd *fd);
+
+/* override to allow tests to hook poll() usage */
+typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int);
+extern grpc_poll_function_type grpc_poll_function;
+extern grpc_wakeup_fd grpc_global_wakeup_fd;
+
+#endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */
diff --git a/src/core/lib/iomgr/exec_ctx.c b/src/core/lib/iomgr/exec_ctx.c
new file mode 100644
index 0000000..2146c7d
--- /dev/null
+++ b/src/core/lib/iomgr/exec_ctx.c
@@ -0,0 +1,151 @@
+/*
+ *
+ * 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/iomgr/exec_ctx.h"
+
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+
+#include "src/core/lib/profiling/timers.h"
+
+#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
+bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
+  bool did_something = 0;
+  GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
+  while (!grpc_closure_list_empty(exec_ctx->closure_list)) {
+    grpc_closure *c = exec_ctx->closure_list.head;
+    exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
+    while (c != NULL) {
+      bool success = (bool)(c->final_data & 1);
+      grpc_closure *next = (grpc_closure *)(c->final_data & ~(uintptr_t)1);
+      did_something = true;
+      GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
+      c->cb(exec_ctx, c->cb_arg, success);
+      GPR_TIMER_END("grpc_exec_ctx_flush.cb", 0);
+      c = next;
+    }
+  }
+  GPR_TIMER_END("grpc_exec_ctx_flush", 0);
+  return did_something;
+}
+
+void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
+  grpc_exec_ctx_flush(exec_ctx);
+}
+
+void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                           bool success,
+                           grpc_workqueue *offload_target_or_null) {
+  GPR_ASSERT(offload_target_or_null == NULL);
+  grpc_closure_list_add(&exec_ctx->closure_list, closure, success);
+}
+
+void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
+                                grpc_closure_list *list,
+                                grpc_workqueue *offload_target_or_null) {
+  GPR_ASSERT(offload_target_or_null == NULL);
+  grpc_closure_list_move(list, &exec_ctx->closure_list);
+}
+
+void grpc_exec_ctx_global_init(void) {}
+void grpc_exec_ctx_global_shutdown(void) {}
+#else
+static gpr_mu g_mu;
+static gpr_cv g_cv;
+static int g_threads = 0;
+
+static void run_closure(void *arg) {
+  grpc_closure *closure = arg;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  closure->cb(&exec_ctx, closure->cb_arg, (closure->final_data & 1) != 0);
+  grpc_exec_ctx_finish(&exec_ctx);
+  gpr_mu_lock(&g_mu);
+  if (--g_threads == 0) {
+    gpr_cv_signal(&g_cv);
+  }
+  gpr_mu_unlock(&g_mu);
+}
+
+static void start_closure(grpc_closure *closure) {
+  gpr_thd_id id;
+  gpr_mu_lock(&g_mu);
+  g_threads++;
+  gpr_mu_unlock(&g_mu);
+  gpr_thd_new(&id, run_closure, closure, NULL);
+}
+
+bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { return false; }
+
+void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {}
+
+void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                           bool success,
+                           grpc_workqueue *offload_target_or_null) {
+  GPR_ASSERT(offload_target_or_null == NULL);
+  if (closure == NULL) return;
+  closure->final_data = success;
+  start_closure(closure);
+}
+
+void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
+                                grpc_closure_list *list,
+                                grpc_workqueue *offload_target_or_null) {
+  GPR_ASSERT(offload_target_or_null == NULL);
+  if (list == NULL) return;
+  grpc_closure *p = list->head;
+  while (p) {
+    grpc_closure *start = p;
+    p = grpc_closure_next(start);
+    start_closure(start);
+  }
+  grpc_closure_list r = GRPC_CLOSURE_LIST_INIT;
+  *list = r;
+}
+
+void grpc_exec_ctx_global_init(void) {
+  gpr_mu_init(&g_mu);
+  gpr_cv_init(&g_cv);
+}
+
+void grpc_exec_ctx_global_shutdown(void) {
+  gpr_mu_lock(&g_mu);
+  while (g_threads != 0) {
+    gpr_cv_wait(&g_cv, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
+  }
+  gpr_mu_unlock(&g_mu);
+
+  gpr_mu_destroy(&g_mu);
+  gpr_cv_destroy(&g_cv);
+}
+#endif
diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h
new file mode 100644
index 0000000..976cc40
--- /dev/null
+++ b/src/core/lib/iomgr/exec_ctx.h
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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_EXEC_CTX_H
+#define GRPC_CORE_LIB_IOMGR_EXEC_CTX_H
+
+#include "src/core/lib/iomgr/closure.h"
+
+/* #define GRPC_EXECUTION_CONTEXT_SANITIZER 1 */
+
+/** A workqueue represents a list of work to be executed asynchronously.
+    Forward declared here to avoid a circular dependency with workqueue.h. */
+struct grpc_workqueue;
+typedef struct grpc_workqueue grpc_workqueue;
+
+#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
+/** Execution context.
+ *  A bag of data that collects information along a callstack.
+ *  Generally created at public API entry points, and passed down as
+ *  pointer to child functions that manipulate it.
+ *
+ *  Specific responsibilities (this may grow in the future):
+ *  - track a list of work that needs to be delayed until the top of the
+ *    call stack (this provides a convenient mechanism to run callbacks
+ *    without worrying about locking issues)
+ *
+ *  CONVENTIONS:
+ *  Instance of this must ALWAYS be constructed on the stack, never
+ *  heap allocated. Instances and pointers to them must always be called
+ *  exec_ctx. Instances are always passed as the first argument
+ *  to a function that takes it, and always as a pointer (grpc_exec_ctx
+ *  is never copied).
+ */
+struct grpc_exec_ctx {
+  grpc_closure_list closure_list;
+};
+
+#define GRPC_EXEC_CTX_INIT \
+  { GRPC_CLOSURE_LIST_INIT }
+#else
+struct grpc_exec_ctx {
+  int unused;
+};
+#define GRPC_EXEC_CTX_INIT \
+  { 0 }
+#endif
+
+/** Flush any work that has been enqueued onto this grpc_exec_ctx.
+ *  Caller must guarantee that no interfering locks are held.
+ *  Returns true if work was performed, false otherwise. */
+bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx);
+/** Finish any pending work for a grpc_exec_ctx. Must be called before
+ *  the instance is destroyed, or work may be lost. */
+void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx);
+/** Add a closure to be executed at the next flush/finish point */
+void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                           bool success,
+                           grpc_workqueue *offload_target_or_null);
+/** Add a list of closures to be executed at the next flush/finish point.
+ *  Leaves \a list empty. */
+void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
+                                grpc_closure_list *list,
+                                grpc_workqueue *offload_target_or_null);
+
+void grpc_exec_ctx_global_init(void);
+
+void grpc_exec_ctx_global_init(void);
+void grpc_exec_ctx_global_shutdown(void);
+
+#endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */
diff --git a/src/core/lib/iomgr/executor.c b/src/core/lib/iomgr/executor.c
new file mode 100644
index 0000000..36e22e4
--- /dev/null
+++ b/src/core/lib/iomgr/executor.c
@@ -0,0 +1,143 @@
+/*
+ *
+ * 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/iomgr/executor.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+typedef struct grpc_executor_data {
+  int busy;          /**< is the thread currently running? */
+  int shutting_down; /**< has \a grpc_shutdown() been invoked? */
+  int pending_join;  /**< has the thread finished but not been joined? */
+  grpc_closure_list closures; /**< collection of pending work */
+  gpr_thd_id tid; /**< thread id of the thread, only valid if \a busy or \a
+                     pending_join are true */
+  gpr_thd_options options;
+  gpr_mu mu;
+} grpc_executor;
+
+static grpc_executor g_executor;
+
+void grpc_executor_init() {
+  memset(&g_executor, 0, sizeof(grpc_executor));
+  gpr_mu_init(&g_executor.mu);
+  g_executor.options = gpr_thd_options_default();
+  gpr_thd_options_set_joinable(&g_executor.options);
+}
+
+/* thread body */
+static void closure_exec_thread_func(void *ignored) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (1) {
+    gpr_mu_lock(&g_executor.mu);
+    if (g_executor.shutting_down != 0) {
+      gpr_mu_unlock(&g_executor.mu);
+      break;
+    }
+    if (grpc_closure_list_empty(g_executor.closures)) {
+      /* no more work, time to die */
+      GPR_ASSERT(g_executor.busy == 1);
+      g_executor.busy = 0;
+      gpr_mu_unlock(&g_executor.mu);
+      break;
+    } else {
+      grpc_exec_ctx_enqueue_list(&exec_ctx, &g_executor.closures, NULL);
+    }
+    gpr_mu_unlock(&g_executor.mu);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+/* Spawn the thread if new work has arrived a no thread is up */
+static void maybe_spawn_locked() {
+  if (grpc_closure_list_empty(g_executor.closures) == 1) {
+    return;
+  }
+  if (g_executor.shutting_down == 1) {
+    return;
+  }
+
+  if (g_executor.busy != 0) {
+    /* Thread still working. New work will be picked up by already running
+     * thread. Not spawning anything. */
+    return;
+  } else if (g_executor.pending_join != 0) {
+    /* Pickup the remains of the previous incarnations of the thread. */
+    gpr_thd_join(g_executor.tid);
+    g_executor.pending_join = 0;
+  }
+
+  /* All previous instances of the thread should have been joined at this point.
+   * Spawn time! */
+  g_executor.busy = 1;
+  gpr_thd_new(&g_executor.tid, closure_exec_thread_func, NULL,
+              &g_executor.options);
+  g_executor.pending_join = 1;
+}
+
+void grpc_executor_enqueue(grpc_closure *closure, bool success) {
+  gpr_mu_lock(&g_executor.mu);
+  if (g_executor.shutting_down == 0) {
+    grpc_closure_list_add(&g_executor.closures, closure, success);
+    maybe_spawn_locked();
+  }
+  gpr_mu_unlock(&g_executor.mu);
+}
+
+void grpc_executor_shutdown() {
+  int pending_join;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  gpr_mu_lock(&g_executor.mu);
+  pending_join = g_executor.pending_join;
+  g_executor.shutting_down = 1;
+  gpr_mu_unlock(&g_executor.mu);
+  /* we can release the lock at this point despite the access to the closure
+   * list below because we aren't accepting new work */
+
+  /* Execute pending callbacks, some may be performing cleanups */
+  grpc_exec_ctx_enqueue_list(&exec_ctx, &g_executor.closures, NULL);
+  grpc_exec_ctx_finish(&exec_ctx);
+  GPR_ASSERT(grpc_closure_list_empty(g_executor.closures));
+  if (pending_join) {
+    gpr_thd_join(g_executor.tid);
+  }
+  gpr_mu_destroy(&g_executor.mu);
+}
diff --git a/src/core/lib/iomgr/executor.h b/src/core/lib/iomgr/executor.h
new file mode 100644
index 0000000..b7e6f51
--- /dev/null
+++ b/src/core/lib/iomgr/executor.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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_EXECUTOR_H
+#define GRPC_CORE_LIB_IOMGR_EXECUTOR_H
+
+#include "src/core/lib/iomgr/closure.h"
+
+/** Initialize the global executor.
+ *
+ * This mechanism is meant to outsource work (grpc_closure instances) to a
+ * thread, for those cases where blocking isn't an option but there isn't a
+ * non-blocking solution available. */
+void grpc_executor_init();
+
+/** Enqueue \a closure for its eventual execution of \a f(arg) on a separate
+ * thread */
+void grpc_executor_enqueue(grpc_closure *closure, bool success);
+
+/** Shutdown the executor, running all pending work as part of the call */
+void grpc_executor_shutdown();
+
+#endif /* GRPC_CORE_LIB_IOMGR_EXECUTOR_H */
diff --git a/src/core/lib/iomgr/iocp_windows.c b/src/core/lib/iomgr/iocp_windows.c
new file mode 100644
index 0000000..d46558a
--- /dev/null
+++ b/src/core/lib/iomgr/iocp_windows.c
@@ -0,0 +1,208 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include <winsock2.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_win32.h>
+#include <grpc/support/thd.h>
+
+#include "src/core/lib/iomgr/iocp_windows.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+#include "src/core/lib/iomgr/timer.h"
+
+static ULONG g_iocp_kick_token;
+static OVERLAPPED g_iocp_custom_overlap;
+
+static gpr_atm g_custom_events = 0;
+
+static HANDLE g_iocp;
+
+static DWORD 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 INFINITE;
+  }
+  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 (DWORD)gpr_time_to_millis(gpr_time_add(
+      timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
+}
+
+grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
+                                     gpr_timespec deadline) {
+  BOOL success;
+  DWORD bytes = 0;
+  DWORD flags = 0;
+  ULONG_PTR completion_key;
+  LPOVERLAPPED overlapped;
+  grpc_winsocket *socket;
+  grpc_winsocket_callback_info *info;
+  grpc_closure *closure = NULL;
+  success = GetQueuedCompletionStatus(
+      g_iocp, &bytes, &completion_key, &overlapped,
+      deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type)));
+  if (success == 0 && overlapped == NULL) {
+    return GRPC_IOCP_WORK_TIMEOUT;
+  }
+  GPR_ASSERT(completion_key && overlapped);
+  if (overlapped == &g_iocp_custom_overlap) {
+    gpr_atm_full_fetch_add(&g_custom_events, -1);
+    if (completion_key == (ULONG_PTR)&g_iocp_kick_token) {
+      /* We were awoken from a kick. */
+      return GRPC_IOCP_WORK_KICK;
+    }
+    gpr_log(GPR_ERROR, "Unknown custom completion key.");
+    abort();
+  }
+
+  socket = (grpc_winsocket *)completion_key;
+  if (overlapped == &socket->write_info.overlapped) {
+    info = &socket->write_info;
+  } else if (overlapped == &socket->read_info.overlapped) {
+    info = &socket->read_info;
+  } else {
+    gpr_log(GPR_ERROR, "Unknown IOCP operation");
+    abort();
+  }
+  success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
+                                   FALSE, &flags);
+  info->bytes_transfered = bytes;
+  info->wsa_error = success ? 0 : WSAGetLastError();
+  GPR_ASSERT(overlapped == &info->overlapped);
+  GPR_ASSERT(!info->has_pending_iocp);
+  gpr_mu_lock(&socket->state_mu);
+  if (info->closure) {
+    closure = info->closure;
+    info->closure = NULL;
+  } else {
+    info->has_pending_iocp = 1;
+  }
+  gpr_mu_unlock(&socket->state_mu);
+  grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+  return GRPC_IOCP_WORK_WORK;
+}
+
+void grpc_iocp_init(void) {
+  g_iocp =
+      CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0);
+  GPR_ASSERT(g_iocp);
+}
+
+void grpc_iocp_kick(void) {
+  BOOL success;
+
+  gpr_atm_full_fetch_add(&g_custom_events, 1);
+  success = PostQueuedCompletionStatus(g_iocp, 0, (ULONG_PTR)&g_iocp_kick_token,
+                                       &g_iocp_custom_overlap);
+  GPR_ASSERT(success);
+}
+
+void grpc_iocp_flush(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_iocp_work_status work_status;
+
+  do {
+    work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
+  } while (work_status == GRPC_IOCP_WORK_KICK ||
+           grpc_exec_ctx_flush(&exec_ctx));
+}
+
+void grpc_iocp_shutdown(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (gpr_atm_acq_load(&g_custom_events)) {
+    grpc_iocp_work(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  GPR_ASSERT(CloseHandle(g_iocp));
+}
+
+void grpc_iocp_add_socket(grpc_winsocket *socket) {
+  HANDLE ret;
+  if (socket->added_to_iocp) return;
+  ret = CreateIoCompletionPort((HANDLE)socket->socket, g_iocp,
+                               (uintptr_t)socket, 0);
+  if (!ret) {
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    gpr_log(GPR_ERROR, "Unable to add socket to iocp: %s", utf8_message);
+    gpr_free(utf8_message);
+    __debugbreak();
+    abort();
+  }
+  socket->added_to_iocp = 1;
+  GPR_ASSERT(ret == g_iocp);
+}
+
+/* Calling notify_on_read or write means either of two things:
+   -) The IOCP already completed in the background, and we need to call
+   the callback now.
+   -) The IOCP hasn't completed yet, and we're queuing it for later. */
+static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx,
+                                  grpc_winsocket *socket, grpc_closure *closure,
+                                  grpc_winsocket_callback_info *info) {
+  GPR_ASSERT(info->closure == NULL);
+  gpr_mu_lock(&socket->state_mu);
+  if (info->has_pending_iocp) {
+    info->has_pending_iocp = 0;
+    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+  } else {
+    info->closure = closure;
+  }
+  gpr_mu_unlock(&socket->state_mu);
+}
+
+void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
+                                 grpc_winsocket *socket,
+                                 grpc_closure *closure) {
+  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info);
+}
+
+void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
+                                grpc_closure *closure) {
+  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info);
+}
+
+#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/iocp_windows.h b/src/core/lib/iomgr/iocp_windows.h
new file mode 100644
index 0000000..ae210fa
--- /dev/null
+++ b/src/core/lib/iomgr/iocp_windows.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * 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_IOCP_WINDOWS_H
+#define GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H
+
+#include <grpc/support/sync.h>
+
+#include "src/core/lib/iomgr/socket_windows.h"
+
+typedef enum {
+  GRPC_IOCP_WORK_WORK,
+  GRPC_IOCP_WORK_TIMEOUT,
+  GRPC_IOCP_WORK_KICK
+} grpc_iocp_work_status;
+
+grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
+                                     gpr_timespec deadline);
+void grpc_iocp_init(void);
+void grpc_iocp_kick(void);
+void grpc_iocp_flush(void);
+void grpc_iocp_shutdown(void);
+void grpc_iocp_add_socket(grpc_winsocket *);
+
+void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
+                                 grpc_winsocket *winsocket,
+                                 grpc_closure *closure);
+
+void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx,
+                                grpc_winsocket *winsocket,
+                                grpc_closure *closure);
+
+#endif /* GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H */
diff --git a/src/core/lib/iomgr/iomgr.c b/src/core/lib/iomgr/iomgr.c
new file mode 100644
index 0000000..1466639
--- /dev/null
+++ b/src/core/lib/iomgr/iomgr.c
@@ -0,0 +1,173 @@
+/*
+ *
+ * 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/iomgr/iomgr.h"
+
+#include <stdlib.h>
+#include <string.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/thd.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+
+static gpr_mu g_mu;
+static gpr_cv g_rcv;
+static int g_shutdown;
+static grpc_iomgr_object g_root_object;
+
+void grpc_iomgr_init(void) {
+  g_shutdown = 0;
+  gpr_mu_init(&g_mu);
+  gpr_cv_init(&g_rcv);
+  grpc_exec_ctx_global_init();
+  grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC));
+  g_root_object.next = g_root_object.prev = &g_root_object;
+  g_root_object.name = "root";
+  grpc_iomgr_platform_init();
+}
+
+static size_t count_objects(void) {
+  grpc_iomgr_object *obj;
+  size_t n = 0;
+  for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
+    n++;
+  }
+  return n;
+}
+
+static void dump_objects(const char *kind) {
+  grpc_iomgr_object *obj;
+  for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
+    gpr_log(GPR_DEBUG, "%s OBJECT: %s %p", kind, obj->name, obj);
+  }
+}
+
+void grpc_iomgr_shutdown(void) {
+  gpr_timespec shutdown_deadline = gpr_time_add(
+      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN));
+  gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  grpc_iomgr_platform_flush();
+
+  gpr_mu_lock(&g_mu);
+  g_shutdown = 1;
+  while (g_root_object.next != &g_root_object) {
+    if (gpr_time_cmp(
+            gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time),
+            gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
+      if (g_root_object.next != &g_root_object) {
+        gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed",
+                count_objects());
+      }
+      last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
+    }
+    if (grpc_timer_check(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC),
+                         NULL)) {
+      gpr_mu_unlock(&g_mu);
+      grpc_exec_ctx_flush(&exec_ctx);
+      gpr_mu_lock(&g_mu);
+      continue;
+    }
+    if (g_root_object.next != &g_root_object) {
+      gpr_timespec short_deadline = gpr_time_add(
+          gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN));
+      if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) {
+        if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) {
+          if (g_root_object.next != &g_root_object) {
+            gpr_log(GPR_DEBUG,
+                    "Failed to free %d iomgr objects before shutdown deadline: "
+                    "memory leaks are likely",
+                    count_objects());
+            dump_objects("LEAKED");
+            if (grpc_iomgr_abort_on_leaks()) {
+              abort();
+            }
+          }
+          break;
+        }
+      }
+    }
+  }
+  gpr_mu_unlock(&g_mu);
+
+  grpc_timer_list_shutdown(&exec_ctx);
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  /* ensure all threads have left g_mu */
+  gpr_mu_lock(&g_mu);
+  gpr_mu_unlock(&g_mu);
+
+  grpc_iomgr_platform_shutdown();
+  grpc_exec_ctx_global_shutdown();
+  gpr_mu_destroy(&g_mu);
+  gpr_cv_destroy(&g_rcv);
+}
+
+void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) {
+  obj->name = gpr_strdup(name);
+  gpr_mu_lock(&g_mu);
+  obj->next = &g_root_object;
+  obj->prev = g_root_object.prev;
+  obj->next->prev = obj->prev->next = obj;
+  gpr_mu_unlock(&g_mu);
+}
+
+void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
+  gpr_mu_lock(&g_mu);
+  obj->next->prev = obj->prev;
+  obj->prev->next = obj->next;
+  gpr_cv_signal(&g_rcv);
+  gpr_mu_unlock(&g_mu);
+  gpr_free(obj->name);
+}
+
+bool grpc_iomgr_abort_on_leaks(void) {
+  char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
+  if (env == NULL) return false;
+  static const char *truthy[] = {"yes",  "Yes",  "YES", "true",
+                                 "True", "TRUE", "1"};
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
+    if (0 == strcmp(env, truthy[i])) return true;
+  }
+  return false;
+}
diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h
new file mode 100644
index 0000000..6c82de7
--- /dev/null
+++ b/src/core/lib/iomgr/iomgr.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * 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_IOMGR_H
+#define GRPC_CORE_LIB_IOMGR_IOMGR_H
+
+/** Initializes the iomgr. */
+void grpc_iomgr_init(void);
+
+/** Signals the intention to shutdown the iomgr. */
+void grpc_iomgr_shutdown(void);
+
+#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */
diff --git a/src/core/lib/iomgr/iomgr_internal.h b/src/core/lib/iomgr/iomgr_internal.h
new file mode 100644
index 0000000..805be1f
--- /dev/null
+++ b/src/core/lib/iomgr/iomgr_internal.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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_IOMGR_INTERNAL_H
+#define GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H
+
+#include <stdbool.h>
+
+#include "src/core/lib/iomgr/iomgr.h"
+
+typedef struct grpc_iomgr_object {
+  char *name;
+  struct grpc_iomgr_object *next;
+  struct grpc_iomgr_object *prev;
+} grpc_iomgr_object;
+
+void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name);
+void grpc_iomgr_unregister_object(grpc_iomgr_object *obj);
+
+void grpc_iomgr_platform_init(void);
+/** flush any globally queued work from iomgr */
+void grpc_iomgr_platform_flush(void);
+/** tear down all platform specific global iomgr structures */
+void grpc_iomgr_platform_shutdown(void);
+
+bool grpc_iomgr_abort_on_leaks(void);
+
+#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */
diff --git a/src/core/lib/iomgr/iomgr_posix.c b/src/core/lib/iomgr/iomgr_posix.c
new file mode 100644
index 0000000..016c501
--- /dev/null
+++ b/src/core/lib/iomgr/iomgr_posix.c
@@ -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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_SOCKET
+
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/iomgr_posix.h"
+#include "src/core/lib/iomgr/tcp_posix.h"
+
+void grpc_iomgr_platform_init(void) {
+  grpc_event_engine_init();
+  grpc_register_tracer("tcp", &grpc_tcp_trace);
+}
+
+void grpc_iomgr_platform_flush(void) {}
+
+void grpc_iomgr_platform_shutdown(void) { grpc_event_engine_shutdown(); }
+
+#endif /* GRPC_POSIX_SOCKET */
diff --git a/src/core/lib/iomgr/iomgr_posix.h b/src/core/lib/iomgr/iomgr_posix.h
new file mode 100644
index 0000000..d5eade9
--- /dev/null
+++ b/src/core/lib/iomgr/iomgr_posix.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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_IOMGR_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_IOMGR_POSIX_H
+
+#include "src/core/lib/iomgr/iomgr_internal.h"
+
+#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_POSIX_H */
diff --git a/src/core/lib/iomgr/iomgr_windows.c b/src/core/lib/iomgr/iomgr_windows.c
new file mode 100644
index 0000000..398517f
--- /dev/null
+++ b/src/core/lib/iomgr/iomgr_windows.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include "src/core/lib/iomgr/sockaddr_win32.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/iomgr/iocp_windows.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/pollset_windows.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+
+/* Windows' io manager is going to be fully designed using IO completion
+   ports. All of what we're doing here is basically make sure that
+   Windows sockets are initialized in and out. */
+
+static void winsock_init(void) {
+  WSADATA wsaData;
+  int status = WSAStartup(MAKEWORD(2, 0), &wsaData);
+  GPR_ASSERT(status == 0);
+}
+
+static void winsock_shutdown(void) {
+  int status = WSACleanup();
+  GPR_ASSERT(status == 0);
+}
+
+void grpc_iomgr_platform_init(void) {
+  winsock_init();
+  grpc_iocp_init();
+  grpc_pollset_global_init();
+}
+
+void grpc_iomgr_platform_flush(void) { grpc_iocp_flush(); }
+
+void grpc_iomgr_platform_shutdown(void) {
+  grpc_pollset_global_shutdown();
+  grpc_iocp_shutdown();
+  winsock_shutdown();
+}
+
+#endif /* GRPC_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/pollset.h b/src/core/lib/iomgr/pollset.h
new file mode 100644
index 0000000..c40a474
--- /dev/null
+++ b/src/core/lib/iomgr/pollset.h
@@ -0,0 +1,94 @@
+/*
+ *
+ * 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_POLLSET_H
+#define GRPC_CORE_LIB_IOMGR_POLLSET_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1)
+
+/* A grpc_pollset is a set of file descriptors that a higher level item is
+   interested in. For example:
+    - a server will typically keep a pollset containing all connected channels,
+      so that it can find new calls to service
+    - a completion queue might keep a pollset with an entry for each transport
+      that is servicing a call that it's tracking */
+
+typedef struct grpc_pollset grpc_pollset;
+typedef struct grpc_pollset_worker grpc_pollset_worker;
+
+size_t grpc_pollset_size(void);
+void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
+/* Begin shutting down the pollset, and call closure when done.
+ * pollset's mutex must be held */
+void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                           grpc_closure *closure);
+/** Reset the pollset to its initial state (perhaps with some cached objects);
+ *  must have been previously shutdown */
+void grpc_pollset_reset(grpc_pollset *pollset);
+void grpc_pollset_destroy(grpc_pollset *pollset);
+
+/* Do some work on a pollset.
+   May involve invoking asynchronous callbacks, or actually polling file
+   descriptors.
+   Requires pollset's mutex locked.
+   May unlock its mutex during its execution.
+
+   worker is a (platform-specific) handle that can be used to wake up
+   from grpc_pollset_work before any events are received and before the timeout
+   has expired. It is both initialized and destroyed by grpc_pollset_work.
+   Initialization of worker is guaranteed to occur BEFORE the
+   pollset's mutex is released for the first time by grpc_pollset_work
+   and it is guaranteed that it will not be released by grpc_pollset_work
+   AFTER worker has been destroyed.
+
+   Tries not to block past deadline.
+   May call grpc_closure_list_run on grpc_closure_list, without holding the
+   pollset
+   lock */
+void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                       grpc_pollset_worker **worker, gpr_timespec now,
+                       gpr_timespec deadline);
+
+/* Break one polling thread out of polling work for this pollset.
+   If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers.
+   Otherwise, if specific_worker is non-NULL, then kick that worker. */
+void grpc_pollset_kick(grpc_pollset *pollset,
+                       grpc_pollset_worker *specific_worker);
+
+#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_H */
diff --git a/src/core/lib/iomgr/pollset_set.h b/src/core/lib/iomgr/pollset_set.h
new file mode 100644
index 0000000..34bb728
--- /dev/null
+++ b/src/core/lib/iomgr/pollset_set.h
@@ -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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_IOMGR_POLLSET_SET_H
+#define GRPC_CORE_LIB_IOMGR_POLLSET_SET_H
+
+#include "src/core/lib/iomgr/pollset.h"
+
+/* A grpc_pollset_set is a set of pollsets that are interested in an
+   action. Adding a pollset to a pollset_set automatically adds any
+   fd's (etc) that have been registered with the set_set to that pollset.
+   Registering fd's automatically adds them to all current pollsets. */
+
+typedef struct grpc_pollset_set grpc_pollset_set;
+
+grpc_pollset_set *grpc_pollset_set_create(void);
+void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set);
+void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
+                                  grpc_pollset_set *pollset_set,
+                                  grpc_pollset *pollset);
+void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
+                                  grpc_pollset_set *pollset_set,
+                                  grpc_pollset *pollset);
+void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
+                                      grpc_pollset_set *bag,
+                                      grpc_pollset_set *item);
+void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
+                                      grpc_pollset_set *bag,
+                                      grpc_pollset_set *item);
+
+#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_SET_H */
diff --git a/src/core/lib/iomgr/pollset_set_windows.c b/src/core/lib/iomgr/pollset_set_windows.c
new file mode 100644
index 0000000..89f60b9
--- /dev/null
+++ b/src/core/lib/iomgr/pollset_set_windows.c
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include "src/core/lib/iomgr/pollset_set_windows.h"
+
+grpc_pollset_set* grpc_pollset_set_create(void) { return NULL; }
+
+void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
+
+void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
+                                  grpc_pollset_set* pollset_set,
+                                  grpc_pollset* pollset) {}
+
+void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx,
+                                  grpc_pollset_set* pollset_set,
+                                  grpc_pollset* pollset) {}
+
+void grpc_pollset_set_add_pollset_set(grpc_exec_ctx* exec_ctx,
+                                      grpc_pollset_set* bag,
+                                      grpc_pollset_set* item) {}
+
+void grpc_pollset_set_del_pollset_set(grpc_exec_ctx* exec_ctx,
+                                      grpc_pollset_set* bag,
+                                      grpc_pollset_set* item) {}
+
+#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/pollset_set_windows.h b/src/core/lib/iomgr/pollset_set_windows.h
new file mode 100644
index 0000000..0356749
--- /dev/null
+++ b/src/core/lib/iomgr/pollset_set_windows.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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_POLLSET_SET_WINDOWS_H
+#define GRPC_CORE_LIB_IOMGR_POLLSET_SET_WINDOWS_H
+
+#include "src/core/lib/iomgr/pollset_set.h"
+
+#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_SET_WINDOWS_H */
diff --git a/src/core/lib/iomgr/pollset_windows.c b/src/core/lib/iomgr/pollset_windows.c
new file mode 100644
index 0000000..bff5c58
--- /dev/null
+++ b/src/core/lib/iomgr/pollset_windows.c
@@ -0,0 +1,240 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include <grpc/support/log.h>
+#include <grpc/support/thd.h>
+
+#include "src/core/lib/iomgr/iocp_windows.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/pollset_windows.h"
+
+gpr_mu grpc_polling_mu;
+static grpc_pollset_worker *g_active_poller;
+static grpc_pollset_worker g_global_root_worker;
+
+void grpc_pollset_global_init(void) {
+  gpr_mu_init(&grpc_polling_mu);
+  g_active_poller = NULL;
+  g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next =
+      g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev =
+          &g_global_root_worker;
+}
+
+void grpc_pollset_global_shutdown(void) { gpr_mu_destroy(&grpc_polling_mu); }
+
+static void remove_worker(grpc_pollset_worker *worker,
+                          grpc_pollset_worker_link_type type) {
+  worker->links[type].prev->links[type].next = worker->links[type].next;
+  worker->links[type].next->links[type].prev = worker->links[type].prev;
+  worker->links[type].next = worker->links[type].prev = worker;
+}
+
+static int has_workers(grpc_pollset_worker *root,
+                       grpc_pollset_worker_link_type type) {
+  return root->links[type].next != root;
+}
+
+static grpc_pollset_worker *pop_front_worker(
+    grpc_pollset_worker *root, grpc_pollset_worker_link_type type) {
+  if (has_workers(root, type)) {
+    grpc_pollset_worker *w = root->links[type].next;
+    remove_worker(w, type);
+    return w;
+  } else {
+    return NULL;
+  }
+}
+
+static void push_front_worker(grpc_pollset_worker *root,
+                              grpc_pollset_worker_link_type type,
+                              grpc_pollset_worker *worker) {
+  worker->links[type].prev = root;
+  worker->links[type].next = worker->links[type].prev->links[type].next;
+  worker->links[type].prev->links[type].next =
+      worker->links[type].next->links[type].prev = worker;
+}
+
+size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); }
+
+/* There isn't really any such thing as a pollset under Windows, due to the
+   nature of the IO completion ports. We're still going to provide a minimal
+   set of features for the sake of the rest of grpc. But grpc_pollset_work
+   won't actually do any polling, and return as quickly as possible. */
+
+void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
+  *mu = &grpc_polling_mu;
+  memset(pollset, 0, sizeof(*pollset));
+  pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
+      pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
+          &pollset->root_worker;
+}
+
+void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                           grpc_closure *closure) {
+  pollset->shutting_down = 1;
+  grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
+  if (!pollset->is_iocp_worker) {
+    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+  } else {
+    pollset->on_shutdown = closure;
+  }
+}
+
+void grpc_pollset_destroy(grpc_pollset *pollset) {}
+
+void grpc_pollset_reset(grpc_pollset *pollset) {
+  GPR_ASSERT(pollset->shutting_down);
+  GPR_ASSERT(
+      !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
+  pollset->shutting_down = 0;
+  pollset->is_iocp_worker = 0;
+  pollset->kicked_without_pollers = 0;
+  pollset->on_shutdown = NULL;
+}
+
+void grpc_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;
+
+  int added_worker = 0;
+  worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
+      worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
+          worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next =
+              worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = NULL;
+  worker.kicked = 0;
+  worker.pollset = pollset;
+  gpr_cv_init(&worker.cv);
+  if (!pollset->kicked_without_pollers && !pollset->shutting_down) {
+    if (g_active_poller == NULL) {
+      grpc_pollset_worker *next_worker;
+      /* become poller */
+      pollset->is_iocp_worker = 1;
+      g_active_poller = &worker;
+      gpr_mu_unlock(&grpc_polling_mu);
+      grpc_iocp_work(exec_ctx, deadline);
+      grpc_exec_ctx_flush(exec_ctx);
+      gpr_mu_lock(&grpc_polling_mu);
+      pollset->is_iocp_worker = 0;
+      g_active_poller = NULL;
+      /* try to get a worker from this pollsets worker list */
+      next_worker = pop_front_worker(&pollset->root_worker,
+                                     GRPC_POLLSET_WORKER_LINK_POLLSET);
+      if (next_worker == NULL) {
+        /* try to get a worker from the global list */
+        next_worker = pop_front_worker(&g_global_root_worker,
+                                       GRPC_POLLSET_WORKER_LINK_GLOBAL);
+      }
+      if (next_worker != NULL) {
+        next_worker->kicked = 1;
+        gpr_cv_signal(&next_worker->cv);
+      }
+
+      if (pollset->shutting_down && pollset->on_shutdown != NULL) {
+        grpc_exec_ctx_enqueue(exec_ctx, pollset->on_shutdown, true, NULL);
+        pollset->on_shutdown = NULL;
+      }
+      goto done;
+    }
+    push_front_worker(&g_global_root_worker, GRPC_POLLSET_WORKER_LINK_GLOBAL,
+                      &worker);
+    push_front_worker(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET,
+                      &worker);
+    added_worker = 1;
+    while (!worker.kicked) {
+      if (gpr_cv_wait(&worker.cv, &grpc_polling_mu, deadline)) {
+        break;
+      }
+    }
+  } else {
+    pollset->kicked_without_pollers = 0;
+  }
+done:
+  if (!grpc_closure_list_empty(exec_ctx->closure_list)) {
+    gpr_mu_unlock(&grpc_polling_mu);
+    grpc_exec_ctx_flush(exec_ctx);
+    gpr_mu_lock(&grpc_polling_mu);
+  }
+  if (added_worker) {
+    remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_GLOBAL);
+    remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_POLLSET);
+  }
+  gpr_cv_destroy(&worker.cv);
+  *worker_hdl = NULL;
+}
+
+void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
+  if (specific_worker != NULL) {
+    if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
+      for (specific_worker =
+               p->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next;
+           specific_worker != &p->root_worker;
+           specific_worker =
+               specific_worker->links[GRPC_POLLSET_WORKER_LINK_POLLSET].next) {
+        specific_worker->kicked = 1;
+        gpr_cv_signal(&specific_worker->cv);
+      }
+      p->kicked_without_pollers = 1;
+      if (p->is_iocp_worker) {
+        grpc_iocp_kick();
+      }
+    } else {
+      if (p->is_iocp_worker && g_active_poller == specific_worker) {
+        grpc_iocp_kick();
+      } else {
+        specific_worker->kicked = 1;
+        gpr_cv_signal(&specific_worker->cv);
+      }
+    }
+  } else {
+    specific_worker =
+        pop_front_worker(&p->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET);
+    if (specific_worker != NULL) {
+      grpc_pollset_kick(p, specific_worker);
+    } else if (p->is_iocp_worker) {
+      grpc_iocp_kick();
+    } else {
+      p->kicked_without_pollers = 1;
+    }
+  }
+}
+
+void grpc_kick_poller(void) { grpc_iocp_kick(); }
+
+#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/pollset_windows.h b/src/core/lib/iomgr/pollset_windows.h
new file mode 100644
index 0000000..2642013
--- /dev/null
+++ b/src/core/lib/iomgr/pollset_windows.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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_POLLSET_WINDOWS_H
+#define GRPC_CORE_LIB_IOMGR_POLLSET_WINDOWS_H
+
+#include <grpc/support/sync.h>
+
+#include "src/core/lib/iomgr/socket_windows.h"
+
+/* There isn't really any such thing as a pollset under Windows, due to the
+   nature of the IO completion ports. A Windows "pollset" is merely a mutex
+   used to synchronize with the IOCP, and workers are condition variables
+   used to block threads until work is ready. */
+
+typedef enum {
+  GRPC_POLLSET_WORKER_LINK_POLLSET = 0,
+  GRPC_POLLSET_WORKER_LINK_GLOBAL,
+  GRPC_POLLSET_WORKER_LINK_TYPES
+} grpc_pollset_worker_link_type;
+
+typedef struct grpc_pollset_worker_link {
+  struct grpc_pollset_worker *next;
+  struct grpc_pollset_worker *prev;
+} grpc_pollset_worker_link;
+
+struct grpc_pollset;
+typedef struct grpc_pollset grpc_pollset;
+
+typedef struct grpc_pollset_worker {
+  gpr_cv cv;
+  int kicked;
+  struct grpc_pollset *pollset;
+  grpc_pollset_worker_link links[GRPC_POLLSET_WORKER_LINK_TYPES];
+} grpc_pollset_worker;
+
+struct grpc_pollset {
+  int shutting_down;
+  int kicked_without_pollers;
+  int is_iocp_worker;
+  grpc_pollset_worker root_worker;
+  grpc_closure *on_shutdown;
+};
+
+void grpc_pollset_global_init(void);
+void grpc_pollset_global_shutdown(void);
+
+#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_WINDOWS_H */
diff --git a/src/core/lib/iomgr/resolve_address.h b/src/core/lib/iomgr/resolve_address.h
new file mode 100644
index 0000000..ef198fe
--- /dev/null
+++ b/src/core/lib/iomgr/resolve_address.h
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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_RESOLVE_ADDRESS_H
+#define GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H
+
+#include <stddef.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr.h"
+
+#define GRPC_MAX_SOCKADDR_SIZE 128
+
+typedef struct {
+  char addr[GRPC_MAX_SOCKADDR_SIZE];
+  size_t len;
+} grpc_resolved_address;
+
+typedef struct {
+  size_t naddrs;
+  grpc_resolved_address *addrs;
+} grpc_resolved_addresses;
+
+/* Async result callback:
+   On success: addresses is the result, and the callee must call
+   grpc_resolved_addresses_destroy when it's done with them
+   On failure: addresses is NULL */
+typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg,
+                                grpc_resolved_addresses *addresses);
+/* Asynchronously resolve addr. Use default_port if a port isn't designated
+   in addr, otherwise use the port in addr. */
+/* TODO(ctiller): add a timeout here */
+extern void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr,
+                                    const char *default_port,
+                                    grpc_resolve_cb cb, void *arg);
+/* Destroy resolved addresses */
+void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
+
+/* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
+   result must be freed with grpc_resolved_addresses_destroy. */
+extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
+    const char *name, const char *default_port);
+
+#endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */
diff --git a/src/core/lib/iomgr/resolve_address_posix.c b/src/core/lib/iomgr/resolve_address_posix.c
new file mode 100644
index 0000000..cae91ee
--- /dev/null
+++ b/src/core/lib/iomgr/resolve_address_posix.c
@@ -0,0 +1,183 @@
+/*
+ *
+ * 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_SOCKET
+
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
+#include <string.h>
+#include <sys/types.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/support/block_annotate.h"
+#include "src/core/lib/support/string.h"
+
+typedef struct {
+  char *name;
+  char *default_port;
+  grpc_resolve_cb cb;
+  grpc_closure request_closure;
+  void *arg;
+} request;
+
+static grpc_resolved_addresses *blocking_resolve_address_impl(
+    const char *name, const char *default_port) {
+  struct addrinfo hints;
+  struct addrinfo *result = NULL, *resp;
+  char *host;
+  char *port;
+  int s;
+  size_t i;
+  grpc_resolved_addresses *addrs = NULL;
+
+  if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
+      name[4] == ':' && name[5] != 0) {
+    return grpc_resolve_unix_domain_address(name + 5);
+  }
+
+  /* parse name, splitting it into host and port parts */
+  gpr_split_host_port(name, &host, &port);
+  if (host == NULL) {
+    gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
+    goto done;
+  }
+  if (port == NULL) {
+    if (default_port == NULL) {
+      gpr_log(GPR_ERROR, "no port in name '%s'", name);
+      goto done;
+    }
+    port = gpr_strdup(default_port);
+  }
+
+  /* Call getaddrinfo */
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;     /* ipv4 or ipv6 */
+  hints.ai_socktype = SOCK_STREAM; /* stream socket */
+  hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */
+
+  GRPC_SCHEDULING_START_BLOCKING_REGION;
+  s = getaddrinfo(host, port, &hints, &result);
+  GRPC_SCHEDULING_END_BLOCKING_REGION;
+
+  if (s != 0) {
+    /* Retry if well-known service name is recognized */
+    char *svc[][2] = {{"http", "80"}, {"https", "443"}};
+    for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) {
+      if (strcmp(port, svc[i][0]) == 0) {
+        GRPC_SCHEDULING_START_BLOCKING_REGION;
+        s = getaddrinfo(host, svc[i][1], &hints, &result);
+        GRPC_SCHEDULING_END_BLOCKING_REGION;
+        break;
+      }
+    }
+  }
+
+  if (s != 0) {
+    gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
+    goto done;
+  }
+
+  /* Success path: set addrs non-NULL, fill it in */
+  addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
+  addrs->naddrs = 0;
+  for (resp = result; resp != NULL; resp = resp->ai_next) {
+    addrs->naddrs++;
+  }
+  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
+  i = 0;
+  for (resp = result; resp != NULL; resp = resp->ai_next) {
+    memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
+    addrs->addrs[i].len = resp->ai_addrlen;
+    i++;
+  }
+
+done:
+  gpr_free(host);
+  gpr_free(port);
+  if (result) {
+    freeaddrinfo(result);
+  }
+  return addrs;
+}
+
+grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
+    const char *name, const char *default_port) = blocking_resolve_address_impl;
+
+/* Callback to be passed to grpc_executor to asynch-ify
+ * grpc_blocking_resolve_address */
+static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
+  request *r = rp;
+  grpc_resolved_addresses *resolved =
+      grpc_blocking_resolve_address(r->name, r->default_port);
+  void *arg = r->arg;
+  grpc_resolve_cb cb = r->cb;
+  gpr_free(r->name);
+  gpr_free(r->default_port);
+  cb(exec_ctx, arg, resolved);
+  gpr_free(r);
+}
+
+void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
+  gpr_free(addrs->addrs);
+  gpr_free(addrs);
+}
+
+static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
+                                 const char *default_port, grpc_resolve_cb cb,
+                                 void *arg) {
+  request *r = gpr_malloc(sizeof(request));
+  grpc_closure_init(&r->request_closure, do_request_thread, r);
+  r->name = gpr_strdup(name);
+  r->default_port = gpr_strdup(default_port);
+  r->cb = cb;
+  r->arg = arg;
+  grpc_executor_enqueue(&r->request_closure, 1);
+}
+
+void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
+                             const char *default_port, grpc_resolve_cb cb,
+                             void *arg) = resolve_address_impl;
+
+#endif
diff --git a/src/core/lib/iomgr/resolve_address_windows.c b/src/core/lib/iomgr/resolve_address_windows.c
new file mode 100644
index 0000000..9147362
--- /dev/null
+++ b/src/core/lib/iomgr/resolve_address_windows.c
@@ -0,0 +1,174 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
+#include <string.h>
+#include <sys/types.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_win32.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/support/block_annotate.h"
+#include "src/core/lib/support/string.h"
+
+typedef struct {
+  char *name;
+  char *default_port;
+  grpc_resolve_cb cb;
+  grpc_closure request_closure;
+  void *arg;
+} request;
+
+static grpc_resolved_addresses *blocking_resolve_address_impl(
+    const char *name, const char *default_port) {
+  struct addrinfo hints;
+  struct addrinfo *result = NULL, *resp;
+  char *host;
+  char *port;
+  int s;
+  size_t i;
+  grpc_resolved_addresses *addrs = NULL;
+
+  /* parse name, splitting it into host and port parts */
+  gpr_split_host_port(name, &host, &port);
+  if (host == NULL) {
+    gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
+    goto done;
+  }
+  if (port == NULL) {
+    if (default_port == NULL) {
+      gpr_log(GPR_ERROR, "no port in name '%s'", name);
+      goto done;
+    }
+    port = gpr_strdup(default_port);
+  }
+
+  /* Call getaddrinfo */
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;     /* ipv4 or ipv6 */
+  hints.ai_socktype = SOCK_STREAM; /* stream socket */
+  hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */
+
+  GRPC_SCHEDULING_START_BLOCKING_REGION;
+  s = getaddrinfo(host, port, &hints, &result);
+  GRPC_SCHEDULING_END_BLOCKING_REGION;
+  if (s != 0) {
+    char *error_message = gpr_format_message(s);
+    gpr_log(GPR_ERROR, "getaddrinfo: %s", error_message);
+    gpr_free(error_message);
+    goto done;
+  }
+
+  /* Success path: set addrs non-NULL, fill it in */
+  addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
+  addrs->naddrs = 0;
+  for (resp = result; resp != NULL; resp = resp->ai_next) {
+    addrs->naddrs++;
+  }
+  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
+  i = 0;
+  for (resp = result; resp != NULL; resp = resp->ai_next) {
+    memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
+    addrs->addrs[i].len = resp->ai_addrlen;
+    i++;
+  }
+
+  {
+    for (i = 0; i < addrs->naddrs; i++) {
+      char *buf;
+      grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr,
+                              0);
+      gpr_free(buf);
+    }
+  }
+
+done:
+  gpr_free(host);
+  gpr_free(port);
+  if (result) {
+    freeaddrinfo(result);
+  }
+  return addrs;
+}
+
+grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
+    const char *name, const char *default_port) = blocking_resolve_address_impl;
+
+/* Callback to be passed to grpc_executor to asynch-ify
+ * grpc_blocking_resolve_address */
+static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
+  request *r = rp;
+  grpc_resolved_addresses *resolved =
+      grpc_blocking_resolve_address(r->name, r->default_port);
+  void *arg = r->arg;
+  grpc_resolve_cb cb = r->cb;
+  gpr_free(r->name);
+  gpr_free(r->default_port);
+  cb(exec_ctx, arg, resolved);
+  gpr_free(r);
+}
+
+void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
+  gpr_free(addrs->addrs);
+  gpr_free(addrs);
+}
+
+static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
+                                 const char *default_port, grpc_resolve_cb cb,
+                                 void *arg) {
+  request *r = gpr_malloc(sizeof(request));
+  grpc_closure_init(&r->request_closure, do_request_thread, r);
+  r->name = gpr_strdup(name);
+  r->default_port = gpr_strdup(default_port);
+  r->cb = cb;
+  r->arg = arg;
+  grpc_executor_enqueue(&r->request_closure, 1);
+}
+
+void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
+                             const char *default_port, grpc_resolve_cb cb,
+                             void *arg) = resolve_address_impl;
+
+#endif
diff --git a/src/core/lib/iomgr/sockaddr.h b/src/core/lib/iomgr/sockaddr.h
new file mode 100644
index 0000000..891a2f0
--- /dev/null
+++ b/src/core/lib/iomgr/sockaddr.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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_SOCKADDR_H
+#define GRPC_CORE_LIB_IOMGR_SOCKADDR_H
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+#include "src/core/lib/iomgr/sockaddr_win32.h"
+#endif
+
+#ifdef GPR_POSIX_SOCKETADDR
+#include "src/core/lib/iomgr/sockaddr_posix.h"
+#endif
+
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_H */
diff --git a/src/core/lib/iomgr/sockaddr_posix.h b/src/core/lib/iomgr/sockaddr_posix.h
new file mode 100644
index 0000000..b150de4
--- /dev/null
+++ b/src/core/lib/iomgr/sockaddr_posix.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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_SOCKADDR_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_SOCKADDR_POSIX_H
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_POSIX_H */
diff --git a/src/core/lib/iomgr/sockaddr_utils.c b/src/core/lib/iomgr/sockaddr_utils.c
new file mode 100644
index 0000000..127d95c
--- /dev/null
+++ b/src/core/lib/iomgr/sockaddr_utils.c
@@ -0,0 +1,227 @@
+/*
+ *
+ * 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/iomgr/sockaddr_utils.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/support/string.h"
+
+static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0,    0,
+                                          0, 0, 0, 0, 0xff, 0xff};
+
+int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr,
+                              struct sockaddr_in *addr4_out) {
+  GPR_ASSERT(addr != (struct sockaddr *)addr4_out);
+  if (addr->sa_family == AF_INET6) {
+    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
+    if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
+               sizeof(kV4MappedPrefix)) == 0) {
+      if (addr4_out != NULL) {
+        /* Normalize ::ffff:0.0.0.0/96 to IPv4. */
+        memset(addr4_out, 0, sizeof(*addr4_out));
+        addr4_out->sin_family = AF_INET;
+        /* s6_addr32 would be nice, but it's non-standard. */
+        memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
+        addr4_out->sin_port = addr6->sin6_port;
+      }
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr,
+                              struct sockaddr_in6 *addr6_out) {
+  GPR_ASSERT(addr != (struct sockaddr *)addr6_out);
+  if (addr->sa_family == AF_INET) {
+    const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
+    memset(addr6_out, 0, sizeof(*addr6_out));
+    addr6_out->sin6_family = AF_INET6;
+    memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
+    memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
+    addr6_out->sin6_port = addr4->sin_port;
+    return 1;
+  }
+  return 0;
+}
+
+int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out) {
+  struct sockaddr_in addr4_normalized;
+  if (grpc_sockaddr_is_v4mapped(addr, &addr4_normalized)) {
+    addr = (struct sockaddr *)&addr4_normalized;
+  }
+  if (addr->sa_family == AF_INET) {
+    /* Check for 0.0.0.0 */
+    const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
+    if (addr4->sin_addr.s_addr != 0) {
+      return 0;
+    }
+    *port_out = ntohs(addr4->sin_port);
+    return 1;
+  } else if (addr->sa_family == AF_INET6) {
+    /* Check for :: */
+    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
+    int i;
+    for (i = 0; i < 16; i++) {
+      if (addr6->sin6_addr.s6_addr[i] != 0) {
+        return 0;
+      }
+    }
+    *port_out = ntohs(addr6->sin6_port);
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
+                                  struct sockaddr_in6 *wild6_out) {
+  grpc_sockaddr_make_wildcard4(port, wild4_out);
+  grpc_sockaddr_make_wildcard6(port, wild6_out);
+}
+
+void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out) {
+  GPR_ASSERT(port >= 0 && port < 65536);
+  memset(wild_out, 0, sizeof(*wild_out));
+  wild_out->sin_family = AF_INET;
+  wild_out->sin_port = htons((uint16_t)port);
+}
+
+void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out) {
+  GPR_ASSERT(port >= 0 && port < 65536);
+  memset(wild_out, 0, sizeof(*wild_out));
+  wild_out->sin6_family = AF_INET6;
+  wild_out->sin6_port = htons((uint16_t)port);
+}
+
+int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
+                            int normalize) {
+  const int save_errno = errno;
+  struct sockaddr_in addr_normalized;
+  char ntop_buf[INET6_ADDRSTRLEN];
+  const void *ip = NULL;
+  int port;
+  int ret;
+
+  *out = NULL;
+  if (normalize && grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
+    addr = (const struct sockaddr *)&addr_normalized;
+  }
+  if (addr->sa_family == AF_INET) {
+    const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
+    ip = &addr4->sin_addr;
+    port = ntohs(addr4->sin_port);
+  } else if (addr->sa_family == AF_INET6) {
+    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
+    ip = &addr6->sin6_addr;
+    port = ntohs(addr6->sin6_port);
+  }
+  /* Windows inet_ntop wants a mutable ip pointer */
+  if (ip != NULL &&
+      inet_ntop(addr->sa_family, (void *)ip, ntop_buf, sizeof(ntop_buf)) !=
+          NULL) {
+    ret = gpr_join_host_port(out, ntop_buf, port);
+  } else {
+    ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
+  }
+  /* This is probably redundant, but we wouldn't want to log the wrong error. */
+  errno = save_errno;
+  return ret;
+}
+
+char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
+  char *temp;
+  char *result;
+  struct sockaddr_in addr_normalized;
+
+  if (grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
+    addr = (const struct sockaddr *)&addr_normalized;
+  }
+
+  switch (addr->sa_family) {
+    case AF_INET:
+      grpc_sockaddr_to_string(&temp, addr, 0);
+      gpr_asprintf(&result, "ipv4:%s", temp);
+      gpr_free(temp);
+      return result;
+    case AF_INET6:
+      grpc_sockaddr_to_string(&temp, addr, 0);
+      gpr_asprintf(&result, "ipv6:%s", temp);
+      gpr_free(temp);
+      return result;
+    default:
+      return grpc_sockaddr_to_uri_unix_if_possible(addr);
+  }
+}
+
+int grpc_sockaddr_get_port(const struct sockaddr *addr) {
+  switch (addr->sa_family) {
+    case AF_INET:
+      return ntohs(((struct sockaddr_in *)addr)->sin_port);
+    case AF_INET6:
+      return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
+    default:
+      if (grpc_is_unix_socket(addr)) {
+        return 1;
+      }
+      gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
+              addr->sa_family);
+      return 0;
+  }
+}
+
+int grpc_sockaddr_set_port(const struct sockaddr *addr, int port) {
+  switch (addr->sa_family) {
+    case AF_INET:
+      GPR_ASSERT(port >= 0 && port < 65536);
+      ((struct sockaddr_in *)addr)->sin_port = htons((uint16_t)port);
+      return 1;
+    case AF_INET6:
+      GPR_ASSERT(port >= 0 && port < 65536);
+      ((struct sockaddr_in6 *)addr)->sin6_port = htons((uint16_t)port);
+      return 1;
+    default:
+      gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
+              addr->sa_family);
+      return 0;
+  }
+}
diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/iomgr/sockaddr_utils.h
new file mode 100644
index 0000000..9f81992
--- /dev/null
+++ b/src/core/lib/iomgr/sockaddr_utils.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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_SOCKADDR_UTILS_H
+#define GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H
+
+#include "src/core/lib/iomgr/sockaddr.h"
+
+/* Returns true if addr is an IPv4-mapped IPv6 address within the
+   ::ffff:0.0.0.0/96 range, or false otherwise.
+
+   If addr4_out is non-NULL, the inner IPv4 address will be copied here when
+   returning true. */
+int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr,
+                              struct sockaddr_in *addr4_out);
+
+/* If addr is an AF_INET address, writes the corresponding ::ffff:0.0.0.0/96
+   address to addr6_out and returns true.  Otherwise returns false. */
+int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr,
+                              struct sockaddr_in6 *addr6_out);
+
+/* If addr is ::, 0.0.0.0, or ::ffff:0.0.0.0, writes the port number to
+   *port_out (if not NULL) and returns true, otherwise returns false. */
+int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out);
+
+/* Writes 0.0.0.0:port and [::]:port to separate sockaddrs. */
+void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
+                                  struct sockaddr_in6 *wild6_out);
+
+/* Writes 0.0.0.0:port. */
+void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out);
+
+/* Writes [::]:port. */
+void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out);
+
+/* Return the IP port number of a sockaddr */
+int grpc_sockaddr_get_port(const struct sockaddr *addr);
+
+/* Set IP port number of a sockaddr */
+int grpc_sockaddr_set_port(const struct sockaddr *addr, int port);
+
+/* Converts a sockaddr into a newly-allocated human-readable string.
+
+   Currently, only the AF_INET and AF_INET6 families are recognized.
+   If the normalize flag is enabled, ::ffff:0.0.0.0/96 IPv6 addresses are
+   displayed as plain IPv4.
+
+   Usage is similar to gpr_asprintf: returns the number of bytes written
+   (excluding the final '\0'), and *out points to a string which must later be
+   destroyed using gpr_free().
+
+   In the unlikely event of an error, returns -1 and sets *out to NULL.
+   The existing value of errno is always preserved. */
+int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
+                            int normalize);
+
+char *grpc_sockaddr_to_uri(const struct sockaddr *addr);
+
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
diff --git a/src/core/lib/iomgr/sockaddr_win32.h b/src/core/lib/iomgr/sockaddr_win32.h
new file mode 100644
index 0000000..02aeae7
--- /dev/null
+++ b/src/core/lib/iomgr/sockaddr_win32.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * 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_SOCKADDR_WIN32_H
+#define GRPC_CORE_LIB_IOMGR_SOCKADDR_WIN32_H
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+// must be included after the above
+#include <mswsock.h>
+
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_WIN32_H */
diff --git a/src/core/lib/iomgr/socket_utils_common_posix.c b/src/core/lib/iomgr/socket_utils_common_posix.c
new file mode 100644
index 0000000..fa83cee
--- /dev/null
+++ b/src/core/lib/iomgr/socket_utils_common_posix.c
@@ -0,0 +1,230 @@
+/*
+ *
+ * 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_SOCKET
+
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/sync.h>
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/support/string.h"
+
+/* set a socket to non blocking mode */
+int grpc_set_socket_nonblocking(int fd, int non_blocking) {
+  int oldflags = fcntl(fd, F_GETFL, 0);
+  if (oldflags < 0) {
+    return 0;
+  }
+
+  if (non_blocking) {
+    oldflags |= O_NONBLOCK;
+  } else {
+    oldflags &= ~O_NONBLOCK;
+  }
+
+  if (fcntl(fd, F_SETFL, oldflags) != 0) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int grpc_set_socket_no_sigpipe_if_possible(int fd) {
+#ifdef GPR_HAVE_SO_NOSIGPIPE
+  int val = 1;
+  int newval;
+  socklen_t intlen = sizeof(newval);
+  return 0 == setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val)) &&
+         0 == getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen) &&
+         (newval != 0) == val;
+#else
+  return 1;
+#endif
+}
+
+int grpc_set_socket_ip_pktinfo_if_possible(int fd) {
+#ifdef GPR_HAVE_IP_PKTINFO
+  int get_local_ip = 1;
+  return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
+                         sizeof(get_local_ip));
+#else
+  (void)fd;
+  return 1;
+#endif
+}
+
+int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) {
+#ifdef GPR_HAVE_IPV6_RECVPKTINFO
+  int get_local_ip = 1;
+  return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
+                         sizeof(get_local_ip));
+#else
+  (void)fd;
+  return 1;
+#endif
+}
+
+/* set a socket to close on exec */
+int grpc_set_socket_cloexec(int fd, int close_on_exec) {
+  int oldflags = fcntl(fd, F_GETFD, 0);
+  if (oldflags < 0) {
+    return 0;
+  }
+
+  if (close_on_exec) {
+    oldflags |= FD_CLOEXEC;
+  } else {
+    oldflags &= ~FD_CLOEXEC;
+  }
+
+  if (fcntl(fd, F_SETFD, oldflags) != 0) {
+    return 0;
+  }
+
+  return 1;
+}
+
+/* set a socket to reuse old addresses */
+int grpc_set_socket_reuse_addr(int fd, int reuse) {
+  int val = (reuse != 0);
+  int newval;
+  socklen_t intlen = sizeof(newval);
+  return 0 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) &&
+         0 == getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen) &&
+         (newval != 0) == val;
+}
+
+/* disable nagle */
+int grpc_set_socket_low_latency(int fd, int low_latency) {
+  int val = (low_latency != 0);
+  int newval;
+  socklen_t intlen = sizeof(newval);
+  return 0 == setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) &&
+         0 == getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen) &&
+         (newval != 0) == val;
+}
+
+static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
+static int g_ipv6_loopback_available;
+
+static void probe_ipv6_once(void) {
+  int fd = socket(AF_INET6, SOCK_STREAM, 0);
+  g_ipv6_loopback_available = 0;
+  if (fd < 0) {
+    gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed.");
+  } else {
+    struct sockaddr_in6 addr;
+    memset(&addr, 0, sizeof(addr));
+    addr.sin6_family = AF_INET6;
+    addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */
+    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
+      g_ipv6_loopback_available = 1;
+    } else {
+      gpr_log(GPR_INFO,
+              "Disabling AF_INET6 sockets because ::1 is not available.");
+    }
+    close(fd);
+  }
+}
+
+int grpc_ipv6_loopback_available(void) {
+  gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once);
+  return g_ipv6_loopback_available;
+}
+
+/* This should be 0 in production, but it may be enabled for testing or
+   debugging purposes, to simulate an environment where IPv6 sockets can't
+   also speak IPv4. */
+int grpc_forbid_dualstack_sockets_for_testing = 0;
+
+static int set_socket_dualstack(int fd) {
+  if (!grpc_forbid_dualstack_sockets_for_testing) {
+    const int off = 0;
+    return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off));
+  } else {
+    /* Force an IPv6-only socket, for testing purposes. */
+    const int on = 1;
+    setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+    return 0;
+  }
+}
+
+int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
+                                 int protocol, grpc_dualstack_mode *dsmode) {
+  int family = addr->sa_family;
+  if (family == AF_INET6) {
+    int fd;
+    if (grpc_ipv6_loopback_available()) {
+      fd = socket(family, type, protocol);
+    } else {
+      fd = -1;
+      errno = EAFNOSUPPORT;
+    }
+    /* Check if we've got a valid dualstack socket. */
+    if (fd >= 0 && set_socket_dualstack(fd)) {
+      *dsmode = GRPC_DSMODE_DUALSTACK;
+      return fd;
+    }
+    /* If this isn't an IPv4 address, then return whatever we've got. */
+    if (!grpc_sockaddr_is_v4mapped(addr, NULL)) {
+      *dsmode = GRPC_DSMODE_IPV6;
+      return fd;
+    }
+    /* Fall back to AF_INET. */
+    if (fd >= 0) {
+      close(fd);
+    }
+    family = AF_INET;
+  }
+  *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
+  return socket(family, type, protocol);
+}
+
+#endif
diff --git a/src/core/lib/iomgr/socket_utils_linux.c b/src/core/lib/iomgr/socket_utils_linux.c
new file mode 100644
index 0000000..144e311
--- /dev/null
+++ b/src/core/lib/iomgr/socket_utils_linux.c
@@ -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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_LINUX_SOCKETUTILS
+
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+                 int nonblock, int cloexec) {
+  int flags = 0;
+  flags |= nonblock ? SOCK_NONBLOCK : 0;
+  flags |= cloexec ? SOCK_CLOEXEC : 0;
+  return accept4(sockfd, addr, addrlen, flags);
+}
+
+#endif
diff --git a/src/core/lib/iomgr/socket_utils_posix.c b/src/core/lib/iomgr/socket_utils_posix.c
new file mode 100644
index 0000000..57ae64c
--- /dev/null
+++ b/src/core/lib/iomgr/socket_utils_posix.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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_SOCKETUTILS
+
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <grpc/support/log.h>
+
+int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+                 int nonblock, int cloexec) {
+  int fd, flags;
+
+  fd = accept(sockfd, addr, addrlen);
+  if (fd >= 0) {
+    if (nonblock) {
+      flags = fcntl(fd, F_GETFL, 0);
+      if (flags < 0) goto close_and_error;
+      if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) goto close_and_error;
+    }
+    if (cloexec) {
+      flags = fcntl(fd, F_GETFD, 0);
+      if (flags < 0) goto close_and_error;
+      if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != 0) goto close_and_error;
+    }
+  }
+  return fd;
+
+close_and_error:
+  close(fd);
+  return -1;
+}
+
+#endif /* GPR_POSIX_SOCKETUTILS */
diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h
new file mode 100644
index 0000000..a8f6e5e
--- /dev/null
+++ b/src/core/lib/iomgr/socket_utils_posix.h
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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_SOCKET_UTILS_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H
+
+#include <sys/socket.h>
+#include <unistd.h>
+
+/* a wrapper for accept or accept4 */
+int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+                 int nonblock, int cloexec);
+
+/* set a socket to non blocking mode */
+int grpc_set_socket_nonblocking(int fd, int non_blocking);
+
+/* set a socket to close on exec */
+int grpc_set_socket_cloexec(int fd, int close_on_exec);
+
+/* set a socket to reuse old addresses */
+int grpc_set_socket_reuse_addr(int fd, int reuse);
+
+/* disable nagle */
+int grpc_set_socket_low_latency(int fd, int low_latency);
+
+/* Returns true if this system can create AF_INET6 sockets bound to ::1.
+   The value is probed once, and cached for the life of the process.
+
+   This is more restrictive than checking for socket(AF_INET6) to succeed,
+   because Linux with "net.ipv6.conf.all.disable_ipv6 = 1" is able to create
+   and bind IPv6 sockets, but cannot connect to a getsockname() of [::]:port
+   without a valid loopback interface.  Rather than expose this half-broken
+   state to library users, we turn off IPv6 sockets. */
+int grpc_ipv6_loopback_available(void);
+
+/* Tries to set SO_NOSIGPIPE if available on this platform.
+   Returns 1 on success, 0 on failure.
+   If SO_NO_SIGPIPE is not available, returns 1. */
+int grpc_set_socket_no_sigpipe_if_possible(int fd);
+
+/* Tries to set IP_PKTINFO if available on this platform.
+   Returns 1 on success, 0 on failure.
+   If IP_PKTINFO is not available, returns 1. */
+int grpc_set_socket_ip_pktinfo_if_possible(int fd);
+
+/* Tries to set IPV6_RECVPKTINFO if available on this platform.
+   Returns 1 on success, 0 on failure.
+   If IPV6_RECVPKTINFO is not available, returns 1. */
+int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd);
+
+/* An enum to keep track of IPv4/IPv6 socket modes.
+
+   Currently, this information is only used when a socket is first created, but
+   in the future we may wish to store it alongside the fd.  This would let calls
+   like sendto() know which family to use without asking the kernel first. */
+typedef enum grpc_dualstack_mode {
+  /* Uninitialized, or a non-IP socket. */
+  GRPC_DSMODE_NONE,
+  /* AF_INET only. */
+  GRPC_DSMODE_IPV4,
+  /* AF_INET6 only, because IPV6_V6ONLY could not be cleared. */
+  GRPC_DSMODE_IPV6,
+  /* AF_INET6, which also supports ::ffff-mapped IPv4 addresses. */
+  GRPC_DSMODE_DUALSTACK
+} grpc_dualstack_mode;
+
+/* Only tests should use this flag. */
+extern int grpc_forbid_dualstack_sockets_for_testing;
+
+/* Creates a new socket for connecting to (or listening on) an address.
+
+   If addr is AF_INET6, this creates an IPv6 socket first.  If that fails,
+   and addr is within ::ffff:0.0.0.0/96, then it automatically falls back to
+   an IPv4 socket.
+
+   If addr is AF_INET, AF_UNIX, or anything else, then this is similar to
+   calling socket() directly.
+
+   Returns an fd on success, otherwise returns -1 with errno set to the result
+   of a failed socket() call.
+
+   The *dsmode output indicates which address family was actually created.
+   The recommended way to use this is:
+   - First convert to IPv6 using grpc_sockaddr_to_v4mapped().
+   - Create the socket.
+   - If *dsmode is IPV4, use grpc_sockaddr_is_v4mapped() to convert back to
+     IPv4, so that bind() or connect() see the correct family.
+   Also, it's important to distinguish between DUALSTACK and IPV6 when
+   listening on the [::] wildcard address. */
+int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
+                                 int protocol, grpc_dualstack_mode *dsmode);
+
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H */
diff --git a/src/core/lib/iomgr/socket_windows.c b/src/core/lib/iomgr/socket_windows.c
new file mode 100644
index 0000000..ebd77e0
--- /dev/null
+++ b/src/core/lib/iomgr/socket_windows.c
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include <winsock2.h>
+
+// must be included after winsock2.h
+#include <mswsock.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_win32.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/iomgr/iocp_windows.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/pollset_windows.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+
+grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) {
+  char *final_name;
+  grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket));
+  memset(r, 0, sizeof(grpc_winsocket));
+  r->socket = socket;
+  gpr_mu_init(&r->state_mu);
+  gpr_asprintf(&final_name, "%s:socket=0x%p", name, r);
+  grpc_iomgr_register_object(&r->iomgr_object, final_name);
+  gpr_free(final_name);
+  grpc_iocp_add_socket(r);
+  return r;
+}
+
+/* Schedule a shutdown of the socket operations. Will call the pending
+   operations to abort them. We need to do that this way because of the
+   various callsites of that function, which happens to be in various
+   mutex hold states, and that'd be unsafe to call them directly. */
+void grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
+  /* Grab the function pointer for DisconnectEx for that specific socket.
+     It may change depending on the interface. */
+  int status;
+  GUID guid = WSAID_DISCONNECTEX;
+  LPFN_DISCONNECTEX DisconnectEx;
+  DWORD ioctl_num_bytes;
+
+  status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
+                    &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx),
+                    &ioctl_num_bytes, NULL, NULL);
+
+  if (status == 0) {
+    DisconnectEx(winsocket->socket, NULL, 0, 0);
+  } else {
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    gpr_log(GPR_ERROR, "Unable to retrieve DisconnectEx pointer : %s",
+            utf8_message);
+    gpr_free(utf8_message);
+  }
+  closesocket(winsocket->socket);
+}
+
+void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
+  grpc_iomgr_unregister_object(&winsocket->iomgr_object);
+  gpr_mu_destroy(&winsocket->state_mu);
+  gpr_free(winsocket);
+}
+
+#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h
new file mode 100644
index 0000000..73c4384
--- /dev/null
+++ b/src/core/lib/iomgr/socket_windows.h
@@ -0,0 +1,111 @@
+/*
+ *
+ * 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_SOCKET_WINDOWS_H
+#define GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H
+
+#include <grpc/support/port_platform.h>
+#include <winsock2.h>
+
+#include <grpc/support/atm.h>
+#include <grpc/support/sync.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr_internal.h"
+
+/* This holds the data for an outstanding read or write on a socket.
+   The mutex to protect the concurrent access to that data is the one
+   inside the winsocket wrapper. */
+typedef struct grpc_winsocket_callback_info {
+  /* This is supposed to be a WSAOVERLAPPED, but in order to get that
+     definition, we need to include ws2tcpip.h, which needs to be included
+     from the top, otherwise it'll clash with a previous inclusion of
+     windows.h that in turns includes winsock.h. If anyone knows a way
+     to do it properly, feel free to send a patch. */
+  OVERLAPPED overlapped;
+  /* The callback information for the pending operation. May be empty if the
+     caller hasn't registered a callback yet. */
+  grpc_closure *closure;
+  /* A boolean to describe if the IO Completion Port got a notification for
+     that operation. This will happen if the operation completed before the
+     called had time to register a callback. We could avoid that behavior
+     altogether by forcing the caller to always register its callback before
+     proceeding queue an operation, but it is frequent for an IO Completion
+     Port to trigger quickly. This way we avoid a context switch for calling
+     the callback. We also simplify the read / write operations to avoid having
+     to hold a mutex for a long amount of time. */
+  int has_pending_iocp;
+  /* The results of the overlapped operation. */
+  DWORD bytes_transfered;
+  int wsa_error;
+} grpc_winsocket_callback_info;
+
+/* This is a wrapper to a Windows socket. A socket can have one outstanding
+   read, and one outstanding write. Doing an asynchronous accept means waiting
+   for a read operation. Doing an asynchronous connect means waiting for a
+   write operation. These are completely arbitrary ties between the operation
+   and the kind of event, because we can have one overlapped per pending
+   operation, whichever its nature is. So we could have more dedicated pending
+   operation callbacks for connect and listen. But given the scope of listen
+   and accept, we don't need to go to that extent and waste memory. Also, this
+   is closer to what happens in posix world. */
+typedef struct grpc_winsocket {
+  SOCKET socket;
+
+  grpc_winsocket_callback_info write_info;
+  grpc_winsocket_callback_info read_info;
+
+  gpr_mu state_mu;
+
+  /* You can't add the same socket twice to the same IO Completion Port.
+     This prevents that. */
+  int added_to_iocp;
+
+  grpc_closure shutdown_closure;
+
+  /* A label for iomgr to track outstanding objects */
+  grpc_iomgr_object iomgr_object;
+} grpc_winsocket;
+
+/* Create a wrapped windows handle. This takes ownership of it, meaning that
+   it will be responsible for closing it. */
+grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name);
+
+/* Initiate an asynchronous shutdown of the socket. Will call off any pending
+   operation to cancel them. */
+void grpc_winsocket_shutdown(grpc_winsocket *socket);
+
+/* Destroy a socket. Should only be called if there's no pending operation. */
+void grpc_winsocket_destroy(grpc_winsocket *socket);
+
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */
diff --git a/src/core/lib/iomgr/tcp_client.h b/src/core/lib/iomgr/tcp_client.h
new file mode 100644
index 0000000..a07e0b9
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_client.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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_TCP_CLIENT_H
+#define GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H
+
+#include <grpc/support/time.h>
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/pollset_set.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
+/* Asynchronously connect to an address (specified as (addr, len)), and call
+   cb with arg and the completed connection when done (or call cb with arg and
+   NULL on failure).
+   interested_parties points to a set of pollsets that would be interested
+   in this connection being established (in order to continue their work) */
+void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_connect,
+                             grpc_endpoint **endpoint,
+                             grpc_pollset_set *interested_parties,
+                             const struct sockaddr *addr, size_t addr_len,
+                             gpr_timespec deadline);
+
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H */
diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c
new file mode 100644
index 0000000..e93d573
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_client_posix.c
@@ -0,0 +1,321 @@
+/*
+ *
+ * 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_SOCKET
+
+#include "src/core/lib/iomgr/tcp_client.h"
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/iomgr_posix.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/iomgr/tcp_posix.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/support/string.h"
+
+extern int grpc_tcp_trace;
+
+typedef struct {
+  gpr_mu mu;
+  grpc_fd *fd;
+  gpr_timespec deadline;
+  grpc_timer alarm;
+  int refs;
+  grpc_closure write_closure;
+  grpc_pollset_set *interested_parties;
+  char *addr_str;
+  grpc_endpoint **ep;
+  grpc_closure *closure;
+} async_connect;
+
+static int prepare_socket(const struct sockaddr *addr, int fd) {
+  if (fd < 0) {
+    goto error;
+  }
+
+  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
+      (!grpc_is_unix_socket(addr) && !grpc_set_socket_low_latency(fd, 1)) ||
+      !grpc_set_socket_no_sigpipe_if_possible(fd)) {
+    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
+            strerror(errno));
+    goto error;
+  }
+  return 1;
+
+error:
+  if (fd >= 0) {
+    close(fd);
+  }
+  return 0;
+}
+
+static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
+  int done;
+  async_connect *ac = acp;
+  if (grpc_tcp_trace) {
+    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: success=%d", ac->addr_str,
+            success);
+  }
+  gpr_mu_lock(&ac->mu);
+  if (ac->fd != NULL) {
+    grpc_fd_shutdown(exec_ctx, ac->fd);
+  }
+  done = (--ac->refs == 0);
+  gpr_mu_unlock(&ac->mu);
+  if (done) {
+    gpr_mu_destroy(&ac->mu);
+    gpr_free(ac->addr_str);
+    gpr_free(ac);
+  }
+}
+
+static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
+  async_connect *ac = acp;
+  int so_error = 0;
+  socklen_t so_error_size;
+  int err;
+  int done;
+  grpc_endpoint **ep = ac->ep;
+  grpc_closure *closure = ac->closure;
+  grpc_fd *fd;
+
+  if (grpc_tcp_trace) {
+    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: success=%d",
+            ac->addr_str, success);
+  }
+
+  gpr_mu_lock(&ac->mu);
+  GPR_ASSERT(ac->fd);
+  fd = ac->fd;
+  ac->fd = NULL;
+  gpr_mu_unlock(&ac->mu);
+
+  grpc_timer_cancel(exec_ctx, &ac->alarm);
+
+  gpr_mu_lock(&ac->mu);
+  if (success) {
+    do {
+      so_error_size = sizeof(so_error);
+      err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error,
+                       &so_error_size);
+    } while (err < 0 && errno == EINTR);
+    if (err < 0) {
+      gpr_log(GPR_ERROR, "failed to connect to '%s': getsockopt(ERROR): %s",
+              ac->addr_str, strerror(errno));
+      goto finish;
+    } else if (so_error != 0) {
+      if (so_error == ENOBUFS) {
+        /* We will get one of these errors if we have run out of
+           memory in the kernel for the data structures allocated
+           when you connect a socket.  If this happens it is very
+           likely that if we wait a little bit then try again the
+           connection will work (since other programs or this
+           program will close their network connections and free up
+           memory).  This does _not_ indicate that there is anything
+           wrong with the server we are connecting to, this is a
+           local problem.
+
+           If you are looking at this code, then chances are that
+           your program or another program on the same computer
+           opened too many network connections.  The "easy" fix:
+           don't do that! */
+        gpr_log(GPR_ERROR, "kernel out of buffers");
+        gpr_mu_unlock(&ac->mu);
+        grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure);
+        return;
+      } else {
+        switch (so_error) {
+          case ECONNREFUSED:
+            gpr_log(
+                GPR_ERROR,
+                "failed to connect to '%s': socket error: connection refused",
+                ac->addr_str);
+            break;
+          default:
+            gpr_log(GPR_ERROR, "failed to connect to '%s': socket error: %d",
+                    ac->addr_str, so_error);
+            break;
+        }
+        goto finish;
+      }
+    } else {
+      grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
+      *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
+      fd = NULL;
+      goto finish;
+    }
+  } else {
+    gpr_log(GPR_ERROR, "failed to connect to '%s': timeout occurred",
+            ac->addr_str);
+    goto finish;
+  }
+
+  GPR_UNREACHABLE_CODE(return );
+
+finish:
+  if (fd != NULL) {
+    grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
+    grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
+    fd = NULL;
+  }
+  done = (--ac->refs == 0);
+  gpr_mu_unlock(&ac->mu);
+  if (done) {
+    gpr_mu_destroy(&ac->mu);
+    gpr_free(ac->addr_str);
+    gpr_free(ac);
+  }
+  grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL);
+}
+
+static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
+                                    grpc_closure *closure, grpc_endpoint **ep,
+                                    grpc_pollset_set *interested_parties,
+                                    const struct sockaddr *addr,
+                                    size_t addr_len, gpr_timespec deadline) {
+  int fd;
+  grpc_dualstack_mode dsmode;
+  int err;
+  async_connect *ac;
+  struct sockaddr_in6 addr6_v4mapped;
+  struct sockaddr_in addr4_copy;
+  grpc_fd *fdobj;
+  char *name;
+  char *addr_str;
+
+  *ep = NULL;
+
+  /* Use dualstack sockets where available. */
+  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
+    addr = (const struct sockaddr *)&addr6_v4mapped;
+    addr_len = sizeof(addr6_v4mapped);
+  }
+
+  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
+  if (fd < 0) {
+    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
+  }
+  if (dsmode == GRPC_DSMODE_IPV4) {
+    /* If we got an AF_INET socket, map the address back to IPv4. */
+    GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
+    addr = (struct sockaddr *)&addr4_copy;
+    addr_len = sizeof(addr4_copy);
+  }
+  if (!prepare_socket(addr, fd)) {
+    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+    return;
+  }
+
+  do {
+    GPR_ASSERT(addr_len < ~(socklen_t)0);
+    err = connect(fd, addr, (socklen_t)addr_len);
+  } while (err < 0 && errno == EINTR);
+
+  addr_str = grpc_sockaddr_to_uri(addr);
+  gpr_asprintf(&name, "tcp-client:%s", addr_str);
+
+  fdobj = grpc_fd_create(fd, name);
+
+  if (err >= 0) {
+    *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
+    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+    goto done;
+  }
+
+  if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
+    gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
+    grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
+    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+    goto done;
+  }
+
+  grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);
+
+  ac = gpr_malloc(sizeof(async_connect));
+  ac->closure = closure;
+  ac->ep = ep;
+  ac->fd = fdobj;
+  ac->interested_parties = interested_parties;
+  ac->addr_str = addr_str;
+  addr_str = NULL;
+  gpr_mu_init(&ac->mu);
+  ac->refs = 2;
+  ac->write_closure.cb = on_writable;
+  ac->write_closure.cb_arg = ac;
+
+  if (grpc_tcp_trace) {
+    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
+            ac->addr_str);
+  }
+
+  gpr_mu_lock(&ac->mu);
+  grpc_timer_init(exec_ctx, &ac->alarm,
+                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
+                  tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
+  grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
+  gpr_mu_unlock(&ac->mu);
+
+done:
+  gpr_free(name);
+  gpr_free(addr_str);
+}
+
+// overridden by api_fuzzer.c
+void (*grpc_tcp_client_connect_impl)(
+    grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
+    grpc_pollset_set *interested_parties, const struct sockaddr *addr,
+    size_t addr_len, gpr_timespec deadline) = tcp_client_connect_impl;
+
+void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                             grpc_endpoint **ep,
+                             grpc_pollset_set *interested_parties,
+                             const struct sockaddr *addr, size_t addr_len,
+                             gpr_timespec deadline) {
+  grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, addr,
+                               addr_len, deadline);
+}
+
+#endif
diff --git a/src/core/lib/iomgr/tcp_client_windows.c b/src/core/lib/iomgr/tcp_client_windows.c
new file mode 100644
index 0000000..7d78beb
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_client_windows.c
@@ -0,0 +1,222 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include "src/core/lib/iomgr/sockaddr_win32.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_win32.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/iomgr/iocp_windows.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+#include "src/core/lib/iomgr/tcp_client.h"
+#include "src/core/lib/iomgr/tcp_windows.h"
+#include "src/core/lib/iomgr/timer.h"
+
+typedef struct {
+  grpc_closure *on_done;
+  gpr_mu mu;
+  grpc_winsocket *socket;
+  gpr_timespec deadline;
+  grpc_timer alarm;
+  char *addr_name;
+  int refs;
+  grpc_closure on_connect;
+  grpc_endpoint **endpoint;
+} async_connect;
+
+static void async_connect_unlock_and_cleanup(async_connect *ac) {
+  int done = (--ac->refs == 0);
+  gpr_mu_unlock(&ac->mu);
+  if (done) {
+    if (ac->socket != NULL) grpc_winsocket_destroy(ac->socket);
+    gpr_mu_destroy(&ac->mu);
+    gpr_free(ac->addr_name);
+    gpr_free(ac);
+  }
+}
+
+static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool occured) {
+  async_connect *ac = acp;
+  gpr_mu_lock(&ac->mu);
+  /* If the alarm didn't occur, it got cancelled. */
+  if (ac->socket != NULL && occured) {
+    grpc_winsocket_shutdown(ac->socket);
+  }
+  async_connect_unlock_and_cleanup(ac);
+}
+
+static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, bool from_iocp) {
+  async_connect *ac = acp;
+  SOCKET sock = ac->socket->socket;
+  grpc_endpoint **ep = ac->endpoint;
+  grpc_winsocket_callback_info *info = &ac->socket->write_info;
+  grpc_closure *on_done = ac->on_done;
+
+  grpc_timer_cancel(exec_ctx, &ac->alarm);
+
+  gpr_mu_lock(&ac->mu);
+
+  if (from_iocp) {
+    DWORD transfered_bytes = 0;
+    DWORD flags;
+    BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
+                                              &transfered_bytes, FALSE, &flags);
+    GPR_ASSERT(transfered_bytes == 0);
+    if (!wsa_success) {
+      char *utf8_message = gpr_format_message(WSAGetLastError());
+      gpr_log(GPR_ERROR, "on_connect error connecting to '%s': %s",
+              ac->addr_name, utf8_message);
+      gpr_free(utf8_message);
+    } else {
+      *ep = grpc_tcp_create(ac->socket, ac->addr_name);
+      ac->socket = NULL;
+    }
+  }
+
+  async_connect_unlock_and_cleanup(ac);
+  /* If the connection was aborted, the callback was already called when
+     the deadline was met. */
+  on_done->cb(exec_ctx, on_done->cb_arg, *ep != NULL);
+}
+
+/* Tries to issue one async connection, then schedules both an IOCP
+   notification request for the connection, and one timeout alert. */
+void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
+                             grpc_endpoint **endpoint,
+                             grpc_pollset_set *interested_parties,
+                             const struct sockaddr *addr, size_t addr_len,
+                             gpr_timespec deadline) {
+  SOCKET sock = INVALID_SOCKET;
+  BOOL success;
+  int status;
+  struct sockaddr_in6 addr6_v4mapped;
+  struct sockaddr_in6 local_address;
+  async_connect *ac;
+  grpc_winsocket *socket = NULL;
+  LPFN_CONNECTEX ConnectEx;
+  GUID guid = WSAID_CONNECTEX;
+  DWORD ioctl_num_bytes;
+  const char *message = NULL;
+  char *utf8_message;
+  grpc_winsocket_callback_info *info;
+
+  *endpoint = NULL;
+
+  /* Use dualstack sockets where available. */
+  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
+    addr = (const struct sockaddr *)&addr6_v4mapped;
+    addr_len = sizeof(addr6_v4mapped);
+  }
+
+  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
+                   WSA_FLAG_OVERLAPPED);
+  if (sock == INVALID_SOCKET) {
+    message = "Unable to create socket: %s";
+    goto failure;
+  }
+
+  if (!grpc_tcp_prepare_socket(sock)) {
+    message = "Unable to set socket options: %s";
+    goto failure;
+  }
+
+  /* Grab the function pointer for ConnectEx for that specific socket.
+     It may change depending on the interface. */
+  status =
+      WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
+               &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, NULL, NULL);
+
+  if (status != 0) {
+    message = "Unable to retrieve ConnectEx pointer: %s";
+    goto failure;
+  }
+
+  grpc_sockaddr_make_wildcard6(0, &local_address);
+
+  status = bind(sock, (struct sockaddr *)&local_address, sizeof(local_address));
+  if (status != 0) {
+    message = "Unable to bind socket: %s";
+    goto failure;
+  }
+
+  socket = grpc_winsocket_create(sock, "client");
+  info = &socket->write_info;
+  success =
+      ConnectEx(sock, addr, (int)addr_len, NULL, 0, NULL, &info->overlapped);
+
+  /* It wouldn't be unusual to get a success immediately. But we'll still get
+     an IOCP notification, so let's ignore it. */
+  if (!success) {
+    int error = WSAGetLastError();
+    if (error != ERROR_IO_PENDING) {
+      message = "ConnectEx failed: %s";
+      goto failure;
+    }
+  }
+
+  ac = gpr_malloc(sizeof(async_connect));
+  ac->on_done = on_done;
+  ac->socket = socket;
+  gpr_mu_init(&ac->mu);
+  ac->refs = 2;
+  ac->addr_name = grpc_sockaddr_to_uri(addr);
+  ac->endpoint = endpoint;
+  grpc_closure_init(&ac->on_connect, on_connect, ac);
+
+  grpc_timer_init(exec_ctx, &ac->alarm, deadline, on_alarm, ac,
+                  gpr_now(GPR_CLOCK_MONOTONIC));
+  grpc_socket_notify_on_write(exec_ctx, socket, &ac->on_connect);
+  return;
+
+failure:
+  utf8_message = gpr_format_message(WSAGetLastError());
+  gpr_log(GPR_ERROR, message, utf8_message);
+  gpr_free(utf8_message);
+  if (socket != NULL) {
+    grpc_winsocket_destroy(socket);
+  } else if (sock != INVALID_SOCKET) {
+    closesocket(sock);
+  }
+  grpc_exec_ctx_enqueue(exec_ctx, on_done, false, NULL);
+}
+
+#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c
new file mode 100644
index 0000000..7210aef
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_posix.c
@@ -0,0 +1,492 @@
+/*
+ *
+ * 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_SOCKET
+
+#include "src/core/lib/iomgr/tcp_posix.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+
+#ifdef GPR_HAVE_MSG_NOSIGNAL
+#define SENDMSG_FLAGS MSG_NOSIGNAL
+#else
+#define SENDMSG_FLAGS 0
+#endif
+
+#ifdef GPR_MSG_IOVLEN_TYPE
+typedef GPR_MSG_IOVLEN_TYPE msg_iovlen_type;
+#else
+typedef size_t msg_iovlen_type;
+#endif
+
+int grpc_tcp_trace = 0;
+
+typedef struct {
+  grpc_endpoint base;
+  grpc_fd *em_fd;
+  int fd;
+  int finished_edge;
+  msg_iovlen_type iov_size; /* Number of slices to allocate per read attempt */
+  size_t slice_size;
+  gpr_refcount refcount;
+
+  /* garbage after the last read */
+  gpr_slice_buffer last_read_buffer;
+
+  gpr_slice_buffer *incoming_buffer;
+  gpr_slice_buffer *outgoing_buffer;
+  /** slice within outgoing_buffer to write next */
+  size_t outgoing_slice_idx;
+  /** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */
+  size_t outgoing_byte_idx;
+
+  grpc_closure *read_cb;
+  grpc_closure *write_cb;
+  grpc_closure *release_fd_cb;
+  int *release_fd;
+
+  grpc_closure read_closure;
+  grpc_closure write_closure;
+
+  char *peer_string;
+} grpc_tcp;
+
+static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
+                            bool success);
+static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
+                             bool success);
+
+static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  grpc_fd_shutdown(exec_ctx, tcp->em_fd);
+}
+
+static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
+  grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd,
+                 "tcp_unref_orphan");
+  gpr_slice_buffer_destroy(&tcp->last_read_buffer);
+  gpr_free(tcp->peer_string);
+  gpr_free(tcp);
+}
+
+/*#define GRPC_TCP_REFCOUNT_DEBUG*/
+#ifdef GRPC_TCP_REFCOUNT_DEBUG
+#define TCP_UNREF(cl, tcp, reason) \
+  tcp_unref((cl), (tcp), (reason), __FILE__, __LINE__)
+#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
+static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
+                      const char *reason, const char *file, int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
+          reason, tcp->refcount.count, tcp->refcount.count - 1);
+  if (gpr_unref(&tcp->refcount)) {
+    tcp_free(exec_ctx, tcp);
+  }
+}
+
+static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
+                    int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP   ref %p : %s %d -> %d", tcp,
+          reason, tcp->refcount.count, tcp->refcount.count + 1);
+  gpr_ref(&tcp->refcount);
+}
+#else
+#define TCP_UNREF(cl, tcp, reason) tcp_unref((cl), (tcp))
+#define TCP_REF(tcp, reason) tcp_ref((tcp))
+static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
+  if (gpr_unref(&tcp->refcount)) {
+    tcp_free(exec_ctx, tcp);
+  }
+}
+
+static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
+#endif
+
+static void tcp_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  TCP_UNREF(exec_ctx, tcp, "destroy");
+}
+
+static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, int success) {
+  grpc_closure *cb = tcp->read_cb;
+
+  if (grpc_tcp_trace) {
+    size_t i;
+    gpr_log(GPR_DEBUG, "read: success=%d", success);
+    for (i = 0; i < tcp->incoming_buffer->count; i++) {
+      char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i],
+                                  GPR_DUMP_HEX | GPR_DUMP_ASCII);
+      gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump);
+      gpr_free(dump);
+    }
+  }
+
+  tcp->read_cb = NULL;
+  tcp->incoming_buffer = NULL;
+  cb->cb(exec_ctx, cb->cb_arg, success);
+}
+
+#define MAX_READ_IOVEC 4
+static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
+  struct msghdr msg;
+  struct iovec iov[MAX_READ_IOVEC];
+  ssize_t read_bytes;
+  size_t i;
+
+  GPR_ASSERT(!tcp->finished_edge);
+  GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC);
+  GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC);
+  GPR_TIMER_BEGIN("tcp_continue_read", 0);
+
+  while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) {
+    gpr_slice_buffer_add_indexed(tcp->incoming_buffer,
+                                 gpr_slice_malloc(tcp->slice_size));
+  }
+  for (i = 0; i < tcp->incoming_buffer->count; i++) {
+    iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]);
+    iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]);
+  }
+
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_iov = iov;
+  msg.msg_iovlen = tcp->iov_size;
+  msg.msg_control = NULL;
+  msg.msg_controllen = 0;
+  msg.msg_flags = 0;
+
+  GPR_TIMER_BEGIN("recvmsg", 1);
+  do {
+    read_bytes = recvmsg(tcp->fd, &msg, 0);
+  } while (read_bytes < 0 && errno == EINTR);
+  GPR_TIMER_END("recvmsg", 0);
+
+  if (read_bytes < 0) {
+    /* NB: After calling call_read_cb a parallel call of the read handler may
+     * be running. */
+    if (errno == EAGAIN) {
+      if (tcp->iov_size > 1) {
+        tcp->iov_size /= 2;
+      }
+      /* We've consumed the edge, request a new one */
+      grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
+    } else {
+      /* TODO(klempner): Log interesting errors */
+      gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
+      call_read_cb(exec_ctx, tcp, 0);
+      TCP_UNREF(exec_ctx, tcp, "read");
+    }
+  } else if (read_bytes == 0) {
+    /* 0 read size ==> end of stream */
+    gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
+    call_read_cb(exec_ctx, tcp, 0);
+    TCP_UNREF(exec_ctx, tcp, "read");
+  } else {
+    GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length);
+    if ((size_t)read_bytes < tcp->incoming_buffer->length) {
+      gpr_slice_buffer_trim_end(
+          tcp->incoming_buffer,
+          tcp->incoming_buffer->length - (size_t)read_bytes,
+          &tcp->last_read_buffer);
+    } else if (tcp->iov_size < MAX_READ_IOVEC) {
+      ++tcp->iov_size;
+    }
+    GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length);
+    call_read_cb(exec_ctx, tcp, 1);
+    TCP_UNREF(exec_ctx, tcp, "read");
+  }
+
+  GPR_TIMER_END("tcp_continue_read", 0);
+}
+
+static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
+                            bool success) {
+  grpc_tcp *tcp = (grpc_tcp *)arg;
+  GPR_ASSERT(!tcp->finished_edge);
+
+  if (!success) {
+    gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
+    call_read_cb(exec_ctx, tcp, 0);
+    TCP_UNREF(exec_ctx, tcp, "read");
+  } else {
+    tcp_continue_read(exec_ctx, tcp);
+  }
+}
+
+static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                     gpr_slice_buffer *incoming_buffer, grpc_closure *cb) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  GPR_ASSERT(tcp->read_cb == NULL);
+  tcp->read_cb = cb;
+  tcp->incoming_buffer = incoming_buffer;
+  gpr_slice_buffer_reset_and_unref(incoming_buffer);
+  gpr_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer);
+  TCP_REF(tcp, "read");
+  if (tcp->finished_edge) {
+    tcp->finished_edge = 0;
+    grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
+  } else {
+    grpc_exec_ctx_enqueue(exec_ctx, &tcp->read_closure, true, NULL);
+  }
+}
+
+typedef enum { FLUSH_DONE, FLUSH_PENDING, FLUSH_ERROR } flush_result;
+
+#define MAX_WRITE_IOVEC 16
+static flush_result tcp_flush(grpc_tcp *tcp) {
+  struct msghdr msg;
+  struct iovec iov[MAX_WRITE_IOVEC];
+  msg_iovlen_type iov_size;
+  ssize_t sent_length;
+  size_t sending_length;
+  size_t trailing;
+  size_t unwind_slice_idx;
+  size_t unwind_byte_idx;
+
+  for (;;) {
+    sending_length = 0;
+    unwind_slice_idx = tcp->outgoing_slice_idx;
+    unwind_byte_idx = tcp->outgoing_byte_idx;
+    for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count &&
+                       iov_size != MAX_WRITE_IOVEC;
+         iov_size++) {
+      iov[iov_size].iov_base =
+          GPR_SLICE_START_PTR(
+              tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) +
+          tcp->outgoing_byte_idx;
+      iov[iov_size].iov_len =
+          GPR_SLICE_LENGTH(
+              tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) -
+          tcp->outgoing_byte_idx;
+      sending_length += iov[iov_size].iov_len;
+      tcp->outgoing_slice_idx++;
+      tcp->outgoing_byte_idx = 0;
+    }
+    GPR_ASSERT(iov_size > 0);
+
+    msg.msg_name = NULL;
+    msg.msg_namelen = 0;
+    msg.msg_iov = iov;
+    msg.msg_iovlen = iov_size;
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    msg.msg_flags = 0;
+
+    GPR_TIMER_BEGIN("sendmsg", 1);
+    do {
+      /* TODO(klempner): Cork if this is a partial write */
+      sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS);
+    } while (sent_length < 0 && errno == EINTR);
+    GPR_TIMER_END("sendmsg", 0);
+
+    if (sent_length < 0) {
+      if (errno == EAGAIN) {
+        tcp->outgoing_slice_idx = unwind_slice_idx;
+        tcp->outgoing_byte_idx = unwind_byte_idx;
+        return FLUSH_PENDING;
+      } else {
+        /* TODO(klempner): Log some of these */
+        return FLUSH_ERROR;
+      }
+    }
+
+    GPR_ASSERT(tcp->outgoing_byte_idx == 0);
+    trailing = sending_length - (size_t)sent_length;
+    while (trailing > 0) {
+      size_t slice_length;
+
+      tcp->outgoing_slice_idx--;
+      slice_length = GPR_SLICE_LENGTH(
+          tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]);
+      if (slice_length > trailing) {
+        tcp->outgoing_byte_idx = slice_length - trailing;
+        break;
+      } else {
+        trailing -= slice_length;
+      }
+    }
+
+    if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) {
+      return FLUSH_DONE;
+    }
+  };
+}
+
+static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
+                             bool success) {
+  grpc_tcp *tcp = (grpc_tcp *)arg;
+  flush_result status;
+  grpc_closure *cb;
+
+  if (!success) {
+    cb = tcp->write_cb;
+    tcp->write_cb = NULL;
+    cb->cb(exec_ctx, cb->cb_arg, 0);
+    TCP_UNREF(exec_ctx, tcp, "write");
+    return;
+  }
+
+  status = tcp_flush(tcp);
+  if (status == FLUSH_PENDING) {
+    grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
+  } else {
+    cb = tcp->write_cb;
+    tcp->write_cb = NULL;
+    GPR_TIMER_BEGIN("tcp_handle_write.cb", 0);
+    cb->cb(exec_ctx, cb->cb_arg, status == FLUSH_DONE);
+    GPR_TIMER_END("tcp_handle_write.cb", 0);
+    TCP_UNREF(exec_ctx, tcp, "write");
+  }
+}
+
+static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                      gpr_slice_buffer *buf, grpc_closure *cb) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  flush_result status;
+
+  if (grpc_tcp_trace) {
+    size_t i;
+
+    for (i = 0; i < buf->count; i++) {
+      char *data =
+          gpr_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
+      gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data);
+      gpr_free(data);
+    }
+  }
+
+  GPR_TIMER_BEGIN("tcp_write", 0);
+  GPR_ASSERT(tcp->write_cb == NULL);
+
+  if (buf->length == 0) {
+    GPR_TIMER_END("tcp_write", 0);
+    grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+    return;
+  }
+  tcp->outgoing_buffer = buf;
+  tcp->outgoing_slice_idx = 0;
+  tcp->outgoing_byte_idx = 0;
+
+  status = tcp_flush(tcp);
+  if (status == FLUSH_PENDING) {
+    TCP_REF(tcp, "write");
+    tcp->write_cb = cb;
+    grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
+  } else {
+    grpc_exec_ctx_enqueue(exec_ctx, cb, status == FLUSH_DONE, NULL);
+  }
+
+  GPR_TIMER_END("tcp_write", 0);
+}
+
+static void tcp_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                               grpc_pollset *pollset) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  grpc_pollset_add_fd(exec_ctx, pollset, tcp->em_fd);
+}
+
+static void tcp_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                   grpc_pollset_set *pollset_set) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  grpc_pollset_set_add_fd(exec_ctx, pollset_set, tcp->em_fd);
+}
+
+static char *tcp_get_peer(grpc_endpoint *ep) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  return gpr_strdup(tcp->peer_string);
+}
+
+static const grpc_endpoint_vtable vtable = {
+    tcp_read,     tcp_write,   tcp_add_to_pollset, tcp_add_to_pollset_set,
+    tcp_shutdown, tcp_destroy, tcp_get_peer};
+
+grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
+                               const char *peer_string) {
+  grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
+  tcp->base.vtable = &vtable;
+  tcp->peer_string = gpr_strdup(peer_string);
+  tcp->fd = grpc_fd_wrapped_fd(em_fd);
+  tcp->read_cb = NULL;
+  tcp->write_cb = NULL;
+  tcp->release_fd_cb = NULL;
+  tcp->release_fd = NULL;
+  tcp->incoming_buffer = NULL;
+  tcp->slice_size = slice_size;
+  tcp->iov_size = 1;
+  tcp->finished_edge = 1;
+  /* paired with unref in grpc_tcp_destroy */
+  gpr_ref_init(&tcp->refcount, 1);
+  tcp->em_fd = em_fd;
+  tcp->read_closure.cb = tcp_handle_read;
+  tcp->read_closure.cb_arg = tcp;
+  tcp->write_closure.cb = tcp_handle_write;
+  tcp->write_closure.cb_arg = tcp;
+  gpr_slice_buffer_init(&tcp->last_read_buffer);
+
+  return &tcp->base;
+}
+
+int grpc_tcp_fd(grpc_endpoint *ep) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  GPR_ASSERT(ep->vtable == &vtable);
+  return grpc_fd_wrapped_fd(tcp->em_fd);
+}
+
+void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                     int *fd, grpc_closure *done) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  GPR_ASSERT(ep->vtable == &vtable);
+  tcp->release_fd = fd;
+  tcp->release_fd_cb = done;
+  TCP_UNREF(exec_ctx, tcp, "destroy");
+}
+
+#endif
diff --git a/src/core/lib/iomgr/tcp_posix.h b/src/core/lib/iomgr/tcp_posix.h
new file mode 100644
index 0000000..9912583
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_posix.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * 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_TCP_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_TCP_POSIX_H
+/*
+   Low level TCP "bottom half" implementation, for use by transports built on
+   top of a TCP connection.
+
+   Note that this file does not (yet) include APIs for creating the socket in
+   the first place.
+
+   All calls passing slice transfer ownership of a slice refcount unless
+   otherwise specified.
+*/
+
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/ev_posix.h"
+
+#define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192
+
+extern int grpc_tcp_trace;
+
+/* Create a tcp endpoint given a file desciptor and a read slice size.
+   Takes ownership of fd. */
+grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size,
+                               const char *peer_string);
+
+/* Return the tcp endpoint's fd, or -1 if this is not available. Does not
+   release the fd.
+   Requires: ep must be a tcp endpoint.
+ */
+int grpc_tcp_fd(grpc_endpoint *ep);
+
+/* Destroy the tcp endpoint without closing its fd. *fd will be set and done
+ * will be called when the endpoint is destroyed.
+ * Requires: ep must be a tcp endpoint and fd must not be NULL. */
+void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                     int *fd, grpc_closure *done);
+
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_POSIX_H */
diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h
new file mode 100644
index 0000000..99b9f29
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_server.h
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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_TCP_SERVER_H
+#define GRPC_CORE_LIB_IOMGR_TCP_SERVER_H
+
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/endpoint.h"
+
+/* Forward decl of grpc_tcp_server */
+typedef struct grpc_tcp_server grpc_tcp_server;
+
+typedef struct grpc_tcp_server_acceptor {
+  /* grpc_tcp_server_cb functions share a ref on from_server that is valid
+     until the function returns. */
+  grpc_tcp_server *from_server;
+  /* Indices that may be passed to grpc_tcp_server_port_fd(). */
+  unsigned port_index;
+  unsigned fd_index;
+} grpc_tcp_server_acceptor;
+
+/* Called for newly connected TCP connections. */
+typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg,
+                                   grpc_endpoint *ep,
+                                   grpc_tcp_server_acceptor *acceptor);
+
+/* Create a server, initially not bound to any ports. The caller owns one ref.
+   If shutdown_complete is not NULL, it will be used by
+   grpc_tcp_server_unref() when the ref count reaches zero. */
+grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete);
+
+/* Start listening to bound ports */
+void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
+                           grpc_pollset **pollsets, size_t pollset_count,
+                           grpc_tcp_server_cb on_accept_cb, void *cb_arg);
+
+/* Add a port to the server, returning the newly allocated port on success, or
+   -1 on failure.
+
+   The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
+   both IPv4 and IPv6 connections, but :: is the preferred style.  This usually
+   creates one socket, but possibly two on systems which support IPv6,
+   but not dualstack sockets. */
+/* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
+                  all of the multiple socket port matching logic in one place */
+int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
+                             size_t addr_len);
+
+/* Number of fds at the given port_index, or 0 if port_index is out of
+   bounds. */
+unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, unsigned port_index);
+
+/* Returns the file descriptor of the Mth (fd_index) listening socket of the Nth
+   (port_index) call to add_port() on this server, or -1 if the indices are out
+   of bounds. The file descriptor remains owned by the server, and will be
+   cleaned up when the ref count reaches zero. */
+int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
+                            unsigned fd_index);
+
+/* Ref s and return s. */
+grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s);
+
+/* shutdown_starting is called when ref count has reached zero and the server is
+   about to be destroyed. The server will be deleted after it returns. Calling
+   grpc_tcp_server_ref() from it has no effect. */
+void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
+                                           grpc_closure *shutdown_starting);
+
+/* If the refcount drops to zero, delete s, and call (exec_ctx==NULL) or enqueue
+   a call (exec_ctx!=NULL) to shutdown_complete. */
+void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s);
+
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_H */
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
new file mode 100644
index 0000000..aaeb384
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -0,0 +1,606 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_SOCKET
+
+#include "src/core/lib/iomgr/tcp_server.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.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>
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/iomgr/tcp_posix.h"
+#include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/support/string.h"
+
+#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
+
+static gpr_once s_init_max_accept_queue_size;
+static int s_max_accept_queue_size;
+
+/* one listening port */
+typedef struct grpc_tcp_listener grpc_tcp_listener;
+struct grpc_tcp_listener {
+  int fd;
+  grpc_fd *emfd;
+  grpc_tcp_server *server;
+  union {
+    uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE];
+    struct sockaddr sockaddr;
+  } addr;
+  size_t addr_len;
+  int port;
+  unsigned port_index;
+  unsigned fd_index;
+  grpc_closure read_closure;
+  grpc_closure destroyed_closure;
+  struct grpc_tcp_listener *next;
+  /* When we add a listener, more than one can be created, mainly because of
+     IPv6. A sibling will still be in the normal list, but will be flagged
+     as such. Any action, such as ref or unref, will affect all of the
+     siblings in the list. */
+  struct grpc_tcp_listener *sibling;
+  int is_sibling;
+};
+
+/* the overall server */
+struct grpc_tcp_server {
+  gpr_refcount refs;
+  /* Called whenever accept() succeeds on a server port. */
+  grpc_tcp_server_cb on_accept_cb;
+  void *on_accept_cb_arg;
+
+  gpr_mu mu;
+
+  /* active port count: how many ports are actually still listening */
+  size_t active_ports;
+  /* destroyed port count: how many ports are completely destroyed */
+  size_t destroyed_ports;
+
+  /* is this server shutting down? (boolean) */
+  int shutdown;
+
+  /* linked list of server ports */
+  grpc_tcp_listener *head;
+  grpc_tcp_listener *tail;
+  unsigned nports;
+
+  /* List of closures passed to shutdown_starting_add(). */
+  grpc_closure_list shutdown_starting;
+
+  /* shutdown callback */
+  grpc_closure *shutdown_complete;
+
+  /* all pollsets interested in new connections */
+  grpc_pollset **pollsets;
+  /* number of pollsets in the pollsets array */
+  size_t pollset_count;
+};
+
+grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
+  grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
+  gpr_ref_init(&s->refs, 1);
+  gpr_mu_init(&s->mu);
+  s->active_ports = 0;
+  s->destroyed_ports = 0;
+  s->shutdown = 0;
+  s->shutdown_starting.head = NULL;
+  s->shutdown_starting.tail = NULL;
+  s->shutdown_complete = shutdown_complete;
+  s->on_accept_cb = NULL;
+  s->on_accept_cb_arg = NULL;
+  s->head = NULL;
+  s->tail = NULL;
+  s->nports = 0;
+  return s;
+}
+
+static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  if (s->shutdown_complete != NULL) {
+    grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL);
+  }
+
+  gpr_mu_destroy(&s->mu);
+
+  while (s->head) {
+    grpc_tcp_listener *sp = s->head;
+    s->head = sp->next;
+    gpr_free(sp);
+  }
+
+  gpr_free(s);
+}
+
+static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
+                           bool success) {
+  grpc_tcp_server *s = server;
+  gpr_mu_lock(&s->mu);
+  s->destroyed_ports++;
+  if (s->destroyed_ports == s->nports) {
+    gpr_mu_unlock(&s->mu);
+    finish_shutdown(exec_ctx, s);
+  } else {
+    GPR_ASSERT(s->destroyed_ports < s->nports);
+    gpr_mu_unlock(&s->mu);
+  }
+}
+
+/* called when all listening endpoints have been shutdown, so no further
+   events will be received on them - at this point it's safe to destroy
+   things */
+static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  /* delete ALL the things */
+  gpr_mu_lock(&s->mu);
+
+  if (!s->shutdown) {
+    gpr_mu_unlock(&s->mu);
+    return;
+  }
+
+  if (s->head) {
+    grpc_tcp_listener *sp;
+    for (sp = s->head; sp; sp = sp->next) {
+      grpc_unlink_if_unix_domain_socket(&sp->addr.sockaddr);
+      sp->destroyed_closure.cb = destroyed_port;
+      sp->destroyed_closure.cb_arg = s;
+      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
+                     "tcp_listener_shutdown");
+    }
+    gpr_mu_unlock(&s->mu);
+  } else {
+    gpr_mu_unlock(&s->mu);
+    finish_shutdown(exec_ctx, s);
+  }
+}
+
+static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  gpr_mu_lock(&s->mu);
+
+  GPR_ASSERT(!s->shutdown);
+  s->shutdown = 1;
+
+  /* shutdown all fd's */
+  if (s->active_ports) {
+    grpc_tcp_listener *sp;
+    for (sp = s->head; sp; sp = sp->next) {
+      grpc_fd_shutdown(exec_ctx, sp->emfd);
+    }
+    gpr_mu_unlock(&s->mu);
+  } else {
+    gpr_mu_unlock(&s->mu);
+    deactivated_all_ports(exec_ctx, s);
+  }
+}
+
+/* get max listen queue size on linux */
+static void init_max_accept_queue_size(void) {
+  int n = SOMAXCONN;
+  char buf[64];
+  FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
+  if (fp == NULL) {
+    /* 2.4 kernel. */
+    s_max_accept_queue_size = SOMAXCONN;
+    return;
+  }
+  if (fgets(buf, sizeof buf, fp)) {
+    char *end;
+    long i = strtol(buf, &end, 10);
+    if (i > 0 && i <= INT_MAX && end && *end == 0) {
+      n = (int)i;
+    }
+  }
+  fclose(fp);
+  s_max_accept_queue_size = n;
+
+  if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
+    gpr_log(GPR_INFO,
+            "Suspiciously small accept queue (%d) will probably lead to "
+            "connection drops",
+            s_max_accept_queue_size);
+  }
+}
+
+static int get_max_accept_queue_size(void) {
+  gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
+  return s_max_accept_queue_size;
+}
+
+/* Prepare a recently-created socket for listening. */
+static int prepare_socket(int fd, const struct sockaddr *addr,
+                          size_t addr_len) {
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
+
+  if (fd < 0) {
+    goto error;
+  }
+
+  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
+      (!grpc_is_unix_socket(addr) && (!grpc_set_socket_low_latency(fd, 1) ||
+                                      !grpc_set_socket_reuse_addr(fd, 1))) ||
+      !grpc_set_socket_no_sigpipe_if_possible(fd)) {
+    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
+            strerror(errno));
+    goto error;
+  }
+
+  GPR_ASSERT(addr_len < ~(socklen_t)0);
+  if (bind(fd, addr, (socklen_t)addr_len) < 0) {
+    char *addr_str;
+    grpc_sockaddr_to_string(&addr_str, addr, 0);
+    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
+    gpr_free(addr_str);
+    goto error;
+  }
+
+  if (listen(fd, get_max_accept_queue_size()) < 0) {
+    gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
+    goto error;
+  }
+
+  sockname_len = sizeof(sockname_temp);
+  if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
+    goto error;
+  }
+
+  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+
+error:
+  if (fd >= 0) {
+    close(fd);
+  }
+  return -1;
+}
+
+/* event manager callback when reads are ready */
+static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  grpc_tcp_listener *sp = arg;
+  grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index,
+                                       sp->fd_index};
+  grpc_fd *fdobj;
+  size_t i;
+
+  if (!success) {
+    goto error;
+  }
+
+  /* loop until accept4 returns EAGAIN, and then re-arm notification */
+  for (;;) {
+    struct sockaddr_storage addr;
+    socklen_t addrlen = sizeof(addr);
+    char *addr_str;
+    char *name;
+    /* Note: If we ever decide to return this address to the user, remember to
+       strip off the ::ffff:0.0.0.0/96 prefix first. */
+    int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
+    if (fd < 0) {
+      switch (errno) {
+        case EINTR:
+          continue;
+        case EAGAIN:
+          grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
+          return;
+        default:
+          gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
+          goto error;
+      }
+    }
+
+    grpc_set_socket_no_sigpipe_if_possible(fd);
+
+    addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
+    gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
+
+    if (grpc_tcp_trace) {
+      gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
+    }
+
+    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);
+    }
+    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);
+
+    gpr_free(name);
+    gpr_free(addr_str);
+  }
+
+  GPR_UNREACHABLE_CODE(return );
+
+error:
+  gpr_mu_lock(&sp->server->mu);
+  if (0 == --sp->server->active_ports) {
+    gpr_mu_unlock(&sp->server->mu);
+    deactivated_all_ports(exec_ctx, sp->server);
+  } else {
+    gpr_mu_unlock(&sp->server->mu);
+  }
+}
+
+static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
+                                               const struct sockaddr *addr,
+                                               size_t addr_len,
+                                               unsigned port_index,
+                                               unsigned fd_index) {
+  grpc_tcp_listener *sp = NULL;
+  int port;
+  char *addr_str;
+  char *name;
+
+  port = prepare_socket(fd, addr, addr_len);
+  if (port >= 0) {
+    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
+    gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
+    gpr_mu_lock(&s->mu);
+    s->nports++;
+    GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
+    sp = gpr_malloc(sizeof(grpc_tcp_listener));
+    sp->next = NULL;
+    if (s->head == NULL) {
+      s->head = sp;
+    } else {
+      s->tail->next = sp;
+    }
+    s->tail = sp;
+    sp->server = s;
+    sp->fd = fd;
+    sp->emfd = grpc_fd_create(fd, name);
+    memcpy(sp->addr.untyped, addr, addr_len);
+    sp->addr_len = addr_len;
+    sp->port = port;
+    sp->port_index = port_index;
+    sp->fd_index = fd_index;
+    sp->is_sibling = 0;
+    sp->sibling = NULL;
+    GPR_ASSERT(sp->emfd);
+    gpr_mu_unlock(&s->mu);
+    gpr_free(addr_str);
+    gpr_free(name);
+  }
+
+  return sp;
+}
+
+int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
+                             size_t addr_len) {
+  grpc_tcp_listener *sp;
+  grpc_tcp_listener *sp2 = NULL;
+  int fd;
+  grpc_dualstack_mode dsmode;
+  struct sockaddr_in6 addr6_v4mapped;
+  struct sockaddr_in wild4;
+  struct sockaddr_in6 wild6;
+  struct sockaddr_in addr4_copy;
+  struct sockaddr *allocated_addr = NULL;
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
+  int port;
+  unsigned port_index = 0;
+  unsigned fd_index = 0;
+  if (s->tail != NULL) {
+    port_index = s->tail->port_index + 1;
+  }
+  grpc_unlink_if_unix_domain_socket((struct sockaddr *)addr);
+
+  /* Check if this is a wildcard port, and if so, try to keep the port the same
+     as some previously created listener. */
+  if (grpc_sockaddr_get_port(addr) == 0) {
+    for (sp = s->head; sp; sp = sp->next) {
+      sockname_len = sizeof(sockname_temp);
+      if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
+                           &sockname_len)) {
+        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+        if (port > 0) {
+          allocated_addr = gpr_malloc(addr_len);
+          memcpy(allocated_addr, addr, addr_len);
+          grpc_sockaddr_set_port(allocated_addr, port);
+          addr = allocated_addr;
+          break;
+        }
+      }
+    }
+  }
+
+  sp = NULL;
+
+  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
+    addr = (const struct sockaddr *)&addr6_v4mapped;
+    addr_len = sizeof(addr6_v4mapped);
+  }
+
+  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
+  if (grpc_sockaddr_is_wildcard(addr, &port)) {
+    grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
+
+    /* Try listening on IPv6 first. */
+    addr = (struct sockaddr *)&wild6;
+    addr_len = sizeof(wild6);
+    fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
+    sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
+    if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
+      goto done;
+    }
+    if (sp != NULL) {
+      ++fd_index;
+    }
+    /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
+    if (port == 0 && sp != NULL) {
+      grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
+    }
+    addr = (struct sockaddr *)&wild4;
+    addr_len = sizeof(wild4);
+  }
+
+  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
+  if (fd < 0) {
+    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
+  } else {
+    if (dsmode == GRPC_DSMODE_IPV4 &&
+        grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
+      addr = (struct sockaddr *)&addr4_copy;
+      addr_len = sizeof(addr4_copy);
+    }
+    sp2 = sp;
+    sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
+    if (sp2 != NULL && sp != NULL) {
+      sp2->sibling = sp;
+      sp->is_sibling = 1;
+    }
+  }
+
+done:
+  gpr_free(allocated_addr);
+  if (sp != NULL) {
+    return sp->port;
+  } else {
+    return -1;
+  }
+}
+
+unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
+                                       unsigned port_index) {
+  unsigned num_fds = 0;
+  grpc_tcp_listener *sp;
+  for (sp = s->head; sp && port_index != 0; sp = sp->next) {
+    if (!sp->is_sibling) {
+      --port_index;
+    }
+  }
+  for (; sp; sp = sp->sibling, ++num_fds)
+    ;
+  return num_fds;
+}
+
+int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
+                            unsigned fd_index) {
+  grpc_tcp_listener *sp;
+  for (sp = s->head; sp && port_index != 0; sp = sp->next) {
+    if (!sp->is_sibling) {
+      --port_index;
+    }
+  }
+  for (; sp && fd_index != 0; sp = sp->sibling, --fd_index)
+    ;
+  if (sp) {
+    return sp->fd;
+  } else {
+    return -1;
+  }
+}
+
+void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
+                           grpc_pollset **pollsets, size_t pollset_count,
+                           grpc_tcp_server_cb on_accept_cb,
+                           void *on_accept_cb_arg) {
+  size_t i;
+  grpc_tcp_listener *sp;
+  GPR_ASSERT(on_accept_cb);
+  gpr_mu_lock(&s->mu);
+  GPR_ASSERT(!s->on_accept_cb);
+  GPR_ASSERT(s->active_ports == 0);
+  s->on_accept_cb = on_accept_cb;
+  s->on_accept_cb_arg = on_accept_cb_arg;
+  s->pollsets = pollsets;
+  s->pollset_count = pollset_count;
+  for (sp = s->head; sp; sp = sp->next) {
+    for (i = 0; i < pollset_count; i++) {
+      grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
+    }
+    sp->read_closure.cb = on_read;
+    sp->read_closure.cb_arg = sp;
+    grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
+    s->active_ports++;
+  }
+  gpr_mu_unlock(&s->mu);
+}
+
+grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
+  gpr_ref(&s->refs);
+  return s;
+}
+
+void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
+                                           grpc_closure *shutdown_starting) {
+  gpr_mu_lock(&s->mu);
+  grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1);
+  gpr_mu_unlock(&s->mu);
+}
+
+void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  if (gpr_unref(&s->refs)) {
+    /* Complete shutdown_starting work before destroying. */
+    grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT;
+    gpr_mu_lock(&s->mu);
+    grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL);
+    gpr_mu_unlock(&s->mu);
+    if (exec_ctx == NULL) {
+      grpc_exec_ctx_flush(&local_exec_ctx);
+      tcp_server_destroy(&local_exec_ctx, s);
+      grpc_exec_ctx_finish(&local_exec_ctx);
+    } else {
+      grpc_exec_ctx_finish(&local_exec_ctx);
+      tcp_server_destroy(exec_ctx, s);
+    }
+  }
+}
+
+#endif
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
new file mode 100644
index 0000000..6940dec
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -0,0 +1,557 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include <io.h>
+
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_win32.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/iomgr/iocp_windows.h"
+#include "src/core/lib/iomgr/pollset_windows.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+#include "src/core/lib/iomgr/tcp_server.h"
+#include "src/core/lib/iomgr/tcp_windows.h"
+
+#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
+
+/* one listening port */
+typedef struct grpc_tcp_listener grpc_tcp_listener;
+struct grpc_tcp_listener {
+  /* This seemingly magic number comes from AcceptEx's documentation. each
+     address buffer needs to have at least 16 more bytes at their end. */
+  uint8_t addresses[(sizeof(struct sockaddr_in6) + 16) * 2];
+  /* This will hold the socket for the next accept. */
+  SOCKET new_socket;
+  /* The listener winsocket. */
+  grpc_winsocket *socket;
+  /* The actual TCP port number. */
+  int port;
+  unsigned port_index;
+  grpc_tcp_server *server;
+  /* The cached AcceptEx for that port. */
+  LPFN_ACCEPTEX AcceptEx;
+  int shutting_down;
+  /* closure for socket notification of accept being ready */
+  grpc_closure on_accept;
+  /* linked list */
+  struct grpc_tcp_listener *next;
+};
+
+/* the overall server */
+struct grpc_tcp_server {
+  gpr_refcount refs;
+  /* Called whenever accept() succeeds on a server port. */
+  grpc_tcp_server_cb on_accept_cb;
+  void *on_accept_cb_arg;
+
+  gpr_mu mu;
+
+  /* active port count: how many ports are actually still listening */
+  int active_ports;
+
+  /* linked list of server ports */
+  grpc_tcp_listener *head;
+  grpc_tcp_listener *tail;
+
+  /* List of closures passed to shutdown_starting_add(). */
+  grpc_closure_list shutdown_starting;
+
+  /* shutdown callback */
+  grpc_closure *shutdown_complete;
+};
+
+/* Public function. Allocates the proper data structures to hold a
+   grpc_tcp_server. */
+grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
+  grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
+  gpr_ref_init(&s->refs, 1);
+  gpr_mu_init(&s->mu);
+  s->active_ports = 0;
+  s->on_accept_cb = NULL;
+  s->on_accept_cb_arg = NULL;
+  s->head = NULL;
+  s->tail = NULL;
+  s->shutdown_starting.head = NULL;
+  s->shutdown_starting.tail = NULL;
+  s->shutdown_complete = shutdown_complete;
+  return s;
+}
+
+static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  if (s->shutdown_complete != NULL) {
+    grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL);
+  }
+
+  /* Now that the accepts have been aborted, we can destroy the sockets.
+     The IOCP won't get notified on these, so we can flag them as already
+     closed by the system. */
+  while (s->head) {
+    grpc_tcp_listener *sp = s->head;
+    s->head = sp->next;
+    sp->next = NULL;
+    grpc_winsocket_destroy(sp->socket);
+    gpr_free(sp);
+  }
+  gpr_free(s);
+}
+
+grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
+  gpr_ref(&s->refs);
+  return s;
+}
+
+void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
+                                           grpc_closure *shutdown_starting) {
+  gpr_mu_lock(&s->mu);
+  grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1);
+  gpr_mu_unlock(&s->mu);
+}
+
+static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  int immediately_done = 0;
+  grpc_tcp_listener *sp;
+  gpr_mu_lock(&s->mu);
+
+  /* First, shutdown all fd's. This will queue abortion calls for all
+     of the pending accepts due to the normal operation mechanism. */
+  if (s->active_ports == 0) {
+    immediately_done = 1;
+  }
+  for (sp = s->head; sp; sp = sp->next) {
+    sp->shutting_down = 1;
+    grpc_winsocket_shutdown(sp->socket);
+  }
+  gpr_mu_unlock(&s->mu);
+
+  if (immediately_done) {
+    finish_shutdown(exec_ctx, s);
+  }
+}
+
+void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  if (gpr_unref(&s->refs)) {
+    /* Complete shutdown_starting work before destroying. */
+    grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT;
+    gpr_mu_lock(&s->mu);
+    grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL);
+    gpr_mu_unlock(&s->mu);
+    if (exec_ctx == NULL) {
+      grpc_exec_ctx_flush(&local_exec_ctx);
+      tcp_server_destroy(&local_exec_ctx, s);
+      grpc_exec_ctx_finish(&local_exec_ctx);
+    } else {
+      grpc_exec_ctx_finish(&local_exec_ctx);
+      tcp_server_destroy(exec_ctx, s);
+    }
+  }
+}
+
+/* Prepare (bind) a recently-created socket for listening. */
+static int prepare_socket(SOCKET sock, const struct sockaddr *addr,
+                          size_t addr_len) {
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
+
+  if (sock == INVALID_SOCKET) goto error;
+
+  if (!grpc_tcp_prepare_socket(sock)) {
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    gpr_log(GPR_ERROR, "Unable to prepare socket: %s", utf8_message);
+    gpr_free(utf8_message);
+    goto error;
+  }
+
+  if (bind(sock, addr, (int)addr_len) == SOCKET_ERROR) {
+    char *addr_str;
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    grpc_sockaddr_to_string(&addr_str, addr, 0);
+    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, utf8_message);
+    gpr_free(utf8_message);
+    gpr_free(addr_str);
+    goto error;
+  }
+
+  if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    gpr_log(GPR_ERROR, "listen: %s", utf8_message);
+    gpr_free(utf8_message);
+    goto error;
+  }
+
+  sockname_len = sizeof(sockname_temp);
+  if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) ==
+      SOCKET_ERROR) {
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    gpr_log(GPR_ERROR, "getsockname: %s", utf8_message);
+    gpr_free(utf8_message);
+    goto error;
+  }
+
+  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+
+error:
+  if (sock != INVALID_SOCKET) closesocket(sock);
+  return -1;
+}
+
+static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
+                                              grpc_tcp_listener *sp) {
+  int notify = 0;
+  sp->shutting_down = 0;
+  gpr_mu_lock(&sp->server->mu);
+  GPR_ASSERT(sp->server->active_ports > 0);
+  if (0 == --sp->server->active_ports) {
+    notify = 1;
+  }
+  gpr_mu_unlock(&sp->server->mu);
+  if (notify) {
+    finish_shutdown(exec_ctx, sp->server);
+  }
+}
+
+/* In order to do an async accept, we need to create a socket first which
+   will be the one assigned to the new incoming connection. */
+static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) {
+  SOCKET sock = INVALID_SOCKET;
+  char *message;
+  char *utf8_message;
+  BOOL success;
+  DWORD addrlen = sizeof(struct sockaddr_in6) + 16;
+  DWORD bytes_received = 0;
+
+  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
+                   WSA_FLAG_OVERLAPPED);
+
+  if (sock == INVALID_SOCKET) {
+    message = "Unable to create socket: %s";
+    goto failure;
+  }
+
+  if (!grpc_tcp_prepare_socket(sock)) {
+    message = "Unable to prepare socket: %s";
+    goto failure;
+  }
+
+  /* Start the "accept" asynchronously. */
+  success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0,
+                           addrlen, addrlen, &bytes_received,
+                           &port->socket->read_info.overlapped);
+
+  /* It is possible to get an accept immediately without delay. However, we
+     will still get an IOCP notification for it. So let's just ignore it. */
+  if (!success) {
+    int error = WSAGetLastError();
+    if (error != ERROR_IO_PENDING) {
+      message = "AcceptEx failed: %s";
+      goto failure;
+    }
+  }
+
+  /* We're ready to do the accept. Calling grpc_socket_notify_on_read may
+     immediately process an accept that happened in the meantime. */
+  port->new_socket = sock;
+  grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
+  return;
+
+failure:
+  if (port->shutting_down) {
+    /* We are abandoning the listener port, take that into account to prevent
+       occasional hangs on shutdown. The hang happens when sp->shutting_down
+       change is not seen by on_accept and we proceed to trying new accept,
+       but we fail there because the listening port has been closed in the
+       meantime. */
+    decrement_active_ports_and_notify(exec_ctx, port);
+    return;
+  }
+  utf8_message = gpr_format_message(WSAGetLastError());
+  gpr_log(GPR_ERROR, message, utf8_message);
+  gpr_free(utf8_message);
+  if (sock != INVALID_SOCKET) closesocket(sock);
+}
+
+/* Event manager callback when reads are ready. */
+static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, bool from_iocp) {
+  grpc_tcp_listener *sp = arg;
+  grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0};
+  SOCKET sock = sp->new_socket;
+  grpc_winsocket_callback_info *info = &sp->socket->read_info;
+  grpc_endpoint *ep = NULL;
+  struct sockaddr_storage peer_name;
+  char *peer_name_string;
+  char *fd_name;
+  int peer_name_len = sizeof(peer_name);
+  DWORD transfered_bytes;
+  DWORD flags;
+  BOOL wsa_success;
+  int err;
+
+  /* The general mechanism for shutting down is to queue abortion calls. While
+     this is necessary in the read/write case, it's useless for the accept
+     case. We only need to adjust the pending callback count */
+  if (!from_iocp) {
+    return;
+  }
+
+  /* The IOCP notified us of a completed operation. Let's grab the results,
+     and act accordingly. */
+  transfered_bytes = 0;
+  wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
+                                       &transfered_bytes, FALSE, &flags);
+  if (!wsa_success) {
+    if (sp->shutting_down) {
+      /* During the shutdown case, we ARE expecting an error. So that's well,
+         and we can wake up the shutdown thread. */
+      decrement_active_ports_and_notify(exec_ctx, sp);
+      return;
+    } else {
+      char *utf8_message = gpr_format_message(WSAGetLastError());
+      gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
+      gpr_free(utf8_message);
+      closesocket(sock);
+    }
+  } else {
+    if (!sp->shutting_down) {
+      peer_name_string = NULL;
+      err = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+                       (char *)&sp->socket->socket, sizeof(sp->socket->socket));
+      if (err) {
+        char *utf8_message = gpr_format_message(WSAGetLastError());
+        gpr_log(GPR_ERROR, "setsockopt error: %s", utf8_message);
+        gpr_free(utf8_message);
+      }
+      err = getpeername(sock, (struct sockaddr *)&peer_name, &peer_name_len);
+      if (!err) {
+        peer_name_string = grpc_sockaddr_to_uri((struct sockaddr *)&peer_name);
+      } else {
+        char *utf8_message = gpr_format_message(WSAGetLastError());
+        gpr_log(GPR_ERROR, "getpeername error: %s", utf8_message);
+        gpr_free(utf8_message);
+      }
+      gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string);
+      ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name),
+                           peer_name_string);
+      gpr_free(fd_name);
+      gpr_free(peer_name_string);
+    } else {
+      closesocket(sock);
+    }
+  }
+
+  /* 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,
+                             &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
+     connection. */
+  start_accept(exec_ctx, sp);
+}
+
+static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
+                                               const struct sockaddr *addr,
+                                               size_t addr_len,
+                                               unsigned port_index) {
+  grpc_tcp_listener *sp = NULL;
+  int port;
+  int status;
+  GUID guid = WSAID_ACCEPTEX;
+  DWORD ioctl_num_bytes;
+  LPFN_ACCEPTEX AcceptEx;
+
+  if (sock == INVALID_SOCKET) return NULL;
+
+  /* We need to grab the AcceptEx pointer for that port, as it may be
+     interface-dependent. We'll cache it to avoid doing that again. */
+  status =
+      WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
+               &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL);
+
+  if (status != 0) {
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
+    gpr_free(utf8_message);
+    closesocket(sock);
+    return NULL;
+  }
+
+  port = prepare_socket(sock, addr, addr_len);
+  if (port >= 0) {
+    gpr_mu_lock(&s->mu);
+    GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
+    sp = gpr_malloc(sizeof(grpc_tcp_listener));
+    sp->next = NULL;
+    if (s->head == NULL) {
+      s->head = sp;
+    } else {
+      s->tail->next = sp;
+    }
+    s->tail = sp;
+    sp->server = s;
+    sp->socket = grpc_winsocket_create(sock, "listener");
+    sp->shutting_down = 0;
+    sp->AcceptEx = AcceptEx;
+    sp->new_socket = INVALID_SOCKET;
+    sp->port = port;
+    sp->port_index = port_index;
+    grpc_closure_init(&sp->on_accept, on_accept, sp);
+    GPR_ASSERT(sp->socket);
+    gpr_mu_unlock(&s->mu);
+  }
+
+  return sp;
+}
+
+int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
+                             size_t addr_len) {
+  grpc_tcp_listener *sp;
+  SOCKET sock;
+  struct sockaddr_in6 addr6_v4mapped;
+  struct sockaddr_in6 wildcard;
+  struct sockaddr *allocated_addr = NULL;
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
+  int port;
+  unsigned port_index = 0;
+  if (s->tail != NULL) {
+    port_index = s->tail->port_index + 1;
+  }
+
+  /* Check if this is a wildcard port, and if so, try to keep the port the same
+     as some previously created listener. */
+  if (grpc_sockaddr_get_port(addr) == 0) {
+    for (sp = s->head; sp; sp = sp->next) {
+      sockname_len = sizeof(sockname_temp);
+      if (0 == getsockname(sp->socket->socket,
+                           (struct sockaddr *)&sockname_temp, &sockname_len)) {
+        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+        if (port > 0) {
+          allocated_addr = gpr_malloc(addr_len);
+          memcpy(allocated_addr, addr, addr_len);
+          grpc_sockaddr_set_port(allocated_addr, port);
+          addr = allocated_addr;
+          break;
+        }
+      }
+    }
+  }
+
+  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
+    addr = (const struct sockaddr *)&addr6_v4mapped;
+    addr_len = sizeof(addr6_v4mapped);
+  }
+
+  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
+  if (grpc_sockaddr_is_wildcard(addr, &port)) {
+    grpc_sockaddr_make_wildcard6(port, &wildcard);
+
+    addr = (struct sockaddr *)&wildcard;
+    addr_len = sizeof(wildcard);
+  }
+
+  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
+                   WSA_FLAG_OVERLAPPED);
+  if (sock == INVALID_SOCKET) {
+    char *utf8_message = gpr_format_message(WSAGetLastError());
+    gpr_log(GPR_ERROR, "unable to create socket: %s", utf8_message);
+    gpr_free(utf8_message);
+  }
+
+  sp = add_socket_to_server(s, sock, addr, addr_len, port_index);
+  gpr_free(allocated_addr);
+
+  if (sp) {
+    return sp->port;
+  } else {
+    return -1;
+  }
+}
+
+unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
+                                       unsigned port_index) {
+  grpc_tcp_listener *sp;
+  for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
+    ;
+  if (sp) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
+                            unsigned fd_index) {
+  grpc_tcp_listener *sp;
+  if (fd_index != 0) {
+    /* Windows implementation has only one fd per port_index. */
+    return -1;
+  }
+  for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
+    ;
+  if (sp) {
+    return _open_osfhandle((intptr_t)sp->socket->socket, 0);
+  } else {
+    return -1;
+  }
+}
+
+void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
+                           grpc_pollset **pollset, size_t pollset_count,
+                           grpc_tcp_server_cb on_accept_cb,
+                           void *on_accept_cb_arg) {
+  grpc_tcp_listener *sp;
+  GPR_ASSERT(on_accept_cb);
+  gpr_mu_lock(&s->mu);
+  GPR_ASSERT(!s->on_accept_cb);
+  GPR_ASSERT(s->active_ports == 0);
+  s->on_accept_cb = on_accept_cb;
+  s->on_accept_cb_arg = on_accept_cb_arg;
+  for (sp = s->head; sp; sp = sp->next) {
+    start_accept(exec_ctx, sp);
+    s->active_ports++;
+  }
+  gpr_mu_unlock(&s->mu);
+}
+
+#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c
new file mode 100644
index 0000000..7ee689a
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_windows.c
@@ -0,0 +1,402 @@
+/*
+ *
+ * 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_WINSOCK_SOCKET
+
+#include "src/core/lib/iomgr/sockaddr_win32.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_win32.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/iomgr/iocp_windows.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+#include "src/core/lib/iomgr/tcp_client.h"
+#include "src/core/lib/iomgr/timer.h"
+
+static int set_non_block(SOCKET sock) {
+  int status;
+  unsigned long param = 1;
+  DWORD ret;
+  status =
+      WSAIoctl(sock, FIONBIO, &param, sizeof(param), NULL, 0, &ret, NULL, NULL);
+  return status == 0;
+}
+
+static int set_dualstack(SOCKET sock) {
+  int status;
+  unsigned long param = 0;
+  status = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&param,
+                      sizeof(param));
+  return status == 0;
+}
+
+int grpc_tcp_prepare_socket(SOCKET sock) {
+  if (!set_non_block(sock)) return 0;
+  if (!set_dualstack(sock)) return 0;
+  return 1;
+}
+
+typedef struct grpc_tcp {
+  /* This is our C++ class derivation emulation. */
+  grpc_endpoint base;
+  /* The one socket this endpoint is using. */
+  grpc_winsocket *socket;
+  /* Refcounting how many operations are in progress. */
+  gpr_refcount refcount;
+
+  grpc_closure on_read;
+  grpc_closure on_write;
+
+  grpc_closure *read_cb;
+  grpc_closure *write_cb;
+  gpr_slice read_slice;
+  gpr_slice_buffer *write_slices;
+  gpr_slice_buffer *read_slices;
+
+  /* The IO Completion Port runs from another thread. We need some mechanism
+     to protect ourselves when requesting a shutdown. */
+  gpr_mu mu;
+  int shutting_down;
+
+  char *peer_string;
+} grpc_tcp;
+
+static void tcp_free(grpc_tcp *tcp) {
+  grpc_winsocket_destroy(tcp->socket);
+  gpr_mu_destroy(&tcp->mu);
+  gpr_free(tcp->peer_string);
+  gpr_free(tcp);
+}
+
+/*#define GRPC_TCP_REFCOUNT_DEBUG*/
+#ifdef GRPC_TCP_REFCOUNT_DEBUG
+#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__)
+#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
+static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file,
+                      int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
+          reason, tcp->refcount.count, tcp->refcount.count - 1);
+  if (gpr_unref(&tcp->refcount)) {
+    tcp_free(tcp);
+  }
+}
+
+static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
+                    int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP   ref %p : %s %d -> %d", tcp,
+          reason, tcp->refcount.count, tcp->refcount.count + 1);
+  gpr_ref(&tcp->refcount);
+}
+#else
+#define TCP_UNREF(tcp, reason) tcp_unref((tcp))
+#define TCP_REF(tcp, reason) tcp_ref((tcp))
+static void tcp_unref(grpc_tcp *tcp) {
+  if (gpr_unref(&tcp->refcount)) {
+    tcp_free(tcp);
+  }
+}
+
+static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
+#endif
+
+/* Asynchronous callback from the IOCP, or the background thread. */
+static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) {
+  grpc_tcp *tcp = tcpp;
+  grpc_closure *cb = tcp->read_cb;
+  grpc_winsocket *socket = tcp->socket;
+  gpr_slice sub;
+  grpc_winsocket_callback_info *info = &socket->read_info;
+
+  if (success) {
+    if (info->wsa_error != 0 && !tcp->shutting_down) {
+      if (info->wsa_error != WSAECONNRESET) {
+        char *utf8_message = gpr_format_message(info->wsa_error);
+        gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
+        gpr_free(utf8_message);
+      }
+      success = 0;
+      gpr_slice_unref(tcp->read_slice);
+    } else {
+      if (info->bytes_transfered != 0 && !tcp->shutting_down) {
+        sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
+        gpr_slice_buffer_add(tcp->read_slices, sub);
+        success = 1;
+      } else {
+        gpr_slice_unref(tcp->read_slice);
+        success = 0;
+      }
+    }
+  }
+
+  tcp->read_cb = NULL;
+  TCP_UNREF(tcp, "read");
+  if (cb) {
+    cb->cb(exec_ctx, cb->cb_arg, success);
+  }
+}
+
+static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                     gpr_slice_buffer *read_slices, grpc_closure *cb) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  grpc_winsocket *handle = tcp->socket;
+  grpc_winsocket_callback_info *info = &handle->read_info;
+  int status;
+  DWORD bytes_read = 0;
+  DWORD flags = 0;
+  WSABUF buffer;
+
+  if (tcp->shutting_down) {
+    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+    return;
+  }
+
+  tcp->read_cb = cb;
+  tcp->read_slices = read_slices;
+  gpr_slice_buffer_reset_and_unref(read_slices);
+
+  tcp->read_slice = gpr_slice_malloc(8192);
+
+  buffer.len = (ULONG)GPR_SLICE_LENGTH(
+      tcp->read_slice);  // we know slice size fits in 32bit.
+  buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice);
+
+  TCP_REF(tcp, "read");
+
+  /* First let's try a synchronous, non-blocking read. */
+  status =
+      WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL);
+  info->wsa_error = status == 0 ? 0 : WSAGetLastError();
+
+  /* Did we get data immediately ? Yay. */
+  if (info->wsa_error != WSAEWOULDBLOCK) {
+    info->bytes_transfered = bytes_read;
+    grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, true, NULL);
+    return;
+  }
+
+  /* Otherwise, let's retry, by queuing a read. */
+  memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED));
+  status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags,
+                   &info->overlapped, NULL);
+
+  if (status != 0) {
+    int wsa_error = WSAGetLastError();
+    if (wsa_error != WSA_IO_PENDING) {
+      info->wsa_error = wsa_error;
+      grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, false, NULL);
+      return;
+    }
+  }
+
+  grpc_socket_notify_on_read(exec_ctx, tcp->socket, &tcp->on_read);
+}
+
+/* Asynchronous callback from the IOCP, or the background thread. */
+static void on_write(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) {
+  grpc_tcp *tcp = (grpc_tcp *)tcpp;
+  grpc_winsocket *handle = tcp->socket;
+  grpc_winsocket_callback_info *info = &handle->write_info;
+  grpc_closure *cb;
+
+  gpr_mu_lock(&tcp->mu);
+  cb = tcp->write_cb;
+  tcp->write_cb = NULL;
+  gpr_mu_unlock(&tcp->mu);
+
+  if (success) {
+    if (info->wsa_error != 0) {
+      if (info->wsa_error != WSAECONNRESET) {
+        char *utf8_message = gpr_format_message(info->wsa_error);
+        gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
+        gpr_free(utf8_message);
+      }
+      success = 0;
+    } else {
+      GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length);
+    }
+  }
+
+  TCP_UNREF(tcp, "write");
+  cb->cb(exec_ctx, cb->cb_arg, success);
+}
+
+/* Initiates a write. */
+static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                      gpr_slice_buffer *slices, grpc_closure *cb) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  grpc_winsocket *socket = tcp->socket;
+  grpc_winsocket_callback_info *info = &socket->write_info;
+  unsigned i;
+  DWORD bytes_sent;
+  int status;
+  WSABUF local_buffers[16];
+  WSABUF *allocated = NULL;
+  WSABUF *buffers = local_buffers;
+  size_t len;
+
+  if (tcp->shutting_down) {
+    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+    return;
+  }
+
+  tcp->write_cb = cb;
+  tcp->write_slices = slices;
+  GPR_ASSERT(tcp->write_slices->count <= UINT_MAX);
+  if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) {
+    buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count);
+    allocated = buffers;
+  }
+
+  for (i = 0; i < tcp->write_slices->count; i++) {
+    len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]);
+    GPR_ASSERT(len <= ULONG_MAX);
+    buffers[i].len = (ULONG)len;
+    buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]);
+  }
+
+  /* First, let's try a synchronous, non-blocking write. */
+  status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
+                   &bytes_sent, 0, NULL, NULL);
+  info->wsa_error = status == 0 ? 0 : WSAGetLastError();
+
+  /* We would kind of expect to get a WSAEWOULDBLOCK here, especially on a busy
+     connection that has its send queue filled up. But if we don't, then we can
+     avoid doing an async write operation at all. */
+  if (info->wsa_error != WSAEWOULDBLOCK) {
+    bool ok = false;
+    if (status == 0) {
+      ok = true;
+      GPR_ASSERT(bytes_sent == tcp->write_slices->length);
+    } else {
+      if (info->wsa_error != WSAECONNRESET) {
+        char *utf8_message = gpr_format_message(info->wsa_error);
+        gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message);
+        gpr_free(utf8_message);
+      }
+    }
+    if (allocated) gpr_free(allocated);
+    grpc_exec_ctx_enqueue(exec_ctx, cb, ok, NULL);
+    return;
+  }
+
+  TCP_REF(tcp, "write");
+
+  /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same
+     operation, this time asynchronously. */
+  memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED));
+  status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
+                   &bytes_sent, 0, &socket->write_info.overlapped, NULL);
+  if (allocated) gpr_free(allocated);
+
+  if (status != 0) {
+    int wsa_error = WSAGetLastError();
+    if (wsa_error != WSA_IO_PENDING) {
+      TCP_UNREF(tcp, "write");
+      grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+      return;
+    }
+  }
+
+  /* As all is now setup, we can now ask for the IOCP notification. It may
+     trigger the callback immediately however, but no matter. */
+  grpc_socket_notify_on_write(exec_ctx, socket, &tcp->on_write);
+}
+
+static void win_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                               grpc_pollset *ps) {
+  grpc_tcp *tcp;
+  (void)ps;
+  tcp = (grpc_tcp *)ep;
+  grpc_iocp_add_socket(tcp->socket);
+}
+
+static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                   grpc_pollset_set *pss) {
+  grpc_tcp *tcp;
+  (void)pss;
+  tcp = (grpc_tcp *)ep;
+  grpc_iocp_add_socket(tcp->socket);
+}
+
+/* Initiates a shutdown of the TCP endpoint. This will queue abort callbacks
+   for the potential read and write operations. It is up to the caller to
+   guarantee this isn't called in parallel to a read or write request, so
+   we're not going to protect against these. However the IO Completion Port
+   callback will happen from another thread, so we need to protect against
+   concurrent access of the data structure in that regard. */
+static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  gpr_mu_lock(&tcp->mu);
+  /* At that point, what may happen is that we're already inside the IOCP
+     callback. See the comments in on_read and on_write. */
+  tcp->shutting_down = 1;
+  grpc_winsocket_shutdown(tcp->socket);
+  gpr_mu_unlock(&tcp->mu);
+}
+
+static void win_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  TCP_UNREF(tcp, "destroy");
+}
+
+static char *win_get_peer(grpc_endpoint *ep) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  return gpr_strdup(tcp->peer_string);
+}
+
+static grpc_endpoint_vtable vtable = {
+    win_read,     win_write,   win_add_to_pollset, win_add_to_pollset_set,
+    win_shutdown, win_destroy, win_get_peer};
+
+grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) {
+  grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
+  memset(tcp, 0, sizeof(grpc_tcp));
+  tcp->base.vtable = &vtable;
+  tcp->socket = socket;
+  gpr_mu_init(&tcp->mu);
+  gpr_ref_init(&tcp->refcount, 1);
+  grpc_closure_init(&tcp->on_read, on_read, tcp);
+  grpc_closure_init(&tcp->on_write, on_write, tcp);
+  tcp->peer_string = gpr_strdup(peer_string);
+  return &tcp->base;
+}
+
+#endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/tcp_windows.h b/src/core/lib/iomgr/tcp_windows.h
new file mode 100644
index 0000000..a2f58ed
--- /dev/null
+++ b/src/core/lib/iomgr/tcp_windows.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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_TCP_WINDOWS_H
+#define GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H
+/*
+   Low level TCP "bottom half" implementation, for use by transports built on
+   top of a TCP connection.
+
+   Note that this file does not (yet) include APIs for creating the socket in
+   the first place.
+
+   All calls passing slice transfer ownership of a slice refcount unless
+   otherwise specified.
+*/
+
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+
+/* Create a tcp endpoint given a winsock handle.
+ * Takes ownership of the handle.
+ */
+grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string);
+
+int grpc_tcp_prepare_socket(SOCKET sock);
+
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H */
diff --git a/src/core/lib/iomgr/time_averaged_stats.c b/src/core/lib/iomgr/time_averaged_stats.c
new file mode 100644
index 0000000..da9cae6
--- /dev/null
+++ b/src/core/lib/iomgr/time_averaged_stats.c
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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/iomgr/time_averaged_stats.h"
+
+void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats,
+                                   double init_avg, double regress_weight,
+                                   double persistence_factor) {
+  stats->init_avg = init_avg;
+  stats->regress_weight = regress_weight;
+  stats->persistence_factor = persistence_factor;
+  stats->batch_total_value = 0;
+  stats->batch_num_samples = 0;
+  stats->aggregate_total_weight = 0;
+  stats->aggregate_weighted_avg = init_avg;
+}
+
+void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats,
+                                         double value) {
+  stats->batch_total_value += value;
+  ++stats->batch_num_samples;
+}
+
+double grpc_time_averaged_stats_update_average(
+    grpc_time_averaged_stats* stats) {
+  /* Start with the current batch: */
+  double weighted_sum = stats->batch_total_value;
+  double total_weight = stats->batch_num_samples;
+  if (stats->regress_weight > 0) {
+    /* Add in the regression towards init_avg_: */
+    weighted_sum += stats->regress_weight * stats->init_avg;
+    total_weight += stats->regress_weight;
+  }
+  if (stats->persistence_factor > 0) {
+    /* Add in the persistence: */
+    const double prev_sample_weight =
+        stats->persistence_factor * stats->aggregate_total_weight;
+    weighted_sum += prev_sample_weight * stats->aggregate_weighted_avg;
+    total_weight += prev_sample_weight;
+  }
+  stats->aggregate_weighted_avg =
+      (total_weight > 0) ? (weighted_sum / total_weight) : stats->init_avg;
+  stats->aggregate_total_weight = total_weight;
+  stats->batch_num_samples = 0;
+  stats->batch_total_value = 0;
+  return stats->aggregate_weighted_avg;
+}
diff --git a/src/core/lib/iomgr/time_averaged_stats.h b/src/core/lib/iomgr/time_averaged_stats.h
new file mode 100644
index 0000000..284b31f
--- /dev/null
+++ b/src/core/lib/iomgr/time_averaged_stats.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_IOMGR_TIME_AVERAGED_STATS_H
+#define GRPC_CORE_LIB_IOMGR_TIME_AVERAGED_STATS_H
+
+/* This tracks a time-decaying weighted average.  It works by collecting
+   batches of samples and then mixing their average into a time-decaying
+   weighted mean.  It is designed for batch operations where we do many adds
+   before updating the average. */
+
+typedef struct {
+  /* The initial average value.  This is the reported average until the first
+     grpc_time_averaged_stats_update_average call.  If a positive regress_weight
+     is used, we also regress towards this value on each update. */
+  double init_avg;
+  /* The sample weight of "init_avg" that is mixed in with each call to
+     grpc_time_averaged_stats_update_average.  If the calls to
+     grpc_time_averaged_stats_add_sample stop, this will cause the average to
+     regress back to the mean.  This should be non-negative.  Set it to 0 to
+     disable the bias.  A value of 1 has the effect of adding in 1 bonus sample
+     with value init_avg to each sample period. */
+  double regress_weight;
+  /* This determines the rate of decay of the time-averaging from one period
+     to the next by scaling the aggregate_total_weight of samples from prior
+     periods when combining with the latest period.  It should be in the range
+     [0,1].  A higher value adapts more slowly.  With a value of 0.5, if the
+     batches each have k samples, the samples_in_avg_ will grow to 2 k, so the
+     weighting of the time average will eventually be 1/3 new batch and 2/3
+     old average. */
+  double persistence_factor;
+
+  /* The total value of samples since the last UpdateAverage(). */
+  double batch_total_value;
+  /* The number of samples since the last UpdateAverage(). */
+  double batch_num_samples;
+  /* The time-decayed sum of batch_num_samples_ over previous batches.  This is
+     the "weight" of the old aggregate_weighted_avg_ when updating the
+     average. */
+  double aggregate_total_weight;
+  /* A time-decayed average of the (batch_total_value_ / batch_num_samples_),
+     computed by decaying the samples_in_avg_ weight in the weighted average. */
+  double aggregate_weighted_avg;
+} grpc_time_averaged_stats;
+
+/* See the comments on the members above for an explanation of init_avg,
+   regress_weight, and persistence_factor. */
+void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats,
+                                   double init_avg, double regress_weight,
+                                   double persistence_factor);
+/* Add a sample to the current batch. */
+void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats,
+                                         double value);
+/* Complete a batch and compute the new estimate of the average sample
+   value. */
+double grpc_time_averaged_stats_update_average(grpc_time_averaged_stats* stats);
+
+#endif /* GRPC_CORE_LIB_IOMGR_TIME_AVERAGED_STATS_H */
diff --git a/src/core/lib/iomgr/timer.c b/src/core/lib/iomgr/timer.c
new file mode 100644
index 0000000..acb5b26
--- /dev/null
+++ b/src/core/lib/iomgr/timer.c
@@ -0,0 +1,371 @@
+/*
+ *
+ * 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/iomgr/timer.h"
+
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/iomgr/time_averaged_stats.h"
+#include "src/core/lib/iomgr/timer_heap.h"
+
+#define INVALID_HEAP_INDEX 0xffffffffu
+
+#define LOG2_NUM_SHARDS 5
+#define NUM_SHARDS (1 << LOG2_NUM_SHARDS)
+#define ADD_DEADLINE_SCALE 0.33
+#define MIN_QUEUE_WINDOW_DURATION 0.01
+#define MAX_QUEUE_WINDOW_DURATION 1
+
+typedef struct {
+  gpr_mu mu;
+  grpc_time_averaged_stats stats;
+  /* All and only timers with deadlines <= this will be in the heap. */
+  gpr_timespec queue_deadline_cap;
+  gpr_timespec min_deadline;
+  /* Index in the g_shard_queue */
+  uint32_t shard_queue_index;
+  /* This holds all timers with deadlines < queue_deadline_cap. Timers in this
+     list have the top bit of their deadline set to 0. */
+  grpc_timer_heap heap;
+  /* This holds timers whose deadline is >= queue_deadline_cap. */
+  grpc_timer list;
+} shard_type;
+
+/* Protects g_shard_queue */
+static gpr_mu g_mu;
+/* Allow only one run_some_expired_timers at once */
+static gpr_mu g_checker_mu;
+static gpr_clock_type g_clock_type;
+static shard_type g_shards[NUM_SHARDS];
+/* Protected by g_mu */
+static shard_type *g_shard_queue[NUM_SHARDS];
+static bool g_initialized = false;
+
+static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
+                                   gpr_timespec *next, int success);
+
+static gpr_timespec compute_min_deadline(shard_type *shard) {
+  return grpc_timer_heap_is_empty(&shard->heap)
+             ? shard->queue_deadline_cap
+             : grpc_timer_heap_top(&shard->heap)->deadline;
+}
+
+void grpc_timer_list_init(gpr_timespec now) {
+  uint32_t i;
+
+  g_initialized = true;
+  gpr_mu_init(&g_mu);
+  gpr_mu_init(&g_checker_mu);
+  g_clock_type = now.clock_type;
+
+  for (i = 0; i < NUM_SHARDS; i++) {
+    shard_type *shard = &g_shards[i];
+    gpr_mu_init(&shard->mu);
+    grpc_time_averaged_stats_init(&shard->stats, 1.0 / ADD_DEADLINE_SCALE, 0.1,
+                                  0.5);
+    shard->queue_deadline_cap = now;
+    shard->shard_queue_index = i;
+    grpc_timer_heap_init(&shard->heap);
+    shard->list.next = shard->list.prev = &shard->list;
+    shard->min_deadline = compute_min_deadline(shard);
+    g_shard_queue[i] = shard;
+  }
+}
+
+void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {
+  int i;
+  run_some_expired_timers(exec_ctx, gpr_inf_future(g_clock_type), NULL, 0);
+  for (i = 0; i < NUM_SHARDS; i++) {
+    shard_type *shard = &g_shards[i];
+    gpr_mu_destroy(&shard->mu);
+    grpc_timer_heap_destroy(&shard->heap);
+  }
+  gpr_mu_destroy(&g_mu);
+  gpr_mu_destroy(&g_checker_mu);
+  g_initialized = false;
+}
+
+/* This is a cheap, but good enough, pointer hash for sharding the tasks: */
+static size_t shard_idx(const grpc_timer *info) {
+  size_t x = (size_t)info;
+  return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (NUM_SHARDS - 1);
+}
+
+static double ts_to_dbl(gpr_timespec ts) {
+  return (double)ts.tv_sec + 1e-9 * ts.tv_nsec;
+}
+
+static gpr_timespec dbl_to_ts(double d) {
+  gpr_timespec ts;
+  ts.tv_sec = (int64_t)d;
+  ts.tv_nsec = (int32_t)(1e9 * (d - (double)ts.tv_sec));
+  ts.clock_type = GPR_TIMESPAN;
+  return ts;
+}
+
+static void list_join(grpc_timer *head, grpc_timer *timer) {
+  timer->next = head;
+  timer->prev = head->prev;
+  timer->next->prev = timer->prev->next = timer;
+}
+
+static void list_remove(grpc_timer *timer) {
+  timer->next->prev = timer->prev;
+  timer->prev->next = timer->next;
+}
+
+static void swap_adjacent_shards_in_queue(uint32_t first_shard_queue_index) {
+  shard_type *temp;
+  temp = g_shard_queue[first_shard_queue_index];
+  g_shard_queue[first_shard_queue_index] =
+      g_shard_queue[first_shard_queue_index + 1];
+  g_shard_queue[first_shard_queue_index + 1] = temp;
+  g_shard_queue[first_shard_queue_index]->shard_queue_index =
+      first_shard_queue_index;
+  g_shard_queue[first_shard_queue_index + 1]->shard_queue_index =
+      first_shard_queue_index + 1;
+}
+
+static void note_deadline_change(shard_type *shard) {
+  while (shard->shard_queue_index > 0 &&
+         gpr_time_cmp(
+             shard->min_deadline,
+             g_shard_queue[shard->shard_queue_index - 1]->min_deadline) < 0) {
+    swap_adjacent_shards_in_queue(shard->shard_queue_index - 1);
+  }
+  while (shard->shard_queue_index < NUM_SHARDS - 1 &&
+         gpr_time_cmp(
+             shard->min_deadline,
+             g_shard_queue[shard->shard_queue_index + 1]->min_deadline) > 0) {
+    swap_adjacent_shards_in_queue(shard->shard_queue_index);
+  }
+}
+
+void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
+                     gpr_timespec deadline, grpc_iomgr_cb_func timer_cb,
+                     void *timer_cb_arg, gpr_timespec now) {
+  int is_first_timer = 0;
+  shard_type *shard = &g_shards[shard_idx(timer)];
+  GPR_ASSERT(deadline.clock_type == g_clock_type);
+  GPR_ASSERT(now.clock_type == g_clock_type);
+  grpc_closure_init(&timer->closure, timer_cb, timer_cb_arg);
+  timer->deadline = deadline;
+  timer->triggered = 0;
+
+  if (!g_initialized) {
+    timer->triggered = 1;
+    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, false, NULL);
+    return;
+  }
+
+  if (gpr_time_cmp(deadline, now) <= 0) {
+    timer->triggered = 1;
+    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, true, NULL);
+    return;
+  }
+
+  /* TODO(ctiller): check deadline expired */
+
+  gpr_mu_lock(&shard->mu);
+  grpc_time_averaged_stats_add_sample(&shard->stats,
+                                      ts_to_dbl(gpr_time_sub(deadline, now)));
+  if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) {
+    is_first_timer = grpc_timer_heap_add(&shard->heap, timer);
+  } else {
+    timer->heap_index = INVALID_HEAP_INDEX;
+    list_join(&shard->list, timer);
+  }
+  gpr_mu_unlock(&shard->mu);
+
+  /* Deadline may have decreased, we need to adjust the master queue.  Note
+     that there is a potential racy unlocked region here.  There could be a
+     reordering of multiple grpc_timer_init calls, at this point, but the < test
+     below should ensure that we err on the side of caution.  There could
+     also be a race with grpc_timer_check, which might beat us to the lock.  In
+     that case, it is possible that the timer that we added will have already
+     run by the time we hold the lock, but that too is a safe error.
+     Finally, it's possible that the grpc_timer_check that intervened failed to
+     trigger the new timer because the min_deadline hadn't yet been reduced.
+     In that case, the timer will simply have to wait for the next
+     grpc_timer_check. */
+  if (is_first_timer) {
+    gpr_mu_lock(&g_mu);
+    if (gpr_time_cmp(deadline, shard->min_deadline) < 0) {
+      gpr_timespec old_min_deadline = g_shard_queue[0]->min_deadline;
+      shard->min_deadline = deadline;
+      note_deadline_change(shard);
+      if (shard->shard_queue_index == 0 &&
+          gpr_time_cmp(deadline, old_min_deadline) < 0) {
+        grpc_kick_poller();
+      }
+    }
+    gpr_mu_unlock(&g_mu);
+  }
+}
+
+void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
+  shard_type *shard = &g_shards[shard_idx(timer)];
+  gpr_mu_lock(&shard->mu);
+  if (!timer->triggered) {
+    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, false, NULL);
+    timer->triggered = 1;
+    if (timer->heap_index == INVALID_HEAP_INDEX) {
+      list_remove(timer);
+    } else {
+      grpc_timer_heap_remove(&shard->heap, timer);
+    }
+  }
+  gpr_mu_unlock(&shard->mu);
+}
+
+/* This is called when the queue is empty and "now" has reached the
+   queue_deadline_cap.  We compute a new queue deadline and then scan the map
+   for timers that fall at or under it.  Returns true if the queue is no
+   longer empty.
+   REQUIRES: shard->mu locked */
+static int refill_queue(shard_type *shard, gpr_timespec now) {
+  /* Compute the new queue window width and bound by the limits: */
+  double computed_deadline_delta =
+      grpc_time_averaged_stats_update_average(&shard->stats) *
+      ADD_DEADLINE_SCALE;
+  double deadline_delta =
+      GPR_CLAMP(computed_deadline_delta, MIN_QUEUE_WINDOW_DURATION,
+                MAX_QUEUE_WINDOW_DURATION);
+  grpc_timer *timer, *next;
+
+  /* Compute the new cap and put all timers under it into the queue: */
+  shard->queue_deadline_cap = gpr_time_add(
+      gpr_time_max(now, shard->queue_deadline_cap), dbl_to_ts(deadline_delta));
+  for (timer = shard->list.next; timer != &shard->list; timer = next) {
+    next = timer->next;
+
+    if (gpr_time_cmp(timer->deadline, shard->queue_deadline_cap) < 0) {
+      list_remove(timer);
+      grpc_timer_heap_add(&shard->heap, timer);
+    }
+  }
+  return !grpc_timer_heap_is_empty(&shard->heap);
+}
+
+/* This pops the next non-cancelled timer with deadline <= now from the queue,
+   or returns NULL if there isn't one.
+   REQUIRES: shard->mu locked */
+static grpc_timer *pop_one(shard_type *shard, gpr_timespec now) {
+  grpc_timer *timer;
+  for (;;) {
+    if (grpc_timer_heap_is_empty(&shard->heap)) {
+      if (gpr_time_cmp(now, shard->queue_deadline_cap) < 0) return NULL;
+      if (!refill_queue(shard, now)) return NULL;
+    }
+    timer = grpc_timer_heap_top(&shard->heap);
+    if (gpr_time_cmp(timer->deadline, now) > 0) return NULL;
+    timer->triggered = 1;
+    grpc_timer_heap_pop(&shard->heap);
+    return timer;
+  }
+}
+
+/* REQUIRES: shard->mu unlocked */
+static size_t pop_timers(grpc_exec_ctx *exec_ctx, shard_type *shard,
+                         gpr_timespec now, gpr_timespec *new_min_deadline,
+                         int success) {
+  size_t n = 0;
+  grpc_timer *timer;
+  gpr_mu_lock(&shard->mu);
+  while ((timer = pop_one(shard, now))) {
+    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, success, NULL);
+    n++;
+  }
+  *new_min_deadline = compute_min_deadline(shard);
+  gpr_mu_unlock(&shard->mu);
+  return n;
+}
+
+static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
+                                   gpr_timespec *next, int success) {
+  size_t n = 0;
+
+  /* TODO(ctiller): verify that there are any timers (atomically) here */
+
+  if (gpr_mu_trylock(&g_checker_mu)) {
+    gpr_mu_lock(&g_mu);
+
+    while (gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) {
+      gpr_timespec new_min_deadline;
+
+      /* For efficiency, we pop as many available timers as we can from the
+         shard.  This may violate perfect timer deadline ordering, but that
+         shouldn't be a big deal because we don't make ordering guarantees. */
+      n += pop_timers(exec_ctx, g_shard_queue[0], now, &new_min_deadline,
+                      success);
+
+      /* An grpc_timer_init() on the shard could intervene here, adding a new
+         timer that is earlier than new_min_deadline.  However,
+         grpc_timer_init() will block on the master_lock before it can call
+         set_min_deadline, so this one will complete first and then the Addtimer
+         will reduce the min_deadline (perhaps unnecessarily). */
+      g_shard_queue[0]->min_deadline = new_min_deadline;
+      note_deadline_change(g_shard_queue[0]);
+    }
+
+    if (next) {
+      *next = gpr_time_min(*next, g_shard_queue[0]->min_deadline);
+    }
+
+    gpr_mu_unlock(&g_mu);
+    gpr_mu_unlock(&g_checker_mu);
+  } else if (next != NULL) {
+    /* TODO(ctiller): this forces calling code to do an short poll, and
+       then retry the timer check (because this time through the timer list was
+       contended).
+
+       We could reduce the cost here dramatically by keeping a count of how many
+       currently active pollers got through the uncontended case above
+       successfully, and waking up other pollers IFF that count drops to zero.
+
+       Once that count is in place, this entire else branch could disappear. */
+    *next = gpr_time_min(
+        *next, gpr_time_add(now, gpr_time_from_millis(1, GPR_TIMESPAN)));
+  }
+
+  return (int)n;
+}
+
+bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
+                      gpr_timespec *next) {
+  GPR_ASSERT(now.clock_type == g_clock_type);
+  return run_some_expired_timers(
+      exec_ctx, now, next,
+      gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0);
+}
diff --git a/src/core/lib/iomgr/timer.h b/src/core/lib/iomgr/timer.h
new file mode 100644
index 0000000..a825d2a
--- /dev/null
+++ b/src/core/lib/iomgr/timer.h
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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_TIMER_H
+#define GRPC_CORE_LIB_IOMGR_TIMER_H
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr.h"
+
+typedef struct grpc_timer {
+  gpr_timespec deadline;
+  uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */
+  int triggered;
+  struct grpc_timer *next;
+  struct grpc_timer *prev;
+  grpc_closure closure;
+} grpc_timer;
+
+/* Initialize *timer. When expired or canceled, timer_cb will be called with
+   *timer_cb_arg and status to indicate if it expired (SUCCESS) or was
+   canceled (CANCELLED). timer_cb is guaranteed to be called exactly once,
+   and application code should check the status to determine how it was
+   invoked. The application callback is also responsible for maintaining
+   information about when to free up any user-level state. */
+void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
+                     gpr_timespec deadline, grpc_iomgr_cb_func timer_cb,
+                     void *timer_cb_arg, gpr_timespec now);
+
+/* Note that there is no timer destroy function. This is because the
+   timer is a one-time occurrence with a guarantee that the callback will
+   be called exactly once, either at expiration or cancellation. Thus, all
+   the internal timer event management state is destroyed just before
+   that callback is invoked. If the user has additional state associated with
+   the timer, the user is responsible for determining when it is safe to
+   destroy that state. */
+
+/* Cancel an *timer.
+   There are three cases:
+   1. We normally cancel the timer
+   2. The timer has already run
+   3. We can't cancel the timer because it is "in flight".
+
+   In all of these cases, the cancellation is still considered successful.
+   They are essentially distinguished in that the timer_cb will be run
+   exactly once from either the cancellation (with status CANCELLED)
+   or from the activation (with status SUCCESS)
+
+   Note carefully that the callback function MAY occur in the same callstack
+   as grpc_timer_cancel. It's expected that most timers will be cancelled (their
+   primary use is to implement deadlines), and so this code is optimized such
+   that cancellation costs as little as possible. Making callbacks run inline
+   matches this aim.
+
+   Requires:  cancel() must happen after add() on a given timer */
+void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer);
+
+/* iomgr internal api for dealing with timers */
+
+/* Check for timers to be run, and run them.
+   Return true if timer callbacks were executed.
+   Drops drop_mu if it is non-null before executing callbacks.
+   If next is non-null, TRY to update *next with the next running timer
+   IF that timer occurs before *next current value.
+   *next is never guaranteed to be updated on any given execution; however,
+   with high probability at least one thread in the system will see an update
+   at any time slice. */
+bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
+                      gpr_timespec *next);
+void grpc_timer_list_init(gpr_timespec now);
+void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx);
+
+/* the following must be implemented by each iomgr implementation */
+
+void grpc_kick_poller(void);
+
+#endif /* GRPC_CORE_LIB_IOMGR_TIMER_H */
diff --git a/src/core/lib/iomgr/timer_heap.c b/src/core/lib/iomgr/timer_heap.c
new file mode 100644
index 0000000..2ad9bb9
--- /dev/null
+++ b/src/core/lib/iomgr/timer_heap.c
@@ -0,0 +1,146 @@
+/*
+ *
+ * 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/iomgr/timer_heap.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/useful.h>
+
+/* Adjusts a heap so as to move a hole at position i closer to the root,
+   until a suitable position is found for element t. Then, copies t into that
+   position. This functor is called each time immediately after modifying a
+   value in the underlying container, with the offset of the modified element as
+   its argument. */
+static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) {
+  while (i > 0) {
+    uint32_t parent = (uint32_t)(((int)i - 1) / 2);
+    if (gpr_time_cmp(first[parent]->deadline, t->deadline) <= 0) break;
+    first[i] = first[parent];
+    first[i]->heap_index = i;
+    i = parent;
+  }
+  first[i] = t;
+  t->heap_index = i;
+}
+
+/* Adjusts a heap so as to move a hole at position i farther away from the root,
+   until a suitable position is found for element t.  Then, copies t into that
+   position. */
+static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length,
+                             grpc_timer *t) {
+  for (;;) {
+    uint32_t left_child = 1u + 2u * i;
+    if (left_child >= length) break;
+    uint32_t right_child = left_child + 1;
+    uint32_t next_i = right_child < length &&
+                              gpr_time_cmp(first[left_child]->deadline,
+                                           first[right_child]->deadline) > 0
+                          ? right_child
+                          : left_child;
+    if (gpr_time_cmp(t->deadline, first[next_i]->deadline) <= 0) break;
+    first[i] = first[next_i];
+    first[i]->heap_index = i;
+    i = next_i;
+  }
+  first[i] = t;
+  t->heap_index = i;
+}
+
+#define SHRINK_MIN_ELEMS 8
+#define SHRINK_FULLNESS_FACTOR 2
+
+static void maybe_shrink(grpc_timer_heap *heap) {
+  if (heap->timer_count >= 8 &&
+      heap->timer_count <= heap->timer_capacity / SHRINK_FULLNESS_FACTOR / 2) {
+    heap->timer_capacity = heap->timer_count * SHRINK_FULLNESS_FACTOR;
+    heap->timers =
+        gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *));
+  }
+}
+
+static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) {
+  uint32_t i = timer->heap_index;
+  uint32_t parent = (uint32_t)(((int)i - 1) / 2);
+  if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) > 0) {
+    adjust_upwards(heap->timers, i, timer);
+  } else {
+    adjust_downwards(heap->timers, i, heap->timer_count, timer);
+  }
+}
+
+void grpc_timer_heap_init(grpc_timer_heap *heap) {
+  memset(heap, 0, sizeof(*heap));
+}
+
+void grpc_timer_heap_destroy(grpc_timer_heap *heap) { gpr_free(heap->timers); }
+
+int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer) {
+  if (heap->timer_count == heap->timer_capacity) {
+    heap->timer_capacity =
+        GPR_MAX(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2);
+    heap->timers =
+        gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *));
+  }
+  timer->heap_index = heap->timer_count;
+  adjust_upwards(heap->timers, heap->timer_count, timer);
+  heap->timer_count++;
+  return timer->heap_index == 0;
+}
+
+void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer) {
+  uint32_t i = timer->heap_index;
+  if (i == heap->timer_count - 1) {
+    heap->timer_count--;
+    maybe_shrink(heap);
+    return;
+  }
+  heap->timers[i] = heap->timers[heap->timer_count - 1];
+  heap->timers[i]->heap_index = i;
+  heap->timer_count--;
+  maybe_shrink(heap);
+  note_changed_priority(heap, heap->timers[i]);
+}
+
+int grpc_timer_heap_is_empty(grpc_timer_heap *heap) {
+  return heap->timer_count == 0;
+}
+
+grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap) {
+  return heap->timers[0];
+}
+
+void grpc_timer_heap_pop(grpc_timer_heap *heap) {
+  grpc_timer_heap_remove(heap, grpc_timer_heap_top(heap));
+}
diff --git a/src/core/lib/iomgr/timer_heap.h b/src/core/lib/iomgr/timer_heap.h
new file mode 100644
index 0000000..576c20e
--- /dev/null
+++ b/src/core/lib/iomgr/timer_heap.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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_TIMER_HEAP_H
+#define GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H
+
+#include "src/core/lib/iomgr/timer.h"
+
+typedef struct {
+  grpc_timer **timers;
+  uint32_t timer_count;
+  uint32_t timer_capacity;
+} grpc_timer_heap;
+
+/* return 1 if the new timer is the first timer in the heap */
+int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer);
+
+void grpc_timer_heap_init(grpc_timer_heap *heap);
+void grpc_timer_heap_destroy(grpc_timer_heap *heap);
+
+void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer);
+grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap);
+void grpc_timer_heap_pop(grpc_timer_heap *heap);
+
+int grpc_timer_heap_is_empty(grpc_timer_heap *heap);
+
+#endif /* GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H */
diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c
new file mode 100644
index 0000000..df6cf95
--- /dev/null
+++ b/src/core/lib/iomgr/udp_server.c
@@ -0,0 +1,406 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GRPC_NEED_UDP
+#ifdef GPR_POSIX_SOCKET
+
+#include "src/core/lib/iomgr/udp_server.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grpc/grpc.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>
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/support/string.h"
+
+#define INIT_PORT_CAP 2
+
+/* one listening port */
+typedef struct {
+  int fd;
+  grpc_fd *emfd;
+  grpc_udp_server *server;
+  union {
+    uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE];
+    struct sockaddr sockaddr;
+  } addr;
+  size_t addr_len;
+  grpc_closure read_closure;
+  grpc_closure destroyed_closure;
+  grpc_udp_server_read_cb read_cb;
+} server_port;
+
+/* the overall server */
+struct grpc_udp_server {
+  gpr_mu mu;
+  gpr_cv cv;
+
+  /* active port count: how many ports are actually still listening */
+  size_t active_ports;
+  /* destroyed port count: how many ports are completely destroyed */
+  size_t destroyed_ports;
+
+  /* is this server shutting down? (boolean) */
+  int shutdown;
+
+  /* all listening ports */
+  server_port *ports;
+  size_t nports;
+  size_t port_capacity;
+
+  /* shutdown callback */
+  grpc_closure *shutdown_complete;
+
+  /* all pollsets interested in new connections */
+  grpc_pollset **pollsets;
+  /* number of pollsets in the pollsets array */
+  size_t pollset_count;
+  /* The parent grpc server */
+  grpc_server *grpc_server;
+};
+
+grpc_udp_server *grpc_udp_server_create(void) {
+  grpc_udp_server *s = gpr_malloc(sizeof(grpc_udp_server));
+  gpr_mu_init(&s->mu);
+  gpr_cv_init(&s->cv);
+  s->active_ports = 0;
+  s->destroyed_ports = 0;
+  s->shutdown = 0;
+  s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
+  s->nports = 0;
+  s->port_capacity = INIT_PORT_CAP;
+
+  return s;
+}
+
+static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
+  grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1, NULL);
+
+  gpr_mu_destroy(&s->mu);
+  gpr_cv_destroy(&s->cv);
+
+  gpr_free(s->ports);
+  gpr_free(s);
+}
+
+static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
+                           bool success) {
+  grpc_udp_server *s = server;
+  gpr_mu_lock(&s->mu);
+  s->destroyed_ports++;
+  if (s->destroyed_ports == s->nports) {
+    gpr_mu_unlock(&s->mu);
+    finish_shutdown(exec_ctx, s);
+  } else {
+    gpr_mu_unlock(&s->mu);
+  }
+}
+
+/* called when all listening endpoints have been shutdown, so no further
+   events will be received on them - at this point it's safe to destroy
+   things */
+static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
+  size_t i;
+
+  /* delete ALL the things */
+  gpr_mu_lock(&s->mu);
+
+  if (!s->shutdown) {
+    gpr_mu_unlock(&s->mu);
+    return;
+  }
+
+  if (s->nports) {
+    for (i = 0; i < s->nports; i++) {
+      server_port *sp = &s->ports[i];
+      sp->destroyed_closure.cb = destroyed_port;
+      sp->destroyed_closure.cb_arg = s;
+      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
+                     "udp_listener_shutdown");
+    }
+    gpr_mu_unlock(&s->mu);
+  } else {
+    gpr_mu_unlock(&s->mu);
+    finish_shutdown(exec_ctx, s);
+  }
+}
+
+void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
+                             grpc_closure *on_done) {
+  size_t i;
+  gpr_mu_lock(&s->mu);
+
+  GPR_ASSERT(!s->shutdown);
+  s->shutdown = 1;
+
+  s->shutdown_complete = on_done;
+
+  /* shutdown all fd's */
+  if (s->active_ports) {
+    for (i = 0; i < s->nports; i++) {
+      grpc_fd_shutdown(exec_ctx, s->ports[i].emfd);
+    }
+    gpr_mu_unlock(&s->mu);
+  } else {
+    gpr_mu_unlock(&s->mu);
+    deactivated_all_ports(exec_ctx, s);
+  }
+}
+
+/* Prepare a recently-created socket for listening. */
+static int prepare_socket(int fd, const struct sockaddr *addr,
+                          size_t addr_len) {
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
+
+  if (fd < 0) {
+    goto error;
+  }
+
+  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1)) {
+    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
+            strerror(errno));
+  }
+
+  if (grpc_set_socket_ip_pktinfo_if_possible(fd) &&
+      addr->sa_family == AF_INET6) {
+    grpc_set_socket_ipv6_recvpktinfo_if_possible(fd);
+  }
+
+  GPR_ASSERT(addr_len < ~(socklen_t)0);
+  if (bind(fd, addr, (socklen_t)addr_len) < 0) {
+    char *addr_str;
+    grpc_sockaddr_to_string(&addr_str, addr, 0);
+    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
+    gpr_free(addr_str);
+    goto error;
+  }
+
+  sockname_len = sizeof(sockname_temp);
+  if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
+    goto error;
+  }
+
+  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+
+error:
+  if (fd >= 0) {
+    close(fd);
+  }
+  return -1;
+}
+
+/* event manager callback when reads are ready */
+static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  server_port *sp = arg;
+
+  if (!success) {
+    gpr_mu_lock(&sp->server->mu);
+    if (0 == --sp->server->active_ports) {
+      gpr_mu_unlock(&sp->server->mu);
+      deactivated_all_ports(exec_ctx, sp->server);
+    } else {
+      gpr_mu_unlock(&sp->server->mu);
+    }
+    return;
+  }
+
+  /* Tell the registered callback that data is available to read. */
+  GPR_ASSERT(sp->read_cb);
+  sp->read_cb(exec_ctx, sp->emfd, sp->server->grpc_server);
+
+  /* Re-arm the notification event so we get another chance to read. */
+  grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
+}
+
+static int add_socket_to_server(grpc_udp_server *s, int fd,
+                                const struct sockaddr *addr, size_t addr_len,
+                                grpc_udp_server_read_cb read_cb) {
+  server_port *sp;
+  int port;
+  char *addr_str;
+  char *name;
+
+  port = prepare_socket(fd, addr, addr_len);
+  if (port >= 0) {
+    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
+    gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
+    gpr_free(addr_str);
+    gpr_mu_lock(&s->mu);
+    /* append it to the list under a lock */
+    if (s->nports == s->port_capacity) {
+      s->port_capacity *= 2;
+      s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
+    }
+    sp = &s->ports[s->nports++];
+    sp->server = s;
+    sp->fd = fd;
+    sp->emfd = grpc_fd_create(fd, name);
+    memcpy(sp->addr.untyped, addr, addr_len);
+    sp->addr_len = addr_len;
+    sp->read_cb = read_cb;
+    GPR_ASSERT(sp->emfd);
+    gpr_mu_unlock(&s->mu);
+    gpr_free(name);
+  }
+
+  return port;
+}
+
+int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
+                             size_t addr_len, grpc_udp_server_read_cb read_cb) {
+  int allocated_port1 = -1;
+  int allocated_port2 = -1;
+  unsigned i;
+  int fd;
+  grpc_dualstack_mode dsmode;
+  struct sockaddr_in6 addr6_v4mapped;
+  struct sockaddr_in wild4;
+  struct sockaddr_in6 wild6;
+  struct sockaddr_in addr4_copy;
+  struct sockaddr *allocated_addr = NULL;
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
+  int port;
+
+  /* Check if this is a wildcard port, and if so, try to keep the port the same
+     as some previously created listener. */
+  if (grpc_sockaddr_get_port(addr) == 0) {
+    for (i = 0; i < s->nports; i++) {
+      sockname_len = sizeof(sockname_temp);
+      if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
+                           &sockname_len)) {
+        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+        if (port > 0) {
+          allocated_addr = gpr_malloc(addr_len);
+          memcpy(allocated_addr, addr, addr_len);
+          grpc_sockaddr_set_port(allocated_addr, port);
+          addr = allocated_addr;
+          break;
+        }
+      }
+    }
+  }
+
+  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
+    addr = (const struct sockaddr *)&addr6_v4mapped;
+    addr_len = sizeof(addr6_v4mapped);
+  }
+
+  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
+  if (grpc_sockaddr_is_wildcard(addr, &port)) {
+    grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
+
+    /* Try listening on IPv6 first. */
+    addr = (struct sockaddr *)&wild6;
+    addr_len = sizeof(wild6);
+    fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode);
+    allocated_port1 = add_socket_to_server(s, fd, addr, addr_len, read_cb);
+    if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
+      goto done;
+    }
+
+    /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
+    if (port == 0 && allocated_port1 > 0) {
+      grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
+    }
+    addr = (struct sockaddr *)&wild4;
+    addr_len = sizeof(wild4);
+  }
+
+  fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode);
+  if (fd < 0) {
+    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
+  }
+  if (dsmode == GRPC_DSMODE_IPV4 &&
+      grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
+    addr = (struct sockaddr *)&addr4_copy;
+    addr_len = sizeof(addr4_copy);
+  }
+  allocated_port2 = add_socket_to_server(s, fd, addr, addr_len, read_cb);
+
+done:
+  gpr_free(allocated_addr);
+  return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
+}
+
+int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index) {
+  return (port_index < s->nports) ? s->ports[port_index].fd : -1;
+}
+
+void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
+                           grpc_pollset **pollsets, size_t pollset_count,
+                           grpc_server *server) {
+  size_t i, j;
+  gpr_mu_lock(&s->mu);
+  GPR_ASSERT(s->active_ports == 0);
+  s->pollsets = pollsets;
+  s->grpc_server = server;
+  for (i = 0; i < s->nports; i++) {
+    for (j = 0; j < pollset_count; j++) {
+      grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd);
+    }
+    s->ports[i].read_closure.cb = on_read;
+    s->ports[i].read_closure.cb_arg = &s->ports[i];
+    grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd,
+                           &s->ports[i].read_closure);
+    s->active_ports++;
+  }
+  gpr_mu_unlock(&s->mu);
+}
+
+#endif
+#endif
diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h
new file mode 100644
index 0000000..d8cf957
--- /dev/null
+++ b/src/core/lib/iomgr/udp_server.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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_UDP_SERVER_H
+#define GRPC_CORE_LIB_IOMGR_UDP_SERVER_H
+
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/ev_posix.h"
+
+/* Forward decl of struct grpc_server */
+/* This is not typedef'ed to avoid a typedef-redefinition error */
+struct grpc_server;
+
+/* Forward decl of grpc_udp_server */
+typedef struct grpc_udp_server grpc_udp_server;
+
+/* Called when data is available to read from the socket. */
+typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
+                                        struct grpc_server *server);
+
+/* Create a server, initially not bound to any ports */
+grpc_udp_server *grpc_udp_server_create(void);
+
+/* Start listening to bound ports */
+void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server,
+                           grpc_pollset **pollsets, size_t pollset_count,
+                           struct grpc_server *server);
+
+int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index);
+
+/* Add a port to the server, returning port number on success, or negative
+   on failure.
+
+   The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
+   both IPv4 and IPv6 connections, but :: is the preferred style.  This usually
+   creates one socket, but possibly two on systems which support IPv6,
+   but not dualstack sockets. */
+
+/* TODO(ctiller): deprecate this, and make grpc_udp_server_add_ports to handle
+                  all of the multiple socket port matching logic in one place */
+int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
+                             size_t addr_len, grpc_udp_server_read_cb read_cb);
+
+void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server,
+                             grpc_closure *on_done);
+
+#endif /* GRPC_CORE_LIB_IOMGR_UDP_SERVER_H */
diff --git a/src/core/lib/iomgr/unix_sockets_posix.c b/src/core/lib/iomgr/unix_sockets_posix.c
new file mode 100644
index 0000000..5767c85
--- /dev/null
+++ b/src/core/lib/iomgr/unix_sockets_posix.c
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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/iomgr/unix_sockets_posix.h"
+
+#ifdef GPR_HAVE_UNIX_SOCKET
+
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+void grpc_create_socketpair_if_unix(int sv[2]) {
+  GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
+}
+
+grpc_resolved_addresses *grpc_resolve_unix_domain_address(const char *name) {
+  struct sockaddr_un *un;
+
+  grpc_resolved_addresses *addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
+  addrs->naddrs = 1;
+  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address));
+  un = (struct sockaddr_un *)addrs->addrs->addr;
+  un->sun_family = AF_UNIX;
+  strcpy(un->sun_path, name);
+  addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
+  return addrs;
+}
+
+int grpc_is_unix_socket(const struct sockaddr *addr) {
+  return addr->sa_family == AF_UNIX;
+}
+
+void grpc_unlink_if_unix_domain_socket(const struct sockaddr *addr) {
+  if (addr->sa_family != AF_UNIX) {
+    return;
+  }
+  struct sockaddr_un *un = (struct sockaddr_un *)addr;
+  struct stat st;
+
+  if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
+    unlink(un->sun_path);
+  }
+}
+
+char *grpc_sockaddr_to_uri_unix_if_possible(const struct sockaddr *addr) {
+  if (addr->sa_family != AF_UNIX) {
+    return NULL;
+  }
+
+  char *result;
+  gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path);
+  return result;
+}
+
+#endif
diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h
new file mode 100644
index 0000000..6758c49
--- /dev/null
+++ b/src/core/lib/iomgr/unix_sockets_posix.h
@@ -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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
+void grpc_create_socketpair_if_unix(int sv[2]);
+
+grpc_resolved_addresses *grpc_resolve_unix_domain_address(const char *name);
+
+int grpc_is_unix_socket(const struct sockaddr *addr);
+
+void grpc_unlink_if_unix_domain_socket(const struct sockaddr *addr);
+
+char *grpc_sockaddr_to_uri_unix_if_possible(const struct sockaddr *addr);
+
+#endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */
diff --git a/src/core/lib/iomgr/unix_sockets_posix_noop.c b/src/core/lib/iomgr/unix_sockets_posix_noop.c
new file mode 100644
index 0000000..d309527
--- /dev/null
+++ b/src/core/lib/iomgr/unix_sockets_posix_noop.c
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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/iomgr/unix_sockets_posix.h"
+
+#ifndef GPR_HAVE_UNIX_SOCKET
+
+#include <grpc/support/log.h>
+
+void grpc_create_socketpair_if_unix(int sv[2]) {
+  // TODO: Either implement this for the non-Unix socket case or make
+  // sure that it is never called in any such case. Until then, leave an
+  // assertion to notify if this gets called inadvertently
+  GPR_ASSERT(0);
+}
+
+grpc_resolved_addresses *grpc_resolve_unix_domain_address(const char *name) {
+  return NULL;
+}
+
+int grpc_is_unix_socket(const struct sockaddr *addr) { return false; }
+
+void grpc_unlink_if_unix_domain_socket(const struct sockaddr *addr) {}
+
+char *grpc_sockaddr_to_uri_unix_if_possible(const struct sockaddr *addr) {
+  return NULL;
+}
+
+#endif
diff --git a/src/core/lib/iomgr/wakeup_fd_eventfd.c b/src/core/lib/iomgr/wakeup_fd_eventfd.c
new file mode 100644
index 0000000..8a772ad
--- /dev/null
+++ b/src/core/lib/iomgr/wakeup_fd_eventfd.c
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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_LINUX_EVENTFD
+
+#include <errno.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+#include "src/core/lib/profiling/timers.h"
+
+static void eventfd_create(grpc_wakeup_fd* fd_info) {
+  int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+  /* TODO(klempner): Handle failure more gracefully */
+  GPR_ASSERT(efd >= 0);
+  fd_info->read_fd = efd;
+  fd_info->write_fd = -1;
+}
+
+static void eventfd_consume(grpc_wakeup_fd* fd_info) {
+  eventfd_t value;
+  int err;
+  do {
+    err = eventfd_read(fd_info->read_fd, &value);
+  } while (err < 0 && errno == EINTR);
+}
+
+static void eventfd_wakeup(grpc_wakeup_fd* fd_info) {
+  int err;
+  GPR_TIMER_BEGIN("eventfd_wakeup", 0);
+  do {
+    err = eventfd_write(fd_info->read_fd, 1);
+  } while (err < 0 && errno == EINTR);
+  GPR_TIMER_END("eventfd_wakeup", 0);
+}
+
+static void eventfd_destroy(grpc_wakeup_fd* fd_info) {
+  if (fd_info->read_fd != 0) close(fd_info->read_fd);
+}
+
+static int eventfd_check_availability(void) {
+  /* TODO(klempner): Actually check if eventfd is available */
+  return 1;
+}
+
+const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = {
+    eventfd_create, eventfd_consume, eventfd_wakeup, eventfd_destroy,
+    eventfd_check_availability};
+
+#endif /* GPR_LINUX_EVENTFD */
diff --git a/src/core/lib/iomgr/wakeup_fd_nospecial.c b/src/core/lib/iomgr/wakeup_fd_nospecial.c
new file mode 100644
index 0000000..cb2f707
--- /dev/null
+++ b/src/core/lib/iomgr/wakeup_fd_nospecial.c
@@ -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.
+ *
+ */
+
+/*
+ * This is a dummy file to provide an invalid specialized_wakeup_fd_vtable on
+ * systems without anything better than pipe.
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_NO_SPECIAL_WAKEUP_FD
+
+#include <stddef.h>
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+
+static int check_availability_invalid(void) { return 0; }
+
+const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = {
+    NULL, NULL, NULL, NULL, check_availability_invalid};
+
+#endif /* GPR_POSIX_NO_SPECIAL_WAKEUP_FD */
diff --git a/src/core/lib/iomgr/wakeup_fd_pipe.c b/src/core/lib/iomgr/wakeup_fd_pipe.c
new file mode 100644
index 0000000..e9b9a01
--- /dev/null
+++ b/src/core/lib/iomgr/wakeup_fd_pipe.c
@@ -0,0 +1,102 @@
+/*
+ *
+ * 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_WAKEUP_FD
+
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+
+static void pipe_init(grpc_wakeup_fd* fd_info) {
+  int pipefd[2];
+  /* TODO(klempner): Make this nonfatal */
+  int r = pipe(pipefd);
+  if (0 != r) {
+    gpr_log(GPR_ERROR, "pipe creation failed (%d): %s", errno, strerror(errno));
+    abort();
+  }
+  GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[0], 1));
+  GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[1], 1));
+  fd_info->read_fd = pipefd[0];
+  fd_info->write_fd = pipefd[1];
+}
+
+static void pipe_consume(grpc_wakeup_fd* fd_info) {
+  char buf[128];
+  ssize_t r;
+
+  for (;;) {
+    r = read(fd_info->read_fd, buf, sizeof(buf));
+    if (r > 0) continue;
+    if (r == 0) return;
+    switch (errno) {
+      case EAGAIN:
+        return;
+      case EINTR:
+        continue;
+      default:
+        gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno));
+        return;
+    }
+  }
+}
+
+static void pipe_wakeup(grpc_wakeup_fd* fd_info) {
+  char c = 0;
+  while (write(fd_info->write_fd, &c, 1) != 1 && errno == EINTR)
+    ;
+}
+
+static void pipe_destroy(grpc_wakeup_fd* fd_info) {
+  if (fd_info->read_fd != 0) close(fd_info->read_fd);
+  if (fd_info->write_fd != 0) close(fd_info->write_fd);
+}
+
+static int pipe_check_availability(void) {
+  /* Assume that pipes are always available. */
+  return 1;
+}
+
+const grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable = {
+    pipe_init, pipe_consume, pipe_wakeup, pipe_destroy,
+    pipe_check_availability};
+
+#endif /* GPR_POSIX_WAKUP_FD */
diff --git a/src/core/lib/iomgr/wakeup_fd_pipe.h b/src/core/lib/iomgr/wakeup_fd_pipe.h
new file mode 100644
index 0000000..8972efc
--- /dev/null
+++ b/src/core/lib/iomgr/wakeup_fd_pipe.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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_WAKEUP_FD_PIPE_H
+#define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_PIPE_H
+
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+
+extern grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable;
+
+#endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_PIPE_H */
diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c
new file mode 100644
index 0000000..525369c
--- /dev/null
+++ b/src/core/lib/iomgr/wakeup_fd_posix.c
@@ -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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_WAKEUP_FD
+
+#include <stddef.h>
+#include "src/core/lib/iomgr/wakeup_fd_pipe.h"
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+
+static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL;
+int grpc_allow_specialized_wakeup_fd = 1;
+
+void grpc_wakeup_fd_global_init(void) {
+  if (grpc_allow_specialized_wakeup_fd &&
+      grpc_specialized_wakeup_fd_vtable.check_availability()) {
+    wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable;
+  } else {
+    wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable;
+  }
+}
+
+void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; }
+
+void grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) {
+  wakeup_fd_vtable->init(fd_info);
+}
+
+void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) {
+  wakeup_fd_vtable->consume(fd_info);
+}
+
+void grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) {
+  wakeup_fd_vtable->wakeup(fd_info);
+}
+
+void grpc_wakeup_fd_destroy(grpc_wakeup_fd *fd_info) {
+  wakeup_fd_vtable->destroy(fd_info);
+}
+
+#endif /* GPR_POSIX_WAKEUP_FD */
diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h
new file mode 100644
index 0000000..6b069c1
--- /dev/null
+++ b/src/core/lib/iomgr/wakeup_fd_posix.h
@@ -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.
+ *
+ */
+
+/*
+ * wakeup_fd abstracts the concept of a file descriptor for the purpose of
+ * waking up a thread in select()/poll()/epoll_wait()/etc.
+
+ * The poll() family of system calls provide a way for a thread to block until
+ * there is activity on one (or more) of a set of file descriptors. An
+ * application may wish to wake up this thread to do non file related work. The
+ * typical way to do this is to add a pipe to the set of file descriptors, then
+ * write to the pipe to wake up the thread in poll().
+ *
+ * Linux has a lighter weight eventfd specifically designed for this purpose.
+ * wakeup_fd abstracts the difference between the two.
+ *
+ * Setup:
+ * 1. Before calling anything, call global_init() at least once.
+ * 1. Call grpc_wakeup_fd_create() to get a wakeup_fd.
+ * 2. Add the result of GRPC_WAKEUP_FD_FD to the set of monitored file
+ *    descriptors for the poll() style API you are using. Monitor the file
+ *    descriptor for readability.
+ * 3. To tear down, call grpc_wakeup_fd_destroy(). This closes the underlying
+ *    file descriptor.
+ *
+ * Usage:
+ * 1. To wake up a polling thread, call grpc_wakeup_fd_wakeup() on a wakeup_fd
+ *    it is monitoring.
+ * 2. If the polling thread was awakened by a wakeup_fd event, call
+ *    grpc_wakeup_fd_consume_wakeup() on it.
+ */
+#ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H
+
+void grpc_wakeup_fd_global_init(void);
+void grpc_wakeup_fd_global_destroy(void);
+
+/* Force using the fallback implementation. This is intended for testing
+ * purposes only.*/
+void grpc_wakeup_fd_global_init_force_fallback(void);
+
+typedef struct grpc_wakeup_fd grpc_wakeup_fd;
+
+typedef struct grpc_wakeup_fd_vtable {
+  void (*init)(grpc_wakeup_fd* fd_info);
+  void (*consume)(grpc_wakeup_fd* fd_info);
+  void (*wakeup)(grpc_wakeup_fd* fd_info);
+  void (*destroy)(grpc_wakeup_fd* fd_info);
+  /* Must be called before calling any other functions */
+  int (*check_availability)(void);
+} grpc_wakeup_fd_vtable;
+
+struct grpc_wakeup_fd {
+  int read_fd;
+  int write_fd;
+};
+
+extern int grpc_allow_specialized_wakeup_fd;
+
+#define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd)
+
+void grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info);
+void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info);
+void grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info);
+void grpc_wakeup_fd_destroy(grpc_wakeup_fd* fd_info);
+
+/* Defined in some specialized implementation's .c file, or by
+ * wakeup_fd_nospecial.c if no such implementation exists. */
+extern const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable;
+
+#endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H */
diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h
new file mode 100644
index 0000000..3e2b223
--- /dev/null
+++ b/src/core/lib/iomgr/workqueue.h
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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_WORKQUEUE_H
+#define GRPC_CORE_LIB_IOMGR_WORKQUEUE_H
+
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/pollset.h"
+
+#ifdef GPR_POSIX_SOCKET
+#include "src/core/lib/iomgr/workqueue_posix.h"
+#endif
+
+#ifdef GPR_WIN32
+#include "src/core/lib/iomgr/workqueue_windows.h"
+#endif
+
+/* grpc_workqueue is forward declared in exec_ctx.h */
+
+/** Create a work queue */
+grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx);
+
+void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue);
+
+#define GRPC_WORKQUEUE_REFCOUNT_DEBUG
+#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG
+#define GRPC_WORKQUEUE_REF(p, r) \
+  grpc_workqueue_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_WORKQUEUE_UNREF(cl, p, r) \
+  grpc_workqueue_unref((cl), (p), __FILE__, __LINE__, (r))
+void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line,
+                        const char *reason);
+void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue,
+                          const char *file, int line, const char *reason);
+#else
+#define GRPC_WORKQUEUE_REF(p, r) grpc_workqueue_ref((p))
+#define GRPC_WORKQUEUE_UNREF(cl, p, r) grpc_workqueue_unref((cl), (p))
+void grpc_workqueue_ref(grpc_workqueue *workqueue);
+void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue);
+#endif
+
+/** Bind this workqueue to a pollset */
+void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx,
+                                   grpc_workqueue *workqueue,
+                                   grpc_pollset *pollset);
+
+/** Add a work item to a workqueue */
+void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure,
+                         int success);
+
+#endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_H */
diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c
new file mode 100644
index 0000000..80e7a0b
--- /dev/null
+++ b/src/core/lib/iomgr/workqueue_posix.c
@@ -0,0 +1,143 @@
+/*
+ *
+ * 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_SOCKET
+
+#include "src/core/lib/iomgr/workqueue.h"
+
+#include <stdio.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/iomgr/ev_posix.h"
+
+static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success);
+
+grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx) {
+  char name[32];
+  grpc_workqueue *workqueue = gpr_malloc(sizeof(grpc_workqueue));
+  gpr_ref_init(&workqueue->refs, 1);
+  gpr_mu_init(&workqueue->mu);
+  workqueue->closure_list.head = workqueue->closure_list.tail = NULL;
+  grpc_wakeup_fd_init(&workqueue->wakeup_fd);
+  sprintf(name, "workqueue:%p", (void *)workqueue);
+  workqueue->wakeup_read_fd =
+      grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&workqueue->wakeup_fd), name);
+  grpc_closure_init(&workqueue->read_closure, on_readable, workqueue);
+  grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,
+                         &workqueue->read_closure);
+  return workqueue;
+}
+
+static void workqueue_destroy(grpc_exec_ctx *exec_ctx,
+                              grpc_workqueue *workqueue) {
+  GPR_ASSERT(grpc_closure_list_empty(workqueue->closure_list));
+  grpc_fd_shutdown(exec_ctx, workqueue->wakeup_read_fd);
+}
+
+#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG
+void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line,
+                        const char *reason) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p   ref %d -> %d %s",
+          workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count + 1,
+          reason);
+#else
+void grpc_workqueue_ref(grpc_workqueue *workqueue) {
+#endif
+  gpr_ref(&workqueue->refs);
+}
+
+#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG
+void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue,
+                          const char *file, int line, const char *reason) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p unref %d -> %d %s",
+          workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count - 1,
+          reason);
+#else
+void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
+#endif
+  if (gpr_unref(&workqueue->refs)) {
+    workqueue_destroy(exec_ctx, workqueue);
+  }
+}
+
+void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx,
+                                   grpc_workqueue *workqueue,
+                                   grpc_pollset *pollset) {
+  grpc_pollset_add_fd(exec_ctx, pollset, workqueue->wakeup_read_fd);
+}
+
+void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
+  gpr_mu_lock(&workqueue->mu);
+  if (grpc_closure_list_empty(workqueue->closure_list)) {
+    grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
+  }
+  grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
+  gpr_mu_unlock(&workqueue->mu);
+}
+
+static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  grpc_workqueue *workqueue = arg;
+
+  if (!success) {
+    gpr_mu_destroy(&workqueue->mu);
+    /* HACK: let wakeup_fd code know that we stole the fd */
+    workqueue->wakeup_fd.read_fd = 0;
+    grpc_wakeup_fd_destroy(&workqueue->wakeup_fd);
+    grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy");
+    gpr_free(workqueue);
+  } else {
+    gpr_mu_lock(&workqueue->mu);
+    grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
+    grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd);
+    gpr_mu_unlock(&workqueue->mu);
+    grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,
+                           &workqueue->read_closure);
+  }
+}
+
+void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure,
+                         int success) {
+  gpr_mu_lock(&workqueue->mu);
+  if (grpc_closure_list_empty(workqueue->closure_list)) {
+    grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
+  }
+  grpc_closure_list_add(&workqueue->closure_list, closure, success);
+  gpr_mu_unlock(&workqueue->mu);
+}
+
+#endif /* GPR_POSIX_SOCKET */
diff --git a/src/core/lib/iomgr/workqueue_posix.h b/src/core/lib/iomgr/workqueue_posix.h
new file mode 100644
index 0000000..dcb47e7
--- /dev/null
+++ b/src/core/lib/iomgr/workqueue_posix.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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_WORKQUEUE_POSIX_H
+#define GRPC_CORE_LIB_IOMGR_WORKQUEUE_POSIX_H
+
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+
+struct grpc_fd;
+
+struct grpc_workqueue {
+  gpr_refcount refs;
+
+  gpr_mu mu;
+  grpc_closure_list closure_list;
+
+  grpc_wakeup_fd wakeup_fd;
+  struct grpc_fd *wakeup_read_fd;
+
+  grpc_closure read_closure;
+};
+
+#endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_POSIX_H */
diff --git a/src/core/lib/iomgr/workqueue_windows.c b/src/core/lib/iomgr/workqueue_windows.c
new file mode 100644
index 0000000..c3c0446
--- /dev/null
+++ b/src/core/lib/iomgr/workqueue_windows.c
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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/iomgr/workqueue.h"
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/lib/iomgr/workqueue_windows.h b/src/core/lib/iomgr/workqueue_windows.h
new file mode 100644
index 0000000..e5d5913
--- /dev/null
+++ b/src/core/lib/iomgr/workqueue_windows.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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_WORKQUEUE_WINDOWS_H
+#define GRPC_CORE_LIB_IOMGR_WORKQUEUE_WINDOWS_H
+
+#endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_WINDOWS_H */
diff --git a/src/core/lib/json/json.c b/src/core/lib/json/json.c
new file mode 100644
index 0000000..5b583a1
--- /dev/null
+++ b/src/core/lib/json/json.c
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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 <grpc/support/alloc.h>
+
+#include "src/core/lib/json/json.h"
+
+grpc_json *grpc_json_create(grpc_json_type type) {
+  grpc_json *json = gpr_malloc(sizeof(*json));
+  memset(json, 0, sizeof(*json));
+  json->type = type;
+
+  return json;
+}
+
+void grpc_json_destroy(grpc_json *json) {
+  while (json->child) {
+    grpc_json_destroy(json->child);
+  }
+
+  if (json->next) {
+    json->next->prev = json->prev;
+  }
+
+  if (json->prev) {
+    json->prev->next = json->next;
+  } else if (json->parent) {
+    json->parent->child = json->next;
+  }
+
+  gpr_free(json);
+}
diff --git a/src/core/lib/json/json.h b/src/core/lib/json/json.h
new file mode 100644
index 0000000..681df4b
--- /dev/null
+++ b/src/core/lib/json/json.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_JSON_JSON_H
+#define GRPC_CORE_LIB_JSON_JSON_H
+
+#include <stdlib.h>
+
+#include "src/core/lib/json/json_common.h"
+
+/* A tree-like structure to hold json values. The key and value pointers
+ * are not owned by it.
+ */
+typedef struct grpc_json {
+  struct grpc_json *next;
+  struct grpc_json *prev;
+  struct grpc_json *child;
+  struct grpc_json *parent;
+
+  grpc_json_type type;
+  const char *key;
+  const char *value;
+} grpc_json;
+
+/* The next two functions are going to parse the input string, and
+ * modify it in the process, in order to use its space to store
+ * all of the keys and values for the returned object tree.
+ *
+ * They assume UTF-8 input stream, and will output UTF-8 encoded
+ * strings in the tree. The input stream's UTF-8 isn't validated,
+ * as in, what you input is what you get as an output.
+ *
+ * All the keys and values in the grpc_json objects will be strings
+ * pointing at your input buffer.
+ *
+ * Delete the allocated tree afterward using grpc_json_destroy().
+ */
+grpc_json *grpc_json_parse_string_with_len(char *input, size_t size);
+grpc_json *grpc_json_parse_string(char *input);
+
+/* This function will create a new string using gpr_realloc, and will
+ * deserialize the grpc_json tree into it. It'll be zero-terminated,
+ * but will be allocated in chunks of 256 bytes.
+ *
+ * The indent parameter controls the way the output is formatted.
+ * If indent is 0, then newlines will be suppressed as well, and the
+ * output will be condensed at its maximum.
+ */
+char *grpc_json_dump_to_string(grpc_json *json, int indent);
+
+/* Use these to create or delete a grpc_json object.
+ * Deletion is recursive. We will not attempt to free any of the strings
+ * in any of the objects of that tree.
+ */
+grpc_json *grpc_json_create(grpc_json_type type);
+void grpc_json_destroy(grpc_json *json);
+
+#endif /* GRPC_CORE_LIB_JSON_JSON_H */
diff --git a/src/core/lib/json/json_common.h b/src/core/lib/json/json_common.h
new file mode 100644
index 0000000..fa13088
--- /dev/null
+++ b/src/core/lib/json/json_common.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_JSON_JSON_COMMON_H
+#define GRPC_CORE_LIB_JSON_JSON_COMMON_H
+
+/* The various json types. */
+typedef enum {
+  GRPC_JSON_OBJECT,
+  GRPC_JSON_ARRAY,
+  GRPC_JSON_STRING,
+  GRPC_JSON_NUMBER,
+  GRPC_JSON_TRUE,
+  GRPC_JSON_FALSE,
+  GRPC_JSON_NULL,
+  GRPC_JSON_TOP_LEVEL
+} grpc_json_type;
+
+#endif /* GRPC_CORE_LIB_JSON_JSON_COMMON_H */
diff --git a/src/core/lib/json/json_reader.c b/src/core/lib/json/json_reader.c
new file mode 100644
index 0000000..bc04bcc
--- /dev/null
+++ b/src/core/lib/json/json_reader.c
@@ -0,0 +1,671 @@
+/*
+ *
+ * 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 <grpc/support/port_platform.h>
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/json/json_reader.h"
+
+static void json_reader_string_clear(grpc_json_reader *reader) {
+  reader->vtable->string_clear(reader->userdata);
+}
+
+static void json_reader_string_add_char(grpc_json_reader *reader, uint32_t c) {
+  reader->vtable->string_add_char(reader->userdata, c);
+}
+
+static void json_reader_string_add_utf32(grpc_json_reader *reader,
+                                         uint32_t utf32) {
+  reader->vtable->string_add_utf32(reader->userdata, utf32);
+}
+
+static uint32_t grpc_json_reader_read_char(grpc_json_reader *reader) {
+  return reader->vtable->read_char(reader->userdata);
+}
+
+static void json_reader_container_begins(grpc_json_reader *reader,
+                                         grpc_json_type type) {
+  reader->vtable->container_begins(reader->userdata, type);
+}
+
+static grpc_json_type grpc_json_reader_container_ends(
+    grpc_json_reader *reader) {
+  return reader->vtable->container_ends(reader->userdata);
+}
+
+static void json_reader_set_key(grpc_json_reader *reader) {
+  reader->vtable->set_key(reader->userdata);
+}
+
+static void json_reader_set_string(grpc_json_reader *reader) {
+  reader->vtable->set_string(reader->userdata);
+}
+
+static int json_reader_set_number(grpc_json_reader *reader) {
+  return reader->vtable->set_number(reader->userdata);
+}
+
+static void json_reader_set_true(grpc_json_reader *reader) {
+  reader->vtable->set_true(reader->userdata);
+}
+
+static void json_reader_set_false(grpc_json_reader *reader) {
+  reader->vtable->set_false(reader->userdata);
+}
+
+static void json_reader_set_null(grpc_json_reader *reader) {
+  reader->vtable->set_null(reader->userdata);
+}
+
+/* Call this function to initialize the reader structure. */
+void grpc_json_reader_init(grpc_json_reader *reader,
+                           grpc_json_reader_vtable *vtable, void *userdata) {
+  memset(reader, 0, sizeof(*reader));
+  reader->vtable = vtable;
+  reader->userdata = userdata;
+  json_reader_string_clear(reader);
+  reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
+}
+
+int grpc_json_reader_is_complete(grpc_json_reader *reader) {
+  return ((reader->depth == 0) &&
+          ((reader->state == GRPC_JSON_STATE_END) ||
+           (reader->state == GRPC_JSON_STATE_VALUE_END)));
+}
+
+grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
+  uint32_t c, success;
+
+  /* This state-machine is a strict implementation of ECMA-404 */
+  for (;;) {
+    c = grpc_json_reader_read_char(reader);
+    switch (c) {
+      /* Let's process the error cases first. */
+      case GRPC_JSON_READ_CHAR_ERROR:
+        return GRPC_JSON_READ_ERROR;
+
+      case GRPC_JSON_READ_CHAR_EAGAIN:
+        return GRPC_JSON_EAGAIN;
+
+      case GRPC_JSON_READ_CHAR_EOF:
+        if (grpc_json_reader_is_complete(reader)) {
+          return GRPC_JSON_DONE;
+        } else {
+          return GRPC_JSON_PARSE_ERROR;
+        }
+        break;
+
+      /* Processing whitespaces. */
+      case ' ':
+      case '\t':
+      case '\n':
+      case '\r':
+        switch (reader->state) {
+          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
+          case GRPC_JSON_STATE_OBJECT_KEY_END:
+          case GRPC_JSON_STATE_VALUE_BEGIN:
+          case GRPC_JSON_STATE_VALUE_END:
+          case GRPC_JSON_STATE_END:
+            break;
+
+          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
+          case GRPC_JSON_STATE_VALUE_STRING:
+            if (c != ' ') return GRPC_JSON_PARSE_ERROR;
+            if (reader->unicode_high_surrogate != 0)
+              return GRPC_JSON_PARSE_ERROR;
+            json_reader_string_add_char(reader, c);
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER:
+          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
+          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
+          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
+            success = (uint32_t)json_reader_set_number(reader);
+            if (!success) return GRPC_JSON_PARSE_ERROR;
+            json_reader_string_clear(reader);
+            reader->state = GRPC_JSON_STATE_VALUE_END;
+            break;
+
+          default:
+            return GRPC_JSON_PARSE_ERROR;
+        }
+        break;
+
+      /* Value, object or array terminations. */
+      case ',':
+      case '}':
+      case ']':
+        switch (reader->state) {
+          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
+          case GRPC_JSON_STATE_VALUE_STRING:
+            if (reader->unicode_high_surrogate != 0)
+              return GRPC_JSON_PARSE_ERROR;
+            json_reader_string_add_char(reader, c);
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER:
+          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
+          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
+          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
+            if (reader->depth == 0) {
+              return GRPC_JSON_PARSE_ERROR;
+            } else if ((c == '}') && !reader->in_object) {
+              return GRPC_JSON_PARSE_ERROR;
+            } else if ((c == ']') && !reader->in_array) {
+              return GRPC_JSON_PARSE_ERROR;
+            }
+            success = (uint32_t)json_reader_set_number(reader);
+            if (!success) return GRPC_JSON_PARSE_ERROR;
+            json_reader_string_clear(reader);
+            reader->state = GRPC_JSON_STATE_VALUE_END;
+          /* The missing break here is intentional. */
+
+          case GRPC_JSON_STATE_VALUE_END:
+          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
+          case GRPC_JSON_STATE_VALUE_BEGIN:
+            if (c == ',') {
+              if (reader->state != GRPC_JSON_STATE_VALUE_END) {
+                return GRPC_JSON_PARSE_ERROR;
+              }
+              if (reader->in_object) {
+                reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
+              } else if (reader->in_array) {
+                reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
+              } else {
+                return GRPC_JSON_PARSE_ERROR;
+              }
+            } else {
+              if (reader->depth-- == 0) return GRPC_JSON_PARSE_ERROR;
+              if ((c == '}') && !reader->in_object) {
+                return GRPC_JSON_PARSE_ERROR;
+              }
+              if ((c == '}') &&
+                  (reader->state == GRPC_JSON_STATE_OBJECT_KEY_BEGIN) &&
+                  !reader->container_just_begun) {
+                return GRPC_JSON_PARSE_ERROR;
+              }
+              if ((c == ']') && !reader->in_array) return GRPC_JSON_PARSE_ERROR;
+              if ((c == ']') &&
+                  (reader->state == GRPC_JSON_STATE_VALUE_BEGIN) &&
+                  !reader->container_just_begun) {
+                return GRPC_JSON_PARSE_ERROR;
+              }
+              reader->state = GRPC_JSON_STATE_VALUE_END;
+              switch (grpc_json_reader_container_ends(reader)) {
+                case GRPC_JSON_OBJECT:
+                  reader->in_object = 1;
+                  reader->in_array = 0;
+                  break;
+                case GRPC_JSON_ARRAY:
+                  reader->in_object = 0;
+                  reader->in_array = 1;
+                  break;
+                case GRPC_JSON_TOP_LEVEL:
+                  GPR_ASSERT(reader->depth == 0);
+                  reader->in_object = 0;
+                  reader->in_array = 0;
+                  reader->state = GRPC_JSON_STATE_END;
+                  break;
+                default:
+                  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
+              }
+            }
+            break;
+
+          default:
+            return GRPC_JSON_PARSE_ERROR;
+        }
+        break;
+
+      /* In-string escaping. */
+      case '\\':
+        switch (reader->state) {
+          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
+            reader->escaped_string_was_key = 1;
+            reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_STRING:
+            reader->escaped_string_was_key = 0;
+            reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
+            break;
+
+          /* This is the \\ case. */
+          case GRPC_JSON_STATE_STRING_ESCAPE:
+            if (reader->unicode_high_surrogate != 0)
+              return GRPC_JSON_PARSE_ERROR;
+            json_reader_string_add_char(reader, '\\');
+            if (reader->escaped_string_was_key) {
+              reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
+            } else {
+              reader->state = GRPC_JSON_STATE_VALUE_STRING;
+            }
+            break;
+
+          default:
+            return GRPC_JSON_PARSE_ERROR;
+        }
+        break;
+
+      default:
+        reader->container_just_begun = 0;
+        switch (reader->state) {
+          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
+            if (c != '"') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
+            break;
+
+          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
+            if (reader->unicode_high_surrogate != 0)
+              return GRPC_JSON_PARSE_ERROR;
+            if (c == '"') {
+              reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
+              json_reader_set_key(reader);
+              json_reader_string_clear(reader);
+            } else {
+              if (c < 32) return GRPC_JSON_PARSE_ERROR;
+              json_reader_string_add_char(reader, c);
+            }
+            break;
+
+          case GRPC_JSON_STATE_VALUE_STRING:
+            if (reader->unicode_high_surrogate != 0)
+              return GRPC_JSON_PARSE_ERROR;
+            if (c == '"') {
+              reader->state = GRPC_JSON_STATE_VALUE_END;
+              json_reader_set_string(reader);
+              json_reader_string_clear(reader);
+            } else {
+              if (c < 32) return GRPC_JSON_PARSE_ERROR;
+              json_reader_string_add_char(reader, c);
+            }
+            break;
+
+          case GRPC_JSON_STATE_OBJECT_KEY_END:
+            if (c != ':') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_BEGIN:
+            switch (c) {
+              case 't':
+                reader->state = GRPC_JSON_STATE_VALUE_TRUE_R;
+                break;
+
+              case 'f':
+                reader->state = GRPC_JSON_STATE_VALUE_FALSE_A;
+                break;
+
+              case 'n':
+                reader->state = GRPC_JSON_STATE_VALUE_NULL_U;
+                break;
+
+              case '"':
+                reader->state = GRPC_JSON_STATE_VALUE_STRING;
+                break;
+
+              case '0':
+                json_reader_string_add_char(reader, c);
+                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_ZERO;
+                break;
+
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7':
+              case '8':
+              case '9':
+              case '-':
+                json_reader_string_add_char(reader, c);
+                reader->state = GRPC_JSON_STATE_VALUE_NUMBER;
+                break;
+
+              case '{':
+                reader->container_just_begun = 1;
+                json_reader_container_begins(reader, GRPC_JSON_OBJECT);
+                reader->depth++;
+                reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
+                reader->in_object = 1;
+                reader->in_array = 0;
+                break;
+
+              case '[':
+                reader->container_just_begun = 1;
+                json_reader_container_begins(reader, GRPC_JSON_ARRAY);
+                reader->depth++;
+                reader->in_object = 0;
+                reader->in_array = 1;
+                break;
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_STRING_ESCAPE:
+            if (reader->escaped_string_was_key) {
+              reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
+            } else {
+              reader->state = GRPC_JSON_STATE_VALUE_STRING;
+            }
+            if (reader->unicode_high_surrogate && c != 'u')
+              return GRPC_JSON_PARSE_ERROR;
+            switch (c) {
+              case '"':
+              case '/':
+                json_reader_string_add_char(reader, c);
+                break;
+              case 'b':
+                json_reader_string_add_char(reader, '\b');
+                break;
+              case 'f':
+                json_reader_string_add_char(reader, '\f');
+                break;
+              case 'n':
+                json_reader_string_add_char(reader, '\n');
+                break;
+              case 'r':
+                json_reader_string_add_char(reader, '\r');
+                break;
+              case 't':
+                json_reader_string_add_char(reader, '\t');
+                break;
+              case 'u':
+                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U1;
+                reader->unicode_char = 0;
+                break;
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_STRING_ESCAPE_U1:
+          case GRPC_JSON_STATE_STRING_ESCAPE_U2:
+          case GRPC_JSON_STATE_STRING_ESCAPE_U3:
+          case GRPC_JSON_STATE_STRING_ESCAPE_U4:
+            if ((c >= '0') && (c <= '9')) {
+              c -= '0';
+            } else if ((c >= 'A') && (c <= 'F')) {
+              c -= 'A' - 10;
+            } else if ((c >= 'a') && (c <= 'f')) {
+              c -= 'a' - 10;
+            } else {
+              return GRPC_JSON_PARSE_ERROR;
+            }
+            reader->unicode_char = (uint16_t)(reader->unicode_char << 4);
+            reader->unicode_char = (uint16_t)(reader->unicode_char | c);
+
+            switch (reader->state) {
+              case GRPC_JSON_STATE_STRING_ESCAPE_U1:
+                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U2;
+                break;
+              case GRPC_JSON_STATE_STRING_ESCAPE_U2:
+                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U3;
+                break;
+              case GRPC_JSON_STATE_STRING_ESCAPE_U3:
+                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U4;
+                break;
+              case GRPC_JSON_STATE_STRING_ESCAPE_U4:
+                /* See grpc_json_writer_escape_string to have a description
+                 * of what's going on here.
+                 */
+                if ((reader->unicode_char & 0xfc00) == 0xd800) {
+                  /* high surrogate utf-16 */
+                  if (reader->unicode_high_surrogate != 0)
+                    return GRPC_JSON_PARSE_ERROR;
+                  reader->unicode_high_surrogate = reader->unicode_char;
+                } else if ((reader->unicode_char & 0xfc00) == 0xdc00) {
+                  /* low surrogate utf-16 */
+                  uint32_t utf32;
+                  if (reader->unicode_high_surrogate == 0)
+                    return GRPC_JSON_PARSE_ERROR;
+                  utf32 = 0x10000;
+                  utf32 += (uint32_t)(
+                      (reader->unicode_high_surrogate - 0xd800) * 0x400);
+                  utf32 += (uint32_t)(reader->unicode_char - 0xdc00);
+                  json_reader_string_add_utf32(reader, utf32);
+                  reader->unicode_high_surrogate = 0;
+                } else {
+                  /* anything else */
+                  if (reader->unicode_high_surrogate != 0)
+                    return GRPC_JSON_PARSE_ERROR;
+                  json_reader_string_add_utf32(reader, reader->unicode_char);
+                }
+                if (reader->escaped_string_was_key) {
+                  reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
+                } else {
+                  reader->state = GRPC_JSON_STATE_VALUE_STRING;
+                }
+                break;
+              default:
+                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
+            }
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER:
+            json_reader_string_add_char(reader, c);
+            switch (c) {
+              case '0':
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7':
+              case '8':
+              case '9':
+                break;
+              case 'e':
+              case 'E':
+                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
+                break;
+              case '.':
+                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
+                break;
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
+            json_reader_string_add_char(reader, c);
+            switch (c) {
+              case '0':
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7':
+              case '8':
+              case '9':
+                break;
+              case 'e':
+              case 'E':
+                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
+                break;
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
+            if (c != '.') return GRPC_JSON_PARSE_ERROR;
+            json_reader_string_add_char(reader, c);
+            reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER_DOT:
+            json_reader_string_add_char(reader, c);
+            switch (c) {
+              case '0':
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7':
+              case '8':
+              case '9':
+                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL;
+                break;
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER_E:
+            json_reader_string_add_char(reader, c);
+            switch (c) {
+              case '0':
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7':
+              case '8':
+              case '9':
+              case '+':
+              case '-':
+                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_EPM;
+                break;
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
+            json_reader_string_add_char(reader, c);
+            switch (c) {
+              case '0':
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7':
+              case '8':
+              case '9':
+                break;
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_VALUE_TRUE_R:
+            if (c != 'r') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_TRUE_U;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_TRUE_U:
+            if (c != 'u') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_TRUE_E;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_TRUE_E:
+            if (c != 'e') return GRPC_JSON_PARSE_ERROR;
+            json_reader_set_true(reader);
+            reader->state = GRPC_JSON_STATE_VALUE_END;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_FALSE_A:
+            if (c != 'a') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_FALSE_L;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_FALSE_L:
+            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_FALSE_S;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_FALSE_S:
+            if (c != 's') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_FALSE_E;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_FALSE_E:
+            if (c != 'e') return GRPC_JSON_PARSE_ERROR;
+            json_reader_set_false(reader);
+            reader->state = GRPC_JSON_STATE_VALUE_END;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NULL_U:
+            if (c != 'u') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_NULL_L1;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NULL_L1:
+            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
+            reader->state = GRPC_JSON_STATE_VALUE_NULL_L2;
+            break;
+
+          case GRPC_JSON_STATE_VALUE_NULL_L2:
+            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
+            json_reader_set_null(reader);
+            reader->state = GRPC_JSON_STATE_VALUE_END;
+            break;
+
+          /* All of the VALUE_END cases are handled in the specialized case
+           * above. */
+          case GRPC_JSON_STATE_VALUE_END:
+            switch (c) {
+              case ',':
+              case '}':
+              case ']':
+                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
+                break;
+
+              default:
+                return GRPC_JSON_PARSE_ERROR;
+            }
+            break;
+
+          case GRPC_JSON_STATE_END:
+            return GRPC_JSON_PARSE_ERROR;
+        }
+    }
+  }
+
+  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
+}
diff --git a/src/core/lib/json/json_reader.h b/src/core/lib/json/json_reader.h
new file mode 100644
index 0000000..e0322c5
--- /dev/null
+++ b/src/core/lib/json/json_reader.h
@@ -0,0 +1,160 @@
+/*
+ *
+ * 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_JSON_JSON_READER_H
+#define GRPC_CORE_LIB_JSON_JSON_READER_H
+
+#include <grpc/support/port_platform.h>
+#include "src/core/lib/json/json_common.h"
+
+typedef enum {
+  GRPC_JSON_STATE_OBJECT_KEY_BEGIN,
+  GRPC_JSON_STATE_OBJECT_KEY_STRING,
+  GRPC_JSON_STATE_OBJECT_KEY_END,
+  GRPC_JSON_STATE_VALUE_BEGIN,
+  GRPC_JSON_STATE_VALUE_STRING,
+  GRPC_JSON_STATE_STRING_ESCAPE,
+  GRPC_JSON_STATE_STRING_ESCAPE_U1,
+  GRPC_JSON_STATE_STRING_ESCAPE_U2,
+  GRPC_JSON_STATE_STRING_ESCAPE_U3,
+  GRPC_JSON_STATE_STRING_ESCAPE_U4,
+  GRPC_JSON_STATE_VALUE_NUMBER,
+  GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL,
+  GRPC_JSON_STATE_VALUE_NUMBER_ZERO,
+  GRPC_JSON_STATE_VALUE_NUMBER_DOT,
+  GRPC_JSON_STATE_VALUE_NUMBER_E,
+  GRPC_JSON_STATE_VALUE_NUMBER_EPM,
+  GRPC_JSON_STATE_VALUE_TRUE_R,
+  GRPC_JSON_STATE_VALUE_TRUE_U,
+  GRPC_JSON_STATE_VALUE_TRUE_E,
+  GRPC_JSON_STATE_VALUE_FALSE_A,
+  GRPC_JSON_STATE_VALUE_FALSE_L,
+  GRPC_JSON_STATE_VALUE_FALSE_S,
+  GRPC_JSON_STATE_VALUE_FALSE_E,
+  GRPC_JSON_STATE_VALUE_NULL_U,
+  GRPC_JSON_STATE_VALUE_NULL_L1,
+  GRPC_JSON_STATE_VALUE_NULL_L2,
+  GRPC_JSON_STATE_VALUE_END,
+  GRPC_JSON_STATE_END
+} grpc_json_reader_state;
+
+enum {
+  /* The first non-unicode value is 0x110000. But let's pick
+   * a value high enough to start our error codes from. These
+   * values are safe to return from the read_char function.
+   */
+  GRPC_JSON_READ_CHAR_EOF = 0x7ffffff0,
+  GRPC_JSON_READ_CHAR_EAGAIN,
+  GRPC_JSON_READ_CHAR_ERROR
+};
+
+struct grpc_json_reader;
+
+typedef struct grpc_json_reader_vtable {
+  /* Clears your internal string scratchpad. */
+  void (*string_clear)(void *userdata);
+  /* Adds a char to the string scratchpad. */
+  void (*string_add_char)(void *userdata, uint32_t c);
+  /* Adds a utf32 char to the string scratchpad. */
+  void (*string_add_utf32)(void *userdata, uint32_t c);
+  /* Reads a character from your input. May be utf-8, 16 or 32. */
+  uint32_t (*read_char)(void *userdata);
+  /* Starts a container of type GRPC_JSON_ARRAY or GRPC_JSON_OBJECT. */
+  void (*container_begins)(void *userdata, grpc_json_type type);
+  /* Ends the current container. Must return the type of its parent. */
+  grpc_json_type (*container_ends)(void *userdata);
+  /* Your internal string scratchpad is an object's key. */
+  void (*set_key)(void *userdata);
+  /* Your internal string scratchpad is a string value. */
+  void (*set_string)(void *userdata);
+  /* Your internal string scratchpad is a numerical value. Return 1 if valid. */
+  int (*set_number)(void *userdata);
+  /* Sets the values true, false or null. */
+  void (*set_true)(void *userdata);
+  void (*set_false)(void *userdata);
+  void (*set_null)(void *userdata);
+} grpc_json_reader_vtable;
+
+typedef struct grpc_json_reader {
+  /* That structure is fully private, and initialized by grpc_json_reader_init.
+   * The definition is public so you can put it on your stack.
+   */
+
+  void *userdata;
+  grpc_json_reader_vtable *vtable;
+  int depth;
+  int in_object;
+  int in_array;
+  int escaped_string_was_key;
+  int container_just_begun;
+  uint16_t unicode_char, unicode_high_surrogate;
+  grpc_json_reader_state state;
+} grpc_json_reader;
+
+/* The return type of the parser. */
+typedef enum {
+  GRPC_JSON_DONE,          /* The parser finished successfully. */
+  GRPC_JSON_EAGAIN,        /* The parser yields to get more data. */
+  GRPC_JSON_READ_ERROR,    /* The parser passes through a read error. */
+  GRPC_JSON_PARSE_ERROR,   /* The parser found an error in the json stream. */
+  GRPC_JSON_INTERNAL_ERROR /* The parser got an internal error. */
+} grpc_json_reader_status;
+
+/* Call this function to start parsing the input. It will return the following:
+ *    . GRPC_JSON_DONE if the input got eof, and the parsing finished
+ *      successfully.
+ *    . GRPC_JSON_EAGAIN if the read_char function returned again. Call the
+ *      parser again as needed. It is okay to call the parser in polling mode,
+ *      although a bit dull.
+ *    . GRPC_JSON_READ_ERROR if the read_char function returned an error. The
+ *      state isn't broken however, and the function can be called again if the
+ *      error has been corrected. But please use the EAGAIN feature instead for
+ *      consistency.
+ *    . GRPC_JSON_PARSE_ERROR if the input was somehow invalid.
+ *    . GRPC_JSON_INTERNAL_ERROR if the parser somehow ended into an invalid
+ *      internal state.
+ */
+grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader);
+
+/* Call this function to initialize the reader structure. */
+void grpc_json_reader_init(grpc_json_reader *reader,
+                           grpc_json_reader_vtable *vtable, void *userdata);
+
+/* You may call this from the read_char callback if you don't know where is the
+ * end of your input stream, and you'd like the json reader to hint you that it
+ * has completed reading its input, so you can return an EOF to it. Note that
+ * there might still be trailing whitespaces after that point.
+ */
+int grpc_json_reader_is_complete(grpc_json_reader *reader);
+
+#endif /* GRPC_CORE_LIB_JSON_JSON_READER_H */
diff --git a/src/core/lib/json/json_string.c b/src/core/lib/json/json_string.c
new file mode 100644
index 0000000..4af7ee7
--- /dev/null
+++ b/src/core/lib/json/json_string.c
@@ -0,0 +1,379 @@
+/*
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/json/json_reader.h"
+#include "src/core/lib/json/json_writer.h"
+
+/* The json reader will construct a bunch of grpc_json objects and
+ * link them all up together in a tree-like structure that will represent
+ * the json data in memory.
+ *
+ * It also uses its own input as a scratchpad to store all of the decoded,
+ * unescaped strings. So we need to keep track of all these pointers in
+ * that opaque structure the reader will carry for us.
+ *
+ * Note that this works because the act of parsing json always reduces its
+ * input size, and never expands it.
+ */
+typedef struct {
+  grpc_json *top;
+  grpc_json *current_container;
+  grpc_json *current_value;
+  uint8_t *input;
+  uint8_t *key;
+  uint8_t *string;
+  uint8_t *string_ptr;
+  size_t remaining_input;
+} json_reader_userdata;
+
+/* This json writer will put everything in a big string.
+ * The point is that we allocate that string in chunks of 256 bytes.
+ */
+typedef struct {
+  char *output;
+  size_t free_space;
+  size_t string_len;
+  size_t allocated;
+} json_writer_userdata;
+
+/* This function checks if there's enough space left in the output buffer,
+ * and will enlarge it if necessary. We're only allocating chunks of 256
+ * bytes at a time (or multiples thereof).
+ */
+static void json_writer_output_check(void *userdata, size_t needed) {
+  json_writer_userdata *state = userdata;
+  if (state->free_space >= needed) return;
+  needed -= state->free_space;
+  /* Round up by 256 bytes. */
+  needed = (needed + 0xff) & ~0xffU;
+  state->output = gpr_realloc(state->output, state->allocated + needed);
+  state->free_space += needed;
+  state->allocated += needed;
+}
+
+/* These are needed by the writer's implementation. */
+static void json_writer_output_char(void *userdata, char c) {
+  json_writer_userdata *state = userdata;
+  json_writer_output_check(userdata, 1);
+  state->output[state->string_len++] = c;
+  state->free_space--;
+}
+
+static void json_writer_output_string_with_len(void *userdata, const char *str,
+                                               size_t len) {
+  json_writer_userdata *state = userdata;
+  json_writer_output_check(userdata, len);
+  memcpy(state->output + state->string_len, str, len);
+  state->string_len += len;
+  state->free_space -= len;
+}
+
+static void json_writer_output_string(void *userdata, const char *str) {
+  size_t len = strlen(str);
+  json_writer_output_string_with_len(userdata, str, len);
+}
+
+/* The reader asks us to clear our scratchpad. In our case, we'll simply mark
+ * the end of the current string, and advance our output pointer.
+ */
+static void json_reader_string_clear(void *userdata) {
+  json_reader_userdata *state = userdata;
+  if (state->string) {
+    GPR_ASSERT(state->string_ptr < state->input);
+    *state->string_ptr++ = 0;
+  }
+  state->string = state->string_ptr;
+}
+
+static void json_reader_string_add_char(void *userdata, uint32_t c) {
+  json_reader_userdata *state = userdata;
+  GPR_ASSERT(state->string_ptr < state->input);
+  GPR_ASSERT(c <= 0xff);
+  *state->string_ptr++ = (uint8_t)c;
+}
+
+/* We are converting a UTF-32 character into UTF-8 here,
+ * as described by RFC3629.
+ */
+static void json_reader_string_add_utf32(void *userdata, uint32_t c) {
+  if (c <= 0x7f) {
+    json_reader_string_add_char(userdata, c);
+  } else if (c <= 0x7ff) {
+    uint32_t b1 = 0xc0 | ((c >> 6) & 0x1f);
+    uint32_t b2 = 0x80 | (c & 0x3f);
+    json_reader_string_add_char(userdata, b1);
+    json_reader_string_add_char(userdata, b2);
+  } else if (c <= 0xffff) {
+    uint32_t b1 = 0xe0 | ((c >> 12) & 0x0f);
+    uint32_t b2 = 0x80 | ((c >> 6) & 0x3f);
+    uint32_t b3 = 0x80 | (c & 0x3f);
+    json_reader_string_add_char(userdata, b1);
+    json_reader_string_add_char(userdata, b2);
+    json_reader_string_add_char(userdata, b3);
+  } else if (c <= 0x1fffff) {
+    uint32_t b1 = 0xf0 | ((c >> 18) & 0x07);
+    uint32_t b2 = 0x80 | ((c >> 12) & 0x3f);
+    uint32_t b3 = 0x80 | ((c >> 6) & 0x3f);
+    uint32_t b4 = 0x80 | (c & 0x3f);
+    json_reader_string_add_char(userdata, b1);
+    json_reader_string_add_char(userdata, b2);
+    json_reader_string_add_char(userdata, b3);
+    json_reader_string_add_char(userdata, b4);
+  }
+}
+
+/* We consider that the input may be a zero-terminated string. So we
+ * can end up hitting eof before the end of the alleged string length.
+ */
+static uint32_t json_reader_read_char(void *userdata) {
+  uint32_t r;
+  json_reader_userdata *state = userdata;
+
+  if (state->remaining_input == 0) return GRPC_JSON_READ_CHAR_EOF;
+
+  r = *state->input++;
+  state->remaining_input--;
+
+  if (r == 0) {
+    state->remaining_input = 0;
+    return GRPC_JSON_READ_CHAR_EOF;
+  }
+
+  return r;
+}
+
+/* Helper function to create a new grpc_json object and link it into
+ * our tree-in-progress inside our opaque structure.
+ */
+static grpc_json *json_create_and_link(void *userdata, grpc_json_type type) {
+  json_reader_userdata *state = userdata;
+  grpc_json *json = grpc_json_create(type);
+
+  json->parent = state->current_container;
+  json->prev = state->current_value;
+  state->current_value = json;
+
+  if (json->prev) {
+    json->prev->next = json;
+  }
+  if (json->parent) {
+    if (!json->parent->child) {
+      json->parent->child = json;
+    }
+    if (json->parent->type == GRPC_JSON_OBJECT) {
+      json->key = (char *)state->key;
+    }
+  }
+  if (!state->top) {
+    state->top = json;
+  }
+
+  return json;
+}
+
+static void json_reader_container_begins(void *userdata, grpc_json_type type) {
+  json_reader_userdata *state = userdata;
+  grpc_json *container;
+
+  GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT);
+
+  container = json_create_and_link(userdata, type);
+  state->current_container = container;
+  state->current_value = NULL;
+}
+
+/* It's important to remember that the reader is mostly stateless, so it
+ * isn't trying to remember what the container was prior the one that just
+ * ends. Since we're keeping track of these for our own purpose, we are
+ * able to return that information back, which is useful for it to validate
+ * the input json stream.
+ *
+ * Also note that if we're at the top of the tree, and the last container
+ * ends, we have to return GRPC_JSON_TOP_LEVEL.
+ */
+static grpc_json_type json_reader_container_ends(void *userdata) {
+  grpc_json_type container_type = GRPC_JSON_TOP_LEVEL;
+  json_reader_userdata *state = userdata;
+
+  GPR_ASSERT(state->current_container);
+
+  state->current_value = state->current_container;
+  state->current_container = state->current_container->parent;
+
+  if (state->current_container) {
+    container_type = state->current_container->type;
+  }
+
+  return container_type;
+}
+
+/* The next 3 functions basically are the reader asking us to use our string
+ * scratchpad for one of these 3 purposes.
+ *
+ * Note that in the set_number case, we're not going to try interpreting it.
+ * We'll keep it as a string, and leave it to the caller to evaluate it.
+ */
+static void json_reader_set_key(void *userdata) {
+  json_reader_userdata *state = userdata;
+  state->key = state->string;
+}
+
+static void json_reader_set_string(void *userdata) {
+  json_reader_userdata *state = userdata;
+  grpc_json *json = json_create_and_link(userdata, GRPC_JSON_STRING);
+  json->value = (char *)state->string;
+}
+
+static int json_reader_set_number(void *userdata) {
+  json_reader_userdata *state = userdata;
+  grpc_json *json = json_create_and_link(userdata, GRPC_JSON_NUMBER);
+  json->value = (char *)state->string;
+  return 1;
+}
+
+/* The object types true, false and null are self-sufficient, and don't need
+ * any more information beside their type.
+ */
+static void json_reader_set_true(void *userdata) {
+  json_create_and_link(userdata, GRPC_JSON_TRUE);
+}
+
+static void json_reader_set_false(void *userdata) {
+  json_create_and_link(userdata, GRPC_JSON_FALSE);
+}
+
+static void json_reader_set_null(void *userdata) {
+  json_create_and_link(userdata, GRPC_JSON_NULL);
+}
+
+static grpc_json_reader_vtable reader_vtable = {
+    json_reader_string_clear,     json_reader_string_add_char,
+    json_reader_string_add_utf32, json_reader_read_char,
+    json_reader_container_begins, json_reader_container_ends,
+    json_reader_set_key,          json_reader_set_string,
+    json_reader_set_number,       json_reader_set_true,
+    json_reader_set_false,        json_reader_set_null};
+
+/* And finally, let's define our public API. */
+grpc_json *grpc_json_parse_string_with_len(char *input, size_t size) {
+  grpc_json_reader reader;
+  json_reader_userdata state;
+  grpc_json *json = NULL;
+  grpc_json_reader_status status;
+
+  if (!input) return NULL;
+
+  state.top = state.current_container = state.current_value = NULL;
+  state.string = state.key = NULL;
+  state.string_ptr = state.input = (uint8_t *)input;
+  state.remaining_input = size;
+  grpc_json_reader_init(&reader, &reader_vtable, &state);
+
+  status = grpc_json_reader_run(&reader);
+  json = state.top;
+
+  if ((status != GRPC_JSON_DONE) && json) {
+    grpc_json_destroy(json);
+    json = NULL;
+  }
+
+  return json;
+}
+
+#define UNBOUND_JSON_STRING_LENGTH 0x7fffffff
+
+grpc_json *grpc_json_parse_string(char *input) {
+  return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH);
+}
+
+static void json_dump_recursive(grpc_json_writer *writer, grpc_json *json,
+                                int in_object) {
+  while (json) {
+    if (in_object) grpc_json_writer_object_key(writer, json->key);
+
+    switch (json->type) {
+      case GRPC_JSON_OBJECT:
+      case GRPC_JSON_ARRAY:
+        grpc_json_writer_container_begins(writer, json->type);
+        if (json->child)
+          json_dump_recursive(writer, json->child,
+                              json->type == GRPC_JSON_OBJECT);
+        grpc_json_writer_container_ends(writer, json->type);
+        break;
+      case GRPC_JSON_STRING:
+        grpc_json_writer_value_string(writer, json->value);
+        break;
+      case GRPC_JSON_NUMBER:
+        grpc_json_writer_value_raw(writer, json->value);
+        break;
+      case GRPC_JSON_TRUE:
+        grpc_json_writer_value_raw_with_len(writer, "true", 4);
+        break;
+      case GRPC_JSON_FALSE:
+        grpc_json_writer_value_raw_with_len(writer, "false", 5);
+        break;
+      case GRPC_JSON_NULL:
+        grpc_json_writer_value_raw_with_len(writer, "null", 4);
+        break;
+      default:
+        GPR_UNREACHABLE_CODE(abort());
+    }
+    json = json->next;
+  }
+}
+
+static grpc_json_writer_vtable writer_vtable = {
+    json_writer_output_char, json_writer_output_string,
+    json_writer_output_string_with_len};
+
+char *grpc_json_dump_to_string(grpc_json *json, int indent) {
+  grpc_json_writer writer;
+  json_writer_userdata state;
+
+  state.output = NULL;
+  state.free_space = state.string_len = state.allocated = 0;
+  grpc_json_writer_init(&writer, indent, &writer_vtable, &state);
+
+  json_dump_recursive(&writer, json, 0);
+
+  json_writer_output_char(&state, 0);
+
+  return state.output;
+}
diff --git a/src/core/lib/json/json_writer.c b/src/core/lib/json/json_writer.c
new file mode 100644
index 0000000..b6a17f4
--- /dev/null
+++ b/src/core/lib/json/json_writer.c
@@ -0,0 +1,258 @@
+/*
+ *
+ * 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/json/json_writer.h"
+
+static void json_writer_output_char(grpc_json_writer *writer, char c) {
+  writer->vtable->output_char(writer->userdata, c);
+}
+
+static void json_writer_output_string(grpc_json_writer *writer,
+                                      const char *str) {
+  writer->vtable->output_string(writer->userdata, str);
+}
+
+static void json_writer_output_string_with_len(grpc_json_writer *writer,
+                                               const char *str, size_t len) {
+  writer->vtable->output_string_with_len(writer->userdata, str, len);
+}
+
+void grpc_json_writer_init(grpc_json_writer *writer, int indent,
+                           grpc_json_writer_vtable *vtable, void *userdata) {
+  memset(writer, 0, sizeof(*writer));
+  writer->container_empty = 1;
+  writer->indent = indent;
+  writer->vtable = vtable;
+  writer->userdata = userdata;
+}
+
+static void json_writer_output_indent(grpc_json_writer *writer) {
+  static const char spacesstr[] =
+      "                "
+      "                "
+      "                "
+      "                ";
+
+  unsigned spaces = (unsigned)(writer->depth * writer->indent);
+
+  if (writer->indent == 0) return;
+
+  if (writer->got_key) {
+    json_writer_output_char(writer, ' ');
+    return;
+  }
+
+  while (spaces >= (sizeof(spacesstr) - 1)) {
+    json_writer_output_string_with_len(writer, spacesstr,
+                                       sizeof(spacesstr) - 1);
+    spaces -= (unsigned)(sizeof(spacesstr) - 1);
+  }
+
+  if (spaces == 0) return;
+
+  json_writer_output_string_with_len(
+      writer, spacesstr + sizeof(spacesstr) - 1 - spaces, spaces);
+}
+
+static void json_writer_value_end(grpc_json_writer *writer) {
+  if (writer->container_empty) {
+    writer->container_empty = 0;
+    if ((writer->indent == 0) || (writer->depth == 0)) return;
+    json_writer_output_char(writer, '\n');
+  } else {
+    json_writer_output_char(writer, ',');
+    if (writer->indent == 0) return;
+    json_writer_output_char(writer, '\n');
+  }
+}
+
+static void json_writer_escape_utf16(grpc_json_writer *writer, uint16_t utf16) {
+  static const char hex[] = "0123456789abcdef";
+
+  json_writer_output_string_with_len(writer, "\\u", 2);
+  json_writer_output_char(writer, hex[(utf16 >> 12) & 0x0f]);
+  json_writer_output_char(writer, hex[(utf16 >> 8) & 0x0f]);
+  json_writer_output_char(writer, hex[(utf16 >> 4) & 0x0f]);
+  json_writer_output_char(writer, hex[(utf16)&0x0f]);
+}
+
+static void json_writer_escape_string(grpc_json_writer *writer,
+                                      const char *string) {
+  json_writer_output_char(writer, '"');
+
+  for (;;) {
+    uint8_t c = (uint8_t)*string++;
+    if (c == 0) {
+      break;
+    } else if ((c >= 32) && (c <= 126)) {
+      if ((c == '\\') || (c == '"')) json_writer_output_char(writer, '\\');
+      json_writer_output_char(writer, (char)c);
+    } else if ((c < 32) || (c == 127)) {
+      switch (c) {
+        case '\b':
+          json_writer_output_string_with_len(writer, "\\b", 2);
+          break;
+        case '\f':
+          json_writer_output_string_with_len(writer, "\\f", 2);
+          break;
+        case '\n':
+          json_writer_output_string_with_len(writer, "\\n", 2);
+          break;
+        case '\r':
+          json_writer_output_string_with_len(writer, "\\r", 2);
+          break;
+        case '\t':
+          json_writer_output_string_with_len(writer, "\\t", 2);
+          break;
+        default:
+          json_writer_escape_utf16(writer, c);
+          break;
+      }
+    } else {
+      uint32_t utf32 = 0;
+      int extra = 0;
+      int i;
+      int valid = 1;
+      if ((c & 0xe0) == 0xc0) {
+        utf32 = c & 0x1f;
+        extra = 1;
+      } else if ((c & 0xf0) == 0xe0) {
+        utf32 = c & 0x0f;
+        extra = 2;
+      } else if ((c & 0xf8) == 0xf0) {
+        utf32 = c & 0x07;
+        extra = 3;
+      } else {
+        break;
+      }
+      for (i = 0; i < extra; i++) {
+        utf32 <<= 6;
+        c = (uint8_t)(*string++);
+        /* Breaks out and bail on any invalid UTF-8 sequence, including \0. */
+        if ((c & 0xc0) != 0x80) {
+          valid = 0;
+          break;
+        }
+        utf32 |= c & 0x3f;
+      }
+      if (!valid) break;
+      /* The range 0xd800 - 0xdfff is reserved by the surrogates ad vitam.
+       * Any other range is technically reserved for future usage, so if we
+       * don't want the software to break in the future, we have to allow
+       * anything else. The first non-unicode character is 0x110000. */
+      if (((utf32 >= 0xd800) && (utf32 <= 0xdfff)) || (utf32 >= 0x110000))
+        break;
+      if (utf32 >= 0x10000) {
+        /* If utf32 contains a character that is above 0xffff, it needs to be
+         * broken down into a utf-16 surrogate pair. A surrogate pair is first
+         * a high surrogate, followed by a low surrogate. Each surrogate holds
+         * 10 bits of usable data, thus allowing a total of 20 bits of data.
+         * The high surrogate marker is 0xd800, while the low surrogate marker
+         * is 0xdc00. The low 10 bits of each will be the usable data.
+         *
+         * After re-combining the 20 bits of data, one has to add 0x10000 to
+         * the resulting value, in order to obtain the original character.
+         * This is obviously because the range 0x0000 - 0xffff can be written
+         * without any special trick.
+         *
+         * Since 0x10ffff is the highest allowed character, we're working in
+         * the range 0x00000 - 0xfffff after we decrement it by 0x10000.
+         * That range is exactly 20 bits.
+         */
+        utf32 -= 0x10000;
+        json_writer_escape_utf16(writer, (uint16_t)(0xd800 | (utf32 >> 10)));
+        json_writer_escape_utf16(writer, (uint16_t)(0xdc00 | (utf32 & 0x3ff)));
+      } else {
+        json_writer_escape_utf16(writer, (uint16_t)utf32);
+      }
+    }
+  }
+
+  json_writer_output_char(writer, '"');
+}
+
+void grpc_json_writer_container_begins(grpc_json_writer *writer,
+                                       grpc_json_type type) {
+  if (!writer->got_key) json_writer_value_end(writer);
+  json_writer_output_indent(writer);
+  json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '[');
+  writer->container_empty = 1;
+  writer->got_key = 0;
+  writer->depth++;
+}
+
+void grpc_json_writer_container_ends(grpc_json_writer *writer,
+                                     grpc_json_type type) {
+  if (writer->indent && !writer->container_empty)
+    json_writer_output_char(writer, '\n');
+  writer->depth--;
+  if (!writer->container_empty) json_writer_output_indent(writer);
+  json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '}' : ']');
+  writer->container_empty = 0;
+  writer->got_key = 0;
+}
+
+void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string) {
+  json_writer_value_end(writer);
+  json_writer_output_indent(writer);
+  json_writer_escape_string(writer, string);
+  json_writer_output_char(writer, ':');
+  writer->got_key = 1;
+}
+
+void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string) {
+  if (!writer->got_key) json_writer_value_end(writer);
+  json_writer_output_indent(writer);
+  json_writer_output_string(writer, string);
+  writer->got_key = 0;
+}
+
+void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer,
+                                         const char *string, size_t len) {
+  if (!writer->got_key) json_writer_value_end(writer);
+  json_writer_output_indent(writer);
+  json_writer_output_string_with_len(writer, string, len);
+  writer->got_key = 0;
+}
+
+void grpc_json_writer_value_string(grpc_json_writer *writer,
+                                   const char *string) {
+  if (!writer->got_key) json_writer_value_end(writer);
+  json_writer_output_indent(writer);
+  json_writer_escape_string(writer, string);
+  writer->got_key = 0;
+}
diff --git a/src/core/lib/json/json_writer.h b/src/core/lib/json/json_writer.h
new file mode 100644
index 0000000..faeb41d
--- /dev/null
+++ b/src/core/lib/json/json_writer.h
@@ -0,0 +1,97 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* The idea of the writer is basically symmetrical of the reader. While the
+ * reader emits various calls to your code, the writer takes basically the
+ * same calls and emit json out of it. It doesn't try to make any check on
+ * the order of the calls you do on it. Meaning you can theorically force
+ * it to generate invalid json.
+ *
+ * Also, unlike the reader, the writer expects UTF-8 encoded input strings.
+ * These strings will be UTF-8 validated, and any invalid character will
+ * cut the conversion short, before any invalid UTF-8 sequence, thus forming
+ * a valid UTF-8 string overall.
+ */
+
+#ifndef GRPC_CORE_LIB_JSON_JSON_WRITER_H
+#define GRPC_CORE_LIB_JSON_JSON_WRITER_H
+
+#include <stdlib.h>
+
+#include "src/core/lib/json/json_common.h"
+
+typedef struct grpc_json_writer_vtable {
+  /* Adds a character to the output stream. */
+  void (*output_char)(void *userdata, char);
+  /* Adds a zero-terminated string to the output stream. */
+  void (*output_string)(void *userdata, const char *str);
+  /* Adds a fixed-length string to the output stream. */
+  void (*output_string_with_len)(void *userdata, const char *str, size_t len);
+
+} grpc_json_writer_vtable;
+
+typedef struct grpc_json_writer {
+  void *userdata;
+  grpc_json_writer_vtable *vtable;
+  int indent;
+  int depth;
+  int container_empty;
+  int got_key;
+} grpc_json_writer;
+
+/* Call this to initialize your writer structure. The indent parameter is
+ * specifying the number of spaces to use for indenting the output. If you
+ * use indent=0, then the output will not have any newlines either, thus
+ * emitting a condensed json output.
+ */
+void grpc_json_writer_init(grpc_json_writer *writer, int indent,
+                           grpc_json_writer_vtable *vtable, void *userdata);
+
+/* Signals the beginning of a container. */
+void grpc_json_writer_container_begins(grpc_json_writer *writer,
+                                       grpc_json_type type);
+/* Signals the end of a container. */
+void grpc_json_writer_container_ends(grpc_json_writer *writer,
+                                     grpc_json_type type);
+/* Writes down an object key for the next value. */
+void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string);
+/* Sets a raw value. Useful for numbers. */
+void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string);
+/* Sets a raw value with its length. Useful for values like true or false. */
+void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer,
+                                         const char *string, size_t len);
+/* Sets a string value. It'll be escaped, and utf-8 validated. */
+void grpc_json_writer_value_string(grpc_json_writer *writer,
+                                   const char *string);
+
+#endif /* GRPC_CORE_LIB_JSON_JSON_WRITER_H */
diff --git a/src/core/lib/profiling/basic_timers.c b/src/core/lib/profiling/basic_timers.c
new file mode 100644
index 0000000..50082cd
--- /dev/null
+++ b/src/core/lib/profiling/basic_timers.c
@@ -0,0 +1,275 @@
+/*
+ *
+ * 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 GRPC_BASIC_PROFILER
+
+#include "src/core/lib/profiling/timers.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/time.h>
+#include <stdio.h>
+
+typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
+
+typedef struct gpr_timer_entry {
+  gpr_timespec tm;
+  const char *tagstr;
+  const char *file;
+  short line;
+  char type;
+  uint8_t important;
+  int thd;
+} gpr_timer_entry;
+
+#define MAX_COUNT 1000000
+
+typedef struct gpr_timer_log {
+  size_t num_entries;
+  struct gpr_timer_log *next;
+  struct gpr_timer_log *prev;
+  gpr_timer_entry log[MAX_COUNT];
+} gpr_timer_log;
+
+typedef struct gpr_timer_log_list {
+  gpr_timer_log *head;
+  /* valid iff head!=NULL */
+  gpr_timer_log *tail;
+} gpr_timer_log_list;
+
+static __thread gpr_timer_log *g_thread_log;
+static gpr_once g_once_init = GPR_ONCE_INIT;
+static FILE *output_file;
+static const char *output_filename = "latency_trace.txt";
+static pthread_mutex_t g_mu;
+static pthread_cond_t g_cv;
+static gpr_timer_log_list g_in_progress_logs;
+static gpr_timer_log_list g_done_logs;
+static int g_shutdown;
+static gpr_thd_id g_writing_thread;
+static __thread int g_thread_id;
+static int g_next_thread_id;
+
+static int timer_log_push_back(gpr_timer_log_list *list, gpr_timer_log *log) {
+  if (list->head == NULL) {
+    list->head = list->tail = log;
+    log->next = log->prev = NULL;
+    return 1;
+  } else {
+    log->prev = list->tail;
+    log->next = NULL;
+    list->tail->next = log;
+    list->tail = log;
+    return 0;
+  }
+}
+
+static gpr_timer_log *timer_log_pop_front(gpr_timer_log_list *list) {
+  gpr_timer_log *out = list->head;
+  if (out != NULL) {
+    list->head = out->next;
+    if (list->head != NULL) {
+      list->head->prev = NULL;
+    } else {
+      list->tail = NULL;
+    }
+  }
+  return out;
+}
+
+static void timer_log_remove(gpr_timer_log_list *list, gpr_timer_log *log) {
+  if (log->prev == NULL) {
+    list->head = log->next;
+    if (list->head != NULL) {
+      list->head->prev = NULL;
+    }
+  } else {
+    log->prev->next = log->next;
+  }
+  if (log->next == NULL) {
+    list->tail = log->prev;
+    if (list->tail != NULL) {
+      list->tail->next = NULL;
+    }
+  } else {
+    log->next->prev = log->prev;
+  }
+}
+
+static void write_log(gpr_timer_log *log) {
+  size_t i;
+  if (output_file == NULL) {
+    output_file = fopen(output_filename, "w");
+  }
+  for (i = 0; i < log->num_entries; i++) {
+    gpr_timer_entry *entry = &(log->log[i]);
+    if (gpr_time_cmp(entry->tm, gpr_time_0(entry->tm.clock_type)) < 0) {
+      entry->tm = gpr_time_0(entry->tm.clock_type);
+    }
+    fprintf(output_file,
+            "{\"t\": %lld.%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": "
+            "\"%s\", \"file\": \"%s\", \"line\": %d, \"imp\": %d}\n",
+            (long long)entry->tm.tv_sec, (int)entry->tm.tv_nsec, entry->thd,
+            entry->type, entry->tagstr, entry->file, entry->line,
+            entry->important);
+  }
+}
+
+static void writing_thread(void *unused) {
+  gpr_timer_log *log;
+  pthread_mutex_lock(&g_mu);
+  for (;;) {
+    while ((log = timer_log_pop_front(&g_done_logs)) == NULL && !g_shutdown) {
+      pthread_cond_wait(&g_cv, &g_mu);
+    }
+    if (log != NULL) {
+      pthread_mutex_unlock(&g_mu);
+      write_log(log);
+      free(log);
+      pthread_mutex_lock(&g_mu);
+    }
+    if (g_shutdown) {
+      pthread_mutex_unlock(&g_mu);
+      return;
+    }
+  }
+}
+
+static void flush_logs(gpr_timer_log_list *list) {
+  gpr_timer_log *log;
+  while ((log = timer_log_pop_front(list)) != NULL) {
+    write_log(log);
+    free(log);
+  }
+}
+
+static void finish_writing() {
+  pthread_mutex_lock(&g_mu);
+  g_shutdown = 1;
+  pthread_cond_signal(&g_cv);
+  pthread_mutex_unlock(&g_mu);
+  gpr_thd_join(g_writing_thread);
+
+  gpr_log(GPR_INFO, "flushing logs");
+
+  pthread_mutex_lock(&g_mu);
+  flush_logs(&g_done_logs);
+  flush_logs(&g_in_progress_logs);
+  pthread_mutex_unlock(&g_mu);
+
+  if (output_file) {
+    fclose(output_file);
+  }
+}
+
+void gpr_timers_set_log_filename(const char *filename) {
+  output_filename = filename;
+}
+
+static void init_output() {
+  gpr_thd_options options = gpr_thd_options_default();
+  gpr_thd_options_set_joinable(&options);
+  gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options);
+  atexit(finish_writing);
+}
+
+static void rotate_log() {
+  /* Using malloc here, as this code could end up being called by gpr_malloc */
+  gpr_timer_log *new = malloc(sizeof(*new));
+  gpr_once_init(&g_once_init, init_output);
+  new->num_entries = 0;
+  pthread_mutex_lock(&g_mu);
+  if (g_thread_log != NULL) {
+    timer_log_remove(&g_in_progress_logs, g_thread_log);
+    if (timer_log_push_back(&g_done_logs, g_thread_log)) {
+      pthread_cond_signal(&g_cv);
+    }
+  } else {
+    g_thread_id = g_next_thread_id++;
+  }
+  timer_log_push_back(&g_in_progress_logs, new);
+  pthread_mutex_unlock(&g_mu);
+  g_thread_log = new;
+}
+
+static void gpr_timers_log_add(const char *tagstr, marker_type type,
+                               int important, const char *file, int line) {
+  gpr_timer_entry *entry;
+
+  if (g_thread_log == NULL || g_thread_log->num_entries == MAX_COUNT) {
+    rotate_log();
+  }
+
+  entry = &g_thread_log->log[g_thread_log->num_entries++];
+
+  entry->tm = gpr_now(GPR_CLOCK_PRECISE);
+  entry->tagstr = tagstr;
+  entry->type = type;
+  entry->file = file;
+  entry->line = (short)line;
+  entry->important = important != 0;
+  entry->thd = g_thread_id;
+}
+
+/* Latency profiler API implementation. */
+void gpr_timer_add_mark(const char *tagstr, int important, const char *file,
+                        int line) {
+  gpr_timers_log_add(tagstr, MARK, important, file, line);
+}
+
+void gpr_timer_begin(const char *tagstr, int important, const char *file,
+                     int line) {
+  gpr_timers_log_add(tagstr, BEGIN, important, file, line);
+}
+
+void gpr_timer_end(const char *tagstr, int important, const char *file,
+                   int line) {
+  gpr_timers_log_add(tagstr, END, important, file, line);
+}
+
+/* Basic profiler specific API functions. */
+void gpr_timers_global_init(void) {}
+
+void gpr_timers_global_destroy(void) {}
+
+#else  /* !GRPC_BASIC_PROFILER */
+void gpr_timers_global_init(void) {}
+
+void gpr_timers_global_destroy(void) {}
+
+void gpr_timers_set_log_filename(const char *filename) {}
+#endif /* GRPC_BASIC_PROFILER */
diff --git a/src/core/profiling/stap_probes.d b/src/core/lib/profiling/stap_probes.d
similarity index 100%
rename from src/core/profiling/stap_probes.d
rename to src/core/lib/profiling/stap_probes.d
diff --git a/src/core/lib/profiling/stap_timers.c b/src/core/lib/profiling/stap_timers.c
new file mode 100644
index 0000000..25e38e6
--- /dev/null
+++ b/src/core/lib/profiling/stap_timers.c
@@ -0,0 +1,65 @@
+/*
+ *
+ * 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 GRPC_STAP_PROFILER
+
+#include "src/core/lib/profiling/timers.h"
+
+#include <sys/sdt.h>
+/* Generated from src/core/profiling/stap_probes.d */
+#include "src/core/lib/profiling/stap_probes.h"
+
+/* Latency profiler API implementation. */
+void gpr_timer_add_mark(int tag, const char *tagstr, void *id, const char *file,
+                        int line) {
+  _STAP_ADD_MARK(tag);
+}
+
+void gpr_timer_add_important_mark(int tag, const char *tagstr, void *id,
+                                  const char *file, int line) {
+  _STAP_ADD_IMPORTANT_MARK(tag);
+}
+
+void gpr_timer_begin(int tag, const char *tagstr, void *id, const char *file,
+                     int line) {
+  _STAP_TIMING_NS_BEGIN(tag);
+}
+
+void gpr_timer_end(int tag, const char *tagstr, void *id, const char *file,
+                   int line) {
+  _STAP_TIMING_NS_END(tag);
+}
+
+#endif /* GRPC_STAP_PROFILER */
diff --git a/src/core/lib/profiling/timers.h b/src/core/lib/profiling/timers.h
new file mode 100644
index 0000000..c8567e8
--- /dev/null
+++ b/src/core/lib/profiling/timers.h
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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_PROFILING_TIMERS_H
+#define GRPC_CORE_LIB_PROFILING_TIMERS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gpr_timers_global_init(void);
+void gpr_timers_global_destroy(void);
+
+void gpr_timer_add_mark(const char *tagstr, int important, const char *file,
+                        int line);
+void gpr_timer_begin(const char *tagstr, int important, const char *file,
+                     int line);
+void gpr_timer_end(const char *tagstr, int important, const char *file,
+                   int line);
+
+void gpr_timers_set_log_filename(const char *filename);
+
+#if !(defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
+/* No profiling. No-op all the things. */
+#define GPR_TIMER_MARK(tag, important) \
+  do {                                 \
+  } while (0)
+
+#define GPR_TIMER_BEGIN(tag, important) \
+  do {                                  \
+  } while (0)
+
+#define GPR_TIMER_END(tag, important) \
+  do {                                \
+  } while (0)
+
+#else /* at least one profiler requested... */
+/* ... hopefully only one. */
+#if defined(GRPC_STAP_PROFILER) && defined(GRPC_BASIC_PROFILER)
+#error "GRPC_STAP_PROFILER and GRPC_BASIC_PROFILER are mutually exclusive."
+#endif
+
+/* Generic profiling interface. */
+#define GPR_TIMER_MARK(tag, important) \
+  gpr_timer_add_mark(tag, important, __FILE__, __LINE__);
+
+#define GPR_TIMER_BEGIN(tag, important) \
+  gpr_timer_begin(tag, important, __FILE__, __LINE__);
+
+#define GPR_TIMER_END(tag, important) \
+  gpr_timer_end(tag, important, __FILE__, __LINE__);
+
+#ifdef GRPC_STAP_PROFILER
+/* Empty placeholder for now. */
+#endif /* GRPC_STAP_PROFILER */
+
+#ifdef GRPC_BASIC_PROFILER
+/* Empty placeholder for now. */
+#endif /* GRPC_BASIC_PROFILER */
+
+#endif /* at least one profiler requested. */
+
+#ifdef __cplusplus
+}
+
+#if (defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
+namespace grpc {
+class ProfileScope {
+ public:
+  ProfileScope(const char *desc, bool important) : desc_(desc) {
+    GPR_TIMER_BEGIN(desc_, important ? 1 : 0);
+  }
+  ~ProfileScope() { GPR_TIMER_END(desc_, 0); }
+
+ private:
+  const char *const desc_;
+};
+}
+
+#define GPR_TIMER_SCOPE(tag, important) \
+  ::grpc::ProfileScope _profile_scope_##__LINE__((tag), (important))
+#else
+#define GPR_TIMER_SCOPE(tag, important) \
+  do {                                  \
+  } while (false)
+#endif
+#endif
+
+#endif /* GRPC_CORE_LIB_PROFILING_TIMERS_H */
diff --git a/src/core/lib/security/auth_filters.h b/src/core/lib/security/auth_filters.h
new file mode 100644
index 0000000..7fb56c3
--- /dev/null
+++ b/src/core/lib/security/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_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
new file mode 100644
index 0000000..87f0e05
--- /dev/null
+++ b/src/core/lib/security/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/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
new file mode 100644
index 0000000..c515e7a
--- /dev/null
+++ b/src/core/lib/security/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_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
new file mode 100644
index 0000000..943b1da
--- /dev/null
+++ b/src/core/lib/security/client_auth_filter.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/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 bound to this call; if we need to make external
+     network requests, they should be done under this pollset
+     so that work can progress when this call wants work to
+     progress */
+  grpc_pollset *pollset;
+  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->pollset);
+  grpc_call_credentials_get_request_metadata(
+      exec_ctx, calld->creds, calld->pollset, 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(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                        grpc_pollset *pollset) {
+  call_data *calld = elem->call_data;
+  calld->pollset = pollset;
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {
+  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,          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/credentials.c b/src/core/lib/security/credentials.c
new file mode 100644
index 0000000..fd5ad35
--- /dev/null
+++ b/src/core/lib/security/credentials.c
@@ -0,0 +1,1296 @@
+/*
+ *
+ * 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_pollset *pollset, 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, pollset, 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_pollset *pollset,
+                                     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_pollset *pollset, 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, pollset, 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_pollset *pollset,
+    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, pollset, &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_pollset *pollset,
+    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, pollset, &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_pollset *pollset, 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_pollset *pollset, 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_pollset *pollset;
+  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->pollset, 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_pollset *pollset, 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->pollset = pollset;
+  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++], pollset,
+      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_pollset *pollset,
+                                     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_pollset *pollset,
+                                        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
new file mode 100644
index 0000000..0373cea
--- /dev/null
+++ b/src/core/lib/security/credentials.h
@@ -0,0 +1,377 @@
+/*
+ *
+ * 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/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_pollset *pollset,
+                               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_pollset *pollset, 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_pollset *pollset,
+                                       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_metadata.c b/src/core/lib/security/credentials_metadata.c
new file mode 100644
index 0000000..bd00194
--- /dev/null
+++ b/src/core/lib/security/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.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
new file mode 100644
index 0000000..a07de18
--- /dev/null
+++ b/src/core/lib/security/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.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
new file mode 100644
index 0000000..d29847a
--- /dev/null
+++ b/src/core/lib/security/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.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
new file mode 100644
index 0000000..236f1d7
--- /dev/null
+++ b/src/core/lib/security/google_default_credentials.c
@@ -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.
+ *
+ */
+
+#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/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_pollset *pollset;
+  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(detector->pollset, 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);
+
+  detector.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(detector.pollset, &g_polling_mu);
+  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.pollset, &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, detector.pollset, &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, detector.pollset);
+  grpc_pollset_shutdown(&exec_ctx, detector.pollset, &destroy_closure);
+  grpc_exec_ctx_finish(&exec_ctx);
+  g_polling_mu = NULL;
+
+  gpr_free(detector.pollset);
+
+  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
new file mode 100644
index 0000000..d5fe0c7
--- /dev/null
+++ b/src/core/lib/security/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/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
new file mode 100644
index 0000000..f34476e
--- /dev/null
+++ b/src/core/lib/security/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_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
new file mode 100644
index 0000000..d5bc2c8
--- /dev/null
+++ b/src/core/lib/security/json_token.c
@@ -0,0 +1,411 @@
+/*
+ *
+ * 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
new file mode 100644
index 0000000..123fa65
--- /dev/null
+++ b/src/core/lib/security/json_token.h
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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
new file mode 100644
index 0000000..0e01229
--- /dev/null
+++ b/src/core/lib/security/jwt_verifier.c
@@ -0,0 +1,843 @@
+/*
+ *
+ * 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/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_pollset *pollset;
+  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) {
+  verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
+  memset(ctx, 0, sizeof(verifier_cb_ctx));
+  ctx->verifier = verifier;
+  ctx->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;
+  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->pollset, &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->pollset, &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
new file mode 100644
index 0000000..98a4f6b
--- /dev/null
+++ b/src/core/lib/security/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_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
new file mode 100644
index 0000000..27b0e98
--- /dev/null
+++ b/src/core/lib/security/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/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
new file mode 100644
index 0000000..ff1c663
--- /dev/null
+++ b/src/core/lib/security/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_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
new file mode 100644
index 0000000..2d2023b
--- /dev/null
+++ b/src/core/lib/security/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/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
new file mode 100644
index 0000000..2c893cd
--- /dev/null
+++ b/src/core/lib/security/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_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
new file mode 100644
index 0000000..343e0b5
--- /dev/null
+++ b/src/core/lib/security/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/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
new file mode 100644
index 0000000..81161ec
--- /dev/null
+++ b/src/core/lib/security/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_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
new file mode 100644
index 0000000..7844dc8
--- /dev/null
+++ b/src/core/lib/security/server_auth_filter.c
@@ -0,0 +1,264 @@
+/*
+ *
+ * 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;
+}
+
+static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                        grpc_pollset *pollset) {}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {}
+
+/* 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,          set_pollset,          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/support/alloc.c b/src/core/lib/support/alloc.c
new file mode 100644
index 0000000..618c3f6
--- /dev/null
+++ b/src/core/lib/support/alloc.c
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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/alloc.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <stdlib.h>
+#include "src/core/lib/profiling/timers.h"
+
+static gpr_allocation_functions g_alloc_functions = {malloc, realloc, free};
+
+gpr_allocation_functions gpr_get_allocation_functions() {
+  return g_alloc_functions;
+}
+
+void gpr_set_allocation_functions(gpr_allocation_functions functions) {
+  GPR_ASSERT(functions.malloc_fn != NULL);
+  GPR_ASSERT(functions.realloc_fn != NULL);
+  GPR_ASSERT(functions.free_fn != NULL);
+  g_alloc_functions = functions;
+}
+
+void *gpr_malloc(size_t size) {
+  void *p;
+  if (size == 0) return NULL;
+  GPR_TIMER_BEGIN("gpr_malloc", 0);
+  p = g_alloc_functions.malloc_fn(size);
+  if (!p) {
+    abort();
+  }
+  GPR_TIMER_END("gpr_malloc", 0);
+  return p;
+}
+
+void gpr_free(void *p) {
+  GPR_TIMER_BEGIN("gpr_free", 0);
+  g_alloc_functions.free_fn(p);
+  GPR_TIMER_END("gpr_free", 0);
+}
+
+void *gpr_realloc(void *p, size_t size) {
+  if ((size == 0) && (p == NULL)) return NULL;
+  GPR_TIMER_BEGIN("gpr_realloc", 0);
+  p = g_alloc_functions.realloc_fn(p, size);
+  if (!p) {
+    abort();
+  }
+  GPR_TIMER_END("gpr_realloc", 0);
+  return p;
+}
+
+void *gpr_malloc_aligned(size_t size, size_t alignment_log) {
+  size_t alignment = ((size_t)1) << alignment_log;
+  size_t extra = alignment - 1 + sizeof(void *);
+  void *p = gpr_malloc(size + extra);
+  void **ret = (void **)(((uintptr_t)p + extra) & ~(alignment - 1));
+  ret[-1] = p;
+  return (void *)ret;
+}
+
+void gpr_free_aligned(void *ptr) { gpr_free(((void **)ptr)[-1]); }
diff --git a/src/core/lib/support/avl.c b/src/core/lib/support/avl.c
new file mode 100644
index 0000000..8d3ce23
--- /dev/null
+++ b/src/core/lib/support/avl.c
@@ -0,0 +1,288 @@
+/*
+ *
+ * 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/avl.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+gpr_avl gpr_avl_create(const gpr_avl_vtable *vtable) {
+  gpr_avl out;
+  out.vtable = vtable;
+  out.root = NULL;
+  return out;
+}
+
+static gpr_avl_node *ref_node(gpr_avl_node *node) {
+  if (node) {
+    gpr_ref(&node->refs);
+  }
+  return node;
+}
+
+static void unref_node(const gpr_avl_vtable *vtable, gpr_avl_node *node) {
+  if (node == NULL) {
+    return;
+  }
+  if (gpr_unref(&node->refs)) {
+    vtable->destroy_key(node->key);
+    vtable->destroy_value(node->value);
+    unref_node(vtable, node->left);
+    unref_node(vtable, node->right);
+    gpr_free(node);
+  }
+}
+
+static long node_height(gpr_avl_node *node) {
+  return node == NULL ? 0 : node->height;
+}
+
+#ifndef NDEBUG
+static long calculate_height(gpr_avl_node *node) {
+  return node == NULL ? 0 : 1 + GPR_MAX(calculate_height(node->left),
+                                        calculate_height(node->right));
+}
+
+static gpr_avl_node *assert_invariants(gpr_avl_node *n) {
+  if (n == NULL) return NULL;
+  assert_invariants(n->left);
+  assert_invariants(n->right);
+  assert(calculate_height(n) == n->height);
+  assert(labs(node_height(n->left) - node_height(n->right)) <= 1);
+  return n;
+}
+#else
+static gpr_avl_node *assert_invariants(gpr_avl_node *n) { return n; }
+#endif
+
+gpr_avl_node *new_node(void *key, void *value, gpr_avl_node *left,
+                       gpr_avl_node *right) {
+  gpr_avl_node *node = gpr_malloc(sizeof(*node));
+  gpr_ref_init(&node->refs, 1);
+  node->key = key;
+  node->value = value;
+  node->left = assert_invariants(left);
+  node->right = assert_invariants(right);
+  node->height = 1 + GPR_MAX(node_height(left), node_height(right));
+  return node;
+}
+
+static gpr_avl_node *get(const gpr_avl_vtable *vtable, gpr_avl_node *node,
+                         void *key) {
+  long cmp;
+
+  if (node == NULL) {
+    return NULL;
+  }
+
+  cmp = vtable->compare_keys(node->key, key);
+  if (cmp == 0) {
+    return node;
+  } else if (cmp > 0) {
+    return get(vtable, node->left, key);
+  } else {
+    return get(vtable, node->right, key);
+  }
+}
+
+void *gpr_avl_get(gpr_avl avl, void *key) {
+  gpr_avl_node *node = get(avl.vtable, avl.root, key);
+  return node ? node->value : NULL;
+}
+
+static gpr_avl_node *rotate_left(const gpr_avl_vtable *vtable, void *key,
+                                 void *value, gpr_avl_node *left,
+                                 gpr_avl_node *right) {
+  gpr_avl_node *n =
+      new_node(vtable->copy_key(right->key), vtable->copy_value(right->value),
+               new_node(key, value, left, ref_node(right->left)),
+               ref_node(right->right));
+  unref_node(vtable, right);
+  return n;
+}
+
+static gpr_avl_node *rotate_right(const gpr_avl_vtable *vtable, void *key,
+                                  void *value, gpr_avl_node *left,
+                                  gpr_avl_node *right) {
+  gpr_avl_node *n = new_node(
+      vtable->copy_key(left->key), vtable->copy_value(left->value),
+      ref_node(left->left), new_node(key, value, ref_node(left->right), right));
+  unref_node(vtable, left);
+  return n;
+}
+
+static gpr_avl_node *rotate_left_right(const gpr_avl_vtable *vtable, void *key,
+                                       void *value, gpr_avl_node *left,
+                                       gpr_avl_node *right) {
+  /* rotate_right(..., rotate_left(left), right) */
+  gpr_avl_node *n = new_node(
+      vtable->copy_key(left->right->key),
+      vtable->copy_value(left->right->value),
+      new_node(vtable->copy_key(left->key), vtable->copy_value(left->value),
+               ref_node(left->left), ref_node(left->right->left)),
+      new_node(key, value, ref_node(left->right->right), right));
+  unref_node(vtable, left);
+  return n;
+}
+
+static gpr_avl_node *rotate_right_left(const gpr_avl_vtable *vtable, void *key,
+                                       void *value, gpr_avl_node *left,
+                                       gpr_avl_node *right) {
+  /* rotate_left(..., left, rotate_right(right)) */
+  gpr_avl_node *n = new_node(
+      vtable->copy_key(right->left->key),
+      vtable->copy_value(right->left->value),
+      new_node(key, value, left, ref_node(right->left->left)),
+      new_node(vtable->copy_key(right->key), vtable->copy_value(right->value),
+               ref_node(right->left->right), ref_node(right->right)));
+  unref_node(vtable, right);
+  return n;
+}
+
+static gpr_avl_node *rebalance(const gpr_avl_vtable *vtable, void *key,
+                               void *value, gpr_avl_node *left,
+                               gpr_avl_node *right) {
+  switch (node_height(left) - node_height(right)) {
+    case 2:
+      if (node_height(left->left) - node_height(left->right) == -1) {
+        return assert_invariants(
+            rotate_left_right(vtable, key, value, left, right));
+      } else {
+        return assert_invariants(rotate_right(vtable, key, value, left, right));
+      }
+    case -2:
+      if (node_height(right->left) - node_height(right->right) == 1) {
+        return assert_invariants(
+            rotate_right_left(vtable, key, value, left, right));
+      } else {
+        return assert_invariants(rotate_left(vtable, key, value, left, right));
+      }
+    default:
+      return assert_invariants(new_node(key, value, left, right));
+  }
+}
+
+static gpr_avl_node *add(const gpr_avl_vtable *vtable, gpr_avl_node *node,
+                         void *key, void *value) {
+  long cmp;
+  if (node == NULL) {
+    return new_node(key, value, NULL, NULL);
+  }
+  cmp = vtable->compare_keys(node->key, key);
+  if (cmp == 0) {
+    return new_node(key, value, ref_node(node->left), ref_node(node->right));
+  } else if (cmp > 0) {
+    return rebalance(
+        vtable, vtable->copy_key(node->key), vtable->copy_value(node->value),
+        add(vtable, node->left, key, value), ref_node(node->right));
+  } else {
+    return rebalance(vtable, vtable->copy_key(node->key),
+                     vtable->copy_value(node->value), ref_node(node->left),
+                     add(vtable, node->right, key, value));
+  }
+}
+
+gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value) {
+  gpr_avl_node *old_root = avl.root;
+  avl.root = add(avl.vtable, avl.root, key, value);
+  assert_invariants(avl.root);
+  unref_node(avl.vtable, old_root);
+  return avl;
+}
+
+static gpr_avl_node *in_order_head(gpr_avl_node *node) {
+  while (node->left != NULL) {
+    node = node->left;
+  }
+  return node;
+}
+
+static gpr_avl_node *in_order_tail(gpr_avl_node *node) {
+  while (node->right != NULL) {
+    node = node->right;
+  }
+  return node;
+}
+
+static gpr_avl_node *remove(const gpr_avl_vtable *vtable, gpr_avl_node *node,
+                            void *key) {
+  long cmp;
+  if (node == NULL) {
+    return NULL;
+  }
+  cmp = vtable->compare_keys(node->key, key);
+  if (cmp == 0) {
+    if (node->left == NULL) {
+      return ref_node(node->right);
+    } else if (node->right == NULL) {
+      return ref_node(node->left);
+    } else if (node->left->height < node->right->height) {
+      gpr_avl_node *h = in_order_head(node->right);
+      return rebalance(vtable, vtable->copy_key(h->key),
+                       vtable->copy_value(h->value), ref_node(node->left),
+                       remove(vtable, node->right, h->key));
+    } else {
+      gpr_avl_node *h = in_order_tail(node->left);
+      return rebalance(
+          vtable, vtable->copy_key(h->key), vtable->copy_value(h->value),
+          remove(vtable, node->left, h->key), ref_node(node->right));
+    }
+  } else if (cmp > 0) {
+    return rebalance(vtable, vtable->copy_key(node->key),
+                     vtable->copy_value(node->value),
+                     remove(vtable, node->left, key), ref_node(node->right));
+  } else {
+    return rebalance(vtable, vtable->copy_key(node->key),
+                     vtable->copy_value(node->value), ref_node(node->left),
+                     remove(vtable, node->right, key));
+  }
+}
+
+gpr_avl gpr_avl_remove(gpr_avl avl, void *key) {
+  gpr_avl_node *old_root = avl.root;
+  avl.root = remove(avl.vtable, avl.root, key);
+  assert_invariants(avl.root);
+  unref_node(avl.vtable, old_root);
+  return avl;
+}
+
+gpr_avl gpr_avl_ref(gpr_avl avl) {
+  ref_node(avl.root);
+  return avl;
+}
+
+void gpr_avl_unref(gpr_avl avl) { unref_node(avl.vtable, avl.root); }
diff --git a/src/core/lib/support/backoff.c b/src/core/lib/support/backoff.c
new file mode 100644
index 0000000..e89ef47
--- /dev/null
+++ b/src/core/lib/support/backoff.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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/support/backoff.h"
+
+#include <grpc/support/useful.h>
+
+void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
+                      int64_t min_timeout_millis, int64_t max_timeout_millis) {
+  backoff->multiplier = multiplier;
+  backoff->jitter = jitter;
+  backoff->min_timeout_millis = min_timeout_millis;
+  backoff->max_timeout_millis = max_timeout_millis;
+  backoff->rng_state = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
+}
+
+gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) {
+  backoff->current_timeout_millis = backoff->min_timeout_millis;
+  return gpr_time_add(
+      now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
+}
+
+/* Generate a random number between 0 and 1. */
+static double generate_uniform_random_number(uint32_t *rng_state) {
+  *rng_state = (1103515245 * *rng_state + 12345) % ((uint32_t)1 << 31);
+  return *rng_state / (double)((uint32_t)1 << 31);
+}
+
+gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) {
+  double new_timeout_millis =
+      backoff->multiplier * (double)backoff->current_timeout_millis;
+  double jitter_range = backoff->jitter * new_timeout_millis;
+  double jitter =
+      (2 * generate_uniform_random_number(&backoff->rng_state) - 1) *
+      jitter_range;
+  backoff->current_timeout_millis =
+      GPR_CLAMP((int64_t)(new_timeout_millis + jitter),
+                backoff->min_timeout_millis, backoff->max_timeout_millis);
+  return gpr_time_add(
+      now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
+}
+
+void gpr_backoff_reset(gpr_backoff *backoff) {
+  // forces step() to return a timeout of min_timeout_millis
+  backoff->current_timeout_millis = 0;
+}
diff --git a/src/core/lib/support/backoff.h b/src/core/lib/support/backoff.h
new file mode 100644
index 0000000..6d40c15
--- /dev/null
+++ b/src/core/lib/support/backoff.h
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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_SUPPORT_BACKOFF_H
+#define GRPC_CORE_LIB_SUPPORT_BACKOFF_H
+
+#include <grpc/support/time.h>
+
+typedef struct {
+  /// const: multiplier between retry attempts
+  double multiplier;
+  /// const: amount to randomize backoffs
+  double jitter;
+  /// const: minimum time between retries in milliseconds
+  int64_t min_timeout_millis;
+  /// const: maximum time between retries in milliseconds
+  int64_t max_timeout_millis;
+
+  /// random number generator
+  uint32_t rng_state;
+
+  /// current retry timeout in milliseconds
+  int64_t current_timeout_millis;
+} gpr_backoff;
+
+/// Initialize backoff machinery - does not need to be destroyed
+void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
+                      int64_t min_timeout_millis, int64_t max_timeout_millis);
+
+/// Begin retry loop: returns a timespec for the NEXT retry
+gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now);
+/// Step a retry loop: returns a timespec for the NEXT retry
+gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now);
+/// Reset the backoff, so the next gpr_backoff_step will be a gpr_backoff_begin
+/// instead
+void gpr_backoff_reset(gpr_backoff *backoff);
+
+#endif /* GRPC_CORE_LIB_SUPPORT_BACKOFF_H */
diff --git a/src/core/lib/support/block_annotate.h b/src/core/lib/support/block_annotate.h
new file mode 100644
index 0000000..8fb3802
--- /dev/null
+++ b/src/core/lib/support/block_annotate.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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_SUPPORT_BLOCK_ANNOTATE_H
+#define GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H
+
+/* These annotations identify the beginning and end of regions where
+   the code may block for reasons other than synchronization functions.
+   These include poll, epoll, and getaddrinfo. */
+
+#define GRPC_SCHEDULING_START_BLOCKING_REGION \
+  do {                                        \
+  } while (0)
+#define GRPC_SCHEDULING_END_BLOCKING_REGION \
+  do {                                      \
+  } while (0)
+
+#endif /* GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H */
diff --git a/src/core/lib/support/cmdline.c b/src/core/lib/support/cmdline.c
new file mode 100644
index 0000000..d474986
--- /dev/null
+++ b/src/core/lib/support/cmdline.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 <grpc/support/cmdline.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include "src/core/lib/support/string.h"
+
+typedef enum { ARGTYPE_INT, ARGTYPE_BOOL, ARGTYPE_STRING } argtype;
+
+typedef struct arg {
+  const char *name;
+  const char *help;
+  argtype type;
+  void *value;
+  struct arg *next;
+} arg;
+
+struct gpr_cmdline {
+  const char *description;
+  arg *args;
+  const char *argv0;
+
+  const char *extra_arg_name;
+  const char *extra_arg_help;
+  void (*extra_arg)(void *user_data, const char *arg);
+  void *extra_arg_user_data;
+
+  int (*state)(gpr_cmdline *cl, char *arg);
+  arg *cur_arg;
+
+  int survive_failure;
+};
+
+static int normal_state(gpr_cmdline *cl, char *arg);
+
+gpr_cmdline *gpr_cmdline_create(const char *description) {
+  gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline));
+  memset(cl, 0, sizeof(gpr_cmdline));
+
+  cl->description = description;
+  cl->state = normal_state;
+
+  return cl;
+}
+
+void gpr_cmdline_set_survive_failure(gpr_cmdline *cl) {
+  cl->survive_failure = 1;
+}
+
+void gpr_cmdline_destroy(gpr_cmdline *cl) {
+  while (cl->args) {
+    arg *a = cl->args;
+    cl->args = a->next;
+    gpr_free(a);
+  }
+  gpr_free(cl);
+}
+
+static void add_arg(gpr_cmdline *cl, const char *name, const char *help,
+                    argtype type, void *value) {
+  arg *a;
+
+  for (a = cl->args; a; a = a->next) {
+    GPR_ASSERT(0 != strcmp(a->name, name));
+  }
+
+  a = gpr_malloc(sizeof(arg));
+  memset(a, 0, sizeof(arg));
+  a->name = name;
+  a->help = help;
+  a->type = type;
+  a->value = value;
+  a->next = cl->args;
+  cl->args = a;
+}
+
+void gpr_cmdline_add_int(gpr_cmdline *cl, const char *name, const char *help,
+                         int *value) {
+  add_arg(cl, name, help, ARGTYPE_INT, value);
+}
+
+void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name, const char *help,
+                          int *value) {
+  add_arg(cl, name, help, ARGTYPE_BOOL, value);
+}
+
+void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help,
+                            char **value) {
+  add_arg(cl, name, help, ARGTYPE_STRING, value);
+}
+
+void gpr_cmdline_on_extra_arg(
+    gpr_cmdline *cl, const char *name, const char *help,
+    void (*on_extra_arg)(void *user_data, const char *arg), void *user_data) {
+  GPR_ASSERT(!cl->extra_arg);
+  GPR_ASSERT(on_extra_arg);
+
+  cl->extra_arg = on_extra_arg;
+  cl->extra_arg_user_data = user_data;
+  cl->extra_arg_name = name;
+  cl->extra_arg_help = help;
+}
+
+/* recursively descend argument list, adding the last element
+   to s first - so that arguments are added in the order they were
+   added to the list by api calls */
+static void add_args_to_usage(gpr_strvec *s, arg *a) {
+  char *tmp;
+
+  if (!a) return;
+  add_args_to_usage(s, a->next);
+
+  switch (a->type) {
+    case ARGTYPE_BOOL:
+      gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name);
+      gpr_strvec_add(s, tmp);
+      break;
+    case ARGTYPE_STRING:
+      gpr_asprintf(&tmp, " [--%s=string]", a->name);
+      gpr_strvec_add(s, tmp);
+      break;
+    case ARGTYPE_INT:
+      gpr_asprintf(&tmp, " [--%s=int]", a->name);
+      gpr_strvec_add(s, tmp);
+      break;
+  }
+}
+
+char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) {
+  /* TODO(ctiller): make this prettier */
+  gpr_strvec s;
+  char *tmp;
+  const char *name = strrchr(argv0, '/');
+
+  if (name) {
+    name++;
+  } else {
+    name = argv0;
+  }
+
+  gpr_strvec_init(&s);
+
+  gpr_asprintf(&tmp, "Usage: %s", name);
+  gpr_strvec_add(&s, tmp);
+  add_args_to_usage(&s, cl->args);
+  if (cl->extra_arg) {
+    gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name);
+    gpr_strvec_add(&s, tmp);
+  }
+  gpr_strvec_add(&s, gpr_strdup("\n"));
+
+  tmp = gpr_strvec_flatten(&s, NULL);
+  gpr_strvec_destroy(&s);
+  return tmp;
+}
+
+static int print_usage_and_die(gpr_cmdline *cl) {
+  char *usage = gpr_cmdline_usage_string(cl, cl->argv0);
+  fprintf(stderr, "%s", usage);
+  gpr_free(usage);
+  if (!cl->survive_failure) {
+    exit(1);
+  }
+  return 0;
+}
+
+static int extra_state(gpr_cmdline *cl, char *str) {
+  if (!cl->extra_arg) {
+    return print_usage_and_die(cl);
+  }
+  cl->extra_arg(cl->extra_arg_user_data, str);
+  return 1;
+}
+
+static arg *find_arg(gpr_cmdline *cl, char *name) {
+  arg *a;
+
+  for (a = cl->args; a; a = a->next) {
+    if (0 == strcmp(a->name, name)) {
+      break;
+    }
+  }
+
+  if (!a) {
+    fprintf(stderr, "Unknown argument: %s\n", name);
+    return NULL;
+  }
+
+  return a;
+}
+
+static int value_state(gpr_cmdline *cl, char *str) {
+  long intval;
+  char *end;
+
+  GPR_ASSERT(cl->cur_arg);
+
+  switch (cl->cur_arg->type) {
+    case ARGTYPE_INT:
+      intval = strtol(str, &end, 0);
+      if (*end || intval < INT_MIN || intval > INT_MAX) {
+        fprintf(stderr, "expected integer, got '%s' for %s\n", str,
+                cl->cur_arg->name);
+        return print_usage_and_die(cl);
+      }
+      *(int *)cl->cur_arg->value = (int)intval;
+      break;
+    case ARGTYPE_BOOL:
+      if (0 == strcmp(str, "1") || 0 == strcmp(str, "true")) {
+        *(int *)cl->cur_arg->value = 1;
+      } else if (0 == strcmp(str, "0") || 0 == strcmp(str, "false")) {
+        *(int *)cl->cur_arg->value = 0;
+      } else {
+        fprintf(stderr, "expected boolean, got '%s' for %s\n", str,
+                cl->cur_arg->name);
+        return print_usage_and_die(cl);
+      }
+      break;
+    case ARGTYPE_STRING:
+      *(char **)cl->cur_arg->value = str;
+      break;
+  }
+
+  cl->state = normal_state;
+  return 1;
+}
+
+static int normal_state(gpr_cmdline *cl, char *str) {
+  char *eq = NULL;
+  char *tmp = NULL;
+  char *arg_name = NULL;
+  int r = 1;
+
+  if (0 == strcmp(str, "-help") || 0 == strcmp(str, "--help") ||
+      0 == strcmp(str, "-h")) {
+    return print_usage_and_die(cl);
+  }
+
+  cl->cur_arg = NULL;
+
+  if (str[0] == '-') {
+    if (str[1] == '-') {
+      if (str[2] == 0) {
+        /* handle '--' to move to just extra args */
+        cl->state = extra_state;
+        return 1;
+      }
+      str += 2;
+    } else {
+      str += 1;
+    }
+    /* first byte of str is now past the leading '-' or '--' */
+    if (str[0] == 'n' && str[1] == 'o' && str[2] == '-') {
+      /* str is of the form '--no-foo' - it's a flag disable */
+      str += 3;
+      cl->cur_arg = find_arg(cl, str);
+      if (cl->cur_arg == NULL) {
+        return print_usage_and_die(cl);
+      }
+      if (cl->cur_arg->type != ARGTYPE_BOOL) {
+        fprintf(stderr, "%s is not a flag argument\n", str);
+        return print_usage_and_die(cl);
+      }
+      *(int *)cl->cur_arg->value = 0;
+      return 1; /* early out */
+    }
+    eq = strchr(str, '=');
+    if (eq != NULL) {
+      /* copy the string into a temp buffer and extract the name */
+      tmp = arg_name = gpr_malloc((size_t)(eq - str + 1));
+      memcpy(arg_name, str, (size_t)(eq - str));
+      arg_name[eq - str] = 0;
+    } else {
+      arg_name = str;
+    }
+    cl->cur_arg = find_arg(cl, arg_name);
+    if (cl->cur_arg == NULL) {
+      return print_usage_and_die(cl);
+    }
+    if (eq != NULL) {
+      /* str was of the type --foo=value, parse the value */
+      r = value_state(cl, eq + 1);
+    } else if (cl->cur_arg->type != ARGTYPE_BOOL) {
+      /* flag types don't have a '--foo value' variant, other types do */
+      cl->state = value_state;
+    } else {
+      /* flag parameter: just set the value */
+      *(int *)cl->cur_arg->value = 1;
+    }
+  } else {
+    r = extra_state(cl, str);
+  }
+
+  gpr_free(tmp);
+  return r;
+}
+
+int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) {
+  int i;
+
+  GPR_ASSERT(argc >= 1);
+  cl->argv0 = argv[0];
+
+  for (i = 1; i < argc; i++) {
+    if (!cl->state(cl, argv[i])) {
+      return 0;
+    }
+  }
+  return 1;
+}
diff --git a/src/core/support/cpu_iphone.c b/src/core/lib/support/cpu_iphone.c
similarity index 100%
rename from src/core/support/cpu_iphone.c
rename to src/core/lib/support/cpu_iphone.c
diff --git a/src/core/lib/support/cpu_linux.c b/src/core/lib/support/cpu_linux.c
new file mode 100644
index 0000000..d6f7e7d
--- /dev/null
+++ b/src/core/lib/support/cpu_linux.c
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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 _GNU_SOURCE
+#define _GNU_SOURCE
+#endif /* _GNU_SOURCE */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_CPU_LINUX
+
+#include <errno.h>
+#include <sched.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <grpc/support/cpu.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+static int ncpus = 0;
+
+static void init_num_cpus() {
+  /* This must be signed. sysconf returns -1 when the number cannot be
+     determined */
+  ncpus = (int)sysconf(_SC_NPROCESSORS_ONLN);
+  if (ncpus < 1) {
+    gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1");
+    ncpus = 1;
+  }
+}
+
+unsigned gpr_cpu_num_cores(void) {
+  static gpr_once once = GPR_ONCE_INIT;
+  gpr_once_init(&once, init_num_cpus);
+  return (unsigned)ncpus;
+}
+
+unsigned gpr_cpu_current_cpu(void) {
+  int cpu = sched_getcpu();
+  if (cpu < 0) {
+    gpr_log(GPR_ERROR, "Error determining current CPU: %s\n", strerror(errno));
+    return 0;
+  }
+  return (unsigned)cpu;
+}
+
+#endif /* GPR_CPU_LINUX */
diff --git a/src/core/lib/support/cpu_posix.c b/src/core/lib/support/cpu_posix.c
new file mode 100644
index 0000000..667bde7
--- /dev/null
+++ b/src/core/lib/support/cpu_posix.c
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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_CPU_POSIX
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+static __thread char magic_thread_local;
+
+static long ncpus = 0;
+
+static void init_ncpus() {
+  ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+  if (ncpus < 1 || ncpus > INT32_MAX) {
+    gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1");
+    ncpus = 1;
+  }
+}
+
+unsigned gpr_cpu_num_cores(void) {
+  static gpr_once once = GPR_ONCE_INIT;
+  gpr_once_init(&once, init_ncpus);
+  return (unsigned)ncpus;
+}
+
+/* This is a cheap, but good enough, pointer hash for sharding things: */
+static size_t shard_ptr(const void *info) {
+  size_t x = (size_t)info;
+  return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) % gpr_cpu_num_cores();
+}
+
+unsigned gpr_cpu_current_cpu(void) {
+  /* NOTE: there's no way I know to return the actual cpu index portably...
+     most code that's using this is using it to shard across work queues though,
+     so here we use thread identity instead to achieve a similar though not
+     identical effect */
+  return (unsigned)shard_ptr(&magic_thread_local);
+}
+
+#endif /* GPR_CPU_POSIX */
diff --git a/src/core/support/cpu_windows.c b/src/core/lib/support/cpu_windows.c
similarity index 100%
rename from src/core/support/cpu_windows.c
rename to src/core/lib/support/cpu_windows.c
diff --git a/src/core/lib/support/env.h b/src/core/lib/support/env.h
new file mode 100644
index 0000000..ec3959b
--- /dev/null
+++ b/src/core/lib/support/env.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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_SUPPORT_ENV_H
+#define GRPC_CORE_LIB_SUPPORT_ENV_H
+
+#include <stdio.h>
+
+#include <grpc/support/slice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Env utility functions */
+
+/* Gets the environment variable value with the specified name.
+   Returns a newly allocated string. It is the responsability of the caller to
+   gpr_free the return value if not NULL (which means that the environment
+   variable exists). */
+char *gpr_getenv(const char *name);
+
+/* Sets the the environment with the specified name to the specified value. */
+void gpr_setenv(const char *name, const char *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_SUPPORT_ENV_H */
diff --git a/src/core/lib/support/env_linux.c b/src/core/lib/support/env_linux.c
new file mode 100644
index 0000000..2436eb2
--- /dev/null
+++ b/src/core/lib/support/env_linux.c
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* for secure_getenv. */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_LINUX_ENV
+
+#include "src/core/lib/support/env.h"
+
+#include <dlfcn.h>
+#include <features.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/support/string.h"
+
+char *gpr_getenv(const char *name) {
+#if defined(GPR_BACKWARDS_COMPATIBILITY_MODE)
+  typedef char *(*getenv_type)(const char *);
+  static getenv_type getenv_func = NULL;
+  /* Check to see which getenv variant is supported (go from most
+   * to least secure) */
+  const char *names[] = {"secure_getenv", "__secure_getenv", "getenv"};
+  for (size_t i = 0; getenv_func == NULL && i < GPR_ARRAY_SIZE(names); i++) {
+    getenv_func = (getenv_type)dlsym(RTLD_DEFAULT, names[i]);
+    if (getenv_func != NULL && strstr(names[i], "secure") == NULL) {
+      gpr_log(GPR_DEBUG,
+              "Warning: insecure environment read function '%s' used",
+              names[i]);
+    }
+  }
+  char *result = getenv_func(name);
+  return result == NULL ? result : gpr_strdup(result);
+#elif __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17)
+  char *result = secure_getenv(name);
+  return result == NULL ? result : gpr_strdup(result);
+#else
+  gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used",
+          "getenv");
+  char *result = getenv(name);
+  return result == NULL ? result : gpr_strdup(result);
+#endif
+}
+
+void gpr_setenv(const char *name, const char *value) {
+  int res = setenv(name, value, 1);
+  GPR_ASSERT(res == 0);
+}
+
+#endif /* GPR_LINUX_ENV */
diff --git a/src/core/lib/support/env_posix.c b/src/core/lib/support/env_posix.c
new file mode 100644
index 0000000..ff47630
--- /dev/null
+++ b/src/core/lib/support/env_posix.c
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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_ENV
+
+#include "src/core/lib/support/env.h"
+
+#include <stdlib.h>
+
+#include <grpc/support/log.h>
+
+#include <grpc/support/string_util.h>
+#include "src/core/lib/support/string.h"
+
+char *gpr_getenv(const char *name) {
+  char *result = getenv(name);
+  return result == NULL ? result : gpr_strdup(result);
+}
+
+void gpr_setenv(const char *name, const char *value) {
+  int res = setenv(name, value, 1);
+  GPR_ASSERT(res == 0);
+}
+
+#endif /* GPR_POSIX_ENV */
diff --git a/src/core/lib/support/env_win32.c b/src/core/lib/support/env_win32.c
new file mode 100644
index 0000000..ef84c94
--- /dev/null
+++ b/src/core/lib/support/env_win32.c
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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/support/env.h"
+#include "src/core/lib/support/string.h"
+
+#ifdef __MINGW32__
+errno_t getenv_s(size_t *size_needed, char *buffer, size_t size,
+                 const char *varname);
+#else
+#include <stdlib.h>
+#endif
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+char *gpr_getenv(const char *name) {
+  size_t size;
+  char *result = NULL;
+  errno_t err;
+
+  err = getenv_s(&size, NULL, 0, name);
+  if (err || (size == 0)) return NULL;
+  result = gpr_malloc(size);
+  err = getenv_s(&size, result, size, name);
+  if (err) {
+    gpr_free(result);
+    return NULL;
+  }
+  return result;
+}
+
+void gpr_setenv(const char *name, const char *value) {
+  errno_t res = _putenv_s(name, value);
+  GPR_ASSERT(res == 0);
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/lib/support/histogram.c b/src/core/lib/support/histogram.c
new file mode 100644
index 0000000..7b016bb
--- /dev/null
+++ b/src/core/lib/support/histogram.c
@@ -0,0 +1,244 @@
+/*
+ *
+ * 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/histogram.h>
+
+#include <math.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
+
+/* Histograms are stored with exponentially increasing bucket sizes.
+   The first bucket is [0, m) where m = 1 + resolution
+   Bucket n (n>=1) contains [m**n, m**(n+1))
+   There are sufficient buckets to reach max_bucket_start */
+
+struct gpr_histogram {
+  /* Sum of all values seen so far */
+  double sum;
+  /* Sum of squares of all values seen so far */
+  double sum_of_squares;
+  /* number of values seen so far */
+  double count;
+  /* m in the description */
+  double multiplier;
+  double one_on_log_multiplier;
+  /* minimum value seen */
+  double min_seen;
+  /* maximum value seen */
+  double max_seen;
+  /* maximum representable value */
+  double max_possible;
+  /* number of buckets */
+  size_t num_buckets;
+  /* the buckets themselves */
+  uint32_t *buckets;
+};
+
+/* determine a bucket index given a value - does no bounds checking */
+static size_t bucket_for_unchecked(gpr_histogram *h, double x) {
+  return (size_t)(log(x) * h->one_on_log_multiplier);
+}
+
+/* bounds checked version of the above */
+static size_t bucket_for(gpr_histogram *h, double x) {
+  size_t bucket = bucket_for_unchecked(h, GPR_CLAMP(x, 1.0, h->max_possible));
+  GPR_ASSERT(bucket < h->num_buckets);
+  return bucket;
+}
+
+/* at what value does a bucket start? */
+static double bucket_start(gpr_histogram *h, double x) {
+  return pow(h->multiplier, x);
+}
+
+gpr_histogram *gpr_histogram_create(double resolution,
+                                    double max_bucket_start) {
+  gpr_histogram *h = gpr_malloc(sizeof(gpr_histogram));
+  GPR_ASSERT(resolution > 0.0);
+  GPR_ASSERT(max_bucket_start > resolution);
+  h->sum = 0.0;
+  h->sum_of_squares = 0.0;
+  h->multiplier = 1.0 + resolution;
+  h->one_on_log_multiplier = 1.0 / log(1.0 + resolution);
+  h->max_possible = max_bucket_start;
+  h->count = 0.0;
+  h->min_seen = max_bucket_start;
+  h->max_seen = 0.0;
+  h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
+  GPR_ASSERT(h->num_buckets > 1);
+  GPR_ASSERT(h->num_buckets < 100000000);
+  h->buckets = gpr_malloc(sizeof(uint32_t) * h->num_buckets);
+  memset(h->buckets, 0, sizeof(uint32_t) * h->num_buckets);
+  return h;
+}
+
+void gpr_histogram_destroy(gpr_histogram *h) {
+  gpr_free(h->buckets);
+  gpr_free(h);
+}
+
+void gpr_histogram_add(gpr_histogram *h, double x) {
+  h->sum += x;
+  h->sum_of_squares += x * x;
+  h->count++;
+  if (x < h->min_seen) {
+    h->min_seen = x;
+  }
+  if (x > h->max_seen) {
+    h->max_seen = x;
+  }
+  h->buckets[bucket_for(h, x)]++;
+}
+
+int gpr_histogram_merge(gpr_histogram *dst, const gpr_histogram *src) {
+  if ((dst->num_buckets != src->num_buckets) ||
+      (dst->multiplier != src->multiplier)) {
+    /* Fail because these histograms don't match */
+    return 0;
+  }
+  gpr_histogram_merge_contents(dst, src->buckets, src->num_buckets,
+                               src->min_seen, src->max_seen, src->sum,
+                               src->sum_of_squares, src->count);
+  return 1;
+}
+
+void gpr_histogram_merge_contents(gpr_histogram *dst, const uint32_t *data,
+                                  size_t data_count, double min_seen,
+                                  double max_seen, double sum,
+                                  double sum_of_squares, double count) {
+  size_t i;
+  GPR_ASSERT(dst->num_buckets == data_count);
+  dst->sum += sum;
+  dst->sum_of_squares += sum_of_squares;
+  dst->count += count;
+  if (min_seen < dst->min_seen) {
+    dst->min_seen = min_seen;
+  }
+  if (max_seen > dst->max_seen) {
+    dst->max_seen = max_seen;
+  }
+  for (i = 0; i < dst->num_buckets; i++) {
+    dst->buckets[i] += data[i];
+  }
+}
+
+static double threshold_for_count_below(gpr_histogram *h, double count_below) {
+  double count_so_far;
+  double lower_bound;
+  double upper_bound;
+  size_t lower_idx;
+  size_t upper_idx;
+
+  if (h->count == 0) {
+    return 0.0;
+  }
+
+  if (count_below <= 0) {
+    return h->min_seen;
+  }
+  if (count_below >= h->count) {
+    return h->max_seen;
+  }
+
+  /* find the lowest bucket that gets us above count_below */
+  count_so_far = 0.0;
+  for (lower_idx = 0; lower_idx < h->num_buckets; lower_idx++) {
+    count_so_far += h->buckets[lower_idx];
+    if (count_so_far >= count_below) {
+      break;
+    }
+  }
+  if (count_so_far == count_below) {
+    /* this bucket hits the threshold exactly... we should be midway through
+       any run of zero values following the bucket */
+    for (upper_idx = lower_idx + 1; upper_idx < h->num_buckets; upper_idx++) {
+      if (h->buckets[upper_idx]) {
+        break;
+      }
+    }
+    return (bucket_start(h, (double)lower_idx) +
+            bucket_start(h, (double)upper_idx)) /
+           2.0;
+  } else {
+    /* treat values as uniform throughout the bucket, and find where this value
+       should lie */
+    lower_bound = bucket_start(h, (double)lower_idx);
+    upper_bound = bucket_start(h, (double)(lower_idx + 1));
+    return GPR_CLAMP(upper_bound -
+                         (upper_bound - lower_bound) *
+                             (count_so_far - count_below) /
+                             h->buckets[lower_idx],
+                     h->min_seen, h->max_seen);
+  }
+}
+
+double gpr_histogram_percentile(gpr_histogram *h, double percentile) {
+  return threshold_for_count_below(h, h->count * percentile / 100.0);
+}
+
+double gpr_histogram_mean(gpr_histogram *h) {
+  GPR_ASSERT(h->count != 0);
+  return h->sum / h->count;
+}
+
+double gpr_histogram_stddev(gpr_histogram *h) {
+  return sqrt(gpr_histogram_variance(h));
+}
+
+double gpr_histogram_variance(gpr_histogram *h) {
+  if (h->count == 0) return 0.0;
+  return (h->sum_of_squares * h->count - h->sum * h->sum) /
+         (h->count * h->count);
+}
+
+double gpr_histogram_maximum(gpr_histogram *h) { return h->max_seen; }
+
+double gpr_histogram_minimum(gpr_histogram *h) { return h->min_seen; }
+
+double gpr_histogram_count(gpr_histogram *h) { return h->count; }
+
+double gpr_histogram_sum(gpr_histogram *h) { return h->sum; }
+
+double gpr_histogram_sum_of_squares(gpr_histogram *h) {
+  return h->sum_of_squares;
+}
+
+const uint32_t *gpr_histogram_get_contents(gpr_histogram *h, size_t *size) {
+  *size = h->num_buckets;
+  return h->buckets;
+}
diff --git a/src/core/lib/support/host_port.c b/src/core/lib/support/host_port.c
new file mode 100644
index 0000000..f19bdbc
--- /dev/null
+++ b/src/core/lib/support/host_port.c
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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/host_port.h>
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include "src/core/lib/support/string.h"
+
+int gpr_join_host_port(char **out, const char *host, int port) {
+  if (host[0] != '[' && strchr(host, ':') != NULL) {
+    /* IPv6 literals must be enclosed in brackets. */
+    return gpr_asprintf(out, "[%s]:%d", host, port);
+  } else {
+    /* Ordinary non-bracketed host:port. */
+    return gpr_asprintf(out, "%s:%d", host, port);
+  }
+}
+
+int gpr_split_host_port(const char *name, char **host, char **port) {
+  const char *host_start;
+  size_t host_len;
+  const char *port_start;
+
+  *host = NULL;
+  *port = NULL;
+
+  if (name[0] == '[') {
+    /* Parse a bracketed host, typically an IPv6 literal. */
+    const char *rbracket = strchr(name, ']');
+    if (rbracket == NULL) {
+      /* Unmatched [ */
+      return 0;
+    }
+    if (rbracket[1] == '\0') {
+      /* ]<end> */
+      port_start = NULL;
+    } else if (rbracket[1] == ':') {
+      /* ]:<port?> */
+      port_start = rbracket + 2;
+    } else {
+      /* ]<invalid> */
+      return 0;
+    }
+    host_start = name + 1;
+    host_len = (size_t)(rbracket - host_start);
+    if (memchr(host_start, ':', host_len) == NULL) {
+      /* Require all bracketed hosts to contain a colon, because a hostname or
+         IPv4 address should never use brackets. */
+      return 0;
+    }
+  } else {
+    const char *colon = strchr(name, ':');
+    if (colon != NULL && strchr(colon + 1, ':') == NULL) {
+      /* Exactly 1 colon.  Split into host:port. */
+      host_start = name;
+      host_len = (size_t)(colon - name);
+      port_start = colon + 1;
+    } else {
+      /* 0 or 2+ colons.  Bare hostname or IPv6 litearal. */
+      host_start = name;
+      host_len = strlen(name);
+      port_start = NULL;
+    }
+  }
+
+  /* Allocate return values. */
+  *host = gpr_malloc(host_len + 1);
+  memcpy(*host, host_start, host_len);
+  (*host)[host_len] = '\0';
+
+  if (port_start != NULL) {
+    *port = gpr_strdup(port_start);
+  }
+
+  return 1;
+}
diff --git a/src/core/lib/support/load_file.c b/src/core/lib/support/load_file.c
new file mode 100644
index 0000000..f30aacd
--- /dev/null
+++ b/src/core/lib/support/load_file.c
@@ -0,0 +1,91 @@
+/*
+ *
+ * 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/support/load_file.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/support/block_annotate.h"
+#include "src/core/lib/support/string.h"
+
+gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
+                        int *success) {
+  unsigned char *contents = NULL;
+  size_t contents_size = 0;
+  char *error_msg = NULL;
+  gpr_slice result = gpr_empty_slice();
+  FILE *file;
+  size_t bytes_read = 0;
+
+  GRPC_SCHEDULING_START_BLOCKING_REGION;
+  file = fopen(filename, "rb");
+  if (file == NULL) {
+    gpr_asprintf(&error_msg, "Could not open file %s (error = %s).", filename,
+                 strerror(errno));
+    GPR_ASSERT(error_msg != NULL);
+    goto end;
+  }
+  fseek(file, 0, SEEK_END);
+  /* Converting to size_t on the assumption that it will not fail */
+  contents_size = (size_t)ftell(file);
+  fseek(file, 0, SEEK_SET);
+  contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0));
+  bytes_read = fread(contents, 1, contents_size, file);
+  if (bytes_read < contents_size) {
+    GPR_ASSERT(ferror(file));
+    gpr_asprintf(&error_msg, "Error %s occured while reading file %s.",
+                 strerror(errno), filename);
+    GPR_ASSERT(error_msg != NULL);
+    goto end;
+  }
+  if (success != NULL) *success = 1;
+  if (add_null_terminator) {
+    contents[contents_size++] = 0;
+  }
+  result = gpr_slice_new(contents, contents_size, gpr_free);
+
+end:
+  if (error_msg != NULL) {
+    gpr_log(GPR_ERROR, "%s", error_msg);
+    gpr_free(error_msg);
+    if (success != NULL) *success = 0;
+  }
+  if (file != NULL) fclose(file);
+  GRPC_SCHEDULING_END_BLOCKING_REGION;
+  return result;
+}
diff --git a/src/core/lib/support/load_file.h b/src/core/lib/support/load_file.h
new file mode 100644
index 0000000..9a4b279
--- /dev/null
+++ b/src/core/lib/support/load_file.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_SUPPORT_LOAD_FILE_H
+#define GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H
+
+#include <stdio.h>
+
+#include <grpc/support/slice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Loads the content of a file into a slice. add_null_terminator will add
+   a NULL terminator if non-zero. The success parameter, if not NULL,
+   will be set to 1 in case of success and 0 in case of failure. */
+gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
+                        int *success);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H */
diff --git a/src/core/lib/support/log.c b/src/core/lib/support/log.c
new file mode 100644
index 0000000..882abf6
--- /dev/null
+++ b/src/core/lib/support/log.c
@@ -0,0 +1,99 @@
+/*
+ *
+ * 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/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+
+#include <stdio.h>
+#include <string.h>
+
+extern void gpr_default_log(gpr_log_func_args *args);
+static gpr_log_func g_log_func = gpr_default_log;
+static gpr_atm g_min_severity_to_print = GPR_LOG_VERBOSITY_UNSET;
+
+const char *gpr_log_severity_string(gpr_log_severity severity) {
+  switch (severity) {
+    case GPR_LOG_SEVERITY_DEBUG:
+      return "D";
+    case GPR_LOG_SEVERITY_INFO:
+      return "I";
+    case GPR_LOG_SEVERITY_ERROR:
+      return "E";
+  }
+  GPR_UNREACHABLE_CODE(return "UNKNOWN");
+}
+
+void gpr_log_message(const char *file, int line, gpr_log_severity severity,
+                     const char *message) {
+  if ((gpr_atm)severity < gpr_atm_no_barrier_load(&g_min_severity_to_print))
+    return;
+
+  gpr_log_func_args lfargs;
+  memset(&lfargs, 0, sizeof(lfargs));
+  lfargs.file = file;
+  lfargs.line = line;
+  lfargs.severity = severity;
+  lfargs.message = message;
+  g_log_func(&lfargs);
+}
+
+void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print) {
+  gpr_atm_no_barrier_store(&g_min_severity_to_print,
+                           (gpr_atm)min_severity_to_print);
+}
+
+void gpr_log_verbosity_init() {
+  char *verbosity = gpr_getenv("GRPC_VERBOSITY");
+  if (verbosity == NULL) return;
+
+  gpr_atm min_severity_to_print = GPR_LOG_VERBOSITY_UNSET;
+  if (strcmp(verbosity, "DEBUG") == 0) {
+    min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG;
+  } else if (strcmp(verbosity, "INFO") == 0) {
+    min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO;
+  } else if (strcmp(verbosity, "ERROR") == 0) {
+    min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR;
+  }
+  gpr_free(verbosity);
+  if ((gpr_atm_no_barrier_load(&g_min_severity_to_print)) ==
+      GPR_LOG_VERBOSITY_UNSET) {
+    gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print);
+  }
+}
+
+void gpr_set_log_function(gpr_log_func f) { g_log_func = f; }
diff --git a/src/core/lib/support/log_android.c b/src/core/lib/support/log_android.c
new file mode 100644
index 0000000..94c8100
--- /dev/null
+++ b/src/core/lib/support/log_android.c
@@ -0,0 +1,87 @@
+/*
+ *
+ * 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_ANDROID
+
+#include <android/log.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+static android_LogPriority severity_to_log_priority(gpr_log_severity severity) {
+  switch (severity) {
+    case GPR_LOG_SEVERITY_DEBUG:
+      return ANDROID_LOG_DEBUG;
+    case GPR_LOG_SEVERITY_INFO:
+      return ANDROID_LOG_INFO;
+    case GPR_LOG_SEVERITY_ERROR:
+      return ANDROID_LOG_ERROR;
+  }
+  return ANDROID_LOG_DEFAULT;
+}
+
+void gpr_log(const char *file, int line, gpr_log_severity severity,
+             const char *format, ...) {
+  char *message = NULL;
+  va_list args;
+  va_start(args, format);
+  vasprintf(&message, format, args);
+  va_end(args);
+  gpr_log_message(file, line, severity, message);
+  free(message);
+}
+
+void gpr_default_log(gpr_log_func_args *args) {
+  char *final_slash;
+  const char *display_file;
+  char *output = NULL;
+
+  final_slash = strrchr(args->file, '/');
+  if (final_slash == NULL)
+    display_file = args->file;
+  else
+    display_file = final_slash + 1;
+
+  asprintf(&output, "%s:%d] %s", display_file, args->line, args->message);
+
+  __android_log_write(severity_to_log_priority(args->severity), "GRPC", output);
+
+  /* allocated by asprintf => use free, not gpr_free */
+  free(output);
+}
+
+#endif /* GPR_ANDROID */
diff --git a/src/core/lib/support/log_linux.c b/src/core/lib/support/log_linux.c
new file mode 100644
index 0000000..ff3febb
--- /dev/null
+++ b/src/core/lib/support/log_linux.c
@@ -0,0 +1,106 @@
+/*
+ *
+ * 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 _POSIX_SOURCE
+#define _POSIX_SOURCE
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_LINUX
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+#include <linux/unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <time.h>
+#include <unistd.h>
+
+static long gettid(void) { return syscall(__NR_gettid); }
+
+void gpr_log(const char *file, int line, gpr_log_severity severity,
+             const char *format, ...) {
+  char *message = NULL;
+  va_list args;
+  va_start(args, format);
+  if (vasprintf(&message, format, args) == -1) {
+    va_end(args);
+    return;
+  }
+  va_end(args);
+  gpr_log_message(file, line, severity, message);
+  /* message has been allocated by vasprintf above, and needs free */
+  free(message);
+}
+
+void gpr_default_log(gpr_log_func_args *args) {
+  char *final_slash;
+  char *prefix;
+  const char *display_file;
+  char time_buffer[64];
+  time_t timer;
+  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
+  struct tm tm;
+
+  timer = (time_t)now.tv_sec;
+  final_slash = strrchr(args->file, '/');
+  if (final_slash == NULL)
+    display_file = args->file;
+  else
+    display_file = final_slash + 1;
+
+  if (!localtime_r(&timer, &tm)) {
+    strcpy(time_buffer, "error:localtime");
+  } else if (0 ==
+             strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
+    strcpy(time_buffer, "error:strftime");
+  }
+
+  gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]",
+               gpr_log_severity_string(args->severity), time_buffer,
+               (int)(now.tv_nsec), gettid(), display_file, args->line);
+
+  fprintf(stderr, "%-60s %s\n", prefix, args->message);
+  gpr_free(prefix);
+}
+
+#endif
diff --git a/src/core/lib/support/log_posix.c b/src/core/lib/support/log_posix.c
new file mode 100644
index 0000000..6ae6320
--- /dev/null
+++ b/src/core/lib/support/log_posix.c
@@ -0,0 +1,102 @@
+/*
+ *
+ * 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>
+
+#if defined(GPR_POSIX_LOG)
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+static intptr_t gettid(void) { return (intptr_t)pthread_self(); }
+
+void gpr_log(const char *file, int line, gpr_log_severity severity,
+             const char *format, ...) {
+  char buf[64];
+  char *allocated = NULL;
+  char *message = NULL;
+  int ret;
+  va_list args;
+  va_start(args, format);
+  ret = vsnprintf(buf, sizeof(buf), format, args);
+  va_end(args);
+  if (ret < 0) {
+    message = NULL;
+  } else if ((size_t)ret <= sizeof(buf) - 1) {
+    message = buf;
+  } else {
+    message = allocated = gpr_malloc((size_t)ret + 1);
+    va_start(args, format);
+    vsnprintf(message, (size_t)(ret + 1), format, args);
+    va_end(args);
+  }
+  gpr_log_message(file, line, severity, message);
+  gpr_free(allocated);
+}
+
+void gpr_default_log(gpr_log_func_args *args) {
+  char *final_slash;
+  const char *display_file;
+  char time_buffer[64];
+  time_t timer;
+  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
+  struct tm tm;
+
+  timer = (time_t)now.tv_sec;
+  final_slash = strrchr(args->file, '/');
+  if (final_slash == NULL)
+    display_file = args->file;
+  else
+    display_file = final_slash + 1;
+
+  if (!localtime_r(&timer, &tm)) {
+    strcpy(time_buffer, "error:localtime");
+  } else if (0 ==
+             strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
+    strcpy(time_buffer, "error:strftime");
+  }
+
+  fprintf(stderr, "%s%s.%09d %7tu %s:%d] %s\n",
+          gpr_log_severity_string(args->severity), time_buffer,
+          (int)(now.tv_nsec), gettid(), display_file, args->line,
+          args->message);
+}
+
+#endif /* defined(GPR_POSIX_LOG) */
diff --git a/src/core/lib/support/log_win32.c b/src/core/lib/support/log_win32.c
new file mode 100644
index 0000000..ba78497
--- /dev/null
+++ b/src/core/lib/support/log_win32.c
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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 <stdarg.h>
+#include <stdio.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_win32.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/string_win32.h"
+
+void gpr_log(const char *file, int line, gpr_log_severity severity,
+             const char *format, ...) {
+  char *message = NULL;
+  va_list args;
+  int ret;
+
+  /* Determine the length. */
+  va_start(args, format);
+  ret = _vscprintf(format, args);
+  va_end(args);
+  if (ret < 0) {
+    message = NULL;
+  } else {
+    /* Allocate a new buffer, with space for the NUL terminator. */
+    size_t strp_buflen = (size_t)ret + 1;
+    message = gpr_malloc(strp_buflen);
+
+    /* Print to the buffer. */
+    va_start(args, format);
+    ret = vsnprintf_s(message, strp_buflen, _TRUNCATE, format, args);
+    va_end(args);
+    if ((size_t)ret != strp_buflen - 1) {
+      /* This should never happen. */
+      gpr_free(message);
+      message = NULL;
+    }
+  }
+
+  gpr_log_message(file, line, severity, message);
+  gpr_free(message);
+}
+
+/* Simple starter implementation */
+void gpr_default_log(gpr_log_func_args *args) {
+  char *final_slash;
+  const char *display_file;
+  char time_buffer[64];
+  time_t timer;
+  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
+  struct tm tm;
+
+  timer = (time_t)now.tv_sec;
+  final_slash = strrchr(args->file, '\\');
+  if (final_slash == NULL)
+    display_file = args->file;
+  else
+    display_file = final_slash + 1;
+
+  if (localtime_s(&tm, &timer)) {
+    strcpy(time_buffer, "error:localtime");
+  } else if (0 ==
+             strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
+    strcpy(time_buffer, "error:strftime");
+  }
+
+  fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n",
+          gpr_log_severity_string(args->severity), time_buffer,
+          (int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line,
+          args->message);
+  fflush(stderr);
+}
+
+char *gpr_format_message(int messageid) {
+  LPTSTR tmessage;
+  char *message;
+  DWORD status = FormatMessage(
+      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+          FORMAT_MESSAGE_IGNORE_INSERTS,
+      NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+      (LPTSTR)(&tmessage), 0, NULL);
+  if (status == 0) return gpr_strdup("Unable to retrieve error string");
+  message = gpr_tchar_to_char(tmessage);
+  LocalFree(tmessage);
+  return message;
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/lib/support/murmur_hash.c b/src/core/lib/support/murmur_hash.c
new file mode 100644
index 0000000..5711fff
--- /dev/null
+++ b/src/core/lib/support/murmur_hash.c
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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/support/murmur_hash.h"
+
+#define ROTL32(x, r) ((x) << (r)) | ((x) >> (32 - (r)))
+
+#define FMIX32(h)    \
+  (h) ^= (h) >> 16;  \
+  (h) *= 0x85ebca6b; \
+  (h) ^= (h) >> 13;  \
+  (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;
+  int i;
+
+  uint32_t h1 = seed;
+  uint32_t k1;
+
+  const uint32_t c1 = 0xcc9e2d51;
+  const uint32_t c2 = 0x1b873593;
+
+  const uint32_t *blocks = ((const uint32_t *)key) + nblocks;
+  const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
+
+  /* body */
+  for (i = -(int)nblocks; i; i++) {
+    k1 = GETBLOCK32(blocks, i);
+
+    k1 *= c1;
+    k1 = ROTL32(k1, 15);
+    k1 *= c2;
+
+    h1 ^= k1;
+    h1 = ROTL32(h1, 13);
+    h1 = h1 * 5 + 0xe6546b64;
+  }
+
+  k1 = 0;
+
+  /* tail */
+  switch (len & 3) {
+    case 3:
+      k1 ^= ((uint32_t)tail[2]) << 16;
+    case 2:
+      k1 ^= ((uint32_t)tail[1]) << 8;
+    case 1:
+      k1 ^= tail[0];
+      k1 *= c1;
+      k1 = ROTL32(k1, 15);
+      k1 *= c2;
+      h1 ^= k1;
+  };
+
+  /* finalization */
+  h1 ^= (uint32_t)len;
+  FMIX32(h1);
+  return h1;
+}
diff --git a/src/core/lib/support/murmur_hash.h b/src/core/lib/support/murmur_hash.h
new file mode 100644
index 0000000..6d282ff
--- /dev/null
+++ b/src/core/lib/support/murmur_hash.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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_SUPPORT_MURMUR_HASH_H
+#define GRPC_CORE_LIB_SUPPORT_MURMUR_HASH_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stddef.h>
+
+/* compute the hash of key (length len) */
+uint32_t gpr_murmur_hash3(const void *key, size_t len, uint32_t seed);
+
+#endif /* GRPC_CORE_LIB_SUPPORT_MURMUR_HASH_H */
diff --git a/src/core/support/slice.c b/src/core/lib/support/slice.c
similarity index 100%
rename from src/core/support/slice.c
rename to src/core/lib/support/slice.c
diff --git a/src/core/support/slice_buffer.c b/src/core/lib/support/slice_buffer.c
similarity index 100%
rename from src/core/support/slice_buffer.c
rename to src/core/lib/support/slice_buffer.c
diff --git a/src/core/lib/support/stack_lockfree.c b/src/core/lib/support/stack_lockfree.c
new file mode 100644
index 0000000..9d7c9e5
--- /dev/null
+++ b/src/core/lib/support/stack_lockfree.c
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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/support/stack_lockfree.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+
+/* The lockfree node structure is a single architecture-level
+   word that allows for an atomic CAS to set it up. */
+struct lockfree_node_contents {
+  /* next thing to look at. Actual index for head, next index otherwise */
+  uint16_t index;
+#ifdef GPR_ARCH_64
+  uint16_t pad;
+  uint32_t aba_ctr;
+#else
+#ifdef GPR_ARCH_32
+  uint16_t aba_ctr;
+#else
+#error Unsupported bit width architecture
+#endif
+#endif
+};
+
+/* Use a union to make sure that these are in the same bits as an atm word */
+typedef union lockfree_node {
+  gpr_atm atm;
+  struct lockfree_node_contents contents;
+} lockfree_node;
+
+/* make sure that entries aligned to 8-bytes */
+#define ENTRY_ALIGNMENT_BITS 3
+/* reserve this entry as invalid */
+#define INVALID_ENTRY_INDEX ((1 << 16) - 1)
+
+struct gpr_stack_lockfree {
+  lockfree_node *entries;
+  lockfree_node head; /* An atomic entry describing curr head */
+
+#ifndef NDEBUG
+  /* Bitmap of pushed entries to check for double-push or pop */
+  gpr_atm pushed[(INVALID_ENTRY_INDEX + 1) / (8 * sizeof(gpr_atm))];
+#endif
+};
+
+gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries) {
+  gpr_stack_lockfree *stack;
+  stack = gpr_malloc(sizeof(*stack));
+  /* Since we only allocate 16 bits to represent an entry number,
+   * make sure that we are within the desired range */
+  /* Reserve the highest entry number as a dummy */
+  GPR_ASSERT(entries < INVALID_ENTRY_INDEX);
+  stack->entries = gpr_malloc_aligned(entries * sizeof(stack->entries[0]),
+                                      ENTRY_ALIGNMENT_BITS);
+  /* Clear out all entries */
+  memset(stack->entries, 0, entries * sizeof(stack->entries[0]));
+  memset(&stack->head, 0, sizeof(stack->head));
+#ifndef NDEBUG
+  memset(&stack->pushed, 0, sizeof(stack->pushed));
+#endif
+
+  GPR_ASSERT(sizeof(stack->entries->atm) == sizeof(stack->entries->contents));
+
+  /* Point the head at reserved dummy entry */
+  stack->head.contents.index = INVALID_ENTRY_INDEX;
+/* Fill in the pad and aba_ctr to avoid confusing memcheck tools */
+#ifdef GPR_ARCH_64
+  stack->head.contents.pad = 0;
+#endif
+  stack->head.contents.aba_ctr = 0;
+  return stack;
+}
+
+void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack) {
+  gpr_free_aligned(stack->entries);
+  gpr_free(stack);
+}
+
+int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
+  lockfree_node head;
+  lockfree_node newhead;
+  lockfree_node curent;
+  lockfree_node newent;
+
+  /* First fill in the entry's index and aba ctr for new head */
+  newhead.contents.index = (uint16_t)entry;
+#ifdef GPR_ARCH_64
+  /* Fill in the pad to avoid confusing memcheck tools */
+  newhead.contents.pad = 0;
+#endif
+
+  /* Also post-increment the aba_ctr */
+  curent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
+  newhead.contents.aba_ctr = ++curent.contents.aba_ctr;
+  gpr_atm_no_barrier_store(&stack->entries[entry].atm, curent.atm);
+
+#ifndef NDEBUG
+  /* Check for double push */
+  {
+    int pushed_index = entry / (int)(8 * sizeof(gpr_atm));
+    int pushed_bit = entry % (int)(8 * sizeof(gpr_atm));
+    gpr_atm old_val;
+
+    old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index],
+                                           ((gpr_atm)1 << pushed_bit));
+    GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) == 0);
+  }
+#endif
+
+  do {
+    /* Atomically get the existing head value for use */
+    head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
+    /* Point to it */
+    newent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
+    newent.contents.index = head.contents.index;
+    gpr_atm_no_barrier_store(&stack->entries[entry].atm, newent.atm);
+  } while (!gpr_atm_rel_cas(&(stack->head.atm), head.atm, newhead.atm));
+  /* Use rel_cas above to make sure that entry index is set properly */
+  return head.contents.index == INVALID_ENTRY_INDEX;
+}
+
+int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) {
+  lockfree_node head;
+  lockfree_node newhead;
+
+  do {
+    head.atm = gpr_atm_acq_load(&(stack->head.atm));
+    if (head.contents.index == INVALID_ENTRY_INDEX) {
+      return -1;
+    }
+    newhead.atm =
+        gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm));
+
+  } while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm));
+#ifndef NDEBUG
+  /* Check for valid pop */
+  {
+    int pushed_index = head.contents.index / (8 * sizeof(gpr_atm));
+    int pushed_bit = head.contents.index % (8 * sizeof(gpr_atm));
+    gpr_atm old_val;
+
+    old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index],
+                                           -((gpr_atm)1 << pushed_bit));
+    GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) != 0);
+  }
+#endif
+
+  return head.contents.index;
+}
diff --git a/src/core/lib/support/stack_lockfree.h b/src/core/lib/support/stack_lockfree.h
new file mode 100644
index 0000000..35ef7c2
--- /dev/null
+++ b/src/core/lib/support/stack_lockfree.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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_SUPPORT_STACK_LOCKFREE_H
+#define GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H
+
+#include <stddef.h>
+
+typedef struct gpr_stack_lockfree gpr_stack_lockfree;
+
+/* This stack must specify the maximum number of entries to track.
+   The current implementation only allows up to 65534 entries */
+gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries);
+void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack);
+
+/* Pass in a valid entry number for the next stack entry */
+/* Returns 1 if this is the first element on the stack, 0 otherwise */
+int gpr_stack_lockfree_push(gpr_stack_lockfree *, int entry);
+
+/* Returns -1 on empty or the actual entry number */
+int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack);
+
+#endif /* GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H */
diff --git a/src/core/lib/support/string.c b/src/core/lib/support/string.c
new file mode 100644
index 0000000..a2ab6c5
--- /dev/null
+++ b/src/core/lib/support/string.c
@@ -0,0 +1,296 @@
+/*
+ *
+ * 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/support/string.h"
+
+#include <ctype.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
+
+char *gpr_strdup(const char *src) {
+  char *dst;
+  size_t len;
+
+  if (!src) {
+    return NULL;
+  }
+
+  len = strlen(src) + 1;
+  dst = gpr_malloc(len);
+
+  memcpy(dst, src, len);
+
+  return dst;
+}
+
+typedef struct {
+  size_t capacity;
+  size_t length;
+  char *data;
+} dump_out;
+
+static dump_out dump_out_create(void) {
+  dump_out r = {0, 0, NULL};
+  return r;
+}
+
+static void dump_out_append(dump_out *out, char c) {
+  if (out->length == out->capacity) {
+    out->capacity = GPR_MAX(8, 2 * out->capacity);
+    out->data = gpr_realloc(out->data, out->capacity);
+  }
+  out->data[out->length++] = c;
+}
+
+static void hexdump(dump_out *out, const char *buf, size_t len) {
+  static const char hex[16] = "0123456789abcdef";
+
+  const uint8_t *const beg = (const uint8_t *)buf;
+  const uint8_t *const end = beg + len;
+  const uint8_t *cur;
+
+  for (cur = beg; cur != end; ++cur) {
+    if (cur != beg) dump_out_append(out, ' ');
+    dump_out_append(out, hex[*cur >> 4]);
+    dump_out_append(out, hex[*cur & 0xf]);
+  }
+}
+
+static void asciidump(dump_out *out, const char *buf, size_t len) {
+  const uint8_t *const beg = (const uint8_t *)buf;
+  const uint8_t *const end = beg + len;
+  const uint8_t *cur;
+  int out_was_empty = (out->length == 0);
+  if (!out_was_empty) {
+    dump_out_append(out, ' ');
+    dump_out_append(out, '\'');
+  }
+  for (cur = beg; cur != end; ++cur) {
+    dump_out_append(out, (char)(isprint(*cur) ? *(char *)cur : '.'));
+  }
+  if (!out_was_empty) {
+    dump_out_append(out, '\'');
+  }
+}
+
+char *gpr_dump(const char *buf, size_t len, uint32_t flags) {
+  dump_out out = dump_out_create();
+  if (flags & GPR_DUMP_HEX) {
+    hexdump(&out, buf, len);
+  }
+  if (flags & GPR_DUMP_ASCII) {
+    asciidump(&out, buf, len);
+  }
+  dump_out_append(&out, 0);
+  return out.data;
+}
+
+char *gpr_dump_slice(gpr_slice s, uint32_t flags) {
+  return gpr_dump((const char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s),
+                  flags);
+}
+
+int gpr_parse_bytes_to_uint32(const char *buf, size_t len, uint32_t *result) {
+  uint32_t out = 0;
+  uint32_t new;
+  size_t i;
+
+  if (len == 0) return 0; /* must have some bytes */
+
+  for (i = 0; i < len; i++) {
+    if (buf[i] < '0' || buf[i] > '9') return 0; /* bad char */
+    new = 10 * out + (uint32_t)(buf[i] - '0');
+    if (new < out) return 0; /* overflow */
+    out = new;
+  }
+
+  *result = out;
+  return 1;
+}
+
+void gpr_reverse_bytes(char *str, int len) {
+  char *p1, *p2;
+  for (p1 = str, p2 = str + len - 1; p2 > p1; ++p1, --p2) {
+    char temp = *p1;
+    *p1 = *p2;
+    *p2 = temp;
+  }
+}
+
+int gpr_ltoa(long value, char *string) {
+  long sign;
+  int i = 0;
+
+  if (value == 0) {
+    string[0] = '0';
+    string[1] = 0;
+    return 1;
+  }
+
+  sign = value < 0 ? -1 : 1;
+  while (value) {
+    string[i++] = (char)('0' + sign * (value % 10));
+    value /= 10;
+  }
+  if (sign < 0) string[i++] = '-';
+  gpr_reverse_bytes(string, i);
+  string[i] = 0;
+  return i;
+}
+
+int int64_ttoa(int64_t value, char *string) {
+  int64_t sign;
+  int i = 0;
+
+  if (value == 0) {
+    string[0] = '0';
+    string[1] = 0;
+    return 1;
+  }
+
+  sign = value < 0 ? -1 : 1;
+  while (value) {
+    string[i++] = (char)('0' + sign * (value % 10));
+    value /= 10;
+  }
+  if (sign < 0) string[i++] = '-';
+  gpr_reverse_bytes(string, i);
+  string[i] = 0;
+  return i;
+}
+
+char *gpr_strjoin(const char **strs, size_t nstrs, size_t *final_length) {
+  return gpr_strjoin_sep(strs, nstrs, "", final_length);
+}
+
+char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep,
+                      size_t *final_length) {
+  const size_t sep_len = strlen(sep);
+  size_t out_length = 0;
+  size_t i;
+  char *out;
+  for (i = 0; i < nstrs; i++) {
+    out_length += strlen(strs[i]);
+  }
+  out_length += 1; /* null terminator */
+  if (nstrs > 0) {
+    out_length += sep_len * (nstrs - 1); /* separators */
+  }
+  out = gpr_malloc(out_length);
+  out_length = 0;
+  for (i = 0; i < nstrs; i++) {
+    const size_t slen = strlen(strs[i]);
+    if (i != 0) {
+      memcpy(out + out_length, sep, sep_len);
+      out_length += sep_len;
+    }
+    memcpy(out + out_length, strs[i], slen);
+    out_length += slen;
+  }
+  out[out_length] = 0;
+  if (final_length != NULL) {
+    *final_length = out_length;
+  }
+  return out;
+}
+
+/** Finds the initial (\a begin) and final (\a end) offsets of the next
+ * substring from \a str + \a read_offset until the next \a sep or the end of \a
+ * str.
+ *
+ * Returns 1 and updates \a begin and \a end. Returns 0 otherwise. */
+static int slice_find_separator_offset(const gpr_slice str, const char *sep,
+                                       const size_t read_offset, size_t *begin,
+                                       size_t *end) {
+  size_t i;
+  const uint8_t *str_ptr = GPR_SLICE_START_PTR(str) + read_offset;
+  const size_t str_len = GPR_SLICE_LENGTH(str) - read_offset;
+  const size_t sep_len = strlen(sep);
+  if (str_len < sep_len) {
+    return 0;
+  }
+
+  for (i = 0; i <= str_len - sep_len; i++) {
+    if (memcmp(str_ptr + i, sep, sep_len) == 0) {
+      *begin = read_offset;
+      *end = read_offset + i;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+void gpr_slice_split(gpr_slice str, const char *sep, gpr_slice_buffer *dst) {
+  const size_t sep_len = strlen(sep);
+  size_t begin, end;
+
+  GPR_ASSERT(sep_len > 0);
+
+  if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) {
+    do {
+      gpr_slice_buffer_add_indexed(dst, gpr_slice_sub(str, begin, end));
+    } while (slice_find_separator_offset(str, sep, end + sep_len, &begin,
+                                         &end) != 0);
+    gpr_slice_buffer_add_indexed(
+        dst, gpr_slice_sub(str, end + sep_len, GPR_SLICE_LENGTH(str)));
+  } else { /* no sep found, add whole input */
+    gpr_slice_buffer_add_indexed(dst, gpr_slice_ref(str));
+  }
+}
+
+void gpr_strvec_init(gpr_strvec *sv) { memset(sv, 0, sizeof(*sv)); }
+
+void gpr_strvec_destroy(gpr_strvec *sv) {
+  size_t i;
+  for (i = 0; i < sv->count; i++) {
+    gpr_free(sv->strs[i]);
+  }
+  gpr_free(sv->strs);
+}
+
+void gpr_strvec_add(gpr_strvec *sv, char *str) {
+  if (sv->count == sv->capacity) {
+    sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
+    sv->strs = gpr_realloc(sv->strs, sizeof(char *) * sv->capacity);
+  }
+  sv->strs[sv->count++] = str;
+}
+
+char *gpr_strvec_flatten(gpr_strvec *sv, size_t *final_length) {
+  return gpr_strjoin((const char **)sv->strs, sv->count, final_length);
+}
diff --git a/src/core/lib/support/string.h b/src/core/lib/support/string.h
new file mode 100644
index 0000000..ea58610
--- /dev/null
+++ b/src/core/lib/support/string.h
@@ -0,0 +1,121 @@
+/*
+ *
+ * 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_SUPPORT_STRING_H
+#define GRPC_CORE_LIB_SUPPORT_STRING_H
+
+#include <stddef.h>
+
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* String utility functions */
+
+/* Flags for gpr_dump function. */
+#define GPR_DUMP_HEX 0x00000001
+#define GPR_DUMP_ASCII 0x00000002
+
+/* Converts array buf, of length len, into a C string  according to the flags.
+   Result should be freed with gpr_free() */
+char *gpr_dump(const char *buf, size_t len, uint32_t flags);
+
+/* Calls gpr_dump on a slice. */
+char *gpr_dump_slice(gpr_slice slice, uint32_t flags);
+
+/* Parses an array of bytes into an integer (base 10). Returns 1 on success,
+   0 on failure. */
+int gpr_parse_bytes_to_uint32(const char *data, size_t length,
+                              uint32_t *result);
+
+/* Minimum buffer size for calling ltoa */
+#define GPR_LTOA_MIN_BUFSIZE (3 * sizeof(long))
+
+/* Convert a long to a string in base 10; returns the length of the
+   output string (or 0 on failure).
+   output must be at least GPR_LTOA_MIN_BUFSIZE bytes long. */
+int gpr_ltoa(long value, char *output);
+
+/* Minimum buffer size for calling int64toa */
+#define GPR_INT64TOA_MIN_BUFSIZE (3 * sizeof(int64_t))
+
+/* Convert an int64 to a string in base 10; returns the length of the
+output string (or 0 on failure).
+output must be at least GPR_INT64TOA_MIN_BUFSIZE bytes long.
+NOTE: This function ensures sufficient bit width even on Win x64,
+where long is 32bit is size.*/
+int int64_ttoa(int64_t value, char *output);
+
+/* Reverse a run of bytes */
+void gpr_reverse_bytes(char *str, int len);
+
+/* Join a set of strings, returning the resulting string.
+   Total combined length (excluding null terminator) is returned in total_length
+   if it is non-null. */
+char *gpr_strjoin(const char **strs, size_t nstrs, size_t *total_length);
+
+/* Join a set of strings using a separator, returning the resulting string.
+   Total combined length (excluding null terminator) is returned in total_length
+   if it is non-null. */
+char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep,
+                      size_t *total_length);
+
+/** Split \a str by the separator \a sep. Results are stored in \a dst, which
+ * should be a properly initialized instance. */
+void gpr_slice_split(gpr_slice str, const char *sep, gpr_slice_buffer *dst);
+
+/* A vector of strings... for building up a final string one piece at a time */
+typedef struct {
+  char **strs;
+  size_t count;
+  size_t capacity;
+} gpr_strvec;
+
+/* Initialize/destroy */
+void gpr_strvec_init(gpr_strvec *strs);
+void gpr_strvec_destroy(gpr_strvec *strs);
+/* Add a string to a strvec, takes ownership of the string */
+void gpr_strvec_add(gpr_strvec *strs, char *add);
+/* Return a joined string with all added substrings, optionally setting
+   total_length as per gpr_strjoin */
+char *gpr_strvec_flatten(gpr_strvec *strs, size_t *total_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_SUPPORT_STRING_H */
diff --git a/src/core/lib/support/string_posix.c b/src/core/lib/support/string_posix.c
new file mode 100644
index 0000000..c804ed5
--- /dev/null
+++ b/src/core/lib/support/string_posix.c
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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_STRING
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+int gpr_asprintf(char **strp, const char *format, ...) {
+  va_list args;
+  int ret;
+  char buf[64];
+  size_t strp_buflen;
+
+  /* Use a constant-sized buffer to determine the length. */
+  va_start(args, format);
+  ret = vsnprintf(buf, sizeof(buf), format, args);
+  va_end(args);
+  if (ret < 0) {
+    *strp = NULL;
+    return -1;
+  }
+
+  /* Allocate a new buffer, with space for the NUL terminator. */
+  strp_buflen = (size_t)ret + 1;
+  if ((*strp = gpr_malloc(strp_buflen)) == NULL) {
+    /* This shouldn't happen, because gpr_malloc() calls abort(). */
+    return -1;
+  }
+
+  /* Return early if we have all the bytes. */
+  if (strp_buflen <= sizeof(buf)) {
+    memcpy(*strp, buf, strp_buflen);
+    return ret;
+  }
+
+  /* Try again using the larger buffer. */
+  va_start(args, format);
+  ret = vsnprintf(*strp, strp_buflen, format, args);
+  va_end(args);
+  if ((size_t)ret == strp_buflen - 1) {
+    return ret;
+  }
+
+  /* This should never happen. */
+  gpr_free(*strp);
+  *strp = NULL;
+  return -1;
+}
+
+#endif /* GPR_POSIX_STRING */
diff --git a/src/core/lib/support/string_win32.c b/src/core/lib/support/string_win32.c
new file mode 100644
index 0000000..a2f9857
--- /dev/null
+++ b/src/core/lib/support/string_win32.c
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Posix code for gpr snprintf support. */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/lib/support/string.h"
+
+int gpr_asprintf(char **strp, const char *format, ...) {
+  va_list args;
+  int ret;
+  size_t strp_buflen;
+
+  /* Determine the length. */
+  va_start(args, format);
+  ret = _vscprintf(format, args);
+  va_end(args);
+  if (ret < 0) {
+    *strp = NULL;
+    return -1;
+  }
+
+  /* Allocate a new buffer, with space for the NUL terminator. */
+  strp_buflen = (size_t)ret + 1;
+  if ((*strp = gpr_malloc(strp_buflen)) == NULL) {
+    /* This shouldn't happen, because gpr_malloc() calls abort(). */
+    return -1;
+  }
+
+  /* Print to the buffer. */
+  va_start(args, format);
+  ret = vsnprintf_s(*strp, strp_buflen, _TRUNCATE, format, args);
+  va_end(args);
+  if ((size_t)ret == strp_buflen - 1) {
+    return ret;
+  }
+
+  /* This should never happen. */
+  gpr_free(*strp);
+  *strp = NULL;
+  return -1;
+}
+
+#if defined UNICODE || defined _UNICODE
+LPTSTR
+gpr_char_to_tchar(LPCSTR input) {
+  LPTSTR ret;
+  int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
+  if (needed <= 0) return NULL;
+  ret = gpr_malloc((unsigned)needed * sizeof(TCHAR));
+  MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed);
+  return ret;
+}
+
+LPSTR
+gpr_tchar_to_char(LPCTSTR input) {
+  LPSTR ret;
+  int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL);
+  if (needed <= 0) return NULL;
+  ret = gpr_malloc((unsigned)needed);
+  WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL);
+  return ret;
+}
+#else
+char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); }
+
+char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); }
+#endif
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/lib/support/string_win32.h b/src/core/lib/support/string_win32.h
new file mode 100644
index 0000000..ff4a694
--- /dev/null
+++ b/src/core/lib/support/string_win32.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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_SUPPORT_STRING_WIN32_H
+#define GRPC_CORE_LIB_SUPPORT_STRING_WIN32_H
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+/* These allocate new strings using gpr_malloc to convert from and to utf-8. */
+LPTSTR gpr_char_to_tchar(LPCSTR input);
+LPSTR gpr_tchar_to_char(LPCTSTR input);
+
+#endif /* GPR_WIN32 */
+
+#endif /* GRPC_CORE_LIB_SUPPORT_STRING_WIN32_H */
diff --git a/src/core/lib/support/subprocess_posix.c b/src/core/lib/support/subprocess_posix.c
new file mode 100644
index 0000000..4f4de92
--- /dev/null
+++ b/src/core/lib/support/subprocess_posix.c
@@ -0,0 +1,112 @@
+/*
+ *
+ * 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_SUBPROCESS
+
+#include <grpc/support/subprocess.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+struct gpr_subprocess {
+  int pid;
+  int joined;
+};
+
+const char *gpr_subprocess_binary_extension() { return ""; }
+
+gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
+  gpr_subprocess *r;
+  int pid;
+  char **exec_args;
+
+  pid = fork();
+  if (pid == -1) {
+    return NULL;
+  } else if (pid == 0) {
+    exec_args = gpr_malloc(((size_t)argc + 1) * sizeof(char *));
+    memcpy(exec_args, argv, (size_t)argc * sizeof(char *));
+    exec_args[argc] = NULL;
+    execv(exec_args[0], exec_args);
+    /* if we reach here, an error has occurred */
+    gpr_log(GPR_ERROR, "execv '%s' failed: %s", exec_args[0], strerror(errno));
+    _exit(1);
+    return NULL;
+  } else {
+    r = gpr_malloc(sizeof(gpr_subprocess));
+    memset(r, 0, sizeof(*r));
+    r->pid = pid;
+    return r;
+  }
+}
+
+void gpr_subprocess_destroy(gpr_subprocess *p) {
+  if (!p->joined) {
+    kill(p->pid, SIGKILL);
+    gpr_subprocess_join(p);
+  }
+  gpr_free(p);
+}
+
+int gpr_subprocess_join(gpr_subprocess *p) {
+  int status;
+retry:
+  if (waitpid(p->pid, &status, 0) == -1) {
+    if (errno == EINTR) {
+      goto retry;
+    }
+    gpr_log(GPR_ERROR, "waitpid failed: %s", strerror(errno));
+    return -1;
+  }
+  return status;
+}
+
+void gpr_subprocess_interrupt(gpr_subprocess *p) {
+  if (!p->joined) {
+    kill(p->pid, SIGINT);
+  }
+}
+
+#endif /* GPR_POSIX_SUBPROCESS */
diff --git a/src/core/lib/support/subprocess_windows.c b/src/core/lib/support/subprocess_windows.c
new file mode 100644
index 0000000..264306f
--- /dev/null
+++ b/src/core/lib/support/subprocess_windows.c
@@ -0,0 +1,141 @@
+/*
+ *
+ * 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 <grpc/support/port_platform.h>
+
+#ifdef GPR_WINDOWS_SUBPROCESS
+
+#include <string.h>
+#include <tchar.h>
+#include <windows.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/subprocess.h>
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/string_win32.h"
+
+struct gpr_subprocess {
+  PROCESS_INFORMATION pi;
+  int joined;
+  int interrupted;
+};
+
+const char *gpr_subprocess_binary_extension() { return ".exe"; }
+
+gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
+  gpr_subprocess *r;
+
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+
+  char *args = gpr_strjoin_sep(argv, (size_t)argc, " ", NULL);
+  TCHAR *args_tchar;
+
+  args_tchar = gpr_char_to_tchar(args);
+  gpr_free(args);
+
+  memset(&si, 0, sizeof(si));
+  si.cb = sizeof(si);
+  memset(&pi, 0, sizeof(pi));
+
+  if (!CreateProcess(NULL, args_tchar, NULL, NULL, FALSE,
+                     CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) {
+    gpr_free(args_tchar);
+    return NULL;
+  }
+  gpr_free(args_tchar);
+
+  r = gpr_malloc(sizeof(gpr_subprocess));
+  memset(r, 0, sizeof(*r));
+  r->pi = pi;
+  return r;
+}
+
+void gpr_subprocess_destroy(gpr_subprocess *p) {
+  if (p) {
+    if (!p->joined) {
+      gpr_subprocess_interrupt(p);
+      gpr_subprocess_join(p);
+    }
+    if (p->pi.hProcess) {
+      CloseHandle(p->pi.hProcess);
+    }
+    if (p->pi.hThread) {
+      CloseHandle(p->pi.hThread);
+    }
+    gpr_free(p);
+  }
+}
+
+int gpr_subprocess_join(gpr_subprocess *p) {
+  DWORD dwExitCode;
+  if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
+    if (dwExitCode == STILL_ACTIVE) {
+      if (WaitForSingleObject(p->pi.hProcess, INFINITE) == WAIT_OBJECT_0) {
+        p->joined = 1;
+        goto getExitCode;
+      }
+      return -1;  // failed to join
+    } else {
+      goto getExitCode;
+    }
+  } else {
+    return -1;  // failed to get exit code
+  }
+
+getExitCode:
+  if (p->interrupted) {
+    return 0;
+  }
+  if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
+    return (int)dwExitCode;
+  } else {
+    return -1;  // failed to get exit code
+  }
+}
+
+void gpr_subprocess_interrupt(gpr_subprocess *p) {
+  DWORD dwExitCode;
+  if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
+    if (dwExitCode == STILL_ACTIVE) {
+      gpr_log(GPR_INFO, "sending ctrl-break");
+      GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, p->pi.dwProcessId);
+      p->joined = 1;
+      p->interrupted = 1;
+    }
+  }
+  return;
+}
+
+#endif /* GPR_WINDOWS_SUBPROCESS */
diff --git a/src/core/lib/support/sync.c b/src/core/lib/support/sync.c
new file mode 100644
index 0000000..44b83f8
--- /dev/null
+++ b/src/core/lib/support/sync.c
@@ -0,0 +1,127 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Generic implementation of synchronization primitives. */
+
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+/* Number of mutexes to allocate for events, to avoid lock contention.
+   Should be a prime. */
+enum { event_sync_partitions = 31 };
+
+/* Events are partitioned by address to avoid lock contention. */
+static struct sync_array_s {
+  gpr_mu mu;
+  gpr_cv cv;
+} sync_array[event_sync_partitions];
+
+/* This routine is executed once on first use, via event_once */
+static gpr_once event_once = GPR_ONCE_INIT;
+static void event_initialize(void) {
+  int i;
+  for (i = 0; i != event_sync_partitions; i++) {
+    gpr_mu_init(&sync_array[i].mu);
+    gpr_cv_init(&sync_array[i].cv);
+  }
+}
+
+/* Hash ev into an element of sync_array[]. */
+static struct sync_array_s *hash(gpr_event *ev) {
+  return &sync_array[((uintptr_t)ev) % event_sync_partitions];
+}
+
+void gpr_event_init(gpr_event *ev) {
+  gpr_once_init(&event_once, &event_initialize);
+  ev->state = 0;
+}
+
+void gpr_event_set(gpr_event *ev, void *value) {
+  struct sync_array_s *s = hash(ev);
+  gpr_mu_lock(&s->mu);
+  GPR_ASSERT(gpr_atm_acq_load(&ev->state) == 0);
+  gpr_atm_rel_store(&ev->state, (gpr_atm)value);
+  gpr_cv_broadcast(&s->cv);
+  gpr_mu_unlock(&s->mu);
+  GPR_ASSERT(value != NULL);
+}
+
+void *gpr_event_get(gpr_event *ev) {
+  return (void *)gpr_atm_acq_load(&ev->state);
+}
+
+void *gpr_event_wait(gpr_event *ev, gpr_timespec abs_deadline) {
+  void *result = (void *)gpr_atm_acq_load(&ev->state);
+  if (result == NULL) {
+    struct sync_array_s *s = hash(ev);
+    gpr_mu_lock(&s->mu);
+    do {
+      result = (void *)gpr_atm_acq_load(&ev->state);
+    } while (result == NULL && !gpr_cv_wait(&s->cv, &s->mu, abs_deadline));
+    gpr_mu_unlock(&s->mu);
+  }
+  return result;
+}
+
+void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
+
+void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
+
+void gpr_ref_non_zero(gpr_refcount *r) {
+  gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
+  GPR_ASSERT(prior > 0);
+}
+
+void gpr_refn(gpr_refcount *r, int n) {
+  gpr_atm_no_barrier_fetch_add(&r->count, n);
+}
+
+int gpr_unref(gpr_refcount *r) {
+  gpr_atm prior = gpr_atm_full_fetch_add(&r->count, -1);
+  GPR_ASSERT(prior > 0);
+  return prior == 1;
+}
+
+void gpr_stats_init(gpr_stats_counter *c, intptr_t n) {
+  gpr_atm_rel_store(&c->value, n);
+}
+
+void gpr_stats_inc(gpr_stats_counter *c, intptr_t inc) {
+  gpr_atm_no_barrier_fetch_add(&c->value, inc);
+}
+
+intptr_t gpr_stats_read(const gpr_stats_counter *c) {
+  /* don't need acquire-load, but we have no no-barrier load yet */
+  return gpr_atm_acq_load(&c->value);
+}
diff --git a/src/core/lib/support/sync_posix.c b/src/core/lib/support/sync_posix.c
new file mode 100644
index 0000000..dcb0969
--- /dev/null
+++ b/src/core/lib/support/sync_posix.c
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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_SYNC
+
+#include <errno.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+#include <time.h>
+#include "src/core/lib/profiling/timers.h"
+
+void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
+
+void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); }
+
+void gpr_mu_lock(gpr_mu* mu) {
+  GPR_TIMER_BEGIN("gpr_mu_lock", 0);
+  GPR_ASSERT(pthread_mutex_lock(mu) == 0);
+  GPR_TIMER_END("gpr_mu_lock", 0);
+}
+
+void gpr_mu_unlock(gpr_mu* mu) {
+  GPR_TIMER_BEGIN("gpr_mu_unlock", 0);
+  GPR_ASSERT(pthread_mutex_unlock(mu) == 0);
+  GPR_TIMER_END("gpr_mu_unlock", 0);
+}
+
+int gpr_mu_trylock(gpr_mu* mu) {
+  int err;
+  GPR_TIMER_BEGIN("gpr_mu_trylock", 0);
+  err = pthread_mutex_trylock(mu);
+  GPR_ASSERT(err == 0 || err == EBUSY);
+  GPR_TIMER_END("gpr_mu_trylock", 0);
+  return err == 0;
+}
+
+/*----------------------------------------*/
+
+void gpr_cv_init(gpr_cv* cv) { GPR_ASSERT(pthread_cond_init(cv, NULL) == 0); }
+
+void gpr_cv_destroy(gpr_cv* cv) { GPR_ASSERT(pthread_cond_destroy(cv) == 0); }
+
+int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) {
+  int err = 0;
+  if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) ==
+      0) {
+    err = pthread_cond_wait(cv, mu);
+  } else {
+    struct timespec abs_deadline_ts;
+    abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME);
+    abs_deadline_ts.tv_sec = (time_t)abs_deadline.tv_sec;
+    abs_deadline_ts.tv_nsec = abs_deadline.tv_nsec;
+    err = pthread_cond_timedwait(cv, mu, &abs_deadline_ts);
+  }
+  GPR_ASSERT(err == 0 || err == ETIMEDOUT || err == EAGAIN);
+  return err == ETIMEDOUT;
+}
+
+void gpr_cv_signal(gpr_cv* cv) { GPR_ASSERT(pthread_cond_signal(cv) == 0); }
+
+void gpr_cv_broadcast(gpr_cv* cv) {
+  GPR_ASSERT(pthread_cond_broadcast(cv) == 0);
+}
+
+/*----------------------------------------*/
+
+void gpr_once_init(gpr_once* once, void (*init_function)(void)) {
+  GPR_ASSERT(pthread_once(once, init_function) == 0);
+}
+
+#endif /* GRP_POSIX_SYNC */
diff --git a/src/core/lib/support/sync_win32.c b/src/core/lib/support/sync_win32.c
new file mode 100644
index 0000000..470a9f9
--- /dev/null
+++ b/src/core/lib/support/sync_win32.c
@@ -0,0 +1,133 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Win32 code for gpr synchronization support. */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+
+void gpr_mu_init(gpr_mu *mu) {
+  InitializeCriticalSection(&mu->cs);
+  mu->locked = 0;
+}
+
+void gpr_mu_destroy(gpr_mu *mu) { DeleteCriticalSection(&mu->cs); }
+
+void gpr_mu_lock(gpr_mu *mu) {
+  EnterCriticalSection(&mu->cs);
+  GPR_ASSERT(!mu->locked);
+  mu->locked = 1;
+}
+
+void gpr_mu_unlock(gpr_mu *mu) {
+  mu->locked = 0;
+  LeaveCriticalSection(&mu->cs);
+}
+
+int gpr_mu_trylock(gpr_mu *mu) {
+  int result = TryEnterCriticalSection(&mu->cs);
+  if (result) {
+    if (mu->locked) {                /* This thread already holds the lock. */
+      LeaveCriticalSection(&mu->cs); /* Decrement lock count. */
+      result = 0;                    /* Indicate failure */
+    }
+    mu->locked = 1;
+  }
+  return result;
+}
+
+/*----------------------------------------*/
+
+void gpr_cv_init(gpr_cv *cv) { InitializeConditionVariable(cv); }
+
+void gpr_cv_destroy(gpr_cv *cv) {
+  /* Condition variables don't need destruction in Win32. */
+}
+
+int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
+  int timeout = 0;
+  DWORD timeout_max_ms;
+  mu->locked = 0;
+  if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) ==
+      0) {
+    SleepConditionVariableCS(cv, &mu->cs, INFINITE);
+  } else {
+    abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME);
+    gpr_timespec now = gpr_now(abs_deadline.clock_type);
+    int64_t now_ms = (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000;
+    int64_t deadline_ms =
+        (int64_t)abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000;
+    if (now_ms >= deadline_ms) {
+      timeout = 1;
+    } else {
+      if ((deadline_ms - now_ms) >= INFINITE) {
+        timeout_max_ms = INFINITE - 1;
+      } else {
+        timeout_max_ms = (DWORD)(deadline_ms - now_ms);
+      }
+      timeout = (SleepConditionVariableCS(cv, &mu->cs, timeout_max_ms) == 0 &&
+                 GetLastError() == ERROR_TIMEOUT);
+    }
+  }
+  mu->locked = 1;
+  return timeout;
+}
+
+void gpr_cv_signal(gpr_cv *cv) { WakeConditionVariable(cv); }
+
+void gpr_cv_broadcast(gpr_cv *cv) { WakeAllConditionVariable(cv); }
+
+/*----------------------------------------*/
+
+static void *dummy;
+struct run_once_func_arg {
+  void (*init_function)(void);
+};
+static BOOL CALLBACK run_once_func(gpr_once *once, void *v, void **pv) {
+  struct run_once_func_arg *arg = v;
+  (*arg->init_function)();
+  return 1;
+}
+
+void gpr_once_init(gpr_once *once, void (*init_function)(void)) {
+  struct run_once_func_arg arg;
+  arg.init_function = init_function;
+  InitOnceExecuteOnce(once, run_once_func, &arg, &dummy);
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/support/thd.c b/src/core/lib/support/thd.c
similarity index 100%
rename from src/core/support/thd.c
rename to src/core/lib/support/thd.c
diff --git a/src/core/lib/support/thd_internal.h b/src/core/lib/support/thd_internal.h
new file mode 100644
index 0000000..975d553
--- /dev/null
+++ b/src/core/lib/support/thd_internal.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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_SUPPORT_THD_INTERNAL_H
+#define GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H
+
+/* Internal interfaces between modules within the gpr support library.  */
+
+#endif /* GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H */
diff --git a/src/core/lib/support/thd_posix.c b/src/core/lib/support/thd_posix.c
new file mode 100644
index 0000000..2fc23bf
--- /dev/null
+++ b/src/core/lib/support/thd_posix.c
@@ -0,0 +1,95 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Posix implementation for gpr threads. */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_SYNC
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct thd_arg {
+  void (*body)(void *arg); /* body of a thread */
+  void *arg;               /* argument to a thread */
+};
+
+/* Body of every thread started via gpr_thd_new. */
+static void *thread_body(void *v) {
+  struct thd_arg a = *(struct thd_arg *)v;
+  free(v);
+  (*a.body)(a.arg);
+  return NULL;
+}
+
+int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
+                const gpr_thd_options *options) {
+  int thread_started;
+  pthread_attr_t attr;
+  pthread_t p;
+  /* don't use gpr_malloc as we may cause an infinite recursion with
+   * the profiling code */
+  struct thd_arg *a = malloc(sizeof(*a));
+  GPR_ASSERT(a != NULL);
+  a->body = thd_body;
+  a->arg = arg;
+
+  GPR_ASSERT(pthread_attr_init(&attr) == 0);
+  if (gpr_thd_options_is_detached(options)) {
+    GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ==
+               0);
+  } else {
+    GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) ==
+               0);
+  }
+  thread_started = (pthread_create(&p, &attr, &thread_body, a) == 0);
+  GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
+  if (!thread_started) {
+    /* don't use gpr_free, as this was allocated using malloc (see above) */
+    free(a);
+  }
+  *t = (gpr_thd_id)p;
+  return thread_started;
+}
+
+gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)pthread_self(); }
+
+void gpr_thd_join(gpr_thd_id t) { pthread_join((pthread_t)t, NULL); }
+
+#endif /* GPR_POSIX_SYNC */
diff --git a/src/core/lib/support/thd_win32.c b/src/core/lib/support/thd_win32.c
new file mode 100644
index 0000000..6deb314
--- /dev/null
+++ b/src/core/lib/support/thd_win32.c
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Windows implementation for gpr threads. */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/thd.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+#define thread_local __declspec(thread)
+#elif defined(__GNUC__)
+#define thread_local __thread
+#else
+#error "Unknown compiler - please file a bug report"
+#endif
+
+struct thd_info {
+  void (*body)(void *arg); /* body of a thread */
+  void *arg;               /* argument to a thread */
+  HANDLE join_event;       /* if joinable, the join event */
+  int joinable;            /* true if not detached */
+};
+
+static thread_local struct thd_info *g_thd_info;
+
+/* Destroys a thread info */
+static void destroy_thread(struct thd_info *t) {
+  if (t->joinable) CloseHandle(t->join_event);
+  gpr_free(t);
+}
+
+/* Body of every thread started via gpr_thd_new. */
+static DWORD WINAPI thread_body(void *v) {
+  g_thd_info = (struct thd_info *)v;
+  g_thd_info->body(g_thd_info->arg);
+  if (g_thd_info->joinable) {
+    BOOL ret = SetEvent(g_thd_info->join_event);
+    GPR_ASSERT(ret);
+  } else {
+    destroy_thread(g_thd_info);
+  }
+  return 0;
+}
+
+int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
+                const gpr_thd_options *options) {
+  HANDLE handle;
+  struct thd_info *info = gpr_malloc(sizeof(*info));
+  info->body = thd_body;
+  info->arg = arg;
+  *t = 0;
+  if (gpr_thd_options_is_joinable(options)) {
+    info->joinable = 1;
+    info->join_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (info->join_event == NULL) {
+      gpr_free(info);
+      return 0;
+    }
+  } else {
+    info->joinable = 0;
+  }
+  handle = CreateThread(NULL, 64 * 1024, thread_body, info, 0, NULL);
+  if (handle == NULL) {
+    destroy_thread(info);
+  } else {
+    *t = (gpr_thd_id)info;
+    CloseHandle(handle);
+  }
+  return handle != NULL;
+}
+
+gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)g_thd_info; }
+
+void gpr_thd_join(gpr_thd_id t) {
+  struct thd_info *info = (struct thd_info *)t;
+  DWORD ret = WaitForSingleObject(info->join_event, INFINITE);
+  GPR_ASSERT(ret == WAIT_OBJECT_0);
+  destroy_thread(info);
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/lib/support/time.c b/src/core/lib/support/time.c
new file mode 100644
index 0000000..57f8331
--- /dev/null
+++ b/src/core/lib/support/time.c
@@ -0,0 +1,304 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Generic implementation of time calls. */
+
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+int gpr_time_cmp(gpr_timespec a, gpr_timespec b) {
+  int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
+  GPR_ASSERT(a.clock_type == b.clock_type);
+  if (cmp == 0) {
+    cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
+  }
+  return cmp;
+}
+
+gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b) {
+  return gpr_time_cmp(a, b) < 0 ? a : b;
+}
+
+gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b) {
+  return gpr_time_cmp(a, b) > 0 ? a : b;
+}
+
+gpr_timespec gpr_time_0(gpr_clock_type type) {
+  gpr_timespec out;
+  out.tv_sec = 0;
+  out.tv_nsec = 0;
+  out.clock_type = type;
+  return out;
+}
+
+gpr_timespec gpr_inf_future(gpr_clock_type type) {
+  gpr_timespec out;
+  out.tv_sec = INT64_MAX;
+  out.tv_nsec = 0;
+  out.clock_type = type;
+  return out;
+}
+
+gpr_timespec gpr_inf_past(gpr_clock_type type) {
+  gpr_timespec out;
+  out.tv_sec = INT64_MIN;
+  out.tv_nsec = 0;
+  out.clock_type = type;
+  return out;
+}
+
+/* TODO(ctiller): consider merging _nanos, _micros, _millis into a single
+   function for maintainability. Similarly for _seconds, _minutes, and _hours */
+
+gpr_timespec gpr_time_from_nanos(int64_t ns, gpr_clock_type type) {
+  gpr_timespec result;
+  result.clock_type = type;
+  if (ns == INT64_MAX) {
+    result = gpr_inf_future(type);
+  } else if (ns == INT64_MIN) {
+    result = gpr_inf_past(type);
+  } else if (ns >= 0) {
+    result.tv_sec = ns / GPR_NS_PER_SEC;
+    result.tv_nsec = (int32_t)(ns - result.tv_sec * GPR_NS_PER_SEC);
+  } else {
+    /* Calculation carefully formulated to avoid any possible under/overflow. */
+    result.tv_sec = (-(999999999 - (ns + GPR_NS_PER_SEC)) / GPR_NS_PER_SEC) - 1;
+    result.tv_nsec = (int32_t)(ns - result.tv_sec * GPR_NS_PER_SEC);
+  }
+  return result;
+}
+
+gpr_timespec gpr_time_from_micros(int64_t us, gpr_clock_type type) {
+  gpr_timespec result;
+  result.clock_type = type;
+  if (us == INT64_MAX) {
+    result = gpr_inf_future(type);
+  } else if (us == INT64_MIN) {
+    result = gpr_inf_past(type);
+  } else if (us >= 0) {
+    result.tv_sec = us / 1000000;
+    result.tv_nsec = (int32_t)((us - result.tv_sec * 1000000) * 1000);
+  } else {
+    /* Calculation carefully formulated to avoid any possible under/overflow. */
+    result.tv_sec = (-(999999 - (us + 1000000)) / 1000000) - 1;
+    result.tv_nsec = (int32_t)((us - result.tv_sec * 1000000) * 1000);
+  }
+  return result;
+}
+
+gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type type) {
+  gpr_timespec result;
+  result.clock_type = type;
+  if (ms == INT64_MAX) {
+    result = gpr_inf_future(type);
+  } else if (ms == INT64_MIN) {
+    result = gpr_inf_past(type);
+  } else if (ms >= 0) {
+    result.tv_sec = ms / 1000;
+    result.tv_nsec = (int32_t)((ms - result.tv_sec * 1000) * 1000000);
+  } else {
+    /* Calculation carefully formulated to avoid any possible under/overflow. */
+    result.tv_sec = (-(999 - (ms + 1000)) / 1000) - 1;
+    result.tv_nsec = (int32_t)((ms - result.tv_sec * 1000) * 1000000);
+  }
+  return result;
+}
+
+gpr_timespec gpr_time_from_seconds(int64_t s, gpr_clock_type type) {
+  gpr_timespec result;
+  result.clock_type = type;
+  if (s == INT64_MAX) {
+    result = gpr_inf_future(type);
+  } else if (s == INT64_MIN) {
+    result = gpr_inf_past(type);
+  } else {
+    result.tv_sec = s;
+    result.tv_nsec = 0;
+  }
+  return result;
+}
+
+gpr_timespec gpr_time_from_minutes(int64_t m, gpr_clock_type type) {
+  gpr_timespec result;
+  result.clock_type = type;
+  if (m >= INT64_MAX / 60) {
+    result = gpr_inf_future(type);
+  } else if (m <= INT64_MIN / 60) {
+    result = gpr_inf_past(type);
+  } else {
+    result.tv_sec = m * 60;
+    result.tv_nsec = 0;
+  }
+  return result;
+}
+
+gpr_timespec gpr_time_from_hours(int64_t h, gpr_clock_type type) {
+  gpr_timespec result;
+  result.clock_type = type;
+  if (h >= INT64_MAX / 3600) {
+    result = gpr_inf_future(type);
+  } else if (h <= INT64_MIN / 3600) {
+    result = gpr_inf_past(type);
+  } else {
+    result.tv_sec = h * 3600;
+    result.tv_nsec = 0;
+  }
+  return result;
+}
+
+gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) {
+  gpr_timespec sum;
+  int64_t inc = 0;
+  GPR_ASSERT(b.clock_type == GPR_TIMESPAN);
+  sum.clock_type = a.clock_type;
+  sum.tv_nsec = a.tv_nsec + b.tv_nsec;
+  if (sum.tv_nsec >= GPR_NS_PER_SEC) {
+    sum.tv_nsec -= GPR_NS_PER_SEC;
+    inc++;
+  }
+  if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) {
+    sum = a;
+  } else if (b.tv_sec == INT64_MAX ||
+             (b.tv_sec >= 0 && a.tv_sec >= INT64_MAX - b.tv_sec)) {
+    sum = gpr_inf_future(sum.clock_type);
+  } else if (b.tv_sec == INT64_MIN ||
+             (b.tv_sec <= 0 && a.tv_sec <= INT64_MIN - b.tv_sec)) {
+    sum = gpr_inf_past(sum.clock_type);
+  } else {
+    sum.tv_sec = a.tv_sec + b.tv_sec;
+    if (inc != 0 && sum.tv_sec == INT64_MAX - 1) {
+      sum = gpr_inf_future(sum.clock_type);
+    } else {
+      sum.tv_sec += inc;
+    }
+  }
+  return sum;
+}
+
+gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) {
+  gpr_timespec diff;
+  int64_t dec = 0;
+  if (b.clock_type == GPR_TIMESPAN) {
+    diff.clock_type = a.clock_type;
+  } else {
+    GPR_ASSERT(a.clock_type == b.clock_type);
+    diff.clock_type = GPR_TIMESPAN;
+  }
+  diff.tv_nsec = a.tv_nsec - b.tv_nsec;
+  if (diff.tv_nsec < 0) {
+    diff.tv_nsec += GPR_NS_PER_SEC;
+    dec++;
+  }
+  if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) {
+    diff = a;
+  } else if (b.tv_sec == INT64_MIN ||
+             (b.tv_sec <= 0 && a.tv_sec >= INT64_MAX + b.tv_sec)) {
+    diff = gpr_inf_future(GPR_CLOCK_REALTIME);
+  } else if (b.tv_sec == INT64_MAX ||
+             (b.tv_sec >= 0 && a.tv_sec <= INT64_MIN + b.tv_sec)) {
+    diff = gpr_inf_past(GPR_CLOCK_REALTIME);
+  } else {
+    diff.tv_sec = a.tv_sec - b.tv_sec;
+    if (dec != 0 && diff.tv_sec == INT64_MIN + 1) {
+      diff = gpr_inf_past(GPR_CLOCK_REALTIME);
+    } else {
+      diff.tv_sec -= dec;
+    }
+  }
+  return diff;
+}
+
+int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold) {
+  int cmp_ab;
+
+  GPR_ASSERT(a.clock_type == b.clock_type);
+  GPR_ASSERT(threshold.clock_type == GPR_TIMESPAN);
+
+  cmp_ab = gpr_time_cmp(a, b);
+  if (cmp_ab == 0) return 1;
+  if (cmp_ab < 0) {
+    return gpr_time_cmp(gpr_time_sub(b, a), threshold) <= 0;
+  } else {
+    return gpr_time_cmp(gpr_time_sub(a, b), threshold) <= 0;
+  }
+}
+
+int32_t gpr_time_to_millis(gpr_timespec t) {
+  if (t.tv_sec >= 2147483) {
+    if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) {
+      return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS;
+    }
+    return 2147483647;
+  } else if (t.tv_sec <= -2147483) {
+    /* TODO(ctiller): correct handling here (it's so far in the past do we
+       care?) */
+    return -2147483647;
+  } else {
+    return (int32_t)(t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS);
+  }
+}
+
+double gpr_timespec_to_micros(gpr_timespec t) {
+  return (double)t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3;
+}
+
+gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
+  if (t.clock_type == clock_type) {
+    return t;
+  }
+
+  if (t.tv_nsec == 0) {
+    if (t.tv_sec == INT64_MAX) {
+      t.clock_type = clock_type;
+      return t;
+    }
+    if (t.tv_sec == INT64_MIN) {
+      t.clock_type = clock_type;
+      return t;
+    }
+  }
+
+  if (clock_type == GPR_TIMESPAN) {
+    return gpr_time_sub(t, gpr_now(t.clock_type));
+  }
+
+  if (t.clock_type == GPR_TIMESPAN) {
+    return gpr_time_add(gpr_now(clock_type), t);
+  }
+
+  return gpr_time_add(gpr_now(clock_type),
+                      gpr_time_sub(t, gpr_now(t.clock_type)));
+}
diff --git a/src/core/lib/support/time_posix.c b/src/core/lib/support/time_posix.c
new file mode 100644
index 0000000..1154207
--- /dev/null
+++ b/src/core/lib/support/time_posix.c
@@ -0,0 +1,176 @@
+/*
+ *
+ * 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>
+#include "src/core/lib/support/time_precise.h"
+
+#ifdef GPR_POSIX_TIME
+
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#ifdef __linux__
+#include <sys/syscall.h>
+#endif
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/support/block_annotate.h"
+
+static struct timespec timespec_from_gpr(gpr_timespec gts) {
+  struct timespec rv;
+  if (sizeof(time_t) < sizeof(int64_t)) {
+    /* fine to assert, as this is only used in gpr_sleep_until */
+    GPR_ASSERT(gts.tv_sec <= INT32_MAX && gts.tv_sec >= INT32_MIN);
+  }
+  rv.tv_sec = (time_t)gts.tv_sec;
+  rv.tv_nsec = gts.tv_nsec;
+  return rv;
+}
+
+#if _POSIX_TIMERS > 0
+static gpr_timespec gpr_from_timespec(struct timespec ts,
+                                      gpr_clock_type clock_type) {
+  /*
+   * timespec.tv_sec can have smaller size than gpr_timespec.tv_sec,
+   * but we are only using this function to implement gpr_now
+   * so there's no need to handle "infinity" values.
+   */
+  gpr_timespec rv;
+  rv.tv_sec = ts.tv_sec;
+  rv.tv_nsec = (int32_t)ts.tv_nsec;
+  rv.clock_type = clock_type;
+  return rv;
+}
+
+/** maps gpr_clock_type --> clockid_t for clock_gettime */
+static const clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC,
+                                                  CLOCK_REALTIME};
+
+void gpr_time_init(void) { gpr_precise_clock_init(); }
+
+static gpr_timespec now_impl(gpr_clock_type clock_type) {
+  struct timespec now;
+  GPR_ASSERT(clock_type != GPR_TIMESPAN);
+  if (clock_type == GPR_CLOCK_PRECISE) {
+    gpr_timespec ret;
+    gpr_precise_clock_now(&ret);
+    return ret;
+  } else {
+#if defined(GPR_BACKWARDS_COMPATIBILITY_MODE) && defined(__linux__)
+    /* avoid ABI problems by invoking syscalls directly */
+    syscall(SYS_clock_gettime, clockid_for_gpr_clock[clock_type], &now);
+#else
+    clock_gettime(clockid_for_gpr_clock[clock_type], &now);
+#endif
+    return gpr_from_timespec(now, clock_type);
+  }
+}
+#else
+/* For some reason Apple's OSes haven't implemented clock_gettime. */
+
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <sys/time.h>
+
+static double g_time_scale;
+static uint64_t g_time_start;
+
+void gpr_time_init(void) {
+  mach_timebase_info_data_t tb = {0, 1};
+  gpr_precise_clock_init();
+  mach_timebase_info(&tb);
+  g_time_scale = tb.numer;
+  g_time_scale /= tb.denom;
+  g_time_start = mach_absolute_time();
+}
+
+static gpr_timespec now_impl(gpr_clock_type clock) {
+  gpr_timespec now;
+  struct timeval now_tv;
+  double now_dbl;
+
+  now.clock_type = clock;
+  switch (clock) {
+    case GPR_CLOCK_REALTIME:
+      gettimeofday(&now_tv, NULL);
+      now.tv_sec = now_tv.tv_sec;
+      now.tv_nsec = now_tv.tv_usec * 1000;
+      break;
+    case GPR_CLOCK_MONOTONIC:
+      now_dbl = (mach_absolute_time() - g_time_start) * g_time_scale;
+      now.tv_sec = (int64_t)(now_dbl * 1e-9);
+      now.tv_nsec = (int32_t)(now_dbl - ((double)now.tv_sec) * 1e9);
+      break;
+    case GPR_CLOCK_PRECISE:
+      gpr_precise_clock_now(&now);
+      break;
+    case GPR_TIMESPAN:
+      abort();
+  }
+
+  return now;
+}
+#endif
+
+gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl;
+
+gpr_timespec gpr_now(gpr_clock_type clock_type) {
+  return gpr_now_impl(clock_type);
+}
+
+void gpr_sleep_until(gpr_timespec until) {
+  gpr_timespec now;
+  gpr_timespec delta;
+  struct timespec delta_ts;
+  int ns_result;
+
+  for (;;) {
+    /* We could simplify by using clock_nanosleep instead, but it might be
+     * slightly less portable. */
+    now = gpr_now(until.clock_type);
+    if (gpr_time_cmp(until, now) <= 0) {
+      return;
+    }
+
+    delta = gpr_time_sub(until, now);
+    delta_ts = timespec_from_gpr(delta);
+    GRPC_SCHEDULING_START_BLOCKING_REGION;
+    ns_result = nanosleep(&delta_ts, NULL);
+    GRPC_SCHEDULING_END_BLOCKING_REGION;
+    if (ns_result == 0) {
+      break;
+    }
+  }
+}
+
+#endif /* GPR_POSIX_TIME */
diff --git a/src/core/support/time_precise.c b/src/core/lib/support/time_precise.c
similarity index 100%
rename from src/core/support/time_precise.c
rename to src/core/lib/support/time_precise.c
diff --git a/src/core/lib/support/time_precise.h b/src/core/lib/support/time_precise.h
new file mode 100644
index 0000000..30818d0
--- /dev/null
+++ b/src/core/lib/support/time_precise.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_SUPPORT_TIME_PRECISE_H
+#define GRPC_CORE_LIB_SUPPORT_TIME_PRECISE_H
+
+#include <grpc/support/time.h>
+
+void gpr_precise_clock_init(void);
+void gpr_precise_clock_now(gpr_timespec *clk);
+
+#endif /* GRPC_CORE_LIB_SUPPORT_TIME_PRECISE_H */
diff --git a/src/core/lib/support/time_win32.c b/src/core/lib/support/time_win32.c
new file mode 100644
index 0000000..f7acbd1
--- /dev/null
+++ b/src/core/lib/support/time_win32.c
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Win32 code for gpr time support. */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <limits.h>
+#include <process.h>
+#include <sys/timeb.h>
+
+#include "src/core/lib/support/block_annotate.h"
+#include "src/core/lib/support/time_precise.h"
+
+static LARGE_INTEGER g_start_time;
+static double g_time_scale;
+
+void gpr_time_init(void) {
+  LARGE_INTEGER frequency;
+  QueryPerformanceFrequency(&frequency);
+  QueryPerformanceCounter(&g_start_time);
+  g_time_scale = 1.0 / (double)frequency.QuadPart;
+}
+
+gpr_timespec gpr_now(gpr_clock_type clock) {
+  gpr_timespec now_tv;
+  LONGLONG diff;
+  struct _timeb now_tb;
+  LARGE_INTEGER timestamp;
+  double now_dbl;
+  now_tv.clock_type = clock;
+  switch (clock) {
+    case GPR_CLOCK_REALTIME:
+      _ftime_s(&now_tb);
+      now_tv.tv_sec = (int64_t)now_tb.time;
+      now_tv.tv_nsec = now_tb.millitm * 1000000;
+      break;
+    case GPR_CLOCK_MONOTONIC:
+    case GPR_CLOCK_PRECISE:
+      QueryPerformanceCounter(&timestamp);
+      diff = timestamp.QuadPart - g_start_time.QuadPart;
+      now_dbl = (double)diff * g_time_scale;
+      now_tv.tv_sec = (int64_t)now_dbl;
+      now_tv.tv_nsec = (int32_t)((now_dbl - (double)now_tv.tv_sec) * 1e9);
+      break;
+    case GPR_TIMESPAN:
+      abort();
+      break;
+  }
+  return now_tv;
+}
+
+void gpr_sleep_until(gpr_timespec until) {
+  gpr_timespec now;
+  gpr_timespec delta;
+  int64_t sleep_millis;
+
+  for (;;) {
+    /* We could simplify by using clock_nanosleep instead, but it might be
+     * slightly less portable. */
+    now = gpr_now(until.clock_type);
+    if (gpr_time_cmp(until, now) <= 0) {
+      return;
+    }
+
+    delta = gpr_time_sub(until, now);
+    sleep_millis =
+        delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS;
+    GPR_ASSERT((sleep_millis >= 0) && (sleep_millis <= INT_MAX));
+    GRPC_SCHEDULING_START_BLOCKING_REGION;
+    Sleep((DWORD)sleep_millis);
+    GRPC_SCHEDULING_END_BLOCKING_REGION;
+  }
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/support/tls_pthread.c b/src/core/lib/support/tls_pthread.c
similarity index 100%
rename from src/core/support/tls_pthread.c
rename to src/core/lib/support/tls_pthread.c
diff --git a/src/core/lib/support/tmpfile.h b/src/core/lib/support/tmpfile.h
new file mode 100644
index 0000000..059142a
--- /dev/null
+++ b/src/core/lib/support/tmpfile.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_SUPPORT_TMPFILE_H
+#define GRPC_CORE_LIB_SUPPORT_TMPFILE_H
+
+#include <stdio.h>
+
+#include <grpc/support/slice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a temporary file from a prefix.
+   If tmp_filename is not NULL, *tmp_filename is assigned the name of the
+   created file and it is the responsibility of the caller to gpr_free it
+   unless an error occurs in which case it will be set to NULL. */
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_SUPPORT_TMPFILE_H */
diff --git a/src/core/lib/support/tmpfile_posix.c b/src/core/lib/support/tmpfile_posix.c
new file mode 100644
index 0000000..9e0e7ad
--- /dev/null
+++ b/src/core/lib/support/tmpfile_posix.c
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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/support/tmpfile.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/support/string.h"
+
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) {
+  FILE *result = NULL;
+  char *template;
+  int fd;
+
+  if (tmp_filename != NULL) *tmp_filename = NULL;
+
+  gpr_asprintf(&template, "/tmp/%s_XXXXXX", prefix);
+  GPR_ASSERT(template != NULL);
+
+  fd = mkstemp(template);
+  if (fd == -1) {
+    gpr_log(GPR_ERROR, "mkstemp failed for template %s with error %s.",
+            template, strerror(errno));
+    goto end;
+  }
+  result = fdopen(fd, "w+");
+  if (result == NULL) {
+    gpr_log(GPR_ERROR, "Could not open file %s from fd %d (error = %s).",
+            template, fd, strerror(errno));
+    unlink(template);
+    close(fd);
+    goto end;
+  }
+
+end:
+  if (result != NULL && tmp_filename != NULL) {
+    *tmp_filename = template;
+  } else {
+    gpr_free(template);
+  }
+  return result;
+}
+
+#endif /* GPR_POSIX_FILE */
diff --git a/src/core/lib/support/tmpfile_win32.c b/src/core/lib/support/tmpfile_win32.c
new file mode 100644
index 0000000..0cb2904
--- /dev/null
+++ b/src/core/lib/support/tmpfile_win32.c
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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 <io.h>
+#include <stdio.h>
+#include <string.h>
+#include <tchar.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/support/string_win32.h"
+#include "src/core/lib/support/tmpfile.h"
+
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) {
+  FILE *result = NULL;
+  LPTSTR template_string = NULL;
+  TCHAR tmp_path[MAX_PATH];
+  TCHAR tmp_filename[MAX_PATH];
+  DWORD status;
+  UINT success;
+
+  if (tmp_filename_out != NULL) *tmp_filename_out = NULL;
+
+  /* Convert our prefix to TCHAR. */
+  template_string = gpr_char_to_tchar(prefix);
+  GPR_ASSERT(template_string);
+
+  /* Get the path to the best temporary folder available. */
+  status = GetTempPath(MAX_PATH, tmp_path);
+  if (status == 0 || status > MAX_PATH) goto end;
+
+  /* Generate a unique filename with our template + temporary path. */
+  success = GetTempFileName(tmp_path, template_string, 0, tmp_filename);
+  if (!success) goto end;
+
+  /* Open a file there. */
+  if (_tfopen_s(&result, tmp_filename, TEXT("wb+")) != 0) goto end;
+
+end:
+  if (result && tmp_filename_out) {
+    *tmp_filename_out = gpr_tchar_to_char(tmp_filename);
+  }
+
+  gpr_free(template_string);
+  return result;
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/support/wrap_memcpy.c b/src/core/lib/support/wrap_memcpy.c
similarity index 100%
rename from src/core/support/wrap_memcpy.c
rename to src/core/lib/support/wrap_memcpy.c
diff --git a/src/core/lib/surface/alarm.c b/src/core/lib/surface/alarm.c
new file mode 100644
index 0000000..2cf2f00
--- /dev/null
+++ b/src/core/lib/surface/alarm.c
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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/grpc.h>
+#include <grpc/support/alloc.h>
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/surface/completion_queue.h"
+
+struct grpc_alarm {
+  grpc_timer alarm;
+  grpc_cq_completion completion;
+  /** completion queue where events about this alarm will be posted */
+  grpc_completion_queue *cq;
+  /** user supplied tag */
+  void *tag;
+};
+
+static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg,
+                                      grpc_cq_completion *c) {}
+
+static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  grpc_alarm *alarm = arg;
+  grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, success,
+                 do_nothing_end_completion, NULL, &alarm->completion);
+}
+
+grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline,
+                              void *tag) {
+  grpc_alarm *alarm = gpr_malloc(sizeof(grpc_alarm));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_CQ_INTERNAL_REF(cq, "alarm");
+  alarm->cq = cq;
+  alarm->tag = tag;
+
+  grpc_cq_begin_op(cq, tag);
+  grpc_timer_init(&exec_ctx, &alarm->alarm,
+                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
+                  alarm_cb, alarm, gpr_now(GPR_CLOCK_MONOTONIC));
+  grpc_exec_ctx_finish(&exec_ctx);
+  return alarm;
+}
+
+void grpc_alarm_cancel(grpc_alarm *alarm) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_timer_cancel(&exec_ctx, &alarm->alarm);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void grpc_alarm_destroy(grpc_alarm *alarm) {
+  grpc_alarm_cancel(alarm);
+  GRPC_CQ_INTERNAL_UNREF(alarm->cq, "alarm");
+  gpr_free(alarm);
+}
diff --git a/src/core/lib/surface/api_trace.c b/src/core/lib/surface/api_trace.c
new file mode 100644
index 0000000..79e3e5c
--- /dev/null
+++ b/src/core/lib/surface/api_trace.c
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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/surface/api_trace.h"
+
+int grpc_api_trace = 0;
diff --git a/src/core/lib/surface/api_trace.h b/src/core/lib/surface/api_trace.h
new file mode 100644
index 0000000..c60aaba
--- /dev/null
+++ b/src/core/lib/surface/api_trace.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * 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_SURFACE_API_TRACE_H
+#define GRPC_CORE_LIB_SURFACE_API_TRACE_H
+
+#include <grpc/support/log.h>
+#include "src/core/lib/debug/trace.h"
+
+extern int grpc_api_trace;
+
+/* Provide unwrapping macros because we're in C89 and variadic macros weren't
+   introduced until C99... */
+#define GRPC_API_TRACE_UNWRAP0()
+#define GRPC_API_TRACE_UNWRAP1(a) , a
+#define GRPC_API_TRACE_UNWRAP2(a, b) , a, b
+#define GRPC_API_TRACE_UNWRAP3(a, b, c) , a, b, c
+#define GRPC_API_TRACE_UNWRAP4(a, b, c, d) , a, b, c, d
+#define GRPC_API_TRACE_UNWRAP5(a, b, c, d, e) , a, b, c, d, e
+#define GRPC_API_TRACE_UNWRAP6(a, b, c, d, e, f) , a, b, c, d, e, f
+#define GRPC_API_TRACE_UNWRAP7(a, b, c, d, e, f, g) , a, b, c, d, e, f, g
+#define GRPC_API_TRACE_UNWRAP8(a, b, c, d, e, f, g, h) , a, b, c, d, e, f, g, h
+#define GRPC_API_TRACE_UNWRAP9(a, b, c, d, e, f, g, h, i) \
+  , a, b, c, d, e, f, g, h, i
+#define GRPC_API_TRACE_UNWRAP10(a, b, c, d, e, f, g, h, i, j) \
+  , a, b, c, d, e, f, g, h, i, j
+
+/* Due to the limitations of C89's preprocessor, the arity of the var-arg list
+   'nargs' must be specified. */
+#define GRPC_API_TRACE(fmt, nargs, args)                      \
+  if (grpc_api_trace) {                                       \
+    gpr_log(GPR_INFO, fmt GRPC_API_TRACE_UNWRAP##nargs args); \
+  }
+
+#endif /* GRPC_CORE_LIB_SURFACE_API_TRACE_H */
diff --git a/src/core/lib/surface/byte_buffer.c b/src/core/lib/surface/byte_buffer.c
new file mode 100644
index 0000000..a093a37
--- /dev/null
+++ b/src/core/lib/surface/byte_buffer.c
@@ -0,0 +1,97 @@
+/*
+ *
+ * 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/byte_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices,
+                                              size_t nslices) {
+  return grpc_raw_compressed_byte_buffer_create(slices, nslices,
+                                                GRPC_COMPRESS_NONE);
+}
+
+grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create(
+    gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression) {
+  size_t i;
+  grpc_byte_buffer *bb = gpr_malloc(sizeof(grpc_byte_buffer));
+  bb->type = GRPC_BB_RAW;
+  bb->data.raw.compression = compression;
+  gpr_slice_buffer_init(&bb->data.raw.slice_buffer);
+  for (i = 0; i < nslices; i++) {
+    gpr_slice_ref(slices[i]);
+    gpr_slice_buffer_add(&bb->data.raw.slice_buffer, slices[i]);
+  }
+  return bb;
+}
+
+grpc_byte_buffer *grpc_raw_byte_buffer_from_reader(
+    grpc_byte_buffer_reader *reader) {
+  grpc_byte_buffer *bb = gpr_malloc(sizeof(grpc_byte_buffer));
+  gpr_slice slice;
+  bb->type = GRPC_BB_RAW;
+  bb->data.raw.compression = GRPC_COMPRESS_NONE;
+  gpr_slice_buffer_init(&bb->data.raw.slice_buffer);
+
+  while (grpc_byte_buffer_reader_next(reader, &slice)) {
+    gpr_slice_buffer_add(&bb->data.raw.slice_buffer, slice);
+  }
+  return bb;
+}
+
+grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb) {
+  switch (bb->type) {
+    case GRPC_BB_RAW:
+      return grpc_raw_byte_buffer_create(bb->data.raw.slice_buffer.slices,
+                                         bb->data.raw.slice_buffer.count);
+  }
+  GPR_UNREACHABLE_CODE(return NULL);
+}
+
+void grpc_byte_buffer_destroy(grpc_byte_buffer *bb) {
+  if (!bb) return;
+  switch (bb->type) {
+    case GRPC_BB_RAW:
+      gpr_slice_buffer_destroy(&bb->data.raw.slice_buffer);
+      break;
+  }
+  gpr_free(bb);
+}
+
+size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) {
+  switch (bb->type) {
+    case GRPC_BB_RAW:
+      return bb->data.raw.slice_buffer.length;
+  }
+  GPR_UNREACHABLE_CODE(return 0);
+}
diff --git a/src/core/lib/surface/byte_buffer_reader.c b/src/core/lib/surface/byte_buffer_reader.c
new file mode 100644
index 0000000..809fd5f
--- /dev/null
+++ b/src/core/lib/surface/byte_buffer_reader.c
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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/byte_buffer_reader.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/compression.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/lib/compression/message_compress.h"
+
+static int is_compressed(grpc_byte_buffer *buffer) {
+  switch (buffer->type) {
+    case GRPC_BB_RAW:
+      if (buffer->data.raw.compression == GRPC_COMPRESS_NONE) {
+        return 0 /* GPR_FALSE */;
+      }
+      break;
+  }
+  return 1 /* GPR_TRUE */;
+}
+
+void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
+                                  grpc_byte_buffer *buffer) {
+  gpr_slice_buffer decompressed_slices_buffer;
+  reader->buffer_in = buffer;
+  switch (reader->buffer_in->type) {
+    case GRPC_BB_RAW:
+      gpr_slice_buffer_init(&decompressed_slices_buffer);
+      if (is_compressed(reader->buffer_in)) {
+        grpc_msg_decompress(reader->buffer_in->data.raw.compression,
+                            &reader->buffer_in->data.raw.slice_buffer,
+                            &decompressed_slices_buffer);
+        reader->buffer_out =
+            grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices,
+                                        decompressed_slices_buffer.count);
+        gpr_slice_buffer_destroy(&decompressed_slices_buffer);
+      } else { /* not compressed, use the input buffer as output */
+        reader->buffer_out = reader->buffer_in;
+      }
+      reader->current.index = 0;
+      break;
+  }
+}
+
+void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) {
+  switch (reader->buffer_in->type) {
+    case GRPC_BB_RAW:
+      /* keeping the same if-else structure as in the init function */
+      if (is_compressed(reader->buffer_in)) {
+        grpc_byte_buffer_destroy(reader->buffer_out);
+      }
+      break;
+  }
+}
+
+int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
+                                 gpr_slice *slice) {
+  switch (reader->buffer_in->type) {
+    case GRPC_BB_RAW: {
+      gpr_slice_buffer *slice_buffer;
+      slice_buffer = &reader->buffer_out->data.raw.slice_buffer;
+      if (reader->current.index < slice_buffer->count) {
+        *slice = gpr_slice_ref(slice_buffer->slices[reader->current.index]);
+        reader->current.index += 1;
+        return 1;
+      }
+      break;
+    }
+  }
+  return 0;
+}
+
+gpr_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) {
+  gpr_slice in_slice;
+  size_t bytes_read = 0;
+  const size_t input_size = grpc_byte_buffer_length(reader->buffer_out);
+  gpr_slice out_slice = gpr_slice_malloc(input_size);
+  uint8_t *const outbuf = GPR_SLICE_START_PTR(out_slice); /* just an alias */
+
+  while (grpc_byte_buffer_reader_next(reader, &in_slice) != 0) {
+    const size_t slice_length = GPR_SLICE_LENGTH(in_slice);
+    memcpy(&(outbuf[bytes_read]), GPR_SLICE_START_PTR(in_slice), slice_length);
+    bytes_read += slice_length;
+    gpr_slice_unref(in_slice);
+    GPR_ASSERT(bytes_read <= input_size);
+  }
+  return out_slice;
+}
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
new file mode 100644
index 0000000..fa12b6e
--- /dev/null
+++ b/src/core/lib/surface/call.c
@@ -0,0 +1,1519 @@
+/*
+ *
+ * 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 <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/compression.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/compression/algorithm_metadata.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+/** The maximum number of concurrent batches possible.
+    Based upon the maximum number of individually queueable ops in the batch
+   api:
+      - initial metadata send
+      - message send
+      - status/close send (depending on client/server)
+      - initial metadata recv
+      - message recv
+      - status/close recv (depending on client/server) */
+#define MAX_CONCURRENT_BATCHES 6
+
+typedef struct {
+  grpc_ioreq_completion_func on_complete;
+  void *user_data;
+  int success;
+} completed_request;
+
+#define MAX_SEND_EXTRA_METADATA_COUNT 3
+
+/* Status data for a request can come from several sources; this
+   enumerates them all, and acts as a priority sorting for which
+   status to return to the application - earlier entries override
+   later ones */
+typedef enum {
+  /* Status came from the application layer overriding whatever
+     the wire says */
+  STATUS_FROM_API_OVERRIDE = 0,
+  /* Status came from 'the wire' - or somewhere below the surface
+     layer */
+  STATUS_FROM_WIRE,
+  /* Status was created by some internal channel stack operation */
+  STATUS_FROM_CORE,
+  /* Status came from the server sending status */
+  STATUS_FROM_SERVER_STATUS,
+  STATUS_SOURCE_COUNT
+} status_source;
+
+typedef struct {
+  uint8_t is_set;
+  grpc_status_code code;
+  grpc_mdstr *details;
+} received_status;
+
+/* How far through the GRPC stream have we read? */
+typedef enum {
+  /* We are still waiting for initial metadata to complete */
+  READ_STATE_INITIAL = 0,
+  /* We have gotten initial metadata, and are reading either
+     messages or trailing metadata */
+  READ_STATE_GOT_INITIAL_METADATA,
+  /* The stream is closed for reading */
+  READ_STATE_READ_CLOSED,
+  /* The stream is closed for reading & writing */
+  READ_STATE_STREAM_CLOSED
+} read_state;
+
+typedef enum {
+  WRITE_STATE_INITIAL = 0,
+  WRITE_STATE_STARTED,
+  WRITE_STATE_WRITE_CLOSED
+} write_state;
+
+typedef struct batch_control {
+  grpc_call *call;
+  grpc_cq_completion cq_completion;
+  grpc_closure finish_batch;
+  void *notify_tag;
+  gpr_refcount steps_to_complete;
+
+  uint8_t send_initial_metadata;
+  uint8_t send_message;
+  uint8_t send_final_op;
+  uint8_t recv_initial_metadata;
+  uint8_t recv_message;
+  uint8_t recv_final_op;
+  uint8_t is_notify_tag_closure;
+  uint8_t success;
+} batch_control;
+
+struct grpc_call {
+  grpc_completion_queue *cq;
+  grpc_channel *channel;
+  grpc_call *parent;
+  grpc_call *first_child;
+  /* TODO(ctiller): share with cq if possible? */
+  gpr_mu mu;
+
+  /* client or server call */
+  bool is_client;
+  /* is the alarm set */
+  bool have_alarm;
+  /** has grpc_call_destroy been called */
+  bool destroy_called;
+  /** flag indicating that cancellation is inherited */
+  bool cancellation_is_inherited;
+  /** bitmask of live batches */
+  uint8_t used_batches;
+  /** which ops are in-flight */
+  bool sent_initial_metadata;
+  bool sending_message;
+  bool sent_final_op;
+  bool received_initial_metadata;
+  bool receiving_message;
+  bool requested_final_op;
+  bool received_final_op;
+
+  /* have we received initial metadata */
+  bool has_initial_md_been_received;
+
+  batch_control active_batches[MAX_CONCURRENT_BATCHES];
+
+  /* first idx: is_receiving, second idx: is_trailing */
+  grpc_metadata_batch metadata_batch[2][2];
+
+  /* Buffered read metadata waiting to be returned to the application.
+     Element 0 is initial metadata, element 1 is trailing metadata. */
+  grpc_metadata_array *buffered_metadata[2];
+
+  /* Received call statuses from various sources */
+  received_status status[STATUS_SOURCE_COUNT];
+
+  /* Call stats: only valid after trailing metadata received */
+  grpc_transport_stream_stats stats;
+
+  /* Compression algorithm for the call */
+  grpc_compression_algorithm compression_algorithm;
+  /* Supported encodings (compression algorithms), a bitset */
+  uint32_t encodings_accepted_by_peer;
+
+  /* Contexts for various subsystems (security, tracing, ...). */
+  grpc_call_context_element context[GRPC_CONTEXT_COUNT];
+
+  /* Deadline alarm - if have_alarm is non-zero */
+  grpc_timer alarm;
+
+  /* for the client, extra metadata is initial metadata; for the
+     server, it's trailing metadata */
+  grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT];
+  int send_extra_metadata_count;
+  gpr_timespec send_deadline;
+
+  /** siblings: children of the same parent form a list, and this list is
+     protected under
+      parent->mu */
+  grpc_call *sibling_next;
+  grpc_call *sibling_prev;
+
+  grpc_slice_buffer_stream sending_stream;
+  grpc_byte_stream *receiving_stream;
+  grpc_byte_buffer **receiving_buffer;
+  gpr_slice receiving_slice;
+  grpc_closure receiving_slice_ready;
+  grpc_closure receiving_stream_ready;
+  grpc_closure receiving_initial_metadata_ready;
+  uint32_t test_only_last_message_flags;
+
+  union {
+    struct {
+      grpc_status_code *status;
+      char **status_details;
+      size_t *status_details_capacity;
+    } client;
+    struct {
+      int *cancelled;
+    } server;
+  } final_op;
+
+  void *saved_receiving_stream_ready_bctlp;
+};
+
+#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
+#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
+#define CALL_ELEM_FROM_CALL(call, idx) \
+  grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
+#define CALL_FROM_TOP_ELEM(top_elem) \
+  CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem))
+
+static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                               gpr_timespec deadline);
+static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                       grpc_transport_stream_op *op);
+static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
+                                          grpc_status_code status,
+                                          const char *description);
+static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack,
+                         bool success);
+static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
+                                  bool success);
+
+grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
+                            uint32_t propagation_mask,
+                            grpc_completion_queue *cq,
+                            const void *server_transport_data,
+                            grpc_mdelem **add_initial_metadata,
+                            size_t add_initial_metadata_count,
+                            gpr_timespec send_deadline) {
+  size_t i, j;
+  grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_call *call;
+  GPR_TIMER_BEGIN("grpc_call_create", 0);
+  call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
+  memset(call, 0, sizeof(grpc_call));
+  gpr_mu_init(&call->mu);
+  call->channel = channel;
+  call->cq = cq;
+  call->parent = parent_call;
+  call->is_client = server_transport_data == NULL;
+  if (call->is_client) {
+    GPR_ASSERT(add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT);
+    for (i = 0; i < add_initial_metadata_count; i++) {
+      call->send_extra_metadata[i].md = add_initial_metadata[i];
+    }
+    call->send_extra_metadata_count = (int)add_initial_metadata_count;
+  } else {
+    GPR_ASSERT(add_initial_metadata_count == 0);
+    call->send_extra_metadata_count = 0;
+  }
+  for (i = 0; i < 2; i++) {
+    for (j = 0; j < 2; j++) {
+      call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+    }
+  }
+  call->send_deadline = send_deadline;
+  GRPC_CHANNEL_INTERNAL_REF(channel, "call");
+  /* initial refcount dropped by grpc_call_destroy */
+  grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call,
+                       call->context, server_transport_data,
+                       CALL_STACK_FROM_CALL(call));
+  if (cq != NULL) {
+    GRPC_CQ_INTERNAL_REF(cq, "bind");
+    grpc_call_stack_set_pollset(&exec_ctx, CALL_STACK_FROM_CALL(call),
+                                grpc_cq_pollset(cq));
+  }
+  if (parent_call != NULL) {
+    GRPC_CALL_INTERNAL_REF(parent_call, "child");
+    GPR_ASSERT(call->is_client);
+    GPR_ASSERT(!parent_call->is_client);
+
+    gpr_mu_lock(&parent_call->mu);
+
+    if (propagation_mask & GRPC_PROPAGATE_DEADLINE) {
+      send_deadline = gpr_time_min(
+          gpr_convert_clock_type(send_deadline,
+                                 parent_call->send_deadline.clock_type),
+          parent_call->send_deadline);
+    }
+    /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with
+     * GRPC_PROPAGATE_STATS_CONTEXT */
+    /* TODO(ctiller): This should change to use the appropriate census start_op
+     * call. */
+    if (propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) {
+      GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
+      grpc_call_context_set(call, GRPC_CONTEXT_TRACING,
+                            parent_call->context[GRPC_CONTEXT_TRACING].value,
+                            NULL);
+    } else {
+      GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
+    }
+    if (propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
+      call->cancellation_is_inherited = 1;
+    }
+
+    if (parent_call->first_child == NULL) {
+      parent_call->first_child = call;
+      call->sibling_next = call->sibling_prev = call;
+    } else {
+      call->sibling_next = parent_call->first_child;
+      call->sibling_prev = parent_call->first_child->sibling_prev;
+      call->sibling_next->sibling_prev = call->sibling_prev->sibling_next =
+          call;
+    }
+
+    gpr_mu_unlock(&parent_call->mu);
+  }
+  if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) !=
+      0) {
+    set_deadline_alarm(&exec_ctx, call, send_deadline);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  GPR_TIMER_END("grpc_call_create", 0);
+  return call;
+}
+
+void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                                    grpc_completion_queue *cq) {
+  GPR_ASSERT(cq);
+  call->cq = cq;
+  GRPC_CQ_INTERNAL_REF(cq, "bind");
+  grpc_call_stack_set_pollset(exec_ctx, CALL_STACK_FROM_CALL(call),
+                              grpc_cq_pollset(cq));
+}
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+#define REF_REASON reason
+#define REF_ARG , const char *reason
+#else
+#define REF_REASON ""
+#define REF_ARG
+#endif
+void grpc_call_internal_ref(grpc_call *c REF_ARG) {
+  GRPC_CALL_STACK_REF(CALL_STACK_FROM_CALL(c), REF_REASON);
+}
+void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
+  GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
+}
+
+static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, bool success) {
+  size_t i;
+  int ii;
+  grpc_call *c = call;
+  GPR_TIMER_BEGIN("destroy_call", 0);
+  for (i = 0; i < 2; i++) {
+    grpc_metadata_batch_destroy(
+        &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]);
+  }
+  if (c->receiving_stream != NULL) {
+    grpc_byte_stream_destroy(exec_ctx, c->receiving_stream);
+  }
+  grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c));
+  GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->channel, "call");
+  gpr_mu_destroy(&c->mu);
+  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+    if (c->status[i].details) {
+      GRPC_MDSTR_UNREF(c->status[i].details);
+    }
+  }
+  for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
+    GRPC_MDELEM_UNREF(c->send_extra_metadata[ii].md);
+  }
+  for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
+    if (c->context[i].destroy) {
+      c->context[i].destroy(c->context[i].value);
+    }
+  }
+  if (c->cq) {
+    GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
+  }
+  gpr_free(c);
+  GPR_TIMER_END("destroy_call", 0);
+}
+
+static void set_status_code(grpc_call *call, status_source source,
+                            uint32_t status) {
+  if (call->status[source].is_set) return;
+
+  call->status[source].is_set = 1;
+  call->status[source].code = (grpc_status_code)status;
+
+  /* TODO(ctiller): what to do about the flush that was previously here */
+}
+
+static void set_compression_algorithm(grpc_call *call,
+                                      grpc_compression_algorithm algo) {
+  call->compression_algorithm = algo;
+}
+
+grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
+    grpc_call *call) {
+  grpc_compression_algorithm algorithm;
+  gpr_mu_lock(&call->mu);
+  algorithm = call->compression_algorithm;
+  gpr_mu_unlock(&call->mu);
+  return algorithm;
+}
+
+uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
+  uint32_t flags;
+  gpr_mu_lock(&call->mu);
+  flags = call->test_only_last_message_flags;
+  gpr_mu_unlock(&call->mu);
+  return flags;
+}
+
+static void destroy_encodings_accepted_by_peer(void *p) { return; }
+
+static void set_encodings_accepted_by_peer(grpc_call *call, grpc_mdelem *mdel) {
+  size_t i;
+  grpc_compression_algorithm algorithm;
+  gpr_slice_buffer accept_encoding_parts;
+  gpr_slice accept_encoding_slice;
+  void *accepted_user_data;
+
+  accepted_user_data =
+      grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
+  if (accepted_user_data != NULL) {
+    call->encodings_accepted_by_peer =
+        (uint32_t)(((uintptr_t)accepted_user_data) - 1);
+    return;
+  }
+
+  accept_encoding_slice = mdel->value->slice;
+  gpr_slice_buffer_init(&accept_encoding_parts);
+  gpr_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
+
+  /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
+   * zeroes the whole grpc_call */
+  /* Always support no compression */
+  GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
+  for (i = 0; i < accept_encoding_parts.count; i++) {
+    const gpr_slice *accept_encoding_entry_slice =
+        &accept_encoding_parts.slices[i];
+    if (grpc_compression_algorithm_parse(
+            (const char *)GPR_SLICE_START_PTR(*accept_encoding_entry_slice),
+            GPR_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
+      GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
+    } else {
+      char *accept_encoding_entry_str =
+          gpr_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
+      gpr_log(GPR_ERROR,
+              "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
+              accept_encoding_entry_str);
+      gpr_free(accept_encoding_entry_str);
+    }
+  }
+
+  gpr_slice_buffer_destroy(&accept_encoding_parts);
+
+  grpc_mdelem_set_user_data(
+      mdel, destroy_encodings_accepted_by_peer,
+      (void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
+}
+
+uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
+  uint32_t encodings_accepted_by_peer;
+  gpr_mu_lock(&call->mu);
+  encodings_accepted_by_peer = call->encodings_accepted_by_peer;
+  gpr_mu_unlock(&call->mu);
+  return encodings_accepted_by_peer;
+}
+
+static void set_status_details(grpc_call *call, status_source source,
+                               grpc_mdstr *status) {
+  if (call->status[source].details != NULL) {
+    GRPC_MDSTR_UNREF(call->status[source].details);
+  }
+  call->status[source].details = status;
+}
+
+static void get_final_status(grpc_call *call,
+                             void (*set_value)(grpc_status_code code,
+                                               void *user_data),
+                             void *set_value_user_data) {
+  int i;
+  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+    if (call->status[i].is_set) {
+      set_value(call->status[i].code, set_value_user_data);
+      return;
+    }
+  }
+  if (call->is_client) {
+    set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
+  } else {
+    set_value(GRPC_STATUS_OK, set_value_user_data);
+  }
+}
+
+static void get_final_details(grpc_call *call, char **out_details,
+                              size_t *out_details_capacity) {
+  int i;
+  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+    if (call->status[i].is_set) {
+      if (call->status[i].details) {
+        gpr_slice details = call->status[i].details->slice;
+        size_t len = GPR_SLICE_LENGTH(details);
+        if (len + 1 > *out_details_capacity) {
+          *out_details_capacity =
+              GPR_MAX(len + 1, *out_details_capacity * 3 / 2);
+          *out_details = gpr_realloc(*out_details, *out_details_capacity);
+        }
+        memcpy(*out_details, GPR_SLICE_START_PTR(details), len);
+        (*out_details)[len] = 0;
+      } else {
+        goto no_details;
+      }
+      return;
+    }
+  }
+
+no_details:
+  if (0 == *out_details_capacity) {
+    *out_details_capacity = 8;
+    *out_details = gpr_malloc(*out_details_capacity);
+  }
+  **out_details = 0;
+}
+
+static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
+  return (grpc_linked_mdelem *)&md->internal_data;
+}
+
+static int prepare_application_metadata(grpc_call *call, int count,
+                                        grpc_metadata *metadata,
+                                        int is_trailing,
+                                        int prepend_extra_metadata) {
+  int i;
+  grpc_metadata_batch *batch =
+      &call->metadata_batch[0 /* is_receiving */][is_trailing];
+  for (i = 0; i < count; i++) {
+    grpc_metadata *md = &metadata[i];
+    grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
+    GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
+    l->md = grpc_mdelem_from_string_and_buffer(
+        md->key, (const uint8_t *)md->value, md->value_length);
+    if (!grpc_header_key_is_legal(grpc_mdstr_as_c_string(l->md->key),
+                                  GRPC_MDSTR_LENGTH(l->md->key))) {
+      gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
+              grpc_mdstr_as_c_string(l->md->key));
+      break;
+    } else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
+                                      GRPC_MDSTR_LENGTH(l->md->key)) &&
+               !grpc_header_nonbin_value_is_legal(
+                   grpc_mdstr_as_c_string(l->md->value),
+                   GRPC_MDSTR_LENGTH(l->md->value))) {
+      gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
+      break;
+    }
+  }
+  if (i != count) {
+    for (int j = 0; j <= i; j++) {
+      grpc_metadata *md = &metadata[j];
+      grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
+      GRPC_MDELEM_UNREF(l->md);
+    }
+    return 0;
+  }
+  if (prepend_extra_metadata) {
+    if (call->send_extra_metadata_count == 0) {
+      prepend_extra_metadata = 0;
+    } else {
+      for (i = 0; i < call->send_extra_metadata_count; i++) {
+        GRPC_MDELEM_REF(call->send_extra_metadata[i].md);
+      }
+      for (i = 1; i < call->send_extra_metadata_count; i++) {
+        call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
+      }
+      for (i = 0; i < call->send_extra_metadata_count - 1; i++) {
+        call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1];
+      }
+    }
+  }
+  for (i = 1; i < count; i++) {
+    linked_from_md(&metadata[i])->prev = linked_from_md(&metadata[i - 1]);
+  }
+  for (i = 0; i < count - 1; i++) {
+    linked_from_md(&metadata[i])->next = linked_from_md(&metadata[i + 1]);
+  }
+  switch (prepend_extra_metadata * 2 + (count != 0)) {
+    case 0:
+      /* no prepend, no metadata => nothing to do */
+      batch->list.head = batch->list.tail = NULL;
+      break;
+    case 1:
+      /* metadata, but no prepend */
+      batch->list.head = linked_from_md(&metadata[0]);
+      batch->list.tail = linked_from_md(&metadata[count - 1]);
+      batch->list.head->prev = NULL;
+      batch->list.tail->next = NULL;
+      break;
+    case 2:
+      /* prepend, but no md */
+      batch->list.head = &call->send_extra_metadata[0];
+      batch->list.tail =
+          &call->send_extra_metadata[call->send_extra_metadata_count - 1];
+      batch->list.head->prev = NULL;
+      batch->list.tail->next = NULL;
+      break;
+    case 3:
+      /* prepend AND md */
+      batch->list.head = &call->send_extra_metadata[0];
+      call->send_extra_metadata[call->send_extra_metadata_count - 1].next =
+          linked_from_md(&metadata[0]);
+      linked_from_md(&metadata[0])->prev =
+          &call->send_extra_metadata[call->send_extra_metadata_count - 1];
+      batch->list.tail = linked_from_md(&metadata[count - 1]);
+      batch->list.head->prev = NULL;
+      batch->list.tail->next = NULL;
+      break;
+    default:
+      GPR_UNREACHABLE_CODE(return 0);
+  }
+
+  return 1;
+}
+
+void grpc_call_destroy(grpc_call *c) {
+  int cancel;
+  grpc_call *parent = c->parent;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GPR_TIMER_BEGIN("grpc_call_destroy", 0);
+  GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
+
+  if (parent) {
+    gpr_mu_lock(&parent->mu);
+    if (c == parent->first_child) {
+      parent->first_child = c->sibling_next;
+      if (c == parent->first_child) {
+        parent->first_child = NULL;
+      }
+      c->sibling_prev->sibling_next = c->sibling_next;
+      c->sibling_next->sibling_prev = c->sibling_prev;
+    }
+    gpr_mu_unlock(&parent->mu);
+    GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
+  }
+
+  gpr_mu_lock(&c->mu);
+  GPR_ASSERT(!c->destroy_called);
+  c->destroy_called = 1;
+  if (c->have_alarm) {
+    grpc_timer_cancel(&exec_ctx, &c->alarm);
+  }
+  cancel = !c->received_final_op;
+  gpr_mu_unlock(&c->mu);
+  if (cancel) grpc_call_cancel(c, NULL);
+  GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
+  grpc_exec_ctx_finish(&exec_ctx);
+  GPR_TIMER_END("grpc_call_destroy", 0);
+}
+
+grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
+  GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
+  GPR_ASSERT(!reserved);
+  return grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Cancelled",
+                                      NULL);
+}
+
+grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
+                                             grpc_status_code status,
+                                             const char *description,
+                                             void *reserved) {
+  grpc_call_error r;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GRPC_API_TRACE(
+      "grpc_call_cancel_with_status("
+      "c=%p, status=%d, description=%s, reserved=%p)",
+      4, (c, (int)status, description, reserved));
+  GPR_ASSERT(reserved == NULL);
+  gpr_mu_lock(&c->mu);
+  r = cancel_with_status(&exec_ctx, c, status, description);
+  gpr_mu_unlock(&c->mu);
+  grpc_exec_ctx_finish(&exec_ctx);
+  return r;
+}
+
+typedef struct cancel_closure {
+  grpc_closure closure;
+  grpc_call *call;
+  grpc_status_code status;
+} cancel_closure;
+
+static void done_cancel(grpc_exec_ctx *exec_ctx, void *ccp, bool success) {
+  cancel_closure *cc = ccp;
+  GRPC_CALL_INTERNAL_UNREF(exec_ctx, cc->call, "cancel");
+  gpr_free(cc);
+}
+
+static void send_cancel(grpc_exec_ctx *exec_ctx, void *ccp, bool success) {
+  grpc_transport_stream_op op;
+  cancel_closure *cc = ccp;
+  memset(&op, 0, sizeof(op));
+  op.cancel_with_status = cc->status;
+  /* reuse closure to catch completion */
+  grpc_closure_init(&cc->closure, done_cancel, cc);
+  op.on_complete = &cc->closure;
+  execute_op(exec_ctx, cc->call, &op);
+}
+
+static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
+                                          grpc_status_code status,
+                                          const char *description) {
+  grpc_mdstr *details =
+      description ? grpc_mdstr_from_string(description) : NULL;
+  cancel_closure *cc = gpr_malloc(sizeof(*cc));
+
+  GPR_ASSERT(status != GRPC_STATUS_OK);
+
+  set_status_code(c, STATUS_FROM_API_OVERRIDE, (uint32_t)status);
+  set_status_details(c, STATUS_FROM_API_OVERRIDE, details);
+
+  grpc_closure_init(&cc->closure, send_cancel, cc);
+  cc->call = c;
+  cc->status = status;
+  GRPC_CALL_INTERNAL_REF(c, "cancel");
+  grpc_exec_ctx_enqueue(exec_ctx, &cc->closure, true, NULL);
+
+  return GRPC_CALL_OK;
+}
+
+static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                       grpc_transport_stream_op *op) {
+  grpc_call_element *elem;
+
+  GPR_TIMER_BEGIN("execute_op", 0);
+  elem = CALL_ELEM_FROM_CALL(call, 0);
+  op->context = call->context;
+  elem->filter->start_transport_stream_op(exec_ctx, elem, op);
+  GPR_TIMER_END("execute_op", 0);
+}
+
+char *grpc_call_get_peer(grpc_call *call) {
+  grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  char *result;
+  GRPC_API_TRACE("grpc_call_get_peer(%p)", 1, (call));
+  result = elem->filter->get_peer(&exec_ctx, elem);
+  if (result == NULL) {
+    result = grpc_channel_get_target(call->channel);
+  }
+  if (result == NULL) {
+    result = gpr_strdup("unknown");
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  return result;
+}
+
+grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
+  return CALL_FROM_TOP_ELEM(elem);
+}
+
+static void call_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  grpc_call *call = arg;
+  gpr_mu_lock(&call->mu);
+  call->have_alarm = 0;
+  if (success) {
+    cancel_with_status(exec_ctx, call, GRPC_STATUS_DEADLINE_EXCEEDED,
+                       "Deadline Exceeded");
+  }
+  gpr_mu_unlock(&call->mu);
+  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "alarm");
+}
+
+static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                               gpr_timespec deadline) {
+  if (call->have_alarm) {
+    gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice");
+    assert(0);
+    return;
+  }
+  GRPC_CALL_INTERNAL_REF(call, "alarm");
+  call->have_alarm = 1;
+  call->send_deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
+  grpc_timer_init(exec_ctx, &call->alarm, call->send_deadline, call_alarm, call,
+                  gpr_now(GPR_CLOCK_MONOTONIC));
+}
+
+/* we offset status by a small amount when storing it into transport metadata
+   as metadata cannot store a 0 value (which is used as OK for grpc_status_codes
+   */
+#define STATUS_OFFSET 1
+static void destroy_status(void *ignored) {}
+
+static uint32_t decode_status(grpc_mdelem *md) {
+  uint32_t status;
+  void *user_data;
+  if (md == GRPC_MDELEM_GRPC_STATUS_0) return 0;
+  if (md == GRPC_MDELEM_GRPC_STATUS_1) return 1;
+  if (md == GRPC_MDELEM_GRPC_STATUS_2) return 2;
+  user_data = grpc_mdelem_get_user_data(md, destroy_status);
+  if (user_data != NULL) {
+    status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
+  } else {
+    if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
+                                   GPR_SLICE_LENGTH(md->value->slice),
+                                   &status)) {
+      status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
+    }
+    grpc_mdelem_set_user_data(md, destroy_status,
+                              (void *)(intptr_t)(status + STATUS_OFFSET));
+  }
+  return status;
+}
+
+static uint32_t decode_compression(grpc_mdelem *md) {
+  grpc_compression_algorithm algorithm =
+      grpc_compression_algorithm_from_mdstr(md->value);
+  if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
+    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
+    gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str);
+  }
+  return algorithm;
+}
+
+static grpc_mdelem *recv_common_filter(grpc_call *call, grpc_mdelem *elem) {
+  if (elem->key == GRPC_MDSTR_GRPC_STATUS) {
+    GPR_TIMER_BEGIN("status", 0);
+    set_status_code(call, STATUS_FROM_WIRE, decode_status(elem));
+    GPR_TIMER_END("status", 0);
+    return NULL;
+  } else if (elem->key == GRPC_MDSTR_GRPC_MESSAGE) {
+    GPR_TIMER_BEGIN("status-details", 0);
+    set_status_details(call, STATUS_FROM_WIRE, GRPC_MDSTR_REF(elem->value));
+    GPR_TIMER_END("status-details", 0);
+    return NULL;
+  }
+  return elem;
+}
+
+static grpc_mdelem *publish_app_metadata(grpc_call *call, grpc_mdelem *elem,
+                                         int is_trailing) {
+  grpc_metadata_array *dest;
+  grpc_metadata *mdusr;
+  GPR_TIMER_BEGIN("publish_app_metadata", 0);
+  dest = call->buffered_metadata[is_trailing];
+  if (dest->count == dest->capacity) {
+    dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2);
+    dest->metadata =
+        gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
+  }
+  mdusr = &dest->metadata[dest->count++];
+  mdusr->key = grpc_mdstr_as_c_string(elem->key);
+  mdusr->value = grpc_mdstr_as_c_string(elem->value);
+  mdusr->value_length = GPR_SLICE_LENGTH(elem->value->slice);
+  GPR_TIMER_END("publish_app_metadata", 0);
+  return elem;
+}
+
+static grpc_mdelem *recv_initial_filter(void *callp, grpc_mdelem *elem) {
+  grpc_call *call = callp;
+  elem = recv_common_filter(call, elem);
+  if (elem == NULL) {
+    return NULL;
+  } else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) {
+    GPR_TIMER_BEGIN("compression_algorithm", 0);
+    set_compression_algorithm(call, decode_compression(elem));
+    GPR_TIMER_END("compression_algorithm", 0);
+    return NULL;
+  } else if (elem->key == GRPC_MDSTR_GRPC_ACCEPT_ENCODING) {
+    GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
+    set_encodings_accepted_by_peer(call, elem);
+    GPR_TIMER_END("encodings_accepted_by_peer", 0);
+    return NULL;
+  } else {
+    return publish_app_metadata(call, elem, 0);
+  }
+}
+
+static grpc_mdelem *recv_trailing_filter(void *callp, grpc_mdelem *elem) {
+  grpc_call *call = callp;
+  elem = recv_common_filter(call, elem);
+  if (elem == NULL) {
+    return NULL;
+  } else {
+    return publish_app_metadata(call, elem, 1);
+  }
+}
+
+grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
+  return CALL_STACK_FROM_CALL(call);
+}
+
+/*
+ * BATCH API IMPLEMENTATION
+ */
+
+static void set_status_value_directly(grpc_status_code status, void *dest) {
+  *(grpc_status_code *)dest = status;
+}
+
+static void set_cancelled_value(grpc_status_code status, void *dest) {
+  *(int *)dest = (status != GRPC_STATUS_OK);
+}
+
+static bool are_write_flags_valid(uint32_t flags) {
+  /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
+  const uint32_t allowed_write_positions =
+      (GRPC_WRITE_USED_MASK | GRPC_WRITE_INTERNAL_USED_MASK);
+  const uint32_t invalid_positions = ~allowed_write_positions;
+  return !(flags & invalid_positions);
+}
+
+static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
+  /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
+  uint32_t invalid_positions = ~GRPC_INITIAL_METADATA_USED_MASK;
+  if (!is_client) {
+    invalid_positions |= GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST;
+  }
+  return !(flags & invalid_positions);
+}
+
+static batch_control *allocate_batch_control(grpc_call *call) {
+  size_t i;
+  for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
+    if ((call->used_batches & (1 << i)) == 0) {
+      call->used_batches = (uint8_t)(call->used_batches | (uint8_t)(1 << i));
+      return &call->active_batches[i];
+    }
+  }
+  return NULL;
+}
+
+static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
+                                    grpc_cq_completion *storage) {
+  batch_control *bctl = user_data;
+  grpc_call *call = bctl->call;
+  gpr_mu_lock(&call->mu);
+  call->used_batches = (uint8_t)(
+      call->used_batches & ~(uint8_t)(1 << (bctl - call->active_batches)));
+  gpr_mu_unlock(&call->mu);
+  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
+}
+
+static void post_batch_completion(grpc_exec_ctx *exec_ctx,
+                                  batch_control *bctl) {
+  grpc_call *call = bctl->call;
+  if (bctl->is_notify_tag_closure) {
+    grpc_exec_ctx_enqueue(exec_ctx, bctl->notify_tag, bctl->success, NULL);
+    gpr_mu_lock(&call->mu);
+    bctl->call->used_batches =
+        (uint8_t)(bctl->call->used_batches &
+                  ~(uint8_t)(1 << (bctl - bctl->call->active_batches)));
+    gpr_mu_unlock(&call->mu);
+    GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
+  } else {
+    grpc_cq_end_op(exec_ctx, bctl->call->cq, bctl->notify_tag, bctl->success,
+                   finish_batch_completion, bctl, &bctl->cq_completion);
+  }
+}
+
+static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
+                                      batch_control *bctl) {
+  grpc_call *call = bctl->call;
+  for (;;) {
+    size_t remaining = call->receiving_stream->length -
+                       (*call->receiving_buffer)->data.raw.slice_buffer.length;
+    if (remaining == 0) {
+      call->receiving_message = 0;
+      grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
+      call->receiving_stream = NULL;
+      if (gpr_unref(&bctl->steps_to_complete)) {
+        post_batch_completion(exec_ctx, bctl);
+      }
+      return;
+    }
+    if (grpc_byte_stream_next(exec_ctx, call->receiving_stream,
+                              &call->receiving_slice, remaining,
+                              &call->receiving_slice_ready)) {
+      gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
+                           call->receiving_slice);
+    } else {
+      return;
+    }
+  }
+}
+
+static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
+                                  bool success) {
+  batch_control *bctl = bctlp;
+  grpc_call *call = bctl->call;
+
+  if (success) {
+    gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
+                         call->receiving_slice);
+    continue_receiving_slices(exec_ctx, bctl);
+  } else {
+    grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
+    call->receiving_stream = NULL;
+    grpc_byte_buffer_destroy(*call->receiving_buffer);
+    *call->receiving_buffer = NULL;
+    if (gpr_unref(&bctl->steps_to_complete)) {
+      post_batch_completion(exec_ctx, bctl);
+    }
+  }
+}
+
+static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl,
+                                  bool success) {
+  grpc_call *call = bctl->call;
+  if (call->receiving_stream == NULL) {
+    *call->receiving_buffer = NULL;
+    call->receiving_message = 0;
+    if (gpr_unref(&bctl->steps_to_complete)) {
+      post_batch_completion(exec_ctx, bctl);
+    }
+  } else if (call->receiving_stream->length >
+             grpc_channel_get_max_message_length(call->channel)) {
+    cancel_with_status(exec_ctx, call, GRPC_STATUS_INTERNAL,
+                       "Max message size exceeded");
+    grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
+    call->receiving_stream = NULL;
+    *call->receiving_buffer = NULL;
+    call->receiving_message = 0;
+    if (gpr_unref(&bctl->steps_to_complete)) {
+      post_batch_completion(exec_ctx, bctl);
+    }
+  } else {
+    call->test_only_last_message_flags = call->receiving_stream->flags;
+    if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&
+        (call->compression_algorithm > GRPC_COMPRESS_NONE)) {
+      *call->receiving_buffer = grpc_raw_compressed_byte_buffer_create(
+          NULL, 0, call->compression_algorithm);
+    } else {
+      *call->receiving_buffer = grpc_raw_byte_buffer_create(NULL, 0);
+    }
+    grpc_closure_init(&call->receiving_slice_ready, receiving_slice_ready,
+                      bctl);
+    continue_receiving_slices(exec_ctx, bctl);
+    /* early out */
+    return;
+  }
+}
+
+static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
+                                   bool success) {
+  batch_control *bctl = bctlp;
+  grpc_call *call = bctl->call;
+
+  gpr_mu_lock(&bctl->call->mu);
+  if (bctl->call->has_initial_md_been_received || !success ||
+      call->receiving_stream == NULL) {
+    gpr_mu_unlock(&bctl->call->mu);
+    process_data_after_md(exec_ctx, bctlp, success);
+  } else {
+    call->saved_receiving_stream_ready_bctlp = bctlp;
+    gpr_mu_unlock(&bctl->call->mu);
+  }
+}
+
+static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
+                                             void *bctlp, bool success) {
+  batch_control *bctl = bctlp;
+  grpc_call *call = bctl->call;
+
+  gpr_mu_lock(&call->mu);
+
+  if (!success) {
+    bctl->success = false;
+  } else {
+    grpc_metadata_batch *md =
+        &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
+    grpc_metadata_batch_filter(md, recv_initial_filter, call);
+
+    if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
+            0 &&
+        !call->is_client) {
+      GPR_TIMER_BEGIN("set_deadline_alarm", 0);
+      set_deadline_alarm(exec_ctx, call, md->deadline);
+      GPR_TIMER_END("set_deadline_alarm", 0);
+    }
+  }
+
+  call->has_initial_md_been_received = true;
+  if (call->saved_receiving_stream_ready_bctlp != NULL) {
+    grpc_closure *saved_rsr_closure = grpc_closure_create(
+        receiving_stream_ready, call->saved_receiving_stream_ready_bctlp);
+    call->saved_receiving_stream_ready_bctlp = NULL;
+    grpc_exec_ctx_enqueue(exec_ctx, saved_rsr_closure, success, NULL);
+  }
+
+  gpr_mu_unlock(&call->mu);
+
+  if (gpr_unref(&bctl->steps_to_complete)) {
+    post_batch_completion(exec_ctx, bctl);
+  }
+}
+
+static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, bool success) {
+  batch_control *bctl = bctlp;
+  grpc_call *call = bctl->call;
+  grpc_call *child_call;
+  grpc_call *next_child_call;
+
+  gpr_mu_lock(&call->mu);
+  if (bctl->send_initial_metadata) {
+    if (!success) {
+      set_status_code(call, STATUS_FROM_CORE, GRPC_STATUS_UNAVAILABLE);
+    }
+    grpc_metadata_batch_destroy(
+        &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
+  }
+  if (bctl->send_message) {
+    call->sending_message = 0;
+  }
+  if (bctl->send_final_op) {
+    grpc_metadata_batch_destroy(
+        &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
+  }
+  if (bctl->recv_final_op) {
+    grpc_metadata_batch *md =
+        &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+    grpc_metadata_batch_filter(md, recv_trailing_filter, call);
+
+    call->received_final_op = true;
+    if (call->have_alarm) {
+      grpc_timer_cancel(exec_ctx, &call->alarm);
+    }
+    /* propagate cancellation to any interested children */
+    child_call = call->first_child;
+    if (child_call != NULL) {
+      do {
+        next_child_call = child_call->sibling_next;
+        if (child_call->cancellation_is_inherited) {
+          GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
+          grpc_call_cancel(child_call, NULL);
+          GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
+        }
+        child_call = next_child_call;
+      } while (child_call != call->first_child);
+    }
+
+    if (call->is_client) {
+      get_final_status(call, set_status_value_directly,
+                       call->final_op.client.status);
+      get_final_details(call, call->final_op.client.status_details,
+                        call->final_op.client.status_details_capacity);
+    } else {
+      get_final_status(call, set_cancelled_value,
+                       call->final_op.server.cancelled);
+    }
+
+    success = 1;
+  }
+  bctl->success = success != 0;
+  gpr_mu_unlock(&call->mu);
+  if (gpr_unref(&bctl->steps_to_complete)) {
+    post_batch_completion(exec_ctx, bctl);
+  }
+}
+
+static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
+                                        grpc_call *call, const grpc_op *ops,
+                                        size_t nops, void *notify_tag,
+                                        int is_notify_tag_closure) {
+  grpc_transport_stream_op stream_op;
+  size_t i;
+  const grpc_op *op;
+  batch_control *bctl;
+  int num_completion_callbacks_needed = 1;
+  grpc_call_error error = GRPC_CALL_OK;
+
+  GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
+
+  GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
+
+  memset(&stream_op, 0, sizeof(stream_op));
+
+  /* TODO(ctiller): this feels like it could be made lock-free */
+  gpr_mu_lock(&call->mu);
+  bctl = allocate_batch_control(call);
+  memset(bctl, 0, sizeof(*bctl));
+  bctl->call = call;
+  bctl->notify_tag = notify_tag;
+  bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
+
+  if (nops == 0) {
+    GRPC_CALL_INTERNAL_REF(call, "completion");
+    bctl->success = 1;
+    if (!is_notify_tag_closure) {
+      grpc_cq_begin_op(call->cq, notify_tag);
+    }
+    gpr_mu_unlock(&call->mu);
+    post_batch_completion(exec_ctx, bctl);
+    error = GRPC_CALL_OK;
+    goto done;
+  }
+
+  /* rewrite batch ops into a transport op */
+  for (i = 0; i < nops; i++) {
+    op = &ops[i];
+    if (op->reserved != NULL) {
+      error = GRPC_CALL_ERROR;
+      goto done_with_error;
+    }
+    switch (op->op) {
+      case GRPC_OP_SEND_INITIAL_METADATA:
+        /* Flag validation: currently allow no flags */
+        if (!are_initial_metadata_flags_valid(op->flags, call->is_client)) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (call->sent_initial_metadata) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        if (op->data.send_initial_metadata.count > INT_MAX) {
+          error = GRPC_CALL_ERROR_INVALID_METADATA;
+          goto done_with_error;
+        }
+        bctl->send_initial_metadata = 1;
+        call->sent_initial_metadata = 1;
+        if (!prepare_application_metadata(
+                call, (int)op->data.send_initial_metadata.count,
+                op->data.send_initial_metadata.metadata, 0, call->is_client)) {
+          error = GRPC_CALL_ERROR_INVALID_METADATA;
+          goto done_with_error;
+        }
+        /* TODO(ctiller): just make these the same variable? */
+        call->metadata_batch[0][0].deadline = call->send_deadline;
+        stream_op.send_initial_metadata =
+            &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
+        stream_op.send_initial_metadata_flags = op->flags;
+        break;
+      case GRPC_OP_SEND_MESSAGE:
+        if (!are_write_flags_valid(op->flags)) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (op->data.send_message == NULL) {
+          error = GRPC_CALL_ERROR_INVALID_MESSAGE;
+          goto done_with_error;
+        }
+        if (call->sending_message) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        bctl->send_message = 1;
+        call->sending_message = 1;
+        grpc_slice_buffer_stream_init(
+            &call->sending_stream,
+            &op->data.send_message->data.raw.slice_buffer, op->flags);
+        stream_op.send_message = &call->sending_stream.base;
+        break;
+      case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+        /* Flag validation: currently allow no flags */
+        if (op->flags != 0) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (!call->is_client) {
+          error = GRPC_CALL_ERROR_NOT_ON_SERVER;
+          goto done_with_error;
+        }
+        if (call->sent_final_op) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        bctl->send_final_op = 1;
+        call->sent_final_op = 1;
+        stream_op.send_trailing_metadata =
+            &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
+        break;
+      case GRPC_OP_SEND_STATUS_FROM_SERVER:
+        /* Flag validation: currently allow no flags */
+        if (op->flags != 0) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (call->is_client) {
+          error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
+          goto done_with_error;
+        }
+        if (call->sent_final_op) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        if (op->data.send_status_from_server.trailing_metadata_count >
+            INT_MAX) {
+          error = GRPC_CALL_ERROR_INVALID_METADATA;
+          goto done_with_error;
+        }
+        bctl->send_final_op = 1;
+        call->sent_final_op = 1;
+        call->send_extra_metadata_count = 1;
+        call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
+            call->channel, op->data.send_status_from_server.status);
+        if (op->data.send_status_from_server.status_details != NULL) {
+          call->send_extra_metadata[1].md = grpc_mdelem_from_metadata_strings(
+              GRPC_MDSTR_GRPC_MESSAGE,
+              grpc_mdstr_from_string(
+                  op->data.send_status_from_server.status_details));
+          call->send_extra_metadata_count++;
+          set_status_details(
+              call, STATUS_FROM_API_OVERRIDE,
+              GRPC_MDSTR_REF(call->send_extra_metadata[1].md->value));
+        }
+        set_status_code(call, STATUS_FROM_API_OVERRIDE,
+                        (uint32_t)op->data.send_status_from_server.status);
+        if (!prepare_application_metadata(
+                call,
+                (int)op->data.send_status_from_server.trailing_metadata_count,
+                op->data.send_status_from_server.trailing_metadata, 1, 1)) {
+          error = GRPC_CALL_ERROR_INVALID_METADATA;
+          goto done_with_error;
+        }
+        stream_op.send_trailing_metadata =
+            &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
+        break;
+      case GRPC_OP_RECV_INITIAL_METADATA:
+        /* Flag validation: currently allow no flags */
+        if (op->flags != 0) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (call->received_initial_metadata) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        call->received_initial_metadata = 1;
+        call->buffered_metadata[0] = op->data.recv_initial_metadata;
+        grpc_closure_init(&call->receiving_initial_metadata_ready,
+                          receiving_initial_metadata_ready, bctl);
+        bctl->recv_initial_metadata = 1;
+        stream_op.recv_initial_metadata =
+            &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
+        stream_op.recv_initial_metadata_ready =
+            &call->receiving_initial_metadata_ready;
+        num_completion_callbacks_needed++;
+        break;
+      case GRPC_OP_RECV_MESSAGE:
+        /* Flag validation: currently allow no flags */
+        if (op->flags != 0) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (call->receiving_message) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        call->receiving_message = 1;
+        bctl->recv_message = 1;
+        call->receiving_buffer = op->data.recv_message;
+        stream_op.recv_message = &call->receiving_stream;
+        grpc_closure_init(&call->receiving_stream_ready, receiving_stream_ready,
+                          bctl);
+        stream_op.recv_message_ready = &call->receiving_stream_ready;
+        num_completion_callbacks_needed++;
+        break;
+      case GRPC_OP_RECV_STATUS_ON_CLIENT:
+        /* Flag validation: currently allow no flags */
+        if (op->flags != 0) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (!call->is_client) {
+          error = GRPC_CALL_ERROR_NOT_ON_SERVER;
+          goto done_with_error;
+        }
+        if (call->requested_final_op) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        call->requested_final_op = 1;
+        call->buffered_metadata[1] =
+            op->data.recv_status_on_client.trailing_metadata;
+        call->final_op.client.status = op->data.recv_status_on_client.status;
+        call->final_op.client.status_details =
+            op->data.recv_status_on_client.status_details;
+        call->final_op.client.status_details_capacity =
+            op->data.recv_status_on_client.status_details_capacity;
+        bctl->recv_final_op = 1;
+        stream_op.recv_trailing_metadata =
+            &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+        stream_op.collect_stats = &call->stats;
+        break;
+      case GRPC_OP_RECV_CLOSE_ON_SERVER:
+        /* Flag validation: currently allow no flags */
+        if (op->flags != 0) {
+          error = GRPC_CALL_ERROR_INVALID_FLAGS;
+          goto done_with_error;
+        }
+        if (call->is_client) {
+          error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
+          goto done_with_error;
+        }
+        if (call->requested_final_op) {
+          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
+        }
+        call->requested_final_op = 1;
+        call->final_op.server.cancelled =
+            op->data.recv_close_on_server.cancelled;
+        bctl->recv_final_op = 1;
+        stream_op.recv_trailing_metadata =
+            &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+        stream_op.collect_stats = &call->stats;
+        break;
+    }
+  }
+
+  GRPC_CALL_INTERNAL_REF(call, "completion");
+  if (!is_notify_tag_closure) {
+    grpc_cq_begin_op(call->cq, notify_tag);
+  }
+  gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
+
+  stream_op.context = call->context;
+  grpc_closure_init(&bctl->finish_batch, finish_batch, bctl);
+  stream_op.on_complete = &bctl->finish_batch;
+  gpr_mu_unlock(&call->mu);
+
+  execute_op(exec_ctx, call, &stream_op);
+
+done:
+  GPR_TIMER_END("grpc_call_start_batch", 0);
+  return error;
+
+done_with_error:
+  /* reverse any mutations that occured */
+  if (bctl->send_initial_metadata) {
+    call->sent_initial_metadata = 0;
+    grpc_metadata_batch_clear(&call->metadata_batch[0][0]);
+  }
+  if (bctl->send_message) {
+    call->sending_message = 0;
+    grpc_byte_stream_destroy(exec_ctx, &call->sending_stream.base);
+  }
+  if (bctl->send_final_op) {
+    call->sent_final_op = 0;
+    grpc_metadata_batch_clear(&call->metadata_batch[0][1]);
+  }
+  if (bctl->recv_initial_metadata) {
+    call->received_initial_metadata = 0;
+  }
+  if (bctl->recv_message) {
+    call->receiving_message = 0;
+  }
+  if (bctl->recv_final_op) {
+    call->requested_final_op = 0;
+  }
+  gpr_mu_unlock(&call->mu);
+  goto done;
+}
+
+grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
+                                      size_t nops, void *tag, void *reserved) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_call_error err;
+
+  GRPC_API_TRACE(
+      "grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, reserved=%p)",
+      5, (call, ops, (unsigned long)nops, tag, reserved));
+
+  if (reserved != NULL) {
+    err = GRPC_CALL_ERROR;
+  } else {
+    err = call_start_batch(&exec_ctx, call, ops, nops, tag, 0);
+  }
+
+  grpc_exec_ctx_finish(&exec_ctx);
+  return err;
+}
+
+grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx,
+                                                  grpc_call *call,
+                                                  const grpc_op *ops,
+                                                  size_t nops,
+                                                  grpc_closure *closure) {
+  return call_start_batch(exec_ctx, call, ops, nops, closure, 1);
+}
+
+void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
+                           void *value, void (*destroy)(void *value)) {
+  if (call->context[elem].destroy) {
+    call->context[elem].destroy(call->context[elem].value);
+  }
+  call->context[elem].value = value;
+  call->context[elem].destroy = destroy;
+}
+
+void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) {
+  return call->context[elem].value;
+}
+
+uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; }
+
+grpc_compression_algorithm grpc_call_compression_for_level(
+    grpc_call *call, grpc_compression_level level) {
+  gpr_mu_lock(&call->mu);
+  const uint32_t accepted_encodings = call->encodings_accepted_by_peer;
+  gpr_mu_unlock(&call->mu);
+  return grpc_compression_algorithm_for_level(level, accepted_encodings);
+}
diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h
new file mode 100644
index 0000000..2725e06
--- /dev/null
+++ b/src/core/lib/surface/call.h
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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_SURFACE_CALL_H
+#define GRPC_CORE_LIB_SURFACE_CALL_H
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/context.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/surface_trace.h"
+
+#include <grpc/grpc.h>
+#include <grpc/impl/codegen/compression_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*grpc_ioreq_completion_func)(grpc_exec_ctx *exec_ctx,
+                                           grpc_call *call, int success,
+                                           void *user_data);
+
+grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
+                            uint32_t propagation_mask,
+                            grpc_completion_queue *cq,
+                            const void *server_transport_data,
+                            grpc_mdelem **add_initial_metadata,
+                            size_t add_initial_metadata_count,
+                            gpr_timespec send_deadline);
+
+void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                                    grpc_completion_queue *cq);
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+void grpc_call_internal_ref(grpc_call *call, const char *reason);
+void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                              const char *reason);
+#define GRPC_CALL_INTERNAL_REF(call, reason) \
+  grpc_call_internal_ref(call, reason)
+#define GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, reason) \
+  grpc_call_internal_unref(exec_ctx, call, reason)
+#else
+void grpc_call_internal_ref(grpc_call *call);
+void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call);
+#define GRPC_CALL_INTERNAL_REF(call, reason) grpc_call_internal_ref(call)
+#define GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, reason) \
+  grpc_call_internal_unref(exec_ctx, call)
+#endif
+
+grpc_call_stack *grpc_call_get_call_stack(grpc_call *call);
+
+grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx,
+                                                  grpc_call *call,
+                                                  const grpc_op *ops,
+                                                  size_t nops,
+                                                  grpc_closure *closure);
+
+/* Given the top call_element, get the call object. */
+grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element);
+
+void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
+                         grpc_call *call, const grpc_op *ops, size_t nops,
+                         void *tag);
+
+/* Set a context pointer.
+   No thread safety guarantees are made wrt this value. */
+void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
+                           void *value, void (*destroy)(void *value));
+/* Get a context pointer. */
+void *grpc_call_context_get(grpc_call *call, grpc_context_index elem);
+
+#define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \
+  if (grpc_api_trace) grpc_call_log_batch(sev, call, ops, nops, tag)
+
+uint8_t grpc_call_is_client(grpc_call *call);
+
+/* Return an appropriate compression algorithm for the requested compression \a
+ * level in the context of \a call. */
+grpc_compression_algorithm grpc_call_compression_for_level(
+    grpc_call *call, grpc_compression_level level);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_SURFACE_CALL_H */
diff --git a/src/core/lib/surface/call_details.c b/src/core/lib/surface/call_details.c
new file mode 100644
index 0000000..fe73da3
--- /dev/null
+++ b/src/core/lib/surface/call_details.c
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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/grpc.h>
+#include <grpc/support/alloc.h>
+
+#include <string.h>
+
+#include "src/core/lib/surface/api_trace.h"
+
+void grpc_call_details_init(grpc_call_details* cd) {
+  GRPC_API_TRACE("grpc_call_details_init(cd=%p)", 1, (cd));
+  memset(cd, 0, sizeof(*cd));
+}
+
+void grpc_call_details_destroy(grpc_call_details* cd) {
+  GRPC_API_TRACE("grpc_call_details_destroy(cd=%p)", 1, (cd));
+  gpr_free(cd->method);
+  gpr_free(cd->host);
+}
diff --git a/src/core/lib/surface/call_log_batch.c b/src/core/lib/surface/call_log_batch.c
new file mode 100644
index 0000000..a6d1d51
--- /dev/null
+++ b/src/core/lib/surface/call_log_batch.c
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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/surface/call.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+#include "src/core/lib/support/string.h"
+
+static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) {
+  size_t i;
+  for (i = 0; i < count; i++) {
+    gpr_strvec_add(b, gpr_strdup("\nkey="));
+    gpr_strvec_add(b, gpr_strdup(md[i].key));
+
+    gpr_strvec_add(b, gpr_strdup(" value="));
+    gpr_strvec_add(b, gpr_dump(md[i].value, md[i].value_length,
+                               GPR_DUMP_HEX | GPR_DUMP_ASCII));
+  }
+}
+
+char *grpc_op_string(const grpc_op *op) {
+  char *tmp;
+  char *out;
+
+  gpr_strvec b;
+  gpr_strvec_init(&b);
+
+  switch (op->op) {
+    case GRPC_OP_SEND_INITIAL_METADATA:
+      gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA"));
+      add_metadata(&b, op->data.send_initial_metadata.metadata,
+                   op->data.send_initial_metadata.count);
+      break;
+    case GRPC_OP_SEND_MESSAGE:
+      gpr_asprintf(&tmp, "SEND_MESSAGE ptr=%p", op->data.send_message);
+      gpr_strvec_add(&b, tmp);
+      break;
+    case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+      gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
+      break;
+    case GRPC_OP_SEND_STATUS_FROM_SERVER:
+      gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=%s",
+                   op->data.send_status_from_server.status,
+                   op->data.send_status_from_server.status_details);
+      gpr_strvec_add(&b, tmp);
+      add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
+                   op->data.send_status_from_server.trailing_metadata_count);
+      break;
+    case GRPC_OP_RECV_INITIAL_METADATA:
+      gpr_asprintf(&tmp, "RECV_INITIAL_METADATA ptr=%p",
+                   op->data.recv_initial_metadata);
+      gpr_strvec_add(&b, tmp);
+      break;
+    case GRPC_OP_RECV_MESSAGE:
+      gpr_asprintf(&tmp, "RECV_MESSAGE ptr=%p", op->data.recv_message);
+      gpr_strvec_add(&b, tmp);
+      break;
+    case GRPC_OP_RECV_STATUS_ON_CLIENT:
+      gpr_asprintf(&tmp,
+                   "RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
+                   op->data.recv_status_on_client.trailing_metadata,
+                   op->data.recv_status_on_client.status,
+                   op->data.recv_status_on_client.status_details);
+      gpr_strvec_add(&b, tmp);
+      break;
+    case GRPC_OP_RECV_CLOSE_ON_SERVER:
+      gpr_asprintf(&tmp, "RECV_CLOSE_ON_SERVER cancelled=%p",
+                   op->data.recv_close_on_server.cancelled);
+      gpr_strvec_add(&b, tmp);
+  }
+  out = gpr_strvec_flatten(&b, NULL);
+  gpr_strvec_destroy(&b);
+
+  return out;
+}
+
+void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
+                         grpc_call *call, const grpc_op *ops, size_t nops,
+                         void *tag) {
+  char *tmp;
+  size_t i;
+  for (i = 0; i < nops; i++) {
+    tmp = grpc_op_string(&ops[i]);
+    gpr_log(file, line, severity, "ops[%d]: %s", i, tmp);
+    gpr_free(tmp);
+  }
+}
diff --git a/src/core/lib/surface/call_test_only.h b/src/core/lib/surface/call_test_only.h
new file mode 100644
index 0000000..4708899
--- /dev/null
+++ b/src/core/lib/surface/call_test_only.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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_SURFACE_CALL_TEST_ONLY_H
+#define GRPC_CORE_LIB_SURFACE_CALL_TEST_ONLY_H
+
+#include <grpc/grpc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Return the compression algorithm from \a call.
+ *
+ * \warning This function should \b only be used in test code. */
+grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
+    grpc_call *call);
+
+/** Return the message flags from \a call.
+ *
+ * \warning This function should \b only be used in test code. */
+uint32_t grpc_call_test_only_get_message_flags(grpc_call *call);
+
+/** Returns a bitset for the encodings (compression algorithms) supported by \a
+ * call's peer.
+ *
+ * To be indexed by grpc_compression_algorithm enum values. */
+uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_SURFACE_CALL_TEST_ONLY_H */
diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c
new file mode 100644
index 0000000..b6b760b
--- /dev/null
+++ b/src/core/lib/surface/channel.c
@@ -0,0 +1,326 @@
+/*
+ *
+ * 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/surface/channel.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/surface/init.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+/** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
+ *  Avoids needing to take a metadata context lock for sending status
+ *  if the status code is <= NUM_CACHED_STATUS_ELEMS.
+ *  Sized to allow the most commonly used codes to fit in
+ *  (OK, Cancelled, Unknown). */
+#define NUM_CACHED_STATUS_ELEMS 3
+
+typedef struct registered_call {
+  grpc_mdelem *path;
+  grpc_mdelem *authority;
+  struct registered_call *next;
+} registered_call;
+
+struct grpc_channel {
+  int is_client;
+  uint32_t max_message_length;
+  grpc_mdelem *default_authority;
+
+  gpr_mu registered_call_mu;
+  registered_call *registered_calls;
+  char *target;
+};
+
+#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
+#define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \
+  (((grpc_channel *)(channel_stack)) - 1)
+#define CHANNEL_FROM_TOP_ELEM(top_elem) \
+  CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
+
+/* the protobuf library will (by default) start warning at 100megs */
+#define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
+
+static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, bool success);
+
+grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
+                                  const grpc_channel_args *input_args,
+                                  grpc_channel_stack_type channel_stack_type,
+                                  grpc_transport *optional_transport) {
+  bool is_client = grpc_channel_stack_type_is_client(channel_stack_type);
+
+  grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create();
+  grpc_channel_stack_builder_set_channel_arguments(builder, input_args);
+  grpc_channel_stack_builder_set_target(builder, target);
+  grpc_channel_stack_builder_set_transport(builder, optional_transport);
+  grpc_channel *channel;
+  grpc_channel_args *args;
+  if (!grpc_channel_init_create_stack(exec_ctx, builder, channel_stack_type)) {
+    grpc_channel_stack_builder_destroy(builder);
+    return NULL;
+  } else {
+    args = grpc_channel_args_copy(
+        grpc_channel_stack_builder_get_channel_arguments(builder));
+    channel = grpc_channel_stack_builder_finish(
+        exec_ctx, builder, sizeof(grpc_channel), 1, destroy_channel, NULL);
+  }
+
+  memset(channel, 0, sizeof(*channel));
+  channel->target = gpr_strdup(target);
+  channel->is_client = is_client;
+  gpr_mu_init(&channel->registered_call_mu);
+  channel->registered_calls = NULL;
+
+  channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH;
+  if (args) {
+    for (size_t i = 0; i < args->num_args; i++) {
+      if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) {
+        if (args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
+                  GRPC_ARG_MAX_MESSAGE_LENGTH);
+        } else if (args->args[i].value.integer < 0) {
+          gpr_log(GPR_ERROR, "%s ignored: it must be >= 0",
+                  GRPC_ARG_MAX_MESSAGE_LENGTH);
+        } else {
+          channel->max_message_length = (uint32_t)args->args[i].value.integer;
+        }
+      } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
+        if (args->args[i].type != GRPC_ARG_STRING) {
+          gpr_log(GPR_ERROR, "%s ignored: it must be a string",
+                  GRPC_ARG_DEFAULT_AUTHORITY);
+        } else {
+          if (channel->default_authority) {
+            /* setting this takes precedence over anything else */
+            GRPC_MDELEM_UNREF(channel->default_authority);
+          }
+          channel->default_authority = grpc_mdelem_from_strings(
+              ":authority", args->args[i].value.string);
+        }
+      } else if (0 ==
+                 strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
+        if (args->args[i].type != GRPC_ARG_STRING) {
+          gpr_log(GPR_ERROR, "%s ignored: it must be a string",
+                  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
+        } else {
+          if (channel->default_authority) {
+            /* other ways of setting this (notably ssl) take precedence */
+            gpr_log(GPR_ERROR,
+                    "%s ignored: default host already set some other way",
+                    GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
+          } else {
+            channel->default_authority = grpc_mdelem_from_strings(
+                ":authority", args->args[i].value.string);
+          }
+        }
+      }
+    }
+    grpc_channel_args_destroy(args);
+  }
+
+  return channel;
+}
+
+char *grpc_channel_get_target(grpc_channel *channel) {
+  GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
+  return gpr_strdup(channel->target);
+}
+
+static grpc_call *grpc_channel_create_call_internal(
+    grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
+    grpc_completion_queue *cq, grpc_mdelem *path_mdelem,
+    grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
+  grpc_mdelem *send_metadata[2];
+  size_t num_metadata = 0;
+
+  GPR_ASSERT(channel->is_client);
+
+  send_metadata[num_metadata++] = path_mdelem;
+  if (authority_mdelem != NULL) {
+    send_metadata[num_metadata++] = authority_mdelem;
+  } else if (channel->default_authority != NULL) {
+    send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
+  }
+
+  return grpc_call_create(channel, parent_call, propagation_mask, cq, NULL,
+                          send_metadata, num_metadata, deadline);
+}
+
+grpc_call *grpc_channel_create_call(grpc_channel *channel,
+                                    grpc_call *parent_call,
+                                    uint32_t propagation_mask,
+                                    grpc_completion_queue *cq,
+                                    const char *method, const char *host,
+                                    gpr_timespec deadline, void *reserved) {
+  GRPC_API_TRACE(
+      "grpc_channel_create_call("
+      "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
+      "host=%s, "
+      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
+      "reserved=%p)",
+      10, (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
+           (long long)deadline.tv_sec, (int)deadline.tv_nsec,
+           (int)deadline.clock_type, reserved));
+  GPR_ASSERT(!reserved);
+  return grpc_channel_create_call_internal(
+      channel, parent_call, propagation_mask, cq,
+      grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
+                                        grpc_mdstr_from_string(method)),
+      host ? grpc_mdelem_from_metadata_strings(GRPC_MDSTR_AUTHORITY,
+                                               grpc_mdstr_from_string(host))
+           : NULL,
+      deadline);
+}
+
+void *grpc_channel_register_call(grpc_channel *channel, const char *method,
+                                 const char *host, void *reserved) {
+  registered_call *rc = gpr_malloc(sizeof(registered_call));
+  GRPC_API_TRACE(
+      "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
+      4, (channel, method, host, reserved));
+  GPR_ASSERT(!reserved);
+  rc->path = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
+                                               grpc_mdstr_from_string(method));
+  rc->authority = host ? grpc_mdelem_from_metadata_strings(
+                             GRPC_MDSTR_AUTHORITY, grpc_mdstr_from_string(host))
+                       : NULL;
+  gpr_mu_lock(&channel->registered_call_mu);
+  rc->next = channel->registered_calls;
+  channel->registered_calls = rc;
+  gpr_mu_unlock(&channel->registered_call_mu);
+  return rc;
+}
+
+grpc_call *grpc_channel_create_registered_call(
+    grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
+    grpc_completion_queue *completion_queue, void *registered_call_handle,
+    gpr_timespec deadline, void *reserved) {
+  registered_call *rc = registered_call_handle;
+  GRPC_API_TRACE(
+      "grpc_channel_create_registered_call("
+      "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
+      "registered_call_handle=%p, "
+      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
+      "reserved=%p)",
+      9, (channel, parent_call, (unsigned)propagation_mask, completion_queue,
+          registered_call_handle, (long long)deadline.tv_sec,
+          (int)deadline.tv_nsec, (int)deadline.clock_type, reserved));
+  GPR_ASSERT(!reserved);
+  return grpc_channel_create_call_internal(
+      channel, parent_call, propagation_mask, completion_queue,
+      GRPC_MDELEM_REF(rc->path),
+      rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline);
+}
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+#define REF_REASON reason
+#define REF_ARG , const char *reason
+#else
+#define REF_REASON ""
+#define REF_ARG
+#endif
+void grpc_channel_internal_ref(grpc_channel *c REF_ARG) {
+  GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON);
+}
+
+void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel *c REF_ARG) {
+  GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON);
+}
+
+static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg,
+                            bool iomgr_success) {
+  grpc_channel *channel = arg;
+  grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel));
+  while (channel->registered_calls) {
+    registered_call *rc = channel->registered_calls;
+    channel->registered_calls = rc->next;
+    GRPC_MDELEM_UNREF(rc->path);
+    if (rc->authority) {
+      GRPC_MDELEM_UNREF(rc->authority);
+    }
+    gpr_free(rc);
+  }
+  if (channel->default_authority != NULL) {
+    GRPC_MDELEM_UNREF(channel->default_authority);
+  }
+  gpr_mu_destroy(&channel->registered_call_mu);
+  gpr_free(channel->target);
+  gpr_free(channel);
+}
+
+void grpc_channel_destroy(grpc_channel *channel) {
+  grpc_transport_op op;
+  grpc_channel_element *elem;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
+  memset(&op, 0, sizeof(op));
+  op.disconnect = 1;
+  elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
+  elem->filter->start_transport_op(&exec_ctx, elem, &op);
+
+  GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel");
+
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) {
+  return CHANNEL_STACK_FROM_CHANNEL(channel);
+}
+
+grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
+  char tmp[GPR_LTOA_MIN_BUFSIZE];
+  switch (i) {
+    case 0:
+      return GRPC_MDELEM_GRPC_STATUS_0;
+    case 1:
+      return GRPC_MDELEM_GRPC_STATUS_1;
+    case 2:
+      return GRPC_MDELEM_GRPC_STATUS_2;
+  }
+  gpr_ltoa(i, tmp);
+  return grpc_mdelem_from_metadata_strings(GRPC_MDSTR_GRPC_STATUS,
+                                           grpc_mdstr_from_string(tmp));
+}
+
+uint32_t grpc_channel_get_max_message_length(grpc_channel *channel) {
+  return channel->max_message_length;
+}
diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h
new file mode 100644
index 0000000..22dae93
--- /dev/null
+++ b/src/core/lib/surface/channel.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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_SURFACE_CHANNEL_H
+#define GRPC_CORE_LIB_SURFACE_CHANNEL_H
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/surface/channel_stack_type.h"
+
+grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
+                                  const grpc_channel_args *args,
+                                  grpc_channel_stack_type channel_stack_type,
+                                  grpc_transport *optional_transport);
+
+/** Get a (borrowed) pointer to this channels underlying channel stack */
+grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel);
+
+/** Get a grpc_mdelem of grpc-status: X where X is the numeric value of
+    status_code.
+
+    The returned elem is owned by the caller. */
+grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel,
+                                                 int status_code);
+uint32_t grpc_channel_get_max_message_length(grpc_channel *channel);
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+void grpc_channel_internal_ref(grpc_channel *channel, const char *reason);
+void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
+                                 const char *reason);
+#define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \
+  grpc_channel_internal_ref(channel, reason)
+#define GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, reason) \
+  grpc_channel_internal_unref(exec_ctx, channel, reason)
+#else
+void grpc_channel_internal_ref(grpc_channel *channel);
+void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel *channel);
+#define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \
+  grpc_channel_internal_ref(channel)
+#define GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, reason) \
+  grpc_channel_internal_unref(exec_ctx, channel)
+#endif
+
+#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_H */
diff --git a/src/core/lib/surface/channel_init.c b/src/core/lib/surface/channel_init.c
new file mode 100644
index 0000000..0627b34
--- /dev/null
+++ b/src/core/lib/surface/channel_init.c
@@ -0,0 +1,140 @@
+/*
+ *
+ * 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/surface/channel_init.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/useful.h>
+
+typedef struct stage_slot {
+  grpc_channel_init_stage fn;
+  void *arg;
+  int priority;
+  size_t insertion_order;
+} stage_slot;
+
+typedef struct stage_slots {
+  stage_slot *slots;
+  size_t num_slots;
+  size_t cap_slots;
+} stage_slots;
+
+static stage_slots g_slots[GRPC_NUM_CHANNEL_STACK_TYPES];
+static bool g_finalized;
+
+void grpc_channel_init_init(void) {
+  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
+    g_slots[i].slots = NULL;
+    g_slots[i].num_slots = 0;
+    g_slots[i].cap_slots = 0;
+  }
+  g_finalized = false;
+}
+
+void grpc_channel_init_register_stage(grpc_channel_stack_type type,
+                                      int priority,
+                                      grpc_channel_init_stage stage,
+                                      void *stage_arg) {
+  GPR_ASSERT(!g_finalized);
+  if (g_slots[type].cap_slots == g_slots[type].num_slots) {
+    g_slots[type].cap_slots = GPR_MAX(8, 3 * g_slots[type].cap_slots / 2);
+    g_slots[type].slots =
+        gpr_realloc(g_slots[type].slots,
+                    g_slots[type].cap_slots * sizeof(*g_slots[type].slots));
+  }
+  stage_slot *s = &g_slots[type].slots[g_slots[type].num_slots++];
+  s->insertion_order = g_slots[type].num_slots;
+  s->priority = priority;
+  s->fn = stage;
+  s->arg = stage_arg;
+}
+
+static int compare_slots(const void *a, const void *b) {
+  const stage_slot *sa = a;
+  const stage_slot *sb = b;
+
+  int c = GPR_ICMP(sa->priority, sb->priority);
+  if (c != 0) return c;
+  return GPR_ICMP(sa->insertion_order, sb->insertion_order);
+}
+
+void grpc_channel_init_finalize(void) {
+  GPR_ASSERT(!g_finalized);
+  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
+    qsort(g_slots[i].slots, g_slots[i].num_slots, sizeof(*g_slots[i].slots),
+          compare_slots);
+  }
+  g_finalized = true;
+}
+
+void grpc_channel_init_shutdown(void) {
+  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
+    gpr_free(g_slots[i].slots);
+    g_slots[i].slots = (void *)(uintptr_t)0xdeadbeef;
+  }
+}
+
+static const char *name_for_type(grpc_channel_stack_type type) {
+  switch (type) {
+    case GRPC_CLIENT_CHANNEL:
+      return "CLIENT_CHANNEL";
+    case GRPC_CLIENT_SUBCHANNEL:
+      return "CLIENT_SUBCHANNEL";
+    case GRPC_SERVER_CHANNEL:
+      return "SERVER_CHANNEL";
+    case GRPC_CLIENT_LAME_CHANNEL:
+      return "CLIENT_LAME_CHANNEL";
+    case GRPC_CLIENT_DIRECT_CHANNEL:
+      return "CLIENT_DIRECT_CHANNEL";
+    case GRPC_NUM_CHANNEL_STACK_TYPES:
+      break;
+  }
+  GPR_UNREACHABLE_CODE(return "UNKNOWN");
+}
+
+bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx,
+                                    grpc_channel_stack_builder *builder,
+                                    grpc_channel_stack_type type) {
+  GPR_ASSERT(g_finalized);
+
+  grpc_channel_stack_builder_set_name(builder, name_for_type(type));
+
+  for (size_t i = 0; i < g_slots[type].num_slots; i++) {
+    const stage_slot *slot = &g_slots[type].slots[i];
+    if (!slot->fn(builder, slot->arg)) {
+      return false;
+    }
+  }
+
+  return true;
+}
diff --git a/src/core/lib/surface/channel_init.h b/src/core/lib/surface/channel_init.h
new file mode 100644
index 0000000..3a18a61
--- /dev/null
+++ b/src/core/lib/surface/channel_init.h
@@ -0,0 +1,87 @@
+/*
+ *
+ * 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_SURFACE_CHANNEL_INIT_H
+#define GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H
+
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/surface/channel_stack_type.h"
+#include "src/core/lib/transport/transport.h"
+
+#define GRPC_CHANNEL_INIT_BUILTIN_PRIORITY 10000
+
+/// This module provides a way for plugins (and the grpc core library itself)
+/// to register mutators for channel stacks.
+/// It also provides a universal entry path to run those mutators to build
+/// a channel stack for various subsystems.
+
+/// One stage of mutation: call functions against \a builder to influence the
+/// finally constructed channel stack
+typedef bool (*grpc_channel_init_stage)(grpc_channel_stack_builder *builder,
+                                        void *arg);
+
+/// Global initialization of the system
+void grpc_channel_init_init(void);
+
+/// Register one stage of mutators.
+/// Stages are run in priority order (lowest to highest), and then in
+/// registration order (in the case of a tie).
+/// Stages are registered against one of the pre-determined channel stack
+/// types.
+void grpc_channel_init_register_stage(grpc_channel_stack_type type,
+                                      int priority,
+                                      grpc_channel_init_stage stage_fn,
+                                      void *stage_arg);
+
+/// Finalize registration. No more calls to grpc_channel_init_register_stage are
+/// allowed.
+void grpc_channel_init_finalize(void);
+/// Shutdown the channel init system
+void grpc_channel_init_shutdown(void);
+
+/// Construct a channel stack of some sort: see channel_stack.h for details
+/// \a type is the type of channel stack to create
+/// \a prefix_bytes is the number of bytes before the channel stack to allocate
+/// \a args are configuration arguments for the channel stack
+/// \a initial_refs is the initial refcount to give the channel stack
+/// \a destroy and \a destroy_arg specify how to destroy the channel stack
+///    if destroy_arg is NULL, the returned value from this function will be
+///    substituted
+/// \a optional_transport is either NULL or a constructed transport object
+/// Returns a pointer to the base of the memory allocated (the actual channel
+/// stack object will be prefix_bytes past that pointer)
+bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx,
+                                    grpc_channel_stack_builder *builder,
+                                    grpc_channel_stack_type type);
+
+#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H */
diff --git a/src/core/lib/surface/channel_ping.c b/src/core/lib/surface/channel_ping.c
new file mode 100644
index 0000000..5a50698
--- /dev/null
+++ b/src/core/lib/surface/channel_ping.c
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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/surface/channel.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/completion_queue.h"
+
+typedef struct {
+  grpc_closure closure;
+  void *tag;
+  grpc_completion_queue *cq;
+  grpc_cq_completion completion_storage;
+} ping_result;
+
+static void ping_destroy(grpc_exec_ctx *exec_ctx, void *arg,
+                         grpc_cq_completion *storage) {
+  gpr_free(arg);
+}
+
+static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  ping_result *pr = arg;
+  grpc_cq_end_op(exec_ctx, pr->cq, pr->tag, success, ping_destroy, pr,
+                 &pr->completion_storage);
+}
+
+void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq,
+                       void *tag, void *reserved) {
+  grpc_transport_op op;
+  ping_result *pr = gpr_malloc(sizeof(*pr));
+  grpc_channel_element *top_elem =
+      grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GPR_ASSERT(reserved == NULL);
+  memset(&op, 0, sizeof(op));
+  pr->tag = tag;
+  pr->cq = cq;
+  grpc_closure_init(&pr->closure, ping_done, pr);
+  op.send_ping = &pr->closure;
+  op.bind_pollset = grpc_cq_pollset(cq);
+  grpc_cq_begin_op(cq, tag);
+  top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
diff --git a/src/core/lib/surface/channel_stack_type.c b/src/core/lib/surface/channel_stack_type.c
new file mode 100644
index 0000000..c35d603
--- /dev/null
+++ b/src/core/lib/surface/channel_stack_type.c
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/surface/channel_stack_type.h"
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+
+bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type) {
+  switch (type) {
+    case GRPC_CLIENT_CHANNEL:
+      return true;
+    case GRPC_CLIENT_SUBCHANNEL:
+      return true;
+    case GRPC_CLIENT_LAME_CHANNEL:
+      return true;
+    case GRPC_CLIENT_DIRECT_CHANNEL:
+      return true;
+    case GRPC_SERVER_CHANNEL:
+      return false;
+    case GRPC_NUM_CHANNEL_STACK_TYPES:
+      break;
+  }
+  GPR_UNREACHABLE_CODE(return true;);
+}
diff --git a/src/core/lib/surface/channel_stack_type.h b/src/core/lib/surface/channel_stack_type.h
new file mode 100644
index 0000000..4eea4f1
--- /dev/null
+++ b/src/core/lib/surface/channel_stack_type.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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_SURFACE_CHANNEL_STACK_TYPE_H
+#define GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H
+
+#include <stdbool.h>
+
+typedef enum {
+  // normal top-half client channel with load-balancing, connection management
+  GRPC_CLIENT_CHANNEL,
+  // bottom-half of a client channel: everything that happens post-load
+  // balancing (bound to a specific transport)
+  GRPC_CLIENT_SUBCHANNEL,
+  // a permanently broken client channel
+  GRPC_CLIENT_LAME_CHANNEL,
+  // a directly connected client channel (without load-balancing, directly talks
+  // to a transport)
+  GRPC_CLIENT_DIRECT_CHANNEL,
+  // server side channel
+  GRPC_SERVER_CHANNEL,
+  // must be last
+  GRPC_NUM_CHANNEL_STACK_TYPES
+} grpc_channel_stack_type;
+
+bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type);
+
+#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H */
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
new file mode 100644
index 0000000..5ec8808
--- /dev/null
+++ b/src/core/lib/surface/completion_queue.c
@@ -0,0 +1,512 @@
+/*
+ *
+ * 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/surface/completion_queue.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/event_string.h"
+#include "src/core/lib/surface/surface_trace.h"
+
+typedef struct {
+  grpc_pollset_worker **worker;
+  void *tag;
+} plucker;
+
+/* Completion queue structure */
+struct grpc_completion_queue {
+  /** owned by pollset */
+  gpr_mu *mu;
+  /** completed events */
+  grpc_cq_completion completed_head;
+  grpc_cq_completion *completed_tail;
+  /** Number of pending events (+1 if we're not shutdown) */
+  gpr_refcount pending_events;
+  /** Once owning_refs drops to zero, we will destroy the cq */
+  gpr_refcount owning_refs;
+  /** 0 initially, 1 once we've begun shutting down */
+  int shutdown;
+  int shutdown_called;
+  int is_server_cq;
+  int num_pluckers;
+  plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS];
+  grpc_closure pollset_shutdown_done;
+
+#ifndef NDEBUG
+  void **outstanding_tags;
+  size_t outstanding_tag_count;
+  size_t outstanding_tag_capacity;
+#endif
+
+  grpc_completion_queue *next_free;
+};
+
+#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
+
+static gpr_mu g_freelist_mu;
+static grpc_completion_queue *g_freelist;
+
+static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
+                                     bool success);
+
+void grpc_cq_global_init(void) { gpr_mu_init(&g_freelist_mu); }
+
+void grpc_cq_global_shutdown(void) {
+  gpr_mu_destroy(&g_freelist_mu);
+  while (g_freelist) {
+    grpc_completion_queue *next = g_freelist->next_free;
+    grpc_pollset_destroy(POLLSET_FROM_CQ(g_freelist));
+#ifndef NDEBUG
+    gpr_free(g_freelist->outstanding_tags);
+#endif
+    gpr_free(g_freelist);
+    g_freelist = next;
+  }
+}
+
+struct grpc_cq_alarm {
+  grpc_timer alarm;
+  grpc_cq_completion completion;
+  /** completion queue where events about this alarm will be posted */
+  grpc_completion_queue *cq;
+  /** user supplied tag */
+  void *tag;
+};
+
+grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
+  grpc_completion_queue *cc;
+  GPR_ASSERT(!reserved);
+
+  GPR_TIMER_BEGIN("grpc_completion_queue_create", 0);
+
+  GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved));
+
+  gpr_mu_lock(&g_freelist_mu);
+  if (g_freelist == NULL) {
+    gpr_mu_unlock(&g_freelist_mu);
+
+    cc = gpr_malloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
+    grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
+#ifndef NDEBUG
+    cc->outstanding_tags = NULL;
+    cc->outstanding_tag_capacity = 0;
+#endif
+  } else {
+    cc = g_freelist;
+    g_freelist = g_freelist->next_free;
+    gpr_mu_unlock(&g_freelist_mu);
+    /* pollset already initialized */
+  }
+
+  /* Initial ref is dropped by grpc_completion_queue_shutdown */
+  gpr_ref_init(&cc->pending_events, 1);
+  /* One for destroy(), one for pollset_shutdown */
+  gpr_ref_init(&cc->owning_refs, 2);
+  cc->completed_tail = &cc->completed_head;
+  cc->completed_head.next = (uintptr_t)cc->completed_tail;
+  cc->shutdown = 0;
+  cc->shutdown_called = 0;
+  cc->is_server_cq = 0;
+  cc->num_pluckers = 0;
+#ifndef NDEBUG
+  cc->outstanding_tag_count = 0;
+#endif
+  grpc_closure_init(&cc->pollset_shutdown_done, on_pollset_shutdown_done, cc);
+
+  GPR_TIMER_END("grpc_completion_queue_create", 0);
+
+  return cc;
+}
+
+#ifdef GRPC_CQ_REF_COUNT_DEBUG
+void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
+                          const char *file, int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p   ref %d -> %d %s", cc,
+          (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1, reason);
+#else
+void grpc_cq_internal_ref(grpc_completion_queue *cc) {
+#endif
+  gpr_ref(&cc->owning_refs);
+}
+
+static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *arg,
+                                     bool success) {
+  grpc_completion_queue *cc = arg;
+  GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy");
+}
+
+#ifdef GRPC_CQ_REF_COUNT_DEBUG
+void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
+                            const char *file, int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc,
+          (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason);
+#else
+void grpc_cq_internal_unref(grpc_completion_queue *cc) {
+#endif
+  if (gpr_unref(&cc->owning_refs)) {
+    GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head);
+    grpc_pollset_reset(POLLSET_FROM_CQ(cc));
+    gpr_mu_lock(&g_freelist_mu);
+    cc->next_free = g_freelist;
+    g_freelist = cc;
+    gpr_mu_unlock(&g_freelist_mu);
+  }
+}
+
+void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) {
+#ifndef NDEBUG
+  gpr_mu_lock(cc->mu);
+  GPR_ASSERT(!cc->shutdown_called);
+  if (cc->outstanding_tag_count == cc->outstanding_tag_capacity) {
+    cc->outstanding_tag_capacity = GPR_MAX(4, 2 * cc->outstanding_tag_capacity);
+    cc->outstanding_tags =
+        gpr_realloc(cc->outstanding_tags, sizeof(*cc->outstanding_tags) *
+                                              cc->outstanding_tag_capacity);
+  }
+  cc->outstanding_tags[cc->outstanding_tag_count++] = tag;
+  gpr_mu_unlock(cc->mu);
+#endif
+  gpr_ref(&cc->pending_events);
+}
+
+/* Signal the end of an operation - if this is the last waiting-to-be-queued
+   event, then enter shutdown mode */
+/* Queue a GRPC_OP_COMPLETED operation */
+void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
+                    void *tag, int success,
+                    void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
+                                 grpc_cq_completion *storage),
+                    void *done_arg, grpc_cq_completion *storage) {
+  int shutdown;
+  int i;
+  grpc_pollset_worker *pluck_worker;
+#ifndef NDEBUG
+  int found = 0;
+#endif
+
+  GPR_TIMER_BEGIN("grpc_cq_end_op", 0);
+
+  storage->tag = tag;
+  storage->done = done;
+  storage->done_arg = done_arg;
+  storage->next =
+      ((uintptr_t)&cc->completed_head) | ((uintptr_t)(success != 0));
+
+  gpr_mu_lock(cc->mu);
+#ifndef NDEBUG
+  for (i = 0; i < (int)cc->outstanding_tag_count; i++) {
+    if (cc->outstanding_tags[i] == tag) {
+      cc->outstanding_tag_count--;
+      GPR_SWAP(void *, cc->outstanding_tags[i],
+               cc->outstanding_tags[cc->outstanding_tag_count]);
+      found = 1;
+      break;
+    }
+  }
+  GPR_ASSERT(found);
+#endif
+  shutdown = gpr_unref(&cc->pending_events);
+  if (!shutdown) {
+    cc->completed_tail->next =
+        ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
+    cc->completed_tail = storage;
+    pluck_worker = NULL;
+    for (i = 0; i < cc->num_pluckers; i++) {
+      if (cc->pluckers[i].tag == tag) {
+        pluck_worker = *cc->pluckers[i].worker;
+        break;
+      }
+    }
+    grpc_pollset_kick(POLLSET_FROM_CQ(cc), pluck_worker);
+    gpr_mu_unlock(cc->mu);
+  } else {
+    cc->completed_tail->next =
+        ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
+    cc->completed_tail = storage;
+    GPR_ASSERT(!cc->shutdown);
+    GPR_ASSERT(cc->shutdown_called);
+    cc->shutdown = 1;
+    grpc_pollset_shutdown(exec_ctx, POLLSET_FROM_CQ(cc),
+                          &cc->pollset_shutdown_done);
+    gpr_mu_unlock(cc->mu);
+  }
+
+  GPR_TIMER_END("grpc_cq_end_op", 0);
+}
+
+grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
+                                      gpr_timespec deadline, void *reserved) {
+  grpc_event ret;
+  grpc_pollset_worker *worker = NULL;
+  int first_loop = 1;
+  gpr_timespec now;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GPR_TIMER_BEGIN("grpc_completion_queue_next", 0);
+
+  GRPC_API_TRACE(
+      "grpc_completion_queue_next("
+      "cc=%p, "
+      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
+      "reserved=%p)",
+      5, (cc, (long long)deadline.tv_sec, (int)deadline.tv_nsec,
+          (int)deadline.clock_type, reserved));
+  GPR_ASSERT(!reserved);
+
+  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
+
+  GRPC_CQ_INTERNAL_REF(cc, "next");
+  gpr_mu_lock(cc->mu);
+  for (;;) {
+    if (cc->completed_tail != &cc->completed_head) {
+      grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next;
+      cc->completed_head.next = c->next & ~(uintptr_t)1;
+      if (c == cc->completed_tail) {
+        cc->completed_tail = &cc->completed_head;
+      }
+      gpr_mu_unlock(cc->mu);
+      ret.type = GRPC_OP_COMPLETE;
+      ret.success = c->next & 1u;
+      ret.tag = c->tag;
+      c->done(&exec_ctx, c->done_arg, c);
+      break;
+    }
+    if (cc->shutdown) {
+      gpr_mu_unlock(cc->mu);
+      memset(&ret, 0, sizeof(ret));
+      ret.type = GRPC_QUEUE_SHUTDOWN;
+      break;
+    }
+    now = gpr_now(GPR_CLOCK_MONOTONIC);
+    if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
+      gpr_mu_unlock(cc->mu);
+      memset(&ret, 0, sizeof(ret));
+      ret.type = GRPC_QUEUE_TIMEOUT;
+      break;
+    }
+    first_loop = 0;
+    /* Check alarms - these are a global resource so we just ping
+       each time through on every pollset.
+       May update deadline to ensure timely wakeups.
+       TODO(ctiller): can this work be localized? */
+    gpr_timespec iteration_deadline = deadline;
+    if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
+      GPR_TIMER_MARK("alarm_triggered", 0);
+      gpr_mu_unlock(cc->mu);
+      grpc_exec_ctx_flush(&exec_ctx);
+      gpr_mu_lock(cc->mu);
+      continue;
+    } else {
+      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
+                        iteration_deadline);
+    }
+  }
+  GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
+  GRPC_CQ_INTERNAL_UNREF(cc, "next");
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  GPR_TIMER_END("grpc_completion_queue_next", 0);
+
+  return ret;
+}
+
+static int add_plucker(grpc_completion_queue *cc, void *tag,
+                       grpc_pollset_worker **worker) {
+  if (cc->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) {
+    return 0;
+  }
+  cc->pluckers[cc->num_pluckers].tag = tag;
+  cc->pluckers[cc->num_pluckers].worker = worker;
+  cc->num_pluckers++;
+  return 1;
+}
+
+static void del_plucker(grpc_completion_queue *cc, void *tag,
+                        grpc_pollset_worker **worker) {
+  int i;
+  for (i = 0; i < cc->num_pluckers; i++) {
+    if (cc->pluckers[i].tag == tag && cc->pluckers[i].worker == worker) {
+      cc->num_pluckers--;
+      GPR_SWAP(plucker, cc->pluckers[i], cc->pluckers[cc->num_pluckers]);
+      return;
+    }
+  }
+  GPR_UNREACHABLE_CODE(return );
+}
+
+grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
+                                       gpr_timespec deadline, void *reserved) {
+  grpc_event ret;
+  grpc_cq_completion *c;
+  grpc_cq_completion *prev;
+  grpc_pollset_worker *worker = NULL;
+  gpr_timespec now;
+  int first_loop = 1;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GPR_TIMER_BEGIN("grpc_completion_queue_pluck", 0);
+
+  GRPC_API_TRACE(
+      "grpc_completion_queue_pluck("
+      "cc=%p, tag=%p, "
+      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
+      "reserved=%p)",
+      6, (cc, tag, (long long)deadline.tv_sec, (int)deadline.tv_nsec,
+          (int)deadline.clock_type, reserved));
+  GPR_ASSERT(!reserved);
+
+  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
+
+  GRPC_CQ_INTERNAL_REF(cc, "pluck");
+  gpr_mu_lock(cc->mu);
+  for (;;) {
+    prev = &cc->completed_head;
+    while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) !=
+           &cc->completed_head) {
+      if (c->tag == tag) {
+        prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1);
+        if (c == cc->completed_tail) {
+          cc->completed_tail = prev;
+        }
+        gpr_mu_unlock(cc->mu);
+        ret.type = GRPC_OP_COMPLETE;
+        ret.success = c->next & 1u;
+        ret.tag = c->tag;
+        c->done(&exec_ctx, c->done_arg, c);
+        goto done;
+      }
+      prev = c;
+    }
+    if (cc->shutdown) {
+      gpr_mu_unlock(cc->mu);
+      memset(&ret, 0, sizeof(ret));
+      ret.type = GRPC_QUEUE_SHUTDOWN;
+      break;
+    }
+    if (!add_plucker(cc, tag, &worker)) {
+      gpr_log(GPR_DEBUG,
+              "Too many outstanding grpc_completion_queue_pluck calls: maximum "
+              "is %d",
+              GRPC_MAX_COMPLETION_QUEUE_PLUCKERS);
+      gpr_mu_unlock(cc->mu);
+      memset(&ret, 0, sizeof(ret));
+      /* TODO(ctiller): should we use a different result here */
+      ret.type = GRPC_QUEUE_TIMEOUT;
+      break;
+    }
+    now = gpr_now(GPR_CLOCK_MONOTONIC);
+    if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
+      del_plucker(cc, tag, &worker);
+      gpr_mu_unlock(cc->mu);
+      memset(&ret, 0, sizeof(ret));
+      ret.type = GRPC_QUEUE_TIMEOUT;
+      break;
+    }
+    first_loop = 0;
+    /* Check alarms - these are a global resource so we just ping
+       each time through on every pollset.
+       May update deadline to ensure timely wakeups.
+       TODO(ctiller): can this work be localized? */
+    gpr_timespec iteration_deadline = deadline;
+    if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
+      GPR_TIMER_MARK("alarm_triggered", 0);
+      gpr_mu_unlock(cc->mu);
+      grpc_exec_ctx_flush(&exec_ctx);
+      gpr_mu_lock(cc->mu);
+    } else {
+      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
+                        iteration_deadline);
+    }
+    del_plucker(cc, tag, &worker);
+  }
+done:
+  GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
+  GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  GPR_TIMER_END("grpc_completion_queue_pluck", 0);
+
+  return ret;
+}
+
+/* Shutdown simply drops a ref that we reserved at creation time; if we drop
+   to zero here, then enter shutdown mode and wake up any waiters */
+void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GPR_TIMER_BEGIN("grpc_completion_queue_shutdown", 0);
+  GRPC_API_TRACE("grpc_completion_queue_shutdown(cc=%p)", 1, (cc));
+  gpr_mu_lock(cc->mu);
+  if (cc->shutdown_called) {
+    gpr_mu_unlock(cc->mu);
+    GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
+    return;
+  }
+  cc->shutdown_called = 1;
+  if (gpr_unref(&cc->pending_events)) {
+    GPR_ASSERT(!cc->shutdown);
+    cc->shutdown = 1;
+    grpc_pollset_shutdown(&exec_ctx, POLLSET_FROM_CQ(cc),
+                          &cc->pollset_shutdown_done);
+  }
+  gpr_mu_unlock(cc->mu);
+  grpc_exec_ctx_finish(&exec_ctx);
+  GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
+}
+
+void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
+  GRPC_API_TRACE("grpc_completion_queue_destroy(cc=%p)", 1, (cc));
+  GPR_TIMER_BEGIN("grpc_completion_queue_destroy", 0);
+  grpc_completion_queue_shutdown(cc);
+  GRPC_CQ_INTERNAL_UNREF(cc, "destroy");
+  GPR_TIMER_END("grpc_completion_queue_destroy", 0);
+}
+
+grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
+  return POLLSET_FROM_CQ(cc);
+}
+
+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
new file mode 100644
index 0000000..eef82cf
--- /dev/null
+++ b/src/core/lib/surface/completion_queue.h
@@ -0,0 +1,91 @@
+/*
+ *
+ * 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_SURFACE_COMPLETION_QUEUE_H
+#define GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H
+
+/* Internal API for completion queues */
+
+#include <grpc/grpc.h>
+#include "src/core/lib/iomgr/pollset.h"
+
+typedef struct grpc_cq_completion {
+  /** user supplied tag */
+  void *tag;
+  /** done callback - called when this queue element is no longer
+      needed by the completion queue */
+  void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
+               struct grpc_cq_completion *c);
+  void *done_arg;
+  /** next pointer; low bit is used to indicate success or not */
+  uintptr_t next;
+} grpc_cq_completion;
+
+#ifdef GRPC_CQ_REF_COUNT_DEBUG
+void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
+                          const char *file, int line);
+void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
+                            const char *file, int line);
+#define GRPC_CQ_INTERNAL_REF(cc, reason) \
+  grpc_cq_internal_ref(cc, reason, __FILE__, __LINE__)
+#define GRPC_CQ_INTERNAL_UNREF(cc, reason) \
+  grpc_cq_internal_unref(cc, reason, __FILE__, __LINE__)
+#else
+void grpc_cq_internal_ref(grpc_completion_queue *cc);
+void grpc_cq_internal_unref(grpc_completion_queue *cc);
+#define GRPC_CQ_INTERNAL_REF(cc, reason) grpc_cq_internal_ref(cc)
+#define GRPC_CQ_INTERNAL_UNREF(cc, reason) grpc_cq_internal_unref(cc)
+#endif
+
+/* Flag that an operation is beginning: the completion channel will not finish
+   shutdown until a corrensponding grpc_cq_end_* call is made.
+   \a tag is currently used only in debug builds. */
+void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag);
+
+/* Queue a GRPC_OP_COMPLETED operation; tag must correspond to the tag passed to
+   grpc_cq_begin_op */
+void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
+                    void *tag, int success,
+                    void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
+                                 grpc_cq_completion *storage),
+                    void *done_arg, grpc_cq_completion *storage);
+
+grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);
+
+void grpc_cq_mark_server_cq(grpc_completion_queue *cc);
+int grpc_cq_is_server_cq(grpc_completion_queue *cc);
+
+void grpc_cq_global_init(void);
+void grpc_cq_global_shutdown(void);
+
+#endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */
diff --git a/src/core/lib/surface/event_string.c b/src/core/lib/surface/event_string.c
new file mode 100644
index 0000000..1abc6eb
--- /dev/null
+++ b/src/core/lib/surface/event_string.c
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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/surface/event_string.h"
+
+#include <stdio.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/support/string_util.h>
+#include "src/core/lib/support/string.h"
+
+static void addhdr(gpr_strvec *buf, grpc_event *ev) {
+  char *tmp;
+  gpr_asprintf(&tmp, "tag:%p", ev->tag);
+  gpr_strvec_add(buf, tmp);
+}
+
+static const char *errstr(int success) { return success ? "OK" : "ERROR"; }
+
+static void adderr(gpr_strvec *buf, int success) {
+  char *tmp;
+  gpr_asprintf(&tmp, " %s", errstr(success));
+  gpr_strvec_add(buf, tmp);
+}
+
+char *grpc_event_string(grpc_event *ev) {
+  char *out;
+  gpr_strvec buf;
+
+  if (ev == NULL) return gpr_strdup("null");
+
+  gpr_strvec_init(&buf);
+
+  switch (ev->type) {
+    case GRPC_QUEUE_TIMEOUT:
+      gpr_strvec_add(&buf, gpr_strdup("QUEUE_TIMEOUT"));
+      break;
+    case GRPC_QUEUE_SHUTDOWN:
+      gpr_strvec_add(&buf, gpr_strdup("QUEUE_SHUTDOWN"));
+      break;
+    case GRPC_OP_COMPLETE:
+      gpr_strvec_add(&buf, gpr_strdup("OP_COMPLETE: "));
+      addhdr(&buf, ev);
+      adderr(&buf, ev->success);
+      break;
+  }
+
+  out = gpr_strvec_flatten(&buf, NULL);
+  gpr_strvec_destroy(&buf);
+  return out;
+}
diff --git a/src/core/lib/surface/event_string.h b/src/core/lib/surface/event_string.h
new file mode 100644
index 0000000..bc14643
--- /dev/null
+++ b/src/core/lib/surface/event_string.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_SURFACE_EVENT_STRING_H
+#define GRPC_CORE_LIB_SURFACE_EVENT_STRING_H
+
+#include <grpc/grpc.h>
+
+/* Returns a string describing an event. Must be later freed with gpr_free() */
+char *grpc_event_string(grpc_event *ev);
+
+#endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
new file mode 100644
index 0000000..03f379a
--- /dev/null
+++ b/src/core/lib/surface/init.c
@@ -0,0 +1,216 @@
+/*
+ *
+ * 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>
+
+#include <limits.h>
+#include <memory.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/init.h"
+#include "src/core/lib/surface/lame_client.h"
+#include "src/core/lib/surface/server.h"
+#include "src/core/lib/surface/surface_trace.h"
+#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/transport_impl.h"
+
+/* (generated) built in registry of plugins */
+extern void grpc_register_built_in_plugins(void);
+
+#define MAX_PLUGINS 128
+
+static gpr_once g_basic_init = GPR_ONCE_INIT;
+static gpr_mu g_init_mu;
+static int g_initializations;
+
+static void do_basic_init(void) {
+  gpr_log_verbosity_init();
+  gpr_mu_init(&g_init_mu);
+  grpc_register_built_in_plugins();
+  g_initializations = 0;
+}
+
+static bool append_filter(grpc_channel_stack_builder *builder, void *arg) {
+  return grpc_channel_stack_builder_append_filter(
+      builder, (const grpc_channel_filter *)arg, NULL, NULL);
+}
+
+static bool prepend_filter(grpc_channel_stack_builder *builder, void *arg) {
+  return grpc_channel_stack_builder_prepend_filter(
+      builder, (const grpc_channel_filter *)arg, NULL, NULL);
+}
+
+static bool maybe_add_http_filter(grpc_channel_stack_builder *builder,
+                                  void *arg) {
+  grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
+  if (t && strstr(t->vtable->name, "http")) {
+    return grpc_channel_stack_builder_prepend_filter(
+        builder, (const grpc_channel_filter *)arg, NULL, NULL);
+  }
+  return true;
+}
+
+static void register_builtin_channel_init() {
+  grpc_channel_init_register_stage(
+      GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
+      (void *)&grpc_compress_filter);
+  grpc_channel_init_register_stage(
+      GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      prepend_filter, (void *)&grpc_compress_filter);
+  grpc_channel_init_register_stage(
+      GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
+      (void *)&grpc_compress_filter);
+  grpc_channel_init_register_stage(
+      GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      maybe_add_http_filter, (void *)&grpc_http_client_filter);
+  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
+                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                   grpc_add_connected_filter, NULL);
+  grpc_channel_init_register_stage(
+      GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      maybe_add_http_filter, (void *)&grpc_http_client_filter);
+  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
+                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                   grpc_add_connected_filter, NULL);
+  grpc_channel_init_register_stage(
+      GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      maybe_add_http_filter, (void *)&grpc_http_server_filter);
+  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
+                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                   grpc_add_connected_filter, NULL);
+  grpc_channel_init_register_stage(GRPC_CLIENT_LAME_CHANNEL,
+                                   GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+                                   append_filter, (void *)&grpc_lame_filter);
+  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter,
+                                   (void *)&grpc_server_top_filter);
+}
+
+typedef struct grpc_plugin {
+  void (*init)();
+  void (*destroy)();
+} grpc_plugin;
+
+static grpc_plugin g_all_of_the_plugins[MAX_PLUGINS];
+static int g_number_of_plugins = 0;
+
+void grpc_register_plugin(void (*init)(void), void (*destroy)(void)) {
+  GRPC_API_TRACE("grpc_register_plugin(init=%p, destroy=%p)", 2,
+                 ((void *)(intptr_t)init, (void *)(intptr_t)destroy));
+  GPR_ASSERT(g_number_of_plugins != MAX_PLUGINS);
+  g_all_of_the_plugins[g_number_of_plugins].init = init;
+  g_all_of_the_plugins[g_number_of_plugins].destroy = destroy;
+  g_number_of_plugins++;
+}
+
+void grpc_init(void) {
+  int i;
+  gpr_once_init(&g_basic_init, do_basic_init);
+
+  gpr_mu_lock(&g_init_mu);
+  if (++g_initializations == 1) {
+    gpr_time_init();
+    grpc_mdctx_global_init();
+    grpc_channel_init_init();
+    grpc_register_tracer("api", &grpc_api_trace);
+    grpc_register_tracer("channel", &grpc_trace_channel);
+    grpc_register_tracer("connectivity_state", &grpc_connectivity_state_trace);
+    grpc_register_tracer("channel_stack_builder",
+                         &grpc_trace_channel_stack_builder);
+    grpc_register_tracer("http1", &grpc_http1_trace);
+    grpc_security_pre_init();
+    grpc_iomgr_init();
+    grpc_executor_init();
+    grpc_tracer_init("GRPC_TRACE");
+    gpr_timers_global_init();
+    grpc_cq_global_init();
+    for (i = 0; i < g_number_of_plugins; i++) {
+      if (g_all_of_the_plugins[i].init != NULL) {
+        g_all_of_the_plugins[i].init();
+      }
+    }
+    /* register channel finalization AFTER all plugins, to ensure that it's run
+     * at the appropriate time */
+    grpc_register_security_filters();
+    register_builtin_channel_init();
+    /* no more changes to channel init pipelines */
+    grpc_channel_init_finalize();
+  }
+  gpr_mu_unlock(&g_init_mu);
+  GRPC_API_TRACE("grpc_init(void)", 0, ());
+}
+
+void grpc_shutdown(void) {
+  int i;
+  GRPC_API_TRACE("grpc_shutdown(void)", 0, ());
+  gpr_mu_lock(&g_init_mu);
+  if (--g_initializations == 0) {
+    grpc_executor_shutdown();
+    grpc_cq_global_shutdown();
+    grpc_iomgr_shutdown();
+    gpr_timers_global_destroy();
+    grpc_tracer_shutdown();
+    for (i = g_number_of_plugins; i >= 0; i--) {
+      if (g_all_of_the_plugins[i].destroy != NULL) {
+        g_all_of_the_plugins[i].destroy();
+      }
+    }
+    grpc_mdctx_global_shutdown();
+  }
+  gpr_mu_unlock(&g_init_mu);
+}
+
+int grpc_is_initialized(void) {
+  int r;
+  gpr_once_init(&g_basic_init, do_basic_init);
+  gpr_mu_lock(&g_init_mu);
+  r = g_initializations > 0;
+  gpr_mu_unlock(&g_init_mu);
+  return r;
+}
diff --git a/src/core/lib/surface/init.h b/src/core/lib/surface/init.h
new file mode 100644
index 0000000..b1bf57c
--- /dev/null
+++ b/src/core/lib/surface/init.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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_SURFACE_INIT_H
+#define GRPC_CORE_LIB_SURFACE_INIT_H
+
+void grpc_register_security_filters(void);
+void grpc_security_pre_init(void);
+int grpc_is_initialized(void);
+
+#endif /* GRPC_CORE_LIB_SURFACE_INIT_H */
diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c
new file mode 100644
index 0000000..3fda2c9
--- /dev/null
+++ b/src/core/lib/surface/init_secure.c
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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/surface/init.h"
+
+#include <limits.h>
+#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/surface/channel_init.h"
+#include "src/core/lib/tsi/transport_security_interface.h"
+
+void grpc_security_pre_init(void) {
+  grpc_register_tracer("secure_endpoint", &grpc_trace_secure_endpoint);
+  grpc_register_tracer("transport_security", &tsi_tracing_enabled);
+}
+
+static bool maybe_prepend_client_auth_filter(
+    grpc_channel_stack_builder *builder, void *arg) {
+  const grpc_channel_args *args =
+      grpc_channel_stack_builder_get_channel_arguments(builder);
+  if (args) {
+    for (size_t i = 0; i < args->num_args; i++) {
+      if (0 == strcmp(GRPC_SECURITY_CONNECTOR_ARG, args->args[i].key)) {
+        return grpc_channel_stack_builder_prepend_filter(
+            builder, &grpc_client_auth_filter, NULL, NULL);
+      }
+    }
+  }
+  return true;
+}
+
+static bool maybe_prepend_server_auth_filter(
+    grpc_channel_stack_builder *builder, void *arg) {
+  const grpc_channel_args *args =
+      grpc_channel_stack_builder_get_channel_arguments(builder);
+  if (args) {
+    for (size_t i = 0; i < args->num_args; i++) {
+      if (0 == strcmp(GRPC_SERVER_CREDENTIALS_ARG, args->args[i].key)) {
+        return grpc_channel_stack_builder_prepend_filter(
+            builder, &grpc_server_auth_filter, NULL, NULL);
+      }
+    }
+  }
+  return true;
+}
+
+void grpc_register_security_filters(void) {
+  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
+                                   maybe_prepend_client_auth_filter, NULL);
+  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
+                                   maybe_prepend_client_auth_filter, NULL);
+  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
+                                   maybe_prepend_server_auth_filter, NULL);
+}
diff --git a/src/core/lib/surface/init_unsecure.c b/src/core/lib/surface/init_unsecure.c
new file mode 100644
index 0000000..f952739
--- /dev/null
+++ b/src/core/lib/surface/init_unsecure.c
@@ -0,0 +1,38 @@
+/*
+ *
+ * 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/surface/init.h"
+
+void grpc_security_pre_init(void) {}
+
+void grpc_register_security_filters(void) {}
diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c
new file mode 100644
index 0000000..80bd95d
--- /dev/null
+++ b/src/core/lib/surface/lame_client.c
@@ -0,0 +1,158 @@
+/*
+ *
+ * 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/surface/lame_client.h"
+
+#include <grpc/grpc.h>
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel.h"
+
+typedef struct {
+  grpc_linked_mdelem status;
+  grpc_linked_mdelem details;
+} call_data;
+
+typedef struct {
+  grpc_status_code error_code;
+  const char *error_message;
+} channel_data;
+
+static void fill_metadata(grpc_call_element *elem, grpc_metadata_batch *mdb) {
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  char tmp[GPR_LTOA_MIN_BUFSIZE];
+  gpr_ltoa(chand->error_code, tmp);
+  calld->status.md = grpc_mdelem_from_strings("grpc-status", tmp);
+  calld->details.md =
+      grpc_mdelem_from_strings("grpc-message", chand->error_message);
+  calld->status.prev = calld->details.next = NULL;
+  calld->status.next = &calld->details;
+  calld->details.prev = &calld->status;
+  mdb->list.head = &calld->status;
+  mdb->list.tail = &calld->details;
+  mdb->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
+}
+
+static void lame_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
+                                           grpc_call_element *elem,
+                                           grpc_transport_stream_op *op) {
+  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
+  if (op->recv_initial_metadata != NULL) {
+    fill_metadata(elem, op->recv_initial_metadata);
+  } else if (op->recv_trailing_metadata != NULL) {
+    fill_metadata(elem, op->recv_trailing_metadata);
+  }
+  grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+}
+
+static char *lame_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+  return NULL;
+}
+
+static void lame_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                    grpc_channel_element *elem,
+                                    grpc_transport_op *op) {
+  if (op->on_connectivity_state_change) {
+    GPR_ASSERT(*op->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE);
+    *op->connectivity_state = GRPC_CHANNEL_FATAL_FAILURE;
+    op->on_connectivity_state_change->cb(
+        exec_ctx, op->on_connectivity_state_change->cb_arg, 1);
+  }
+  if (op->on_consumed != NULL) {
+    op->on_consumed->cb(exec_ctx, op->on_consumed->cb_arg, 1);
+  }
+  if (op->send_ping != NULL) {
+    op->send_ping->cb(exec_ctx, op->send_ping->cb_arg, 0);
+  }
+}
+
+static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                           grpc_call_element_args *args) {}
+
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {}
+
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  GPR_ASSERT(args->is_first);
+  GPR_ASSERT(args->is_last);
+}
+
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {}
+
+const grpc_channel_filter grpc_lame_filter = {
+    lame_start_transport_stream_op,
+    lame_start_transport_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    lame_get_peer,
+    "lame-client",
+};
+
+#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
+
+grpc_channel *grpc_lame_client_channel_create(const char *target,
+                                              grpc_status_code error_code,
+                                              const char *error_message) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_channel_element *elem;
+  channel_data *chand;
+  grpc_channel *channel = grpc_channel_create(&exec_ctx, target, NULL,
+                                              GRPC_CLIENT_LAME_CHANNEL, NULL);
+  elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
+  GRPC_API_TRACE(
+      "grpc_lame_client_channel_create(target=%s, error_code=%d, "
+      "error_message=%s)",
+      3, (target, (int)error_code, error_message));
+  GPR_ASSERT(elem->filter == &grpc_lame_filter);
+  chand = (channel_data *)elem->channel_data;
+  chand->error_code = error_code;
+  chand->error_message = error_message;
+  grpc_exec_ctx_finish(&exec_ctx);
+  return channel;
+}
diff --git a/src/core/lib/surface/lame_client.h b/src/core/lib/surface/lame_client.h
new file mode 100644
index 0000000..5f6ea34
--- /dev/null
+++ b/src/core/lib/surface/lame_client.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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_SURFACE_LAME_CLIENT_H
+#define GRPC_CORE_LIB_SURFACE_LAME_CLIENT_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+extern const grpc_channel_filter grpc_lame_filter;
+
+#endif /* GRPC_CORE_LIB_SURFACE_LAME_CLIENT_H */
diff --git a/src/core/lib/surface/metadata_array.c b/src/core/lib/surface/metadata_array.c
new file mode 100644
index 0000000..6c2b750
--- /dev/null
+++ b/src/core/lib/surface/metadata_array.c
@@ -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.
+ *
+ */
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+
+#include <string.h>
+
+#include "src/core/lib/surface/api_trace.h"
+
+void grpc_metadata_array_init(grpc_metadata_array* array) {
+  GRPC_API_TRACE("grpc_metadata_array_init(array=%p)", 1, (array));
+  memset(array, 0, sizeof(*array));
+}
+
+void grpc_metadata_array_destroy(grpc_metadata_array* array) {
+  GRPC_API_TRACE("grpc_metadata_array_destroy(array=%p)", 1, (array));
+  gpr_free(array->metadata);
+}
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
new file mode 100644
index 0000000..ad8ee8c
--- /dev/null
+++ b/src/core/lib/surface/server.c
@@ -0,0 +1,1376 @@
+/*
+ *
+ * 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/surface/server.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/support/stack_lockfree.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/init.h"
+#include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+typedef struct listener {
+  void *arg;
+  void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
+                grpc_pollset **pollsets, size_t pollset_count);
+  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
+                  grpc_closure *closure);
+  struct listener *next;
+  grpc_closure destroy_done;
+} listener;
+
+typedef struct call_data call_data;
+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 {
+  requested_call_type type;
+  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;
+  union {
+    struct {
+      grpc_call_details *details;
+    } batch;
+    struct {
+      registered_method *registered_method;
+      gpr_timespec *deadline;
+      grpc_byte_buffer **optional_payload;
+    } registered;
+  } data;
+} requested_call;
+
+typedef struct channel_registered_method {
+  registered_method *server_registered_method;
+  uint32_t flags;
+  grpc_mdstr *method;
+  grpc_mdstr *host;
+} channel_registered_method;
+
+struct channel_data {
+  grpc_server *server;
+  grpc_connectivity_state connectivity_state;
+  grpc_channel *channel;
+  /* linked list of all channels on a server */
+  channel_data *next;
+  channel_data *prev;
+  channel_registered_method *registered_methods;
+  uint32_t registered_method_slots;
+  uint32_t registered_method_max_probes;
+  grpc_closure finish_destroy_channel_closure;
+  grpc_closure channel_connectivity_changed;
+};
+
+typedef struct shutdown_tag {
+  void *tag;
+  grpc_completion_queue *cq;
+  grpc_cq_completion completion;
+} shutdown_tag;
+
+typedef enum {
+  /* waiting for metadata */
+  NOT_STARTED,
+  /* inital metadata read, not flow controlled in yet */
+  PENDING,
+  /* flow controlled in, on completion queue */
+  ACTIVATED,
+  /* cancelled before being queued */
+  ZOMBIED
+} call_state;
+
+typedef struct request_matcher request_matcher;
+
+struct call_data {
+  grpc_call *call;
+
+  /** protects state */
+  gpr_mu mu_state;
+  /** the current state of a call - see call_state */
+  call_state state;
+
+  grpc_mdstr *path;
+  grpc_mdstr *host;
+  gpr_timespec deadline;
+
+  grpc_completion_queue *cq_new;
+
+  grpc_metadata_batch *recv_initial_metadata;
+  bool recv_idempotent_request;
+  grpc_metadata_array initial_metadata;
+
+  request_matcher *request_matcher;
+  grpc_byte_buffer *payload;
+
+  grpc_closure got_initial_metadata;
+  grpc_closure server_on_recv_initial_metadata;
+  grpc_closure kill_zombie_closure;
+  grpc_closure *on_done_recv_initial_metadata;
+
+  grpc_closure publish;
+
+  call_data *pending_next;
+};
+
+struct request_matcher {
+  grpc_server *server;
+  call_data *pending_head;
+  call_data *pending_tail;
+  gpr_stack_lockfree *requests;
+};
+
+struct registered_method {
+  char *method;
+  char *host;
+  grpc_server_register_method_payload_handling payload_handling;
+  uint32_t flags;
+  request_matcher request_matcher;
+  registered_method *next;
+};
+
+typedef struct {
+  grpc_channel **channels;
+  size_t num_channels;
+} channel_broadcaster;
+
+struct grpc_server {
+  grpc_channel_args *channel_args;
+
+  grpc_completion_queue **cqs;
+  grpc_pollset **pollsets;
+  size_t cq_count;
+
+  /* The two following mutexes control access to server-state
+     mu_global controls access to non-call-related state (e.g., channel state)
+     mu_call controls access to call-related state (e.g., the call lists)
+
+     If they are ever required to be nested, you must lock mu_global
+     before mu_call. This is currently used in shutdown processing
+     (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
+  gpr_mu mu_global; /* mutex for server and channel state */
+  gpr_mu mu_call;   /* mutex for call-specific state */
+
+  registered_method *registered_methods;
+  request_matcher unregistered_request_matcher;
+  /** free list of available requested_calls indices */
+  gpr_stack_lockfree *request_freelist;
+  /** requested call backing data */
+  requested_call *requested_calls;
+  size_t max_requested_calls;
+
+  gpr_atm shutdown_flag;
+  uint8_t shutdown_published;
+  size_t num_shutdown_tags;
+  shutdown_tag *shutdown_tags;
+
+  channel_data root_channel_data;
+
+  listener *listeners;
+  int listeners_destroyed;
+  gpr_refcount internal_refcount;
+
+  /** when did we print the last shutdown progress message */
+  gpr_timespec last_shutdown_message_time;
+};
+
+#define SERVER_FROM_CALL_ELEM(elem) \
+  (((channel_data *)(elem)->channel_data)->server)
+
+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);
+/* 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);
+
+/*
+ * channel broadcaster
+ */
+
+/* assumes server locked */
+static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
+  channel_data *c;
+  size_t count = 0;
+  for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
+    count++;
+  }
+  cb->num_channels = count;
+  cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
+  count = 0;
+  for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
+    cb->channels[count++] = c->channel;
+    GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
+  }
+}
+
+struct shutdown_cleanup_args {
+  grpc_closure closure;
+  gpr_slice slice;
+};
+
+static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg,
+                             bool iomgr_status_ignored) {
+  struct shutdown_cleanup_args *a = arg;
+  gpr_slice_unref(a->slice);
+  gpr_free(a);
+}
+
+static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
+                          int send_goaway, int send_disconnect) {
+  grpc_transport_op op;
+  struct shutdown_cleanup_args *sc;
+  grpc_channel_element *elem;
+
+  memset(&op, 0, sizeof(op));
+  op.send_goaway = send_goaway;
+  sc = gpr_malloc(sizeof(*sc));
+  sc->slice = gpr_slice_from_copied_string("Server shutdown");
+  op.goaway_message = &sc->slice;
+  op.goaway_status = GRPC_STATUS_OK;
+  op.disconnect = send_disconnect;
+  grpc_closure_init(&sc->closure, shutdown_cleanup, sc);
+  op.on_consumed = &sc->closure;
+
+  elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
+  elem->filter->start_transport_op(exec_ctx, elem, &op);
+}
+
+static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
+                                         channel_broadcaster *cb,
+                                         int send_goaway,
+                                         int force_disconnect) {
+  size_t i;
+
+  for (i = 0; i < cb->num_channels; i++) {
+    send_shutdown(exec_ctx, cb->channels[i], send_goaway, force_disconnect);
+    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, cb->channels[i], "broadcast");
+  }
+  gpr_free(cb->channels);
+}
+
+/*
+ * request_matcher
+ */
+
+static void request_matcher_init(request_matcher *rm, size_t entries,
+                                 grpc_server *server) {
+  memset(rm, 0, sizeof(*rm));
+  rm->server = server;
+  rm->requests = 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);
+}
+
+static void kill_zombie(grpc_exec_ctx *exec_ctx, void *elem, bool success) {
+  grpc_call_destroy(grpc_call_from_top_element(elem));
+}
+
+static void request_matcher_zombify_all_pending_calls(grpc_exec_ctx *exec_ctx,
+                                                      request_matcher *rm) {
+  while (rm->pending_head) {
+    call_data *calld = rm->pending_head;
+    rm->pending_head = calld->pending_next;
+    gpr_mu_lock(&calld->mu_state);
+    calld->state = ZOMBIED;
+    gpr_mu_unlock(&calld->mu_state);
+    grpc_closure_init(
+        &calld->kill_zombie_closure, kill_zombie,
+        grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
+    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+  }
+}
+
+static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx,
+                                          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]);
+  }
+}
+
+/*
+ * server proper
+ */
+
+static void server_ref(grpc_server *server) {
+  gpr_ref(&server->internal_refcount);
+}
+
+static void server_delete(grpc_exec_ctx *exec_ctx, grpc_server *server) {
+  registered_method *rm;
+  size_t i;
+  grpc_channel_args_destroy(server->channel_args);
+  gpr_mu_destroy(&server->mu_global);
+  gpr_mu_destroy(&server->mu_call);
+  while ((rm = server->registered_methods) != NULL) {
+    server->registered_methods = rm->next;
+    request_matcher_destroy(&rm->request_matcher);
+    gpr_free(rm->method);
+    gpr_free(rm->host);
+    gpr_free(rm);
+  }
+  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);
+  gpr_free(server->shutdown_tags);
+  gpr_free(server->requested_calls);
+  gpr_free(server);
+}
+
+static void server_unref(grpc_exec_ctx *exec_ctx, grpc_server *server) {
+  if (gpr_unref(&server->internal_refcount)) {
+    server_delete(exec_ctx, server);
+  }
+}
+
+static int is_channel_orphaned(channel_data *chand) {
+  return chand->next == chand;
+}
+
+static void orphan_channel(channel_data *chand) {
+  chand->next->prev = chand->prev;
+  chand->prev->next = chand->next;
+  chand->next = chand->prev = chand;
+}
+
+static void finish_destroy_channel(grpc_exec_ctx *exec_ctx, void *cd,
+                                   bool success) {
+  channel_data *chand = cd;
+  grpc_server *server = chand->server;
+  GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "server");
+  server_unref(exec_ctx, server);
+}
+
+static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) {
+  if (is_channel_orphaned(chand)) return;
+  GPR_ASSERT(chand->server != NULL);
+  orphan_channel(chand);
+  server_ref(chand->server);
+  maybe_finish_shutdown(exec_ctx, chand->server);
+  chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
+  chand->finish_destroy_channel_closure.cb_arg = chand;
+
+  grpc_transport_op op;
+  memset(&op, 0, sizeof(op));
+  op.set_accept_stream = true;
+  op.on_consumed = &chand->finish_destroy_channel_closure;
+  grpc_channel_next_op(exec_ctx,
+                       grpc_channel_stack_element(
+                           grpc_channel_get_channel_stack(chand->channel), 0),
+                       &op);
+}
+
+static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
+  gpr_slice slice = value->slice;
+  size_t len = GPR_SLICE_LENGTH(slice);
+
+  if (len + 1 > *capacity) {
+    *capacity = GPR_MAX(len + 1, *capacity * 2);
+    *dest = gpr_realloc(*dest, *capacity);
+  }
+  memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
+}
+
+static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
+                               grpc_cq_completion *c) {
+  requested_call *rc = req;
+  grpc_server *server = rc->server;
+
+  if (rc >= server->requested_calls &&
+      rc < server->requested_calls + server->max_requested_calls) {
+    GPR_ASSERT(rc - server->requested_calls <= INT_MAX);
+    gpr_stack_lockfree_push(server->request_freelist,
+                            (int)(rc - server->requested_calls));
+  } else {
+    gpr_free(req);
+  }
+
+  server_unref(exec_ctx, server);
+}
+
+static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
+                         call_data *calld, 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;
+  GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
+  switch (rc->type) {
+    case BATCH_CALL:
+      GPR_ASSERT(calld->host != NULL);
+      GPR_ASSERT(calld->path != NULL);
+      cpstr(&rc->data.batch.details->host,
+            &rc->data.batch.details->host_capacity, calld->host);
+      cpstr(&rc->data.batch.details->method,
+            &rc->data.batch.details->method_capacity, calld->path);
+      rc->data.batch.details->deadline = calld->deadline;
+      rc->data.batch.details->flags =
+          0 | (calld->recv_idempotent_request
+                   ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
+                   : 0);
+      break;
+    case REGISTERED_CALL:
+      *rc->data.registered.deadline = calld->deadline;
+      if (rc->data.registered.optional_payload) {
+        *rc->data.registered.optional_payload = calld->payload;
+      }
+      break;
+    default:
+      GPR_UNREACHABLE_CODE(return );
+  }
+
+  grpc_call_element *elem =
+      grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
+  channel_data *chand = elem->channel_data;
+  server_ref(chand->server);
+  grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, true, done_request_event, rc,
+                 &rc->completion);
+}
+
+static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  call_data *calld = arg;
+  request_matcher *rm = calld->request_matcher;
+  grpc_server *server = rm->server;
+
+  if (!success || gpr_atm_acq_load(&server->shutdown_flag)) {
+    gpr_mu_lock(&calld->mu_state);
+    calld->state = ZOMBIED;
+    gpr_mu_unlock(&calld->mu_state);
+    grpc_closure_init(
+        &calld->kill_zombie_closure, kill_zombie,
+        grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
+    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+    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;
+    } else {
+      rm->pending_tail->pending_next = calld;
+      rm->pending_tail = calld;
+    }
+    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]);
+  }
+}
+
+static void finish_start_new_rpc(
+    grpc_exec_ctx *exec_ctx, grpc_server *server, grpc_call_element *elem,
+    request_matcher *rm,
+    grpc_server_register_method_payload_handling payload_handling) {
+  call_data *calld = elem->call_data;
+
+  if (gpr_atm_acq_load(&server->shutdown_flag)) {
+    gpr_mu_lock(&calld->mu_state);
+    calld->state = ZOMBIED;
+    gpr_mu_unlock(&calld->mu_state);
+    grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
+    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+    return;
+  }
+
+  calld->request_matcher = rm;
+
+  switch (payload_handling) {
+    case GRPC_SRM_PAYLOAD_NONE:
+      publish_new_rpc(exec_ctx, calld, 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_call_start_batch_and_execute(exec_ctx, calld->call, &op, 1,
+                                        &calld->publish);
+      break;
+    }
+  }
+}
+
+static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+  channel_data *chand = elem->channel_data;
+  call_data *calld = elem->call_data;
+  grpc_server *server = chand->server;
+  uint32_t i;
+  uint32_t hash;
+  channel_registered_method *rm;
+
+  if (chand->registered_methods && calld->path && calld->host) {
+    /* TODO(ctiller): unify these two searches */
+    /* check for an exact match with host */
+    hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
+    for (i = 0; i <= chand->registered_method_max_probes; i++) {
+      rm = &chand->registered_methods[(hash + i) %
+                                      chand->registered_method_slots];
+      if (!rm) break;
+      if (rm->host != calld->host) continue;
+      if (rm->method != calld->path) continue;
+      if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
+          !calld->recv_idempotent_request)
+        continue;
+      finish_start_new_rpc(exec_ctx, server, elem,
+                           &rm->server_registered_method->request_matcher,
+                           rm->server_registered_method->payload_handling);
+      return;
+    }
+    /* check for a wildcard method definition (no host set) */
+    hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
+    for (i = 0; i <= chand->registered_method_max_probes; i++) {
+      rm = &chand->registered_methods[(hash + i) %
+                                      chand->registered_method_slots];
+      if (!rm) break;
+      if (rm->host != NULL) continue;
+      if (rm->method != calld->path) continue;
+      if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
+          !calld->recv_idempotent_request)
+        continue;
+      finish_start_new_rpc(exec_ctx, server, elem,
+                           &rm->server_registered_method->request_matcher,
+                           rm->server_registered_method->payload_handling);
+      return;
+    }
+  }
+  finish_start_new_rpc(exec_ctx, server, elem,
+                       &server->unregistered_request_matcher,
+                       GRPC_SRM_PAYLOAD_NONE);
+}
+
+static int num_listeners(grpc_server *server) {
+  listener *l;
+  int n = 0;
+  for (l = server->listeners; l; l = l->next) {
+    n++;
+  }
+  return n;
+}
+
+static void done_shutdown_event(grpc_exec_ctx *exec_ctx, void *server,
+                                grpc_cq_completion *completion) {
+  server_unref(exec_ctx, server);
+}
+
+static int num_channels(grpc_server *server) {
+  channel_data *chand;
+  int n = 0;
+  for (chand = server->root_channel_data.next;
+       chand != &server->root_channel_data; chand = chand->next) {
+    n++;
+  }
+  return n;
+}
+
+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);
+  }
+}
+
+static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
+                                  grpc_server *server) {
+  size_t i;
+  if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) {
+    return;
+  }
+
+  kill_pending_work_locked(exec_ctx, server);
+
+  if (server->root_channel_data.next != &server->root_channel_data ||
+      server->listeners_destroyed < num_listeners(server)) {
+    if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME),
+                                  server->last_shutdown_message_time),
+                     gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
+      server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
+      gpr_log(GPR_DEBUG,
+              "Waiting for %d channels and %d/%d listeners to be destroyed"
+              " before shutting down server",
+              num_channels(server),
+              num_listeners(server) - server->listeners_destroyed,
+              num_listeners(server));
+    }
+    return;
+  }
+  server->shutdown_published = 1;
+  for (i = 0; i < server->num_shutdown_tags; i++) {
+    server_ref(server);
+    grpc_cq_end_op(exec_ctx, server->shutdown_tags[i].cq,
+                   server->shutdown_tags[i].tag, 1, done_shutdown_event, server,
+                   &server->shutdown_tags[i].completion);
+  }
+}
+
+static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
+  grpc_call_element *elem = user_data;
+  call_data *calld = elem->call_data;
+  if (md->key == GRPC_MDSTR_PATH) {
+    if (calld->path == NULL) {
+      calld->path = GRPC_MDSTR_REF(md->value);
+    }
+    return NULL;
+  } else if (md->key == GRPC_MDSTR_AUTHORITY) {
+    if (calld->host == NULL) {
+      calld->host = GRPC_MDSTR_REF(md->value);
+    }
+    return NULL;
+  }
+  return md;
+}
+
+static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
+                                            bool success) {
+  grpc_call_element *elem = ptr;
+  call_data *calld = elem->call_data;
+  gpr_timespec op_deadline;
+
+  grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, elem);
+  op_deadline = calld->recv_initial_metadata->deadline;
+  if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
+    calld->deadline = op_deadline;
+  }
+  if (calld->host && calld->path) {
+    /* do nothing */
+  } else {
+    success = 0;
+  }
+
+  calld->on_done_recv_initial_metadata->cb(
+      exec_ctx, calld->on_done_recv_initial_metadata->cb_arg, success);
+}
+
+static void server_mutate_op(grpc_call_element *elem,
+                             grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+
+  if (op->recv_initial_metadata != NULL) {
+    GPR_ASSERT(op->recv_idempotent_request == NULL);
+    calld->recv_initial_metadata = op->recv_initial_metadata;
+    calld->on_done_recv_initial_metadata = op->recv_initial_metadata_ready;
+    op->recv_initial_metadata_ready = &calld->server_on_recv_initial_metadata;
+    op->recv_idempotent_request = &calld->recv_idempotent_request;
+  }
+}
+
+static void server_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
+                                             grpc_call_element *elem,
+                                             grpc_transport_stream_op *op) {
+  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
+  server_mutate_op(elem, op);
+  grpc_call_next_op(exec_ctx, elem, op);
+}
+
+static void got_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
+                                 bool success) {
+  grpc_call_element *elem = ptr;
+  call_data *calld = elem->call_data;
+  if (success) {
+    start_new_rpc(exec_ctx, elem);
+  } else {
+    gpr_mu_lock(&calld->mu_state);
+    if (calld->state == NOT_STARTED) {
+      calld->state = ZOMBIED;
+      gpr_mu_unlock(&calld->mu_state);
+      grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
+      grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+    } else if (calld->state == PENDING) {
+      calld->state = ZOMBIED;
+      gpr_mu_unlock(&calld->mu_state);
+      /* zombied call will be destroyed when it's removed from the pending
+         queue... later */
+    } else {
+      gpr_mu_unlock(&calld->mu_state);
+    }
+  }
+}
+
+static void accept_stream(grpc_exec_ctx *exec_ctx, void *cd,
+                          grpc_transport *transport,
+                          const void *transport_server_data) {
+  channel_data *chand = cd;
+  /* create a call */
+  grpc_call *call =
+      grpc_call_create(chand->channel, NULL, 0, NULL, transport_server_data,
+                       NULL, 0, gpr_inf_future(GPR_CLOCK_MONOTONIC));
+  grpc_call_element *elem =
+      grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
+  call_data *calld = elem->call_data;
+  grpc_op op;
+  memset(&op, 0, sizeof(op));
+  op.op = GRPC_OP_RECV_INITIAL_METADATA;
+  op.data.recv_initial_metadata = &calld->initial_metadata;
+  grpc_closure_init(&calld->got_initial_metadata, got_initial_metadata, elem);
+  grpc_call_start_batch_and_execute(exec_ctx, call, &op, 1,
+                                    &calld->got_initial_metadata);
+}
+
+static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd,
+                                         bool iomgr_status_ignored) {
+  channel_data *chand = cd;
+  grpc_server *server = chand->server;
+  if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
+    grpc_transport_op op;
+    memset(&op, 0, sizeof(op));
+    op.on_connectivity_state_change = &chand->channel_connectivity_changed,
+    op.connectivity_state = &chand->connectivity_state;
+    grpc_channel_next_op(exec_ctx,
+                         grpc_channel_stack_element(
+                             grpc_channel_get_channel_stack(chand->channel), 0),
+                         &op);
+  } else {
+    gpr_mu_lock(&server->mu_global);
+    destroy_channel(exec_ctx, chand);
+    gpr_mu_unlock(&server->mu_global);
+    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity");
+  }
+}
+
+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;
+  channel_data *chand = elem->channel_data;
+  memset(calld, 0, sizeof(call_data));
+  calld->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
+  calld->call = grpc_call_from_top_element(elem);
+  gpr_mu_init(&calld->mu_state);
+
+  grpc_closure_init(&calld->server_on_recv_initial_metadata,
+                    server_on_recv_initial_metadata, elem);
+
+  server_ref(chand->server);
+}
+
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {
+  channel_data *chand = elem->channel_data;
+  call_data *calld = elem->call_data;
+
+  GPR_ASSERT(calld->state != PENDING);
+
+  if (calld->host) {
+    GRPC_MDSTR_UNREF(calld->host);
+  }
+  if (calld->path) {
+    GRPC_MDSTR_UNREF(calld->path);
+  }
+  grpc_metadata_array_destroy(&calld->initial_metadata);
+
+  gpr_mu_destroy(&calld->mu_state);
+
+  server_unref(exec_ctx, chand->server);
+}
+
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  channel_data *chand = elem->channel_data;
+  GPR_ASSERT(args->is_first);
+  GPR_ASSERT(!args->is_last);
+  chand->server = NULL;
+  chand->channel = NULL;
+  chand->next = chand->prev = chand;
+  chand->registered_methods = NULL;
+  chand->connectivity_state = GRPC_CHANNEL_IDLE;
+  grpc_closure_init(&chand->channel_connectivity_changed,
+                    channel_connectivity_changed, chand);
+}
+
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {
+  size_t i;
+  channel_data *chand = elem->channel_data;
+  if (chand->registered_methods) {
+    for (i = 0; i < chand->registered_method_slots; i++) {
+      if (chand->registered_methods[i].method) {
+        GRPC_MDSTR_UNREF(chand->registered_methods[i].method);
+      }
+      if (chand->registered_methods[i].host) {
+        GRPC_MDSTR_UNREF(chand->registered_methods[i].host);
+      }
+    }
+    gpr_free(chand->registered_methods);
+  }
+  if (chand->server) {
+    gpr_mu_lock(&chand->server->mu_global);
+    chand->next->prev = chand->prev;
+    chand->prev->next = chand->next;
+    chand->next = chand->prev = chand;
+    maybe_finish_shutdown(exec_ctx, chand->server);
+    gpr_mu_unlock(&chand->server->mu_global);
+    server_unref(exec_ctx, chand->server);
+  }
+}
+
+const grpc_channel_filter grpc_server_top_filter = {
+    server_start_transport_stream_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "server",
+};
+
+void grpc_server_register_completion_queue(grpc_server *server,
+                                           grpc_completion_queue *cq,
+                                           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);
+  n = server->cq_count++;
+  server->cqs = gpr_realloc(server->cqs,
+                            server->cq_count * sizeof(grpc_completion_queue *));
+  server->cqs[n] = cq;
+}
+
+grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
+  size_t i;
+
+  GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved));
+
+  grpc_server *server = gpr_malloc(sizeof(grpc_server));
+
+  GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
+
+  memset(server, 0, sizeof(grpc_server));
+
+  gpr_mu_init(&server->mu_global);
+  gpr_mu_init(&server->mu_call);
+
+  /* decremented by grpc_server_destroy */
+  gpr_ref_init(&server->internal_refcount, 1);
+  server->root_channel_data.next = server->root_channel_data.prev =
+      &server->root_channel_data;
+
+  /* TODO(ctiller): expose a channel_arg for this */
+  server->max_requested_calls = 32768;
+  server->request_freelist =
+      gpr_stack_lockfree_create(server->max_requested_calls);
+  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));
+
+  server->channel_args = grpc_channel_args_copy(args);
+
+  return server;
+}
+
+static int streq(const char *a, const char *b) {
+  if (a == NULL && b == NULL) return 1;
+  if (a == NULL) return 0;
+  if (b == NULL) return 0;
+  return 0 == strcmp(a, b);
+}
+
+void *grpc_server_register_method(
+    grpc_server *server, const char *method, const char *host,
+    grpc_server_register_method_payload_handling payload_handling,
+    uint32_t flags) {
+  registered_method *m;
+  GRPC_API_TRACE(
+      "grpc_server_register_method(server=%p, method=%s, host=%s, "
+      "flags=0x%08x)",
+      4, (server, method, host, flags));
+  if (!method) {
+    gpr_log(GPR_ERROR,
+            "grpc_server_register_method method string cannot be NULL");
+    return NULL;
+  }
+  for (m = server->registered_methods; m; m = m->next) {
+    if (streq(m->method, method) && streq(m->host, host)) {
+      gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
+              host ? host : "*");
+      return NULL;
+    }
+  }
+  if ((flags & ~GRPC_INITIAL_METADATA_USED_MASK) != 0) {
+    gpr_log(GPR_ERROR, "grpc_server_register_method invalid flags 0x%08x",
+            flags);
+    return NULL;
+  }
+  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;
+  m->payload_handling = payload_handling;
+  m->flags = flags;
+  server->registered_methods = m;
+  return m;
+}
+
+void grpc_server_start(grpc_server *server) {
+  listener *l;
+  size_t i;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server));
+
+  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]);
+  }
+
+  for (l = server->listeners; l; l = l->next) {
+    l->start(&exec_ctx, server, l->arg, server->pollsets, server->cq_count);
+  }
+
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
+                                 grpc_transport *transport,
+                                 const grpc_channel_args *args) {
+  size_t i;
+  size_t num_registered_methods;
+  size_t alloc;
+  registered_method *rm;
+  channel_registered_method *crm;
+  grpc_channel *channel;
+  channel_data *chand;
+  grpc_mdstr *host;
+  grpc_mdstr *method;
+  uint32_t hash;
+  size_t slots;
+  uint32_t probes;
+  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(
+              grpc_channel_get_channel_stack(channel), 0)
+              ->channel_data;
+  chand->server = s;
+  server_ref(s);
+  chand->channel = channel;
+
+  num_registered_methods = 0;
+  for (rm = s->registered_methods; rm; rm = rm->next) {
+    num_registered_methods++;
+  }
+  /* build a lookup table phrased in terms of mdstr's in this channels context
+     to quickly find registered methods */
+  if (num_registered_methods > 0) {
+    slots = 2 * num_registered_methods;
+    alloc = sizeof(channel_registered_method) * slots;
+    chand->registered_methods = gpr_malloc(alloc);
+    memset(chand->registered_methods, 0, alloc);
+    for (rm = s->registered_methods; rm; rm = rm->next) {
+      host = rm->host ? grpc_mdstr_from_string(rm->host) : NULL;
+      method = grpc_mdstr_from_string(rm->method);
+      hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
+      for (probes = 0; chand->registered_methods[(hash + probes) % slots]
+                           .server_registered_method != NULL;
+           probes++)
+        ;
+      if (probes > max_probes) max_probes = probes;
+      crm = &chand->registered_methods[(hash + probes) % slots];
+      crm->server_registered_method = rm;
+      crm->flags = rm->flags;
+      crm->host = host;
+      crm->method = method;
+    }
+    GPR_ASSERT(slots <= UINT32_MAX);
+    chand->registered_method_slots = (uint32_t)slots;
+    chand->registered_method_max_probes = max_probes;
+  }
+
+  gpr_mu_lock(&s->mu_global);
+  chand->next = &s->root_channel_data;
+  chand->prev = chand->next->prev;
+  chand->next->prev = chand->prev->next = chand;
+  gpr_mu_unlock(&s->mu_global);
+
+  GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
+  memset(&op, 0, sizeof(op));
+  op.set_accept_stream = true;
+  op.set_accept_stream_fn = accept_stream;
+  op.set_accept_stream_user_data = chand;
+  op.on_connectivity_state_change = &chand->channel_connectivity_changed;
+  op.connectivity_state = &chand->connectivity_state;
+  op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0;
+  grpc_transport_perform_op(exec_ctx, transport, &op);
+}
+
+void done_published_shutdown(grpc_exec_ctx *exec_ctx, void *done_arg,
+                             grpc_cq_completion *storage) {
+  (void)done_arg;
+  gpr_free(storage);
+}
+
+static void listener_destroy_done(grpc_exec_ctx *exec_ctx, void *s,
+                                  bool success) {
+  grpc_server *server = s;
+  gpr_mu_lock(&server->mu_global);
+  server->listeners_destroyed++;
+  maybe_finish_shutdown(exec_ctx, server);
+  gpr_mu_unlock(&server->mu_global);
+}
+
+void grpc_server_shutdown_and_notify(grpc_server *server,
+                                     grpc_completion_queue *cq, void *tag) {
+  listener *l;
+  shutdown_tag *sdt;
+  channel_broadcaster broadcaster;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_API_TRACE("grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", 3,
+                 (server, cq, tag));
+
+  /* lock, and gather up some stuff to do */
+  gpr_mu_lock(&server->mu_global);
+  grpc_cq_begin_op(cq, tag);
+  if (server->shutdown_published) {
+    grpc_cq_end_op(&exec_ctx, cq, tag, 1, done_published_shutdown, NULL,
+                   gpr_malloc(sizeof(grpc_cq_completion)));
+    gpr_mu_unlock(&server->mu_global);
+    goto done;
+  }
+  server->shutdown_tags =
+      gpr_realloc(server->shutdown_tags,
+                  sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
+  sdt = &server->shutdown_tags[server->num_shutdown_tags++];
+  sdt->tag = tag;
+  sdt->cq = cq;
+  if (gpr_atm_acq_load(&server->shutdown_flag)) {
+    gpr_mu_unlock(&server->mu_global);
+    goto done;
+  }
+
+  server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
+
+  channel_broadcaster_init(server, &broadcaster);
+
+  gpr_atm_rel_store(&server->shutdown_flag, 1);
+
+  /* collect all unregistered then registered calls */
+  gpr_mu_lock(&server->mu_call);
+  kill_pending_work_locked(&exec_ctx, server);
+  gpr_mu_unlock(&server->mu_call);
+
+  maybe_finish_shutdown(&exec_ctx, server);
+  gpr_mu_unlock(&server->mu_global);
+
+  /* Shutdown listeners */
+  for (l = server->listeners; l; l = l->next) {
+    grpc_closure_init(&l->destroy_done, listener_destroy_done, server);
+    l->destroy(&exec_ctx, server, l->arg, &l->destroy_done);
+  }
+
+  channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 1, 0);
+
+done:
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void grpc_server_cancel_all_calls(grpc_server *server) {
+  channel_broadcaster broadcaster;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_API_TRACE("grpc_server_cancel_all_calls(server=%p)", 1, (server));
+
+  gpr_mu_lock(&server->mu_global);
+  channel_broadcaster_init(server, &broadcaster);
+  gpr_mu_unlock(&server->mu_global);
+
+  channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 0, 1);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void grpc_server_destroy(grpc_server *server) {
+  listener *l;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  GRPC_API_TRACE("grpc_server_destroy(server=%p)", 1, (server));
+
+  gpr_mu_lock(&server->mu_global);
+  GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners);
+  GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
+
+  while (server->listeners) {
+    l = server->listeners;
+    server->listeners = l->next;
+    gpr_free(l);
+  }
+
+  gpr_mu_unlock(&server->mu_global);
+
+  server_unref(&exec_ctx, server);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void grpc_server_add_listener(
+    grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
+    void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
+                  grpc_pollset **pollsets, size_t pollset_count),
+    void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
+                    grpc_closure *on_done)) {
+  listener *l = gpr_malloc(sizeof(listener));
+  l->arg = arg;
+  l->start = start;
+  l->destroy = destroy;
+  l->next = server->listeners;
+  server->listeners = l;
+}
+
+static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
+                                          grpc_server *server,
+                                          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);
+    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);
+    return GRPC_CALL_OK;
+  }
+  switch (rc->type) {
+    case BATCH_CALL:
+      rm = &server->unregistered_request_matcher;
+      break;
+    case REGISTERED_CALL:
+      rm = &rc->data.registered.registered_method->request_matcher;
+      break;
+  }
+  server->requested_calls[request_id] = *rc;
+  gpr_free(rc);
+  if (gpr_stack_lockfree_push(rm->requests, 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);
+      if (request_id == -1) break;
+      rm->pending_head = calld->pending_next;
+      gpr_mu_unlock(&server->mu_call);
+      gpr_mu_lock(&calld->mu_state);
+      if (calld->state == ZOMBIED) {
+        gpr_mu_unlock(&calld->mu_state);
+        grpc_closure_init(
+            &calld->kill_zombie_closure, kill_zombie,
+            grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
+        grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true,
+                              NULL);
+      } else {
+        GPR_ASSERT(calld->state == PENDING);
+        calld->state = ACTIVATED;
+        gpr_mu_unlock(&calld->mu_state);
+        publish_call(exec_ctx, server, calld,
+                     &server->requested_calls[request_id]);
+      }
+      gpr_mu_lock(&server->mu_call);
+    }
+    gpr_mu_unlock(&server->mu_call);
+  }
+  return GRPC_CALL_OK;
+}
+
+grpc_call_error grpc_server_request_call(
+    grpc_server *server, grpc_call **call, grpc_call_details *details,
+    grpc_metadata_array *initial_metadata,
+    grpc_completion_queue *cq_bound_to_call,
+    grpc_completion_queue *cq_for_notification, void *tag) {
+  grpc_call_error error;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  requested_call *rc = gpr_malloc(sizeof(*rc));
+  GRPC_API_TRACE(
+      "grpc_server_request_call("
+      "server=%p, call=%p, details=%p, initial_metadata=%p, "
+      "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)) {
+    gpr_free(rc);
+    error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
+    goto done;
+  }
+  grpc_cq_begin_op(cq_for_notification, tag);
+  details->reserved = NULL;
+  rc->type = BATCH_CALL;
+  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);
+done:
+  grpc_exec_ctx_finish(&exec_ctx);
+  return error;
+}
+
+grpc_call_error grpc_server_request_registered_call(
+    grpc_server *server, void *rmp, grpc_call **call, gpr_timespec *deadline,
+    grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
+    grpc_completion_queue *cq_bound_to_call,
+    grpc_completion_queue *cq_for_notification, void *tag) {
+  grpc_call_error error;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  requested_call *rc = gpr_malloc(sizeof(*rc));
+  registered_method *rm = rmp;
+  GRPC_API_TRACE(
+      "grpc_server_request_registered_call("
+      "server=%p, rmp=%p, call=%p, deadline=%p, initial_metadata=%p, "
+      "optional_payload=%p, cq_bound_to_call=%p, cq_for_notification=%p, "
+      "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)) {
+    gpr_free(rc);
+    error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
+    goto done;
+  }
+  if ((optional_payload == NULL) !=
+      (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) {
+    gpr_free(rc);
+    error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH;
+    goto done;
+  }
+  grpc_cq_begin_op(cq_for_notification, tag);
+  rc->type = REGISTERED_CALL;
+  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);
+done:
+  grpc_exec_ctx_finish(&exec_ctx);
+  return error;
+}
+
+static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
+                      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);
+}
+
+const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
+  return server->channel_args;
+}
+
+int grpc_server_has_open_connections(grpc_server *server) {
+  int r;
+  gpr_mu_lock(&server->mu_global);
+  r = server->root_channel_data.next != &server->root_channel_data;
+  gpr_mu_unlock(&server->mu_global);
+  return r;
+}
diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h
new file mode 100644
index 0000000..470ef23
--- /dev/null
+++ b/src/core/lib/surface/server.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * 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_SURFACE_SERVER_H
+#define GRPC_CORE_LIB_SURFACE_SERVER_H
+
+#include <grpc/grpc.h>
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/transport/transport.h"
+
+extern const grpc_channel_filter grpc_server_top_filter;
+
+/* Add a listener to the server: when the server starts, it will call start,
+   and when it shuts down, it will call destroy */
+void grpc_server_add_listener(
+    grpc_exec_ctx *exec_ctx, grpc_server *server, void *listener,
+    void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
+                  grpc_pollset **pollsets, size_t npollsets),
+    void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
+                    grpc_closure *on_done));
+
+/* Setup a transport - creates a channel stack, binds the transport to the
+   server */
+void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *server,
+                                 grpc_transport *transport,
+                                 const grpc_channel_args *args);
+
+const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server);
+
+int grpc_server_has_open_connections(grpc_server *server);
+
+#endif /* GRPC_CORE_LIB_SURFACE_SERVER_H */
diff --git a/src/core/lib/surface/surface_trace.h b/src/core/lib/surface/surface_trace.h
new file mode 100644
index 0000000..a69a0ff
--- /dev/null
+++ b/src/core/lib/surface/surface_trace.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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_SURFACE_SURFACE_TRACE_H
+#define GRPC_CORE_LIB_SURFACE_SURFACE_TRACE_H
+
+#include <grpc/support/log.h>
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/surface/api_trace.h"
+
+#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event)    \
+  if (grpc_api_trace) {                                 \
+    char *_ev = grpc_event_string(event);               \
+    gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
+    gpr_free(_ev);                                      \
+  }
+
+#endif /* GRPC_CORE_LIB_SURFACE_SURFACE_TRACE_H */
diff --git a/src/core/lib/surface/validate_metadata.c b/src/core/lib/surface/validate_metadata.c
new file mode 100644
index 0000000..84f0a08
--- /dev/null
+++ b/src/core/lib/surface/validate_metadata.c
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/port_platform.h>
+
+static int conforms_to(const char *s, size_t len, const uint8_t *legal_bits) {
+  const char *p = s;
+  const char *e = s + len;
+  for (; p != e; p++) {
+    int idx = (uint8_t)*p;
+    int byte = idx / 8;
+    int bit = idx % 8;
+    if ((legal_bits[byte] & (1 << bit)) == 0) return 0;
+  }
+  return 1;
+}
+
+int grpc_header_key_is_legal(const char *key, size_t length) {
+  static const uint8_t legal_header_bits[256 / 8] = {
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0x00, 0x00, 0x00,
+      0x80, 0xfe, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  if (length == 0) {
+    return 0;
+  }
+  return conforms_to(key, length, legal_header_bits);
+}
+
+int grpc_header_nonbin_value_is_legal(const char *value, size_t length) {
+  static const uint8_t legal_header_bits[256 / 8] = {
+      0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  return conforms_to(value, length, legal_header_bits);
+}
+
+int grpc_is_binary_header(const char *key, size_t length) {
+  if (length < 5) return 0;
+  return 0 == memcmp(key + length - 4, "-bin", 4);
+}
diff --git a/src/core/lib/surface/version.c b/src/core/lib/surface/version.c
new file mode 100644
index 0000000..fe954cb
--- /dev/null
+++ b/src/core/lib/surface/version.c
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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 is autogenerated from:
+   templates/src/core/surface/version.c.template */
+
+#include <grpc/grpc.h>
+
+const char *grpc_version_string(void) { return "0.14.0-dev"; }
diff --git a/src/core/lib/transport/byte_stream.c b/src/core/lib/transport/byte_stream.c
new file mode 100644
index 0000000..2f6c75c
--- /dev/null
+++ b/src/core/lib/transport/byte_stream.c
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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/transport/byte_stream.h"
+
+#include <stdlib.h>
+
+#include <grpc/support/log.h>
+
+int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
+                          grpc_byte_stream *byte_stream, gpr_slice *slice,
+                          size_t max_size_hint, grpc_closure *on_complete) {
+  return byte_stream->next(exec_ctx, byte_stream, slice, max_size_hint,
+                           on_complete);
+}
+
+void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
+                              grpc_byte_stream *byte_stream) {
+  byte_stream->destroy(exec_ctx, byte_stream);
+}
+
+/* slice_buffer_stream */
+
+static int slice_buffer_stream_next(grpc_exec_ctx *exec_ctx,
+                                    grpc_byte_stream *byte_stream,
+                                    gpr_slice *slice, size_t max_size_hint,
+                                    grpc_closure *on_complete) {
+  grpc_slice_buffer_stream *stream = (grpc_slice_buffer_stream *)byte_stream;
+  GPR_ASSERT(stream->cursor < stream->backing_buffer->count);
+  *slice = gpr_slice_ref(stream->backing_buffer->slices[stream->cursor]);
+  stream->cursor++;
+  return 1;
+}
+
+static void slice_buffer_stream_destroy(grpc_exec_ctx *exec_ctx,
+                                        grpc_byte_stream *byte_stream) {}
+
+void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream,
+                                   gpr_slice_buffer *slice_buffer,
+                                   uint32_t flags) {
+  GPR_ASSERT(slice_buffer->length <= UINT32_MAX);
+  stream->base.length = (uint32_t)slice_buffer->length;
+  stream->base.flags = flags;
+  stream->base.next = slice_buffer_stream_next;
+  stream->base.destroy = slice_buffer_stream_destroy;
+  stream->backing_buffer = slice_buffer;
+  stream->cursor = 0;
+}
diff --git a/src/core/lib/transport/byte_stream.h b/src/core/lib/transport/byte_stream.h
new file mode 100644
index 0000000..95519a9
--- /dev/null
+++ b/src/core/lib/transport/byte_stream.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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_TRANSPORT_BYTE_STREAM_H
+#define GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H
+
+#include <grpc/support/slice_buffer.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+/** Internal bit flag for grpc_begin_message's \a flags signaling the use of
+ * compression for the message */
+#define GRPC_WRITE_INTERNAL_COMPRESS (0x80000000u)
+/** Mask of all valid internal flags. */
+#define GRPC_WRITE_INTERNAL_USED_MASK (GRPC_WRITE_INTERNAL_COMPRESS)
+
+struct grpc_byte_stream;
+typedef struct grpc_byte_stream grpc_byte_stream;
+
+struct grpc_byte_stream {
+  uint32_t length;
+  uint32_t flags;
+  int (*next)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream,
+              gpr_slice *slice, size_t max_size_hint,
+              grpc_closure *on_complete);
+  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream);
+};
+
+/* returns 1 if the bytes are available immediately (in which case
+ * on_complete will not be called), 0 if the bytes will be available
+ * asynchronously.
+ *
+ * on entry, *remaining can be set as a hint as to the maximum number
+ * of bytes that would be acceptable to read.
+ *
+ * fills *buffer, *length, *remaining with the bytes, length of bytes
+ * and length of data remaining to be read before either returning 1
+ * or calling on_complete.
+ *
+ * once a slice is returned into *slice, it is owned by the caller.
+ */
+int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
+                          grpc_byte_stream *byte_stream, gpr_slice *slice,
+                          size_t max_size_hint, grpc_closure *on_complete);
+
+void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
+                              grpc_byte_stream *byte_stream);
+
+/* grpc_byte_stream that wraps a slice buffer */
+typedef struct grpc_slice_buffer_stream {
+  grpc_byte_stream base;
+  gpr_slice_buffer *backing_buffer;
+  size_t cursor;
+} grpc_slice_buffer_stream;
+
+void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream,
+                                   gpr_slice_buffer *slice_buffer,
+                                   uint32_t flags);
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H */
diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c
new file mode 100644
index 0000000..e24ee63
--- /dev/null
+++ b/src/core/lib/transport/connectivity_state.c
@@ -0,0 +1,164 @@
+/*
+ *
+ * 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/transport/connectivity_state.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+int grpc_connectivity_state_trace = 0;
+
+const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
+  switch (state) {
+    case GRPC_CHANNEL_IDLE:
+      return "IDLE";
+    case GRPC_CHANNEL_CONNECTING:
+      return "CONNECTING";
+    case GRPC_CHANNEL_READY:
+      return "READY";
+    case GRPC_CHANNEL_TRANSIENT_FAILURE:
+      return "TRANSIENT_FAILURE";
+    case GRPC_CHANNEL_FATAL_FAILURE:
+      return "FATAL_FAILURE";
+  }
+  GPR_UNREACHABLE_CODE(return "UNKNOWN");
+}
+
+void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
+                                  grpc_connectivity_state init_state,
+                                  const char *name) {
+  tracker->current_state = init_state;
+  tracker->watchers = NULL;
+  tracker->name = gpr_strdup(name);
+}
+
+void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
+                                     grpc_connectivity_state_tracker *tracker) {
+  int success;
+  grpc_connectivity_state_watcher *w;
+  while ((w = tracker->watchers)) {
+    tracker->watchers = w->next;
+
+    if (GRPC_CHANNEL_FATAL_FAILURE != *w->current) {
+      *w->current = GRPC_CHANNEL_FATAL_FAILURE;
+      success = 1;
+    } else {
+      success = 0;
+    }
+    grpc_exec_ctx_enqueue(exec_ctx, w->notify, success, NULL);
+    gpr_free(w);
+  }
+  gpr_free(tracker->name);
+}
+
+grpc_connectivity_state grpc_connectivity_state_check(
+    grpc_connectivity_state_tracker *tracker) {
+  if (grpc_connectivity_state_trace) {
+    gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
+            grpc_connectivity_state_name(tracker->current_state));
+  }
+  return tracker->current_state;
+}
+
+int grpc_connectivity_state_notify_on_state_change(
+    grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
+    grpc_connectivity_state *current, grpc_closure *notify) {
+  if (grpc_connectivity_state_trace) {
+    if (current == NULL) {
+      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
+              tracker->name, notify);
+    } else {
+      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
+              tracker->name, grpc_connectivity_state_name(*current),
+              grpc_connectivity_state_name(tracker->current_state), notify);
+    }
+  }
+  if (current == NULL) {
+    grpc_connectivity_state_watcher *w = tracker->watchers;
+    if (w != NULL && w->notify == notify) {
+      grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
+      tracker->watchers = w->next;
+      gpr_free(w);
+      return 0;
+    }
+    while (w != NULL) {
+      grpc_connectivity_state_watcher *rm_candidate = w->next;
+      if (rm_candidate != NULL && rm_candidate->notify == notify) {
+        grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
+        w->next = w->next->next;
+        gpr_free(rm_candidate);
+        return 0;
+      }
+      w = w->next;
+    }
+    return 0;
+  } else {
+    if (tracker->current_state != *current) {
+      *current = tracker->current_state;
+      grpc_exec_ctx_enqueue(exec_ctx, notify, true, NULL);
+    } else {
+      grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w));
+      w->current = current;
+      w->notify = notify;
+      w->next = tracker->watchers;
+      tracker->watchers = w;
+    }
+    return tracker->current_state == GRPC_CHANNEL_IDLE;
+  }
+}
+
+void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
+                                 grpc_connectivity_state_tracker *tracker,
+                                 grpc_connectivity_state state,
+                                 const char *reason) {
+  grpc_connectivity_state_watcher *w;
+  if (grpc_connectivity_state_trace) {
+    gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s]", tracker, tracker->name,
+            grpc_connectivity_state_name(tracker->current_state),
+            grpc_connectivity_state_name(state), reason);
+  }
+  if (tracker->current_state == state) {
+    return;
+  }
+  GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_FATAL_FAILURE);
+  tracker->current_state = state;
+  while ((w = tracker->watchers) != NULL) {
+    *w->current = tracker->current_state;
+    tracker->watchers = w->next;
+    grpc_exec_ctx_enqueue(exec_ctx, w->notify, true, NULL);
+    gpr_free(w);
+  }
+}
diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h
new file mode 100644
index 0000000..2eb7e09
--- /dev/null
+++ b/src/core/lib/transport/connectivity_state.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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_TRANSPORT_CONNECTIVITY_STATE_H
+#define GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H
+
+#include <grpc/grpc.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+typedef struct grpc_connectivity_state_watcher {
+  /** we keep watchers in a linked list */
+  struct grpc_connectivity_state_watcher *next;
+  /** closure to notify on change */
+  grpc_closure *notify;
+  /** the current state as believed by the watcher */
+  grpc_connectivity_state *current;
+} grpc_connectivity_state_watcher;
+
+typedef struct {
+  /** current connectivity state */
+  grpc_connectivity_state current_state;
+  /** all our watchers */
+  grpc_connectivity_state_watcher *watchers;
+  /** a name to help debugging */
+  char *name;
+} grpc_connectivity_state_tracker;
+
+extern int grpc_connectivity_state_trace;
+
+const char *grpc_connectivity_state_name(grpc_connectivity_state state);
+
+void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
+                                  grpc_connectivity_state init_state,
+                                  const char *name);
+void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
+                                     grpc_connectivity_state_tracker *tracker);
+
+/** Set connectivity state; not thread safe; access must be serialized with an
+ * external lock */
+void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
+                                 grpc_connectivity_state_tracker *tracker,
+                                 grpc_connectivity_state state,
+                                 const char *reason);
+
+grpc_connectivity_state grpc_connectivity_state_check(
+    grpc_connectivity_state_tracker *tracker);
+
+/** Return 1 if the channel should start connecting, 0 otherwise.
+    If current==NULL cancel notify if it is already queued (success==0 in that
+    case) */
+int grpc_connectivity_state_notify_on_state_change(
+    grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
+    grpc_connectivity_state *current, grpc_closure *notify);
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H */
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
new file mode 100644
index 0000000..779efbb
--- /dev/null
+++ b/src/core/lib/transport/metadata.c
@@ -0,0 +1,743 @@
+/*
+ *
+ * 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/transport/metadata.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <grpc/compression.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/support/murmur_hash.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+gpr_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(gpr_slice input);
+
+/* There are two kinds of mdelem and mdstr instances.
+ * Static instances are declared in static_metadata.{h,c} and
+ * are initialized by grpc_mdctx_global_init().
+ * Dynamic instances are stored in hash tables on grpc_mdctx, and are backed
+ * by internal_string and internal_element structures.
+ * Internal helper functions here-in (is_mdstr_static, is_mdelem_static) are
+ * used to determine which kind of element a pointer refers to.
+ */
+
+#define INITIAL_STRTAB_CAPACITY 4
+#define INITIAL_MDTAB_CAPACITY 4
+
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+#define DEBUG_ARGS , const char *file, int line
+#define FWD_DEBUG_ARGS , file, line
+#define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s), __FILE__, __LINE__)
+#else
+#define DEBUG_ARGS
+#define FWD_DEBUG_ARGS
+#define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s))
+#endif
+
+#define TABLE_IDX(hash, log2_shards, capacity) \
+  (((hash) >> (log2_shards)) % (capacity))
+#define SHARD_IDX(hash, log2_shards) ((hash) & ((1 << (log2_shards)) - 1))
+
+typedef void (*destroy_user_data_func)(void *user_data);
+
+#define SIZE_IN_DECODER_TABLE_NOT_SET -1
+/* Shadow structure for grpc_mdstr for non-static values */
+typedef struct internal_string {
+  /* must be byte compatible with grpc_mdstr */
+  gpr_slice slice;
+  uint32_t hash;
+
+  /* private only data */
+  gpr_atm refcnt;
+
+  uint8_t has_base64_and_huffman_encoded;
+  gpr_slice_refcount refcount;
+
+  gpr_slice base64_and_huffman;
+
+  gpr_atm size_in_decoder_table;
+
+  struct internal_string *bucket_next;
+} internal_string;
+
+/* Shadow structure for grpc_mdelem for non-static elements */
+typedef struct internal_metadata {
+  /* must be byte compatible with grpc_mdelem */
+  internal_string *key;
+  internal_string *value;
+
+  /* private only data */
+  gpr_atm refcnt;
+
+  gpr_mu mu_user_data;
+  gpr_atm destroy_user_data;
+  gpr_atm user_data;
+
+  struct internal_metadata *bucket_next;
+} internal_metadata;
+
+typedef struct strtab_shard {
+  gpr_mu mu;
+  internal_string **strs;
+  size_t count;
+  size_t capacity;
+} strtab_shard;
+
+typedef struct mdtab_shard {
+  gpr_mu mu;
+  internal_metadata **elems;
+  size_t count;
+  size_t capacity;
+  size_t free;
+} mdtab_shard;
+
+#define LOG2_STRTAB_SHARD_COUNT 5
+#define LOG2_MDTAB_SHARD_COUNT 4
+#define STRTAB_SHARD_COUNT ((size_t)(1 << LOG2_STRTAB_SHARD_COUNT))
+#define MDTAB_SHARD_COUNT ((size_t)(1 << LOG2_MDTAB_SHARD_COUNT))
+
+/* hash seed: decided at initialization time */
+static uint32_t g_hash_seed;
+static int g_forced_hash_seed = 0;
+
+/* linearly probed hash tables for static element lookup */
+static grpc_mdstr *g_static_strtab[GRPC_STATIC_MDSTR_COUNT * 2];
+static grpc_mdelem *g_static_mdtab[GRPC_STATIC_MDELEM_COUNT * 2];
+static size_t g_static_strtab_maxprobe;
+static size_t g_static_mdtab_maxprobe;
+
+static strtab_shard g_strtab_shard[STRTAB_SHARD_COUNT];
+static mdtab_shard g_mdtab_shard[MDTAB_SHARD_COUNT];
+
+static void gc_mdtab(mdtab_shard *shard);
+
+void grpc_test_only_set_metadata_hash_seed(uint32_t seed) {
+  g_hash_seed = seed;
+  g_forced_hash_seed = 1;
+}
+
+void grpc_mdctx_global_init(void) {
+  size_t i, j;
+  if (!g_forced_hash_seed) {
+    g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
+  }
+  g_static_strtab_maxprobe = 0;
+  g_static_mdtab_maxprobe = 0;
+  /* build static tables */
+  memset(g_static_mdtab, 0, sizeof(g_static_mdtab));
+  memset(g_static_strtab, 0, sizeof(g_static_strtab));
+  for (i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    grpc_mdstr *elem = &grpc_static_mdstr_table[i];
+    const char *str = grpc_static_metadata_strings[i];
+    uint32_t hash = gpr_murmur_hash3(str, strlen(str), g_hash_seed);
+    *(gpr_slice *)&elem->slice = gpr_slice_from_static_string(str);
+    *(uint32_t *)&elem->hash = hash;
+    for (j = 0;; j++) {
+      size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_strtab);
+      if (g_static_strtab[idx] == NULL) {
+        g_static_strtab[idx] = &grpc_static_mdstr_table[i];
+        break;
+      }
+    }
+    if (j > g_static_strtab_maxprobe) {
+      g_static_strtab_maxprobe = j;
+    }
+  }
+  for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
+    grpc_mdelem *elem = &grpc_static_mdelem_table[i];
+    grpc_mdstr *key =
+        &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 0]];
+    grpc_mdstr *value =
+        &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 1]];
+    uint32_t hash = GRPC_MDSTR_KV_HASH(key->hash, value->hash);
+    *(grpc_mdstr **)&elem->key = key;
+    *(grpc_mdstr **)&elem->value = value;
+    for (j = 0;; j++) {
+      size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_mdtab);
+      if (g_static_mdtab[idx] == NULL) {
+        g_static_mdtab[idx] = elem;
+        break;
+      }
+    }
+    if (j > g_static_mdtab_maxprobe) {
+      g_static_mdtab_maxprobe = j;
+    }
+  }
+  /* initialize shards */
+  for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
+    strtab_shard *shard = &g_strtab_shard[i];
+    gpr_mu_init(&shard->mu);
+    shard->count = 0;
+    shard->capacity = INITIAL_STRTAB_CAPACITY;
+    shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity);
+    memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity);
+  }
+  for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
+    mdtab_shard *shard = &g_mdtab_shard[i];
+    gpr_mu_init(&shard->mu);
+    shard->count = 0;
+    shard->free = 0;
+    shard->capacity = INITIAL_MDTAB_CAPACITY;
+    shard->elems = gpr_malloc(sizeof(*shard->elems) * shard->capacity);
+    memset(shard->elems, 0, sizeof(*shard->elems) * shard->capacity);
+  }
+}
+
+void grpc_mdctx_global_shutdown(void) {
+  size_t i;
+  for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
+    mdtab_shard *shard = &g_mdtab_shard[i];
+    gpr_mu_destroy(&shard->mu);
+    gc_mdtab(shard);
+    /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
+    if (shard->count != 0) {
+      gpr_log(GPR_DEBUG, "WARNING: %d metadata elements were leaked",
+              shard->count);
+      if (grpc_iomgr_abort_on_leaks()) {
+        abort();
+      }
+    }
+    gpr_free(shard->elems);
+  }
+  for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
+    strtab_shard *shard = &g_strtab_shard[i];
+    gpr_mu_destroy(&shard->mu);
+    /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
+    if (shard->count != 0) {
+      gpr_log(GPR_DEBUG, "WARNING: %d metadata strings were leaked",
+              shard->count);
+      for (size_t j = 0; j < shard->capacity; j++) {
+        for (internal_string *s = shard->strs[j]; s; s = s->bucket_next) {
+          gpr_log(GPR_DEBUG, "LEAKED: %s",
+                  grpc_mdstr_as_c_string((grpc_mdstr *)s));
+        }
+      }
+      if (grpc_iomgr_abort_on_leaks()) {
+        abort();
+      }
+    }
+    gpr_free(shard->strs);
+  }
+}
+
+static int is_mdstr_static(grpc_mdstr *s) {
+  return s >= &grpc_static_mdstr_table[0] &&
+         s < &grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
+}
+
+static int is_mdelem_static(grpc_mdelem *e) {
+  return e >= &grpc_static_mdelem_table[0] &&
+         e < &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+}
+
+static void ref_md_locked(mdtab_shard *shard,
+                          internal_metadata *md DEBUG_ARGS) {
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "ELM   REF:%p:%d->%d: '%s' = '%s'", md,
+          gpr_atm_no_barrier_load(&md->refcnt),
+          gpr_atm_no_barrier_load(&md->refcnt) + 1,
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
+  if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 2)) {
+    shard->free--;
+  } else {
+    GPR_ASSERT(1 != gpr_atm_no_barrier_fetch_add(&md->refcnt, -1));
+  }
+}
+
+static void grow_strtab(strtab_shard *shard) {
+  size_t capacity = shard->capacity * 2;
+  size_t i;
+  internal_string **strtab;
+  internal_string *s, *next;
+
+  GPR_TIMER_BEGIN("grow_strtab", 0);
+
+  strtab = gpr_malloc(sizeof(internal_string *) * capacity);
+  memset(strtab, 0, sizeof(internal_string *) * capacity);
+
+  for (i = 0; i < shard->capacity; i++) {
+    for (s = shard->strs[i]; s; s = next) {
+      size_t idx = TABLE_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT, capacity);
+      next = s->bucket_next;
+      s->bucket_next = strtab[idx];
+      strtab[idx] = s;
+    }
+  }
+
+  gpr_free(shard->strs);
+  shard->strs = strtab;
+  shard->capacity = capacity;
+
+  GPR_TIMER_END("grow_strtab", 0);
+}
+
+static void internal_destroy_string(strtab_shard *shard, internal_string *is) {
+  internal_string **prev_next;
+  internal_string *cur;
+  GPR_TIMER_BEGIN("internal_destroy_string", 0);
+  if (is->has_base64_and_huffman_encoded) {
+    gpr_slice_unref(is->base64_and_huffman);
+  }
+  for (prev_next = &shard->strs[TABLE_IDX(is->hash, LOG2_STRTAB_SHARD_COUNT,
+                                          shard->capacity)],
+      cur = *prev_next;
+       cur != is; prev_next = &cur->bucket_next, cur = cur->bucket_next)
+    ;
+  *prev_next = cur->bucket_next;
+  shard->count--;
+  gpr_free(is);
+  GPR_TIMER_END("internal_destroy_string", 0);
+}
+
+static void slice_ref(void *p) {
+  internal_string *is =
+      (internal_string *)((char *)p - offsetof(internal_string, refcount));
+  GRPC_MDSTR_REF((grpc_mdstr *)(is));
+}
+
+static void slice_unref(void *p) {
+  internal_string *is =
+      (internal_string *)((char *)p - offsetof(internal_string, refcount));
+  GRPC_MDSTR_UNREF((grpc_mdstr *)(is));
+}
+
+grpc_mdstr *grpc_mdstr_from_string(const char *str) {
+  return grpc_mdstr_from_buffer((const uint8_t *)str, strlen(str));
+}
+
+grpc_mdstr *grpc_mdstr_from_slice(gpr_slice slice) {
+  grpc_mdstr *result = grpc_mdstr_from_buffer(GPR_SLICE_START_PTR(slice),
+                                              GPR_SLICE_LENGTH(slice));
+  gpr_slice_unref(slice);
+  return result;
+}
+
+grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
+  uint32_t hash = gpr_murmur_hash3(buf, length, g_hash_seed);
+  internal_string *s;
+  strtab_shard *shard =
+      &g_strtab_shard[SHARD_IDX(hash, LOG2_STRTAB_SHARD_COUNT)];
+  size_t i;
+  size_t idx;
+
+  GPR_TIMER_BEGIN("grpc_mdstr_from_buffer", 0);
+
+  /* search for a static string */
+  for (i = 0; i <= g_static_strtab_maxprobe; i++) {
+    grpc_mdstr *ss;
+    idx = (hash + i) % GPR_ARRAY_SIZE(g_static_strtab);
+    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)) {
+      GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
+      return ss;
+    }
+  }
+
+  gpr_mu_lock(&shard->mu);
+
+  /* search for an existing string */
+  idx = TABLE_IDX(hash, LOG2_STRTAB_SHARD_COUNT, shard->capacity);
+  for (s = shard->strs[idx]; s; s = s->bucket_next) {
+    if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length &&
+        0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) {
+      GRPC_MDSTR_REF((grpc_mdstr *)s);
+      gpr_mu_unlock(&shard->mu);
+      GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
+      return (grpc_mdstr *)s;
+    }
+  }
+
+  /* not found: create a new string */
+  if (length + 1 < GPR_SLICE_INLINED_SIZE) {
+    /* string data goes directly into the slice */
+    s = gpr_malloc(sizeof(internal_string));
+    gpr_atm_rel_store(&s->refcnt, 2);
+    s->slice.refcount = NULL;
+    memcpy(s->slice.data.inlined.bytes, buf, length);
+    s->slice.data.inlined.bytes[length] = 0;
+    s->slice.data.inlined.length = (uint8_t)length;
+  } else {
+    /* string data goes after the internal_string header, and we +1 for null
+       terminator */
+    s = gpr_malloc(sizeof(internal_string) + length + 1);
+    gpr_atm_rel_store(&s->refcnt, 2);
+    s->refcount.ref = slice_ref;
+    s->refcount.unref = slice_unref;
+    s->slice.refcount = &s->refcount;
+    s->slice.data.refcounted.bytes = (uint8_t *)(s + 1);
+    s->slice.data.refcounted.length = length;
+    memcpy(s->slice.data.refcounted.bytes, buf, length);
+    /* add a null terminator for cheap c string conversion when desired */
+    s->slice.data.refcounted.bytes[length] = 0;
+  }
+  s->has_base64_and_huffman_encoded = 0;
+  s->hash = hash;
+  s->size_in_decoder_table = SIZE_IN_DECODER_TABLE_NOT_SET;
+  s->bucket_next = shard->strs[idx];
+  shard->strs[idx] = s;
+
+  shard->count++;
+
+  if (shard->count > shard->capacity * 2) {
+    grow_strtab(shard);
+  }
+
+  gpr_mu_unlock(&shard->mu);
+  GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
+
+  return (grpc_mdstr *)s;
+}
+
+static void gc_mdtab(mdtab_shard *shard) {
+  size_t i;
+  internal_metadata **prev_next;
+  internal_metadata *md, *next;
+
+  GPR_TIMER_BEGIN("gc_mdtab", 0);
+  for (i = 0; i < shard->capacity; i++) {
+    prev_next = &shard->elems[i];
+    for (md = shard->elems[i]; md; md = next) {
+      void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data);
+      next = md->bucket_next;
+      if (gpr_atm_acq_load(&md->refcnt) == 0) {
+        GRPC_MDSTR_UNREF((grpc_mdstr *)md->key);
+        GRPC_MDSTR_UNREF((grpc_mdstr *)md->value);
+        if (md->user_data) {
+          ((destroy_user_data_func)gpr_atm_no_barrier_load(
+              &md->destroy_user_data))(user_data);
+        }
+        gpr_free(md);
+        *prev_next = next;
+        shard->free--;
+        shard->count--;
+      } else {
+        prev_next = &md->bucket_next;
+      }
+    }
+  }
+  GPR_TIMER_END("gc_mdtab", 0);
+}
+
+static void grow_mdtab(mdtab_shard *shard) {
+  size_t capacity = shard->capacity * 2;
+  size_t i;
+  internal_metadata **mdtab;
+  internal_metadata *md, *next;
+  uint32_t hash;
+
+  GPR_TIMER_BEGIN("grow_mdtab", 0);
+
+  mdtab = gpr_malloc(sizeof(internal_metadata *) * capacity);
+  memset(mdtab, 0, sizeof(internal_metadata *) * capacity);
+
+  for (i = 0; i < shard->capacity; i++) {
+    for (md = shard->elems[i]; md; md = next) {
+      size_t idx;
+      hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
+      next = md->bucket_next;
+      idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, capacity);
+      md->bucket_next = mdtab[idx];
+      mdtab[idx] = md;
+    }
+  }
+
+  gpr_free(shard->elems);
+  shard->elems = mdtab;
+  shard->capacity = capacity;
+
+  GPR_TIMER_END("grow_mdtab", 0);
+}
+
+static void rehash_mdtab(mdtab_shard *shard) {
+  if (shard->free > shard->capacity / 4) {
+    gc_mdtab(shard);
+  } else {
+    grow_mdtab(shard);
+  }
+}
+
+grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *mkey,
+                                               grpc_mdstr *mvalue) {
+  internal_string *key = (internal_string *)mkey;
+  internal_string *value = (internal_string *)mvalue;
+  uint32_t hash = GRPC_MDSTR_KV_HASH(mkey->hash, mvalue->hash);
+  internal_metadata *md;
+  mdtab_shard *shard = &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
+  size_t i;
+  size_t idx;
+
+  GPR_TIMER_BEGIN("grpc_mdelem_from_metadata_strings", 0);
+
+  if (is_mdstr_static(mkey) && is_mdstr_static(mvalue)) {
+    for (i = 0; i <= g_static_mdtab_maxprobe; i++) {
+      grpc_mdelem *smd;
+      idx = (hash + i) % GPR_ARRAY_SIZE(g_static_mdtab);
+      smd = g_static_mdtab[idx];
+      if (smd == NULL) break;
+      if (smd->key == mkey && smd->value == mvalue) {
+        GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
+        return smd;
+      }
+    }
+  }
+
+  gpr_mu_lock(&shard->mu);
+
+  idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, shard->capacity);
+  /* search for an existing pair */
+  for (md = shard->elems[idx]; md; md = md->bucket_next) {
+    if (md->key == key && md->value == value) {
+      REF_MD_LOCKED(shard, md);
+      GRPC_MDSTR_UNREF((grpc_mdstr *)key);
+      GRPC_MDSTR_UNREF((grpc_mdstr *)value);
+      gpr_mu_unlock(&shard->mu);
+      GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
+      return (grpc_mdelem *)md;
+    }
+  }
+
+  /* not found: create a new pair */
+  md = gpr_malloc(sizeof(internal_metadata));
+  gpr_atm_rel_store(&md->refcnt, 2);
+  md->key = key;
+  md->value = value;
+  md->user_data = 0;
+  md->destroy_user_data = 0;
+  md->bucket_next = shard->elems[idx];
+  shard->elems[idx] = md;
+  gpr_mu_init(&md->mu_user_data);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+  gpr_log(GPR_DEBUG, "ELM   NEW:%p:%d: '%s' = '%s'", md,
+          gpr_atm_no_barrier_load(&md->refcnt),
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
+  shard->count++;
+
+  if (shard->count > shard->capacity * 2) {
+    rehash_mdtab(shard);
+  }
+
+  gpr_mu_unlock(&shard->mu);
+
+  GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
+
+  return (grpc_mdelem *)md;
+}
+
+grpc_mdelem *grpc_mdelem_from_strings(const char *key, const char *value) {
+  return grpc_mdelem_from_metadata_strings(grpc_mdstr_from_string(key),
+                                           grpc_mdstr_from_string(value));
+}
+
+grpc_mdelem *grpc_mdelem_from_slices(gpr_slice key, gpr_slice value) {
+  return grpc_mdelem_from_metadata_strings(grpc_mdstr_from_slice(key),
+                                           grpc_mdstr_from_slice(value));
+}
+
+grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key,
+                                                const uint8_t *value,
+                                                size_t value_length) {
+  return grpc_mdelem_from_metadata_strings(
+      grpc_mdstr_from_string(key), grpc_mdstr_from_buffer(value, value_length));
+}
+
+static size_t get_base64_encoded_size(size_t raw_length) {
+  static const uint8_t tail_xtra[3] = {0, 2, 3};
+  return raw_length / 3 * 4 + tail_xtra[raw_length % 3];
+}
+
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem) {
+  size_t overhead_and_key = 32 + GPR_SLICE_LENGTH(elem->key->slice);
+  size_t value_len = GPR_SLICE_LENGTH(elem->value->slice);
+  if (is_mdstr_static(elem->value)) {
+    if (grpc_is_binary_header(
+            (const char *)GPR_SLICE_START_PTR(elem->key->slice),
+            GPR_SLICE_LENGTH(elem->key->slice))) {
+      return overhead_and_key + get_base64_encoded_size(value_len);
+    } else {
+      return overhead_and_key + value_len;
+    }
+  } else {
+    internal_string *is = (internal_string *)elem->value;
+    gpr_atm current_size = gpr_atm_acq_load(&is->size_in_decoder_table);
+    if (current_size == SIZE_IN_DECODER_TABLE_NOT_SET) {
+      if (grpc_is_binary_header(
+              (const char *)GPR_SLICE_START_PTR(elem->key->slice),
+              GPR_SLICE_LENGTH(elem->key->slice))) {
+        current_size = (gpr_atm)get_base64_encoded_size(value_len);
+      } else {
+        current_size = (gpr_atm)value_len;
+      }
+      gpr_atm_rel_store(&is->size_in_decoder_table, current_size);
+    }
+    return overhead_and_key + (size_t)current_size;
+  }
+}
+
+grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
+  internal_metadata *md = (internal_metadata *)gmd;
+  if (is_mdelem_static(gmd)) return gmd;
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "ELM   REF:%p:%d->%d: '%s' = '%s'", md,
+          gpr_atm_no_barrier_load(&md->refcnt),
+          gpr_atm_no_barrier_load(&md->refcnt) + 1,
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
+  /* we can assume the ref count is >= 1 as the application is calling
+     this function - meaning that no adjustment to mdtab_free is necessary,
+     simplifying the logic here to be just an atomic increment */
+  /* use C assert to have this removed in opt builds */
+  assert(gpr_atm_no_barrier_load(&md->refcnt) >= 2);
+  gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
+  return gmd;
+}
+
+void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) {
+  internal_metadata *md = (internal_metadata *)gmd;
+  if (!md) return;
+  if (is_mdelem_static(gmd)) return;
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "ELM UNREF:%p:%d->%d: '%s' = '%s'", md,
+          gpr_atm_no_barrier_load(&md->refcnt),
+          gpr_atm_no_barrier_load(&md->refcnt) - 1,
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
+          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+#endif
+  if (2 == gpr_atm_full_fetch_add(&md->refcnt, -1)) {
+    uint32_t hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
+    mdtab_shard *shard =
+        &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
+    GPR_TIMER_BEGIN("grpc_mdelem_unref.to_zero", 0);
+    gpr_mu_lock(&shard->mu);
+    if (1 == gpr_atm_no_barrier_load(&md->refcnt)) {
+      shard->free++;
+      gpr_atm_no_barrier_store(&md->refcnt, 0);
+    }
+    gpr_mu_unlock(&shard->mu);
+    GPR_TIMER_END("grpc_mdelem_unref.to_zero", 0);
+  }
+}
+
+const char *grpc_mdstr_as_c_string(grpc_mdstr *s) {
+  return (const char *)GPR_SLICE_START_PTR(s->slice);
+}
+
+grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
+  internal_string *s = (internal_string *)gs;
+  if (is_mdstr_static(gs)) return gs;
+  GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) != 0);
+  return gs;
+}
+
+void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
+  internal_string *s = (internal_string *)gs;
+  if (is_mdstr_static(gs)) return;
+  if (2 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
+    strtab_shard *shard =
+        &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
+    gpr_mu_lock(&shard->mu);
+    if (1 == gpr_atm_no_barrier_load(&s->refcnt)) {
+      internal_destroy_string(shard, s);
+    }
+    gpr_mu_unlock(&shard->mu);
+  }
+}
+
+void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) {
+  internal_metadata *im = (internal_metadata *)md;
+  void *result;
+  if (is_mdelem_static(md)) {
+    return (void *)grpc_static_mdelem_user_data[md - grpc_static_mdelem_table];
+  }
+  if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
+    return (void *)gpr_atm_no_barrier_load(&im->user_data);
+  } else {
+    return NULL;
+  }
+  return result;
+}
+
+void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
+                               void *user_data) {
+  internal_metadata *im = (internal_metadata *)md;
+  GPR_ASSERT(!is_mdelem_static(md));
+  GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
+  gpr_mu_lock(&im->mu_user_data);
+  if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
+    /* user data can only be set once */
+    gpr_mu_unlock(&im->mu_user_data);
+    if (destroy_func != NULL) {
+      destroy_func(user_data);
+    }
+    return;
+  }
+  gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
+  gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
+  gpr_mu_unlock(&im->mu_user_data);
+}
+
+gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {
+  internal_string *s = (internal_string *)gs;
+  gpr_slice slice;
+  strtab_shard *shard =
+      &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
+  gpr_mu_lock(&shard->mu);
+  if (!s->has_base64_and_huffman_encoded) {
+    s->base64_and_huffman =
+        grpc_chttp2_base64_encode_and_huffman_compress(s->slice);
+    s->has_base64_and_huffman_encoded = 1;
+  }
+  slice = s->base64_and_huffman;
+  gpr_mu_unlock(&shard->mu);
+  return slice;
+}
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
new file mode 100644
index 0000000..713d9e6
--- /dev/null
+++ b/src/core/lib/transport/metadata.h
@@ -0,0 +1,163 @@
+/*
+ *
+ * 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_TRANSPORT_METADATA_H
+#define GRPC_CORE_LIB_TRANSPORT_METADATA_H
+
+#include <grpc/support/slice.h>
+#include <grpc/support/useful.h>
+
+/* This file provides a mechanism for tracking metadata through the grpc stack.
+   It's not intended for consumption outside of the library.
+
+   Metadata is tracked in the context of a grpc_mdctx. For the time being there
+   is one of these per-channel, avoiding cross channel interference with memory
+   use and lock contention.
+
+   The context tracks unique strings (grpc_mdstr) and pairs of strings
+   (grpc_mdelem). Any of these objects can be checked for equality by comparing
+   their pointers. These objects are reference counted.
+
+   grpc_mdelem can additionally store a (non-NULL) user data pointer. This
+   pointer is intended to be used to cache semantic meaning of a metadata
+   element. For example, an OAuth token may cache the credentials it represents
+   and the time at which it expires in the mdelem user data.
+
+   Combining this metadata cache and the hpack compression table allows us to
+   simply lookup complete preparsed objects quickly, incurring a few atomic
+   ops per metadata element on the fast path.
+
+   grpc_mdelem instances MAY live longer than their refcount implies, and are
+   garbage collected periodically, meaning cached data can easily outlive a
+   single request.
+
+   STATIC METADATA: in static_metadata.h we declare a set of static metadata.
+   These mdelems and mdstrs are available via pre-declared code generated macros
+   and are available to code anywhere between grpc_init() and grpc_shutdown().
+   They are not refcounted, but can be passed to _ref and _unref functions
+   declared here - in which case those functions are effectively no-ops. */
+
+/* Forward declarations */
+typedef struct grpc_mdstr grpc_mdstr;
+typedef struct grpc_mdelem grpc_mdelem;
+
+/* if changing this, make identical changes in internal_string in metadata.c */
+struct grpc_mdstr {
+  const gpr_slice slice;
+  const uint32_t hash;
+  /* there is a private part to this in metadata.c */
+};
+
+/* if changing this, make identical changes in internal_metadata in
+   metadata.c */
+struct grpc_mdelem {
+  grpc_mdstr *const key;
+  grpc_mdstr *const value;
+  /* there is a private part to this in metadata.c */
+};
+
+void grpc_test_only_set_metadata_hash_seed(uint32_t seed);
+
+/* Constructors for grpc_mdstr instances; take a variety of data types that
+   clients may have handy */
+grpc_mdstr *grpc_mdstr_from_string(const char *str);
+/* Unrefs the slice. */
+grpc_mdstr *grpc_mdstr_from_slice(gpr_slice slice);
+grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *str, size_t length);
+
+/* Returns a borrowed slice from the mdstr with its contents base64 encoded
+   and huffman compressed */
+gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *str);
+
+/* Constructors for grpc_mdelem instances; take a variety of data types that
+   clients may have handy */
+grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *key,
+                                               grpc_mdstr *value);
+grpc_mdelem *grpc_mdelem_from_strings(const char *key, const char *value);
+/* Unrefs the slices. */
+grpc_mdelem *grpc_mdelem_from_slices(gpr_slice key, gpr_slice value);
+grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key,
+                                                const uint8_t *value,
+                                                size_t value_length);
+
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem);
+
+/* Mutator and accessor for grpc_mdelem user data. The destructor function
+   is used as a type tag and is checked during user_data fetch. */
+void *grpc_mdelem_get_user_data(grpc_mdelem *md,
+                                void (*if_destroy_func)(void *));
+void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
+                               void *user_data);
+
+/* Reference counting */
+//#define GRPC_METADATA_REFCOUNT_DEBUG
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__)
+#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s), __FILE__, __LINE__)
+#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
+#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s), __FILE__, __LINE__)
+grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s, const char *file, int line);
+void grpc_mdstr_unref(grpc_mdstr *s, const char *file, int line);
+grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md, const char *file, int line);
+void grpc_mdelem_unref(grpc_mdelem *md, const char *file, int line);
+#else
+#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s))
+#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s))
+#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s))
+#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s))
+grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s);
+void grpc_mdstr_unref(grpc_mdstr *s);
+grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
+void grpc_mdelem_unref(grpc_mdelem *md);
+#endif
+
+/* Recover a char* from a grpc_mdstr. The returned string is null terminated.
+   Does not promise that the returned string has no embedded nulls however. */
+const char *grpc_mdstr_as_c_string(grpc_mdstr *s);
+
+#define GRPC_MDSTR_LENGTH(s) (GPR_SLICE_LENGTH(s->slice))
+
+int grpc_mdstr_is_legal_header(grpc_mdstr *s);
+int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s);
+int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
+
+#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash))
+
+void grpc_mdctx_global_init(void);
+void grpc_mdctx_global_shutdown(void);
+
+/* Implementation provided by chttp2_transport */
+extern gpr_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(
+    gpr_slice input);
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */
diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c
new file mode 100644
index 0000000..4567221
--- /dev/null
+++ b/src/core/lib/transport/metadata_batch.c
@@ -0,0 +1,194 @@
+/*
+ *
+ * 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/transport/metadata_batch.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/profiling/timers.h"
+
+static void assert_valid_list(grpc_mdelem_list *list) {
+#ifndef NDEBUG
+  grpc_linked_mdelem *l;
+
+  GPR_ASSERT((list->head == NULL) == (list->tail == NULL));
+  if (!list->head) return;
+  GPR_ASSERT(list->head->prev == NULL);
+  GPR_ASSERT(list->tail->next == NULL);
+  GPR_ASSERT((list->head == list->tail) == (list->head->next == NULL));
+
+  for (l = list->head; l; l = l->next) {
+    GPR_ASSERT(l->md);
+    GPR_ASSERT((l->prev == NULL) == (l == list->head));
+    GPR_ASSERT((l->next == NULL) == (l == list->tail));
+    if (l->next) GPR_ASSERT(l->next->prev == l);
+    if (l->prev) GPR_ASSERT(l->prev->next == l);
+  }
+#endif /* NDEBUG */
+}
+
+#ifndef NDEBUG
+void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) {
+  assert_valid_list(&batch->list);
+}
+#endif /* NDEBUG */
+
+void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
+  batch->list.head = batch->list.tail = NULL;
+  batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
+}
+
+void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) {
+  grpc_linked_mdelem *l;
+  for (l = batch->list.head; l; l = l->next) {
+    GRPC_MDELEM_UNREF(l->md);
+  }
+}
+
+void grpc_metadata_batch_add_head(grpc_metadata_batch *batch,
+                                  grpc_linked_mdelem *storage,
+                                  grpc_mdelem *elem_to_add) {
+  GPR_ASSERT(elem_to_add);
+  storage->md = elem_to_add;
+  grpc_metadata_batch_link_head(batch, storage);
+}
+
+static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
+  assert_valid_list(list);
+  GPR_ASSERT(storage->md);
+  storage->prev = NULL;
+  storage->next = list->head;
+  if (list->head != NULL) {
+    list->head->prev = storage;
+  } else {
+    list->tail = storage;
+  }
+  list->head = storage;
+  assert_valid_list(list);
+}
+
+void grpc_metadata_batch_link_head(grpc_metadata_batch *batch,
+                                   grpc_linked_mdelem *storage) {
+  link_head(&batch->list, storage);
+}
+
+void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
+                                  grpc_linked_mdelem *storage,
+                                  grpc_mdelem *elem_to_add) {
+  GPR_ASSERT(elem_to_add);
+  storage->md = elem_to_add;
+  grpc_metadata_batch_link_tail(batch, storage);
+}
+
+static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
+  assert_valid_list(list);
+  GPR_ASSERT(storage->md);
+  storage->prev = list->tail;
+  storage->next = NULL;
+  storage->reserved = NULL;
+  if (list->tail != NULL) {
+    list->tail->next = storage;
+  } else {
+    list->head = storage;
+  }
+  list->tail = storage;
+  assert_valid_list(list);
+}
+
+void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch,
+                                   grpc_linked_mdelem *storage) {
+  link_tail(&batch->list, storage);
+}
+
+void grpc_metadata_batch_move(grpc_metadata_batch *dst,
+                              grpc_metadata_batch *src) {
+  *dst = *src;
+  memset(src, 0, sizeof(grpc_metadata_batch));
+}
+
+void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
+                                grpc_mdelem *(*filter)(void *user_data,
+                                                       grpc_mdelem *elem),
+                                void *user_data) {
+  grpc_linked_mdelem *l;
+  grpc_linked_mdelem *next;
+
+  GPR_TIMER_BEGIN("grpc_metadata_batch_filter", 0);
+
+  assert_valid_list(&batch->list);
+  for (l = batch->list.head; l; l = next) {
+    grpc_mdelem *orig = l->md;
+    grpc_mdelem *filt = filter(user_data, orig);
+    next = l->next;
+    if (filt == NULL) {
+      if (l->prev) {
+        l->prev->next = l->next;
+      }
+      if (l->next) {
+        l->next->prev = l->prev;
+      }
+      if (batch->list.head == l) {
+        batch->list.head = l->next;
+      }
+      if (batch->list.tail == l) {
+        batch->list.tail = l->prev;
+      }
+      assert_valid_list(&batch->list);
+      GRPC_MDELEM_UNREF(l->md);
+    } else if (filt != orig) {
+      GRPC_MDELEM_UNREF(orig);
+      l->md = filt;
+    }
+  }
+  assert_valid_list(&batch->list);
+
+  GPR_TIMER_END("grpc_metadata_batch_filter", 0);
+}
+
+static grpc_mdelem *no_metadata_for_you(void *user_data, grpc_mdelem *elem) {
+  return NULL;
+}
+
+void grpc_metadata_batch_clear(grpc_metadata_batch *batch) {
+  batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
+  grpc_metadata_batch_filter(batch, no_metadata_for_you, NULL);
+}
+
+int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
+  return batch->list.head == NULL &&
+         gpr_time_cmp(gpr_inf_future(batch->deadline.clock_type),
+                      batch->deadline) == 0;
+}
diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h
new file mode 100644
index 0000000..b626688
--- /dev/null
+++ b/src/core/lib/transport/metadata_batch.h
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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_TRANSPORT_METADATA_BATCH_H
+#define GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
+
+#include <grpc/grpc.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/transport/metadata.h"
+
+typedef struct grpc_linked_mdelem {
+  grpc_mdelem *md;
+  struct grpc_linked_mdelem *next;
+  struct grpc_linked_mdelem *prev;
+  void *reserved;
+} grpc_linked_mdelem;
+
+typedef struct grpc_mdelem_list {
+  grpc_linked_mdelem *head;
+  grpc_linked_mdelem *tail;
+} grpc_mdelem_list;
+
+typedef struct grpc_metadata_batch {
+  /** Metadata elements in this batch */
+  grpc_mdelem_list list;
+  /** Used to calculate grpc-timeout at the point of sending,
+      or gpr_inf_future if this batch does not need to send a
+      grpc-timeout */
+  gpr_timespec deadline;
+} grpc_metadata_batch;
+
+void grpc_metadata_batch_init(grpc_metadata_batch *batch);
+void grpc_metadata_batch_destroy(grpc_metadata_batch *batch);
+void grpc_metadata_batch_clear(grpc_metadata_batch *batch);
+int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch);
+
+/** Moves the metadata information from \a src to \a dst. Upon return, \a src is
+ * zeroed. */
+void grpc_metadata_batch_move(grpc_metadata_batch *dst,
+                              grpc_metadata_batch *src);
+
+/** Add \a storage to the beginning of \a batch. storage->md is
+    assumed to be valid.
+    \a storage is owned by the caller and must survive for the
+    lifetime of batch. This usually means it should be around
+    for the lifetime of the call. */
+void grpc_metadata_batch_link_head(grpc_metadata_batch *batch,
+                                   grpc_linked_mdelem *storage);
+/** Add \a storage to the end of \a batch. storage->md is
+    assumed to be valid.
+    \a storage is owned by the caller and must survive for the
+    lifetime of batch. This usually means it should be around
+    for the lifetime of the call. */
+void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch,
+                                   grpc_linked_mdelem *storage);
+
+/** Add \a elem_to_add as the first element in \a batch, using
+    \a storage as backing storage for the linked list element.
+    \a storage is owned by the caller and must survive for the
+    lifetime of batch. This usually means it should be around
+    for the lifetime of the call.
+    Takes ownership of \a elem_to_add */
+void grpc_metadata_batch_add_head(grpc_metadata_batch *batch,
+                                  grpc_linked_mdelem *storage,
+                                  grpc_mdelem *elem_to_add);
+/** Add \a elem_to_add as the last element in \a batch, using
+    \a storage as backing storage for the linked list element.
+    \a storage is owned by the caller and must survive for the
+    lifetime of batch. This usually means it should be around
+    for the lifetime of the call.
+    Takes ownership of \a elem_to_add */
+void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
+                                  grpc_linked_mdelem *storage,
+                                  grpc_mdelem *elem_to_add);
+
+/** For each element in \a batch, execute \a filter.
+    The return value from \a filter will be substituted for the
+    grpc_mdelem passed to \a filter. If \a filter returns NULL,
+    the element will be moved to the garbage list. */
+void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
+                                grpc_mdelem *(*filter)(void *user_data,
+                                                       grpc_mdelem *elem),
+                                void *user_data);
+
+#ifndef NDEBUG
+void grpc_metadata_batch_assert_ok(grpc_metadata_batch *comd);
+#else
+#define grpc_metadata_batch_assert_ok(comd) \
+  do {                                      \
+  } while (0)
+#endif
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
new file mode 100644
index 0000000..73b0041
--- /dev/null
+++ b/src/core/lib/transport/static_metadata.c
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+/*
+ * WARNING: Auto-generated code.
+ *
+ * To make changes to this file, change
+ * tools/codegen/core/gen_static_metadata.py, and then re-run it.
+ *
+ * See metadata.h for an explanation of the interface here, and metadata.c for
+ * an explanation of what's going on.
+ */
+
+#include "src/core/lib/transport/static_metadata.h"
+
+grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
+
+grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] =
+    {11, 35, 10, 35, 12, 35, 12, 49, 13, 35, 14, 35, 15, 35, 16, 35, 17, 35,
+     19, 35, 20, 35, 21, 35, 24, 35, 25, 35, 26, 35, 27, 35, 28, 35, 29, 35,
+     30, 18, 30, 35, 31, 35, 32, 35, 36, 35, 37, 35, 38, 35, 39, 35, 42, 33,
+     42, 34, 42, 48, 42, 53, 42, 54, 42, 55, 42, 56, 43, 33, 43, 48, 43, 53,
+     46, 0,  46, 1,  46, 2,  50, 35, 57, 35, 58, 35, 59, 35, 60, 35, 61, 35,
+     62, 35, 63, 35, 64, 35, 65, 35, 66, 40, 66, 68, 66, 71, 67, 79, 67, 80,
+     69, 35, 70, 35, 72, 35, 73, 35, 74, 35, 75, 35, 76, 41, 76, 51, 76, 52,
+     77, 35, 78, 35, 81, 3,  81, 4,  81, 5,  81, 6,  81, 7,  81, 8,  81, 9,
+     82, 35, 83, 84, 85, 35, 86, 35, 87, 35, 88, 35, 89, 35};
+
+const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
+    "0",
+    "1",
+    "2",
+    "200",
+    "204",
+    "206",
+    "304",
+    "400",
+    "404",
+    "500",
+    "accept",
+    "accept-charset",
+    "accept-encoding",
+    "accept-language",
+    "accept-ranges",
+    "access-control-allow-origin",
+    "age",
+    "allow",
+    "application/grpc",
+    ":authority",
+    "authorization",
+    "cache-control",
+    "census-bin",
+    "census-binary-bin",
+    "content-disposition",
+    "content-encoding",
+    "content-language",
+    "content-length",
+    "content-location",
+    "content-range",
+    "content-type",
+    "cookie",
+    "date",
+    "deflate",
+    "deflate,gzip",
+    "",
+    "etag",
+    "expect",
+    "expires",
+    "from",
+    "GET",
+    "grpc",
+    "grpc-accept-encoding",
+    "grpc-encoding",
+    "grpc-internal-encoding-request",
+    "grpc-message",
+    "grpc-status",
+    "grpc-timeout",
+    "gzip",
+    "gzip, deflate",
+    "host",
+    "http",
+    "https",
+    "identity",
+    "identity,deflate",
+    "identity,deflate,gzip",
+    "identity,gzip",
+    "if-match",
+    "if-modified-since",
+    "if-none-match",
+    "if-range",
+    "if-unmodified-since",
+    "last-modified",
+    "link",
+    "location",
+    "max-forwards",
+    ":method",
+    ":path",
+    "POST",
+    "proxy-authenticate",
+    "proxy-authorization",
+    "PUT",
+    "range",
+    "referer",
+    "refresh",
+    "retry-after",
+    ":scheme",
+    "server",
+    "set-cookie",
+    "/",
+    "/index.html",
+    ":status",
+    "strict-transport-security",
+    "te",
+    "trailers",
+    "transfer-encoding",
+    "user-agent",
+    "vary",
+    "via",
+    "www-authenticate"};
+
+const uint8_t grpc_static_accept_encoding_metadata[8] = {0,  29, 26, 30,
+                                                         28, 32, 27, 31};
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
new file mode 100644
index 0000000..f9d8bcd
--- /dev/null
+++ b/src/core/lib/transport/static_metadata.h
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+/*
+ * WARNING: Auto-generated code.
+ *
+ * To make changes to this file, change
+ * tools/codegen/core/gen_static_metadata.py, and then re-run it.
+ *
+ * See metadata.h for an explanation of the interface here, and metadata.c for
+ * an explanation of what's going on.
+ */
+
+#ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H
+#define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H
+
+#include "src/core/lib/transport/metadata.h"
+
+#define GRPC_STATIC_MDSTR_COUNT 90
+extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
+/* "0" */
+#define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0])
+/* "1" */
+#define GRPC_MDSTR_1 (&grpc_static_mdstr_table[1])
+/* "2" */
+#define GRPC_MDSTR_2 (&grpc_static_mdstr_table[2])
+/* "200" */
+#define GRPC_MDSTR_200 (&grpc_static_mdstr_table[3])
+/* "204" */
+#define GRPC_MDSTR_204 (&grpc_static_mdstr_table[4])
+/* "206" */
+#define GRPC_MDSTR_206 (&grpc_static_mdstr_table[5])
+/* "304" */
+#define GRPC_MDSTR_304 (&grpc_static_mdstr_table[6])
+/* "400" */
+#define GRPC_MDSTR_400 (&grpc_static_mdstr_table[7])
+/* "404" */
+#define GRPC_MDSTR_404 (&grpc_static_mdstr_table[8])
+/* "500" */
+#define GRPC_MDSTR_500 (&grpc_static_mdstr_table[9])
+/* "accept" */
+#define GRPC_MDSTR_ACCEPT (&grpc_static_mdstr_table[10])
+/* "accept-charset" */
+#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_mdstr_table[11])
+/* "accept-encoding" */
+#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_mdstr_table[12])
+/* "accept-language" */
+#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_mdstr_table[13])
+/* "accept-ranges" */
+#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_mdstr_table[14])
+/* "access-control-allow-origin" */
+#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_mdstr_table[15])
+/* "age" */
+#define GRPC_MDSTR_AGE (&grpc_static_mdstr_table[16])
+/* "allow" */
+#define GRPC_MDSTR_ALLOW (&grpc_static_mdstr_table[17])
+/* "application/grpc" */
+#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (&grpc_static_mdstr_table[18])
+/* ":authority" */
+#define GRPC_MDSTR_AUTHORITY (&grpc_static_mdstr_table[19])
+/* "authorization" */
+#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20])
+/* "cache-control" */
+#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21])
+/* "census-bin" */
+#define GRPC_MDSTR_CENSUS_BIN (&grpc_static_mdstr_table[22])
+/* "census-binary-bin" */
+#define GRPC_MDSTR_CENSUS_BINARY_BIN (&grpc_static_mdstr_table[23])
+/* "content-disposition" */
+#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[24])
+/* "content-encoding" */
+#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[25])
+/* "content-language" */
+#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[26])
+/* "content-length" */
+#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[27])
+/* "content-location" */
+#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[28])
+/* "content-range" */
+#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[29])
+/* "content-type" */
+#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[30])
+/* "cookie" */
+#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[31])
+/* "date" */
+#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[32])
+/* "deflate" */
+#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[33])
+/* "deflate,gzip" */
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[34])
+/* "" */
+#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[35])
+/* "etag" */
+#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[36])
+/* "expect" */
+#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[37])
+/* "expires" */
+#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[38])
+/* "from" */
+#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[39])
+/* "GET" */
+#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[40])
+/* "grpc" */
+#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[41])
+/* "grpc-accept-encoding" */
+#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[42])
+/* "grpc-encoding" */
+#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[43])
+/* "grpc-internal-encoding-request" */
+#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[44])
+/* "grpc-message" */
+#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[45])
+/* "grpc-status" */
+#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46])
+/* "grpc-timeout" */
+#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47])
+/* "gzip" */
+#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[48])
+/* "gzip, deflate" */
+#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_mdstr_table[49])
+/* "host" */
+#define GRPC_MDSTR_HOST (&grpc_static_mdstr_table[50])
+/* "http" */
+#define GRPC_MDSTR_HTTP (&grpc_static_mdstr_table[51])
+/* "https" */
+#define GRPC_MDSTR_HTTPS (&grpc_static_mdstr_table[52])
+/* "identity" */
+#define GRPC_MDSTR_IDENTITY (&grpc_static_mdstr_table[53])
+/* "identity,deflate" */
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (&grpc_static_mdstr_table[54])
+/* "identity,deflate,gzip" */
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
+  (&grpc_static_mdstr_table[55])
+/* "identity,gzip" */
+#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (&grpc_static_mdstr_table[56])
+/* "if-match" */
+#define GRPC_MDSTR_IF_MATCH (&grpc_static_mdstr_table[57])
+/* "if-modified-since" */
+#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_mdstr_table[58])
+/* "if-none-match" */
+#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_mdstr_table[59])
+/* "if-range" */
+#define GRPC_MDSTR_IF_RANGE (&grpc_static_mdstr_table[60])
+/* "if-unmodified-since" */
+#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[61])
+/* "last-modified" */
+#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[62])
+/* "link" */
+#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[63])
+/* "location" */
+#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[64])
+/* "max-forwards" */
+#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[65])
+/* ":method" */
+#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[66])
+/* ":path" */
+#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[67])
+/* "POST" */
+#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[68])
+/* "proxy-authenticate" */
+#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[69])
+/* "proxy-authorization" */
+#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[70])
+/* "PUT" */
+#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[71])
+/* "range" */
+#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[72])
+/* "referer" */
+#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[73])
+/* "refresh" */
+#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[74])
+/* "retry-after" */
+#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[75])
+/* ":scheme" */
+#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[76])
+/* "server" */
+#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[77])
+/* "set-cookie" */
+#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[78])
+/* "/" */
+#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[79])
+/* "/index.html" */
+#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[80])
+/* ":status" */
+#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[81])
+/* "strict-transport-security" */
+#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[82])
+/* "te" */
+#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[83])
+/* "trailers" */
+#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[84])
+/* "transfer-encoding" */
+#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[85])
+/* "user-agent" */
+#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[86])
+/* "vary" */
+#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[87])
+/* "via" */
+#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[88])
+/* "www-authenticate" */
+#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[89])
+
+#define GRPC_STATIC_MDELEM_COUNT 79
+extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
+/* "accept-charset": "" */
+#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY (&grpc_static_mdelem_table[0])
+/* "accept": "" */
+#define GRPC_MDELEM_ACCEPT_EMPTY (&grpc_static_mdelem_table[1])
+/* "accept-encoding": "" */
+#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY (&grpc_static_mdelem_table[2])
+/* "accept-encoding": "gzip, deflate" */
+#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \
+  (&grpc_static_mdelem_table[3])
+/* "accept-language": "" */
+#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[4])
+/* "accept-ranges": "" */
+#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY (&grpc_static_mdelem_table[5])
+/* "access-control-allow-origin": "" */
+#define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \
+  (&grpc_static_mdelem_table[6])
+/* "age": "" */
+#define GRPC_MDELEM_AGE_EMPTY (&grpc_static_mdelem_table[7])
+/* "allow": "" */
+#define GRPC_MDELEM_ALLOW_EMPTY (&grpc_static_mdelem_table[8])
+/* ":authority": "" */
+#define GRPC_MDELEM_AUTHORITY_EMPTY (&grpc_static_mdelem_table[9])
+/* "authorization": "" */
+#define GRPC_MDELEM_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[10])
+/* "cache-control": "" */
+#define GRPC_MDELEM_CACHE_CONTROL_EMPTY (&grpc_static_mdelem_table[11])
+/* "content-disposition": "" */
+#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY (&grpc_static_mdelem_table[12])
+/* "content-encoding": "" */
+#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY (&grpc_static_mdelem_table[13])
+/* "content-language": "" */
+#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[14])
+/* "content-length": "" */
+#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY (&grpc_static_mdelem_table[15])
+/* "content-location": "" */
+#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY (&grpc_static_mdelem_table[16])
+/* "content-range": "" */
+#define GRPC_MDELEM_CONTENT_RANGE_EMPTY (&grpc_static_mdelem_table[17])
+/* "content-type": "application/grpc" */
+#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \
+  (&grpc_static_mdelem_table[18])
+/* "content-type": "" */
+#define GRPC_MDELEM_CONTENT_TYPE_EMPTY (&grpc_static_mdelem_table[19])
+/* "cookie": "" */
+#define GRPC_MDELEM_COOKIE_EMPTY (&grpc_static_mdelem_table[20])
+/* "date": "" */
+#define GRPC_MDELEM_DATE_EMPTY (&grpc_static_mdelem_table[21])
+/* "etag": "" */
+#define GRPC_MDELEM_ETAG_EMPTY (&grpc_static_mdelem_table[22])
+/* "expect": "" */
+#define GRPC_MDELEM_EXPECT_EMPTY (&grpc_static_mdelem_table[23])
+/* "expires": "" */
+#define GRPC_MDELEM_EXPIRES_EMPTY (&grpc_static_mdelem_table[24])
+/* "from": "" */
+#define GRPC_MDELEM_FROM_EMPTY (&grpc_static_mdelem_table[25])
+/* "grpc-accept-encoding": "deflate" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE (&grpc_static_mdelem_table[26])
+/* "grpc-accept-encoding": "deflate,gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
+  (&grpc_static_mdelem_table[27])
+/* "grpc-accept-encoding": "gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP (&grpc_static_mdelem_table[28])
+/* "grpc-accept-encoding": "identity" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
+  (&grpc_static_mdelem_table[29])
+/* "grpc-accept-encoding": "identity,deflate" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
+  (&grpc_static_mdelem_table[30])
+/* "grpc-accept-encoding": "identity,deflate,gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
+  (&grpc_static_mdelem_table[31])
+/* "grpc-accept-encoding": "identity,gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
+  (&grpc_static_mdelem_table[32])
+/* "grpc-encoding": "deflate" */
+#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE (&grpc_static_mdelem_table[33])
+/* "grpc-encoding": "gzip" */
+#define GRPC_MDELEM_GRPC_ENCODING_GZIP (&grpc_static_mdelem_table[34])
+/* "grpc-encoding": "identity" */
+#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY (&grpc_static_mdelem_table[35])
+/* "grpc-status": "0" */
+#define GRPC_MDELEM_GRPC_STATUS_0 (&grpc_static_mdelem_table[36])
+/* "grpc-status": "1" */
+#define GRPC_MDELEM_GRPC_STATUS_1 (&grpc_static_mdelem_table[37])
+/* "grpc-status": "2" */
+#define GRPC_MDELEM_GRPC_STATUS_2 (&grpc_static_mdelem_table[38])
+/* "host": "" */
+#define GRPC_MDELEM_HOST_EMPTY (&grpc_static_mdelem_table[39])
+/* "if-match": "" */
+#define GRPC_MDELEM_IF_MATCH_EMPTY (&grpc_static_mdelem_table[40])
+/* "if-modified-since": "" */
+#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[41])
+/* "if-none-match": "" */
+#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY (&grpc_static_mdelem_table[42])
+/* "if-range": "" */
+#define GRPC_MDELEM_IF_RANGE_EMPTY (&grpc_static_mdelem_table[43])
+/* "if-unmodified-since": "" */
+#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[44])
+/* "last-modified": "" */
+#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45])
+/* "link": "" */
+#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[46])
+/* "location": "" */
+#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[47])
+/* "max-forwards": "" */
+#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[48])
+/* ":method": "GET" */
+#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[49])
+/* ":method": "POST" */
+#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[50])
+/* ":method": "PUT" */
+#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[51])
+/* ":path": "/" */
+#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[52])
+/* ":path": "/index.html" */
+#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[53])
+/* "proxy-authenticate": "" */
+#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[54])
+/* "proxy-authorization": "" */
+#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[55])
+/* "range": "" */
+#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[56])
+/* "referer": "" */
+#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[57])
+/* "refresh": "" */
+#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[58])
+/* "retry-after": "" */
+#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[59])
+/* ":scheme": "grpc" */
+#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[60])
+/* ":scheme": "http" */
+#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[61])
+/* ":scheme": "https" */
+#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[62])
+/* "server": "" */
+#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[63])
+/* "set-cookie": "" */
+#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[64])
+/* ":status": "200" */
+#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[65])
+/* ":status": "204" */
+#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[66])
+/* ":status": "206" */
+#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[67])
+/* ":status": "304" */
+#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[68])
+/* ":status": "400" */
+#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[69])
+/* ":status": "404" */
+#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[70])
+/* ":status": "500" */
+#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[71])
+/* "strict-transport-security": "" */
+#define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
+  (&grpc_static_mdelem_table[72])
+/* "te": "trailers" */
+#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[73])
+/* "transfer-encoding": "" */
+#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[74])
+/* "user-agent": "" */
+#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[75])
+/* "vary": "" */
+#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[76])
+/* "via": "" */
+#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[77])
+/* "www-authenticate": "" */
+#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[78])
+
+extern const uint8_t
+    grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2];
+extern const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT];
+extern const uint8_t grpc_static_accept_encoding_metadata[8];
+#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
+  (&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]])
+#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */
diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c
new file mode 100644
index 0000000..53c634a
--- /dev/null
+++ b/src/core/lib/transport/transport.c
@@ -0,0 +1,203 @@
+/*
+ *
+ * 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/transport/transport.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include "src/core/lib/transport/transport_impl.h"
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) {
+  gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count);
+  gpr_log(GPR_DEBUG, "%s %p:%p   REF %d->%d %s", refcount->object_type,
+          refcount, refcount->destroy.cb_arg, val, val + 1, reason);
+#else
+void grpc_stream_ref(grpc_stream_refcount *refcount) {
+#endif
+  gpr_ref_non_zero(&refcount->refs);
+}
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount,
+                       const char *reason) {
+  gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count);
+  gpr_log(GPR_DEBUG, "%s %p:%p UNREF %d->%d %s", refcount->object_type,
+          refcount, refcount->destroy.cb_arg, val, val - 1, reason);
+#else
+void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
+                       grpc_stream_refcount *refcount) {
+#endif
+  if (gpr_unref(&refcount->refs)) {
+    grpc_exec_ctx_enqueue(exec_ctx, &refcount->destroy, true, NULL);
+  }
+}
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
+                          grpc_iomgr_cb_func cb, void *cb_arg,
+                          const char *object_type) {
+  refcount->object_type = object_type;
+#else
+void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
+                          grpc_iomgr_cb_func cb, void *cb_arg) {
+#endif
+  gpr_ref_init(&refcount->refs, initial_refs);
+  grpc_closure_init(&refcount->destroy, cb, cb_arg);
+}
+
+static void move64(uint64_t *from, uint64_t *to) {
+  *to += *from;
+  *from = 0;
+}
+
+void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from,
+                                       grpc_transport_one_way_stats *to) {
+  move64(&from->framing_bytes, &to->framing_bytes);
+  move64(&from->data_bytes, &to->data_bytes);
+  move64(&from->header_bytes, &to->header_bytes);
+}
+
+void grpc_transport_move_stats(grpc_transport_stream_stats *from,
+                               grpc_transport_stream_stats *to) {
+  grpc_transport_move_one_way_stats(&from->incoming, &to->incoming);
+  grpc_transport_move_one_way_stats(&from->outgoing, &to->outgoing);
+}
+
+size_t grpc_transport_stream_size(grpc_transport *transport) {
+  return transport->vtable->sizeof_stream;
+}
+
+void grpc_transport_destroy(grpc_exec_ctx *exec_ctx,
+                            grpc_transport *transport) {
+  transport->vtable->destroy(exec_ctx, transport);
+}
+
+int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx,
+                               grpc_transport *transport, grpc_stream *stream,
+                               grpc_stream_refcount *refcount,
+                               const void *server_data) {
+  return transport->vtable->init_stream(exec_ctx, transport, stream, refcount,
+                                        server_data);
+}
+
+void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx,
+                                      grpc_transport *transport,
+                                      grpc_stream *stream,
+                                      grpc_transport_stream_op *op) {
+  transport->vtable->perform_stream_op(exec_ctx, transport, stream, op);
+}
+
+void grpc_transport_perform_op(grpc_exec_ctx *exec_ctx,
+                               grpc_transport *transport,
+                               grpc_transport_op *op) {
+  transport->vtable->perform_op(exec_ctx, transport, op);
+}
+
+void grpc_transport_set_pollset(grpc_exec_ctx *exec_ctx,
+                                grpc_transport *transport, grpc_stream *stream,
+                                grpc_pollset *pollset) {
+  transport->vtable->set_pollset(exec_ctx, transport, stream, pollset);
+}
+
+void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
+                                   grpc_transport *transport,
+                                   grpc_stream *stream) {
+  transport->vtable->destroy_stream(exec_ctx, transport, stream);
+}
+
+char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
+                              grpc_transport *transport) {
+  return transport->vtable->get_peer(exec_ctx, transport);
+}
+
+void grpc_transport_stream_op_finish_with_failure(
+    grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op) {
+  grpc_exec_ctx_enqueue(exec_ctx, op->recv_message_ready, false, NULL);
+  grpc_exec_ctx_enqueue(exec_ctx, op->recv_initial_metadata_ready, false, NULL);
+  grpc_exec_ctx_enqueue(exec_ctx, op->on_complete, false, NULL);
+}
+
+void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
+                                               grpc_status_code status) {
+  GPR_ASSERT(status != GRPC_STATUS_OK);
+  if (op->cancel_with_status == GRPC_STATUS_OK) {
+    op->cancel_with_status = status;
+  }
+  if (op->close_with_status != GRPC_STATUS_OK) {
+    op->close_with_status = GRPC_STATUS_OK;
+    if (op->optional_close_message != NULL) {
+      gpr_slice_unref(*op->optional_close_message);
+      op->optional_close_message = NULL;
+    }
+  }
+}
+
+typedef struct {
+  gpr_slice message;
+  grpc_closure *then_call;
+  grpc_closure closure;
+} close_message_data;
+
+static void free_message(grpc_exec_ctx *exec_ctx, void *p, bool iomgr_success) {
+  close_message_data *cmd = p;
+  gpr_slice_unref(cmd->message);
+  if (cmd->then_call != NULL) {
+    cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, iomgr_success);
+  }
+  gpr_free(cmd);
+}
+
+void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
+                                        grpc_status_code status,
+                                        gpr_slice *optional_message) {
+  close_message_data *cmd;
+  GPR_ASSERT(status != GRPC_STATUS_OK);
+  if (op->cancel_with_status != GRPC_STATUS_OK ||
+      op->close_with_status != GRPC_STATUS_OK) {
+    if (optional_message) {
+      gpr_slice_unref(*optional_message);
+    }
+    return;
+  }
+  if (optional_message) {
+    cmd = gpr_malloc(sizeof(*cmd));
+    cmd->message = *optional_message;
+    cmd->then_call = op->on_complete;
+    grpc_closure_init(&cmd->closure, free_message, cmd);
+    op->on_complete = &cmd->closure;
+    op->optional_close_message = &cmd->message;
+  }
+  op->close_with_status = status;
+}
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
new file mode 100644
index 0000000..1eb4463
--- /dev/null
+++ b/src/core/lib/transport/transport.h
@@ -0,0 +1,267 @@
+/*
+ *
+ * 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_TRANSPORT_TRANSPORT_H
+#define GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H
+
+#include <stddef.h>
+
+#include "src/core/lib/channel/context.h"
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/pollset_set.h"
+#include "src/core/lib/transport/byte_stream.h"
+#include "src/core/lib/transport/metadata_batch.h"
+
+/* forward declarations */
+typedef struct grpc_transport grpc_transport;
+
+/* grpc_stream doesn't actually exist. It's used as a typesafe
+   opaque pointer for whatever data the transport wants to track
+   for a stream. */
+typedef struct grpc_stream grpc_stream;
+
+//#define GRPC_STREAM_REFCOUNT_DEBUG
+
+typedef struct grpc_stream_refcount {
+  gpr_refcount refs;
+  grpc_closure destroy;
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+  const char *object_type;
+#endif
+} grpc_stream_refcount;
+
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
+                          grpc_iomgr_cb_func cb, void *cb_arg,
+                          const char *object_type);
+void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason);
+void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount,
+                       const char *reason);
+#define GRPC_STREAM_REF_INIT(rc, ir, cb, cb_arg, objtype) \
+  grpc_stream_ref_init(rc, ir, cb, cb_arg, objtype)
+#else
+void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
+                          grpc_iomgr_cb_func cb, void *cb_arg);
+void grpc_stream_ref(grpc_stream_refcount *refcount);
+void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount);
+#define GRPC_STREAM_REF_INIT(rc, ir, cb, cb_arg, objtype) \
+  grpc_stream_ref_init(rc, ir, cb, cb_arg)
+#endif
+
+typedef struct {
+  uint64_t framing_bytes;
+  uint64_t data_bytes;
+  uint64_t header_bytes;
+} grpc_transport_one_way_stats;
+
+typedef struct grpc_transport_stream_stats {
+  grpc_transport_one_way_stats incoming;
+  grpc_transport_one_way_stats outgoing;
+} grpc_transport_stream_stats;
+
+void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from,
+                                       grpc_transport_one_way_stats *to);
+
+void grpc_transport_move_stats(grpc_transport_stream_stats *from,
+                               grpc_transport_stream_stats *to);
+
+/* Transport stream op: a set of operations to perform on a transport
+   against a single stream */
+typedef struct grpc_transport_stream_op {
+  /** Send initial metadata to the peer, from the provided metadata batch.
+      idempotent_request MUST be set if this is non-null */
+  grpc_metadata_batch *send_initial_metadata;
+  /** Iff send_initial_metadata != NULL, flags associated with
+      send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */
+  uint32_t send_initial_metadata_flags;
+
+  /** Send trailing metadata to the peer, from the provided metadata batch. */
+  grpc_metadata_batch *send_trailing_metadata;
+
+  /** Send message data to the peer, from the provided byte stream. */
+  grpc_byte_stream *send_message;
+
+  /** Receive initial metadata from the stream, into provided metadata batch. */
+  grpc_metadata_batch *recv_initial_metadata;
+  bool *recv_idempotent_request;
+  /** Should be enqueued when initial metadata is ready to be processed. */
+  grpc_closure *recv_initial_metadata_ready;
+
+  /** Receive message data from the stream, into provided byte stream. */
+  grpc_byte_stream **recv_message;
+  /** Should be enqueued when one message is ready to be processed. */
+  grpc_closure *recv_message_ready;
+
+  /** Receive trailing metadata from the stream, into provided metadata batch.
+   */
+  grpc_metadata_batch *recv_trailing_metadata;
+
+  /** Collect any stats into provided buffer, zero internal stat counters */
+  grpc_transport_stream_stats *collect_stats;
+
+  /** Should be enqueued when all requested operations (excluding recv_message
+      and recv_initial_metadata which have their own closures) in a given batch
+      have been completed. */
+  grpc_closure *on_complete;
+
+  /** If != GRPC_STATUS_OK, cancel this stream */
+  grpc_status_code cancel_with_status;
+
+  /** If != GRPC_STATUS_OK, send grpc-status, grpc-message, and close this
+      stream for both reading and writing */
+  grpc_status_code close_with_status;
+  gpr_slice *optional_close_message;
+
+  /* Indexes correspond to grpc_context_index enum values */
+  grpc_call_context_element *context;
+} grpc_transport_stream_op;
+
+/** Transport op: a set of operations to perform on a transport as a whole */
+typedef struct grpc_transport_op {
+  /** Called when processing of this op is done. */
+  grpc_closure *on_consumed;
+  /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
+  grpc_closure *on_connectivity_state_change;
+  grpc_connectivity_state *connectivity_state;
+  /** should the transport be disconnected */
+  int disconnect;
+  /** should we send a goaway?
+      after a goaway is sent, once there are no more active calls on
+      the transport, the transport should disconnect */
+  int send_goaway;
+  /** what should the goaway contain? */
+  grpc_status_code goaway_status;
+  gpr_slice *goaway_message;
+  /** set the callback for accepting new streams;
+      this is a permanent callback, unlike the other one-shot closures.
+      If true, the callback is set to set_accept_stream_fn, with its
+      user_data argument set to set_accept_stream_user_data */
+  bool set_accept_stream;
+  void (*set_accept_stream_fn)(grpc_exec_ctx *exec_ctx, void *user_data,
+                               grpc_transport *transport,
+                               const void *server_data);
+  void *set_accept_stream_user_data;
+  /** add this transport to a pollset */
+  grpc_pollset *bind_pollset;
+  /** add this transport to a pollset_set */
+  grpc_pollset_set *bind_pollset_set;
+  /** send a ping, call this back if not NULL */
+  grpc_closure *send_ping;
+} grpc_transport_op;
+
+/* Returns the amount of memory required to store a grpc_stream for this
+   transport */
+size_t grpc_transport_stream_size(grpc_transport *transport);
+
+/* Initialize transport data for a stream.
+
+   Returns 0 on success, any other (transport-defined) value for failure.
+
+   Arguments:
+     transport   - the transport on which to create this stream
+     stream      - a pointer to uninitialized memory to initialize
+     server_data - either NULL for a client initiated stream, or a pointer
+                   supplied from the accept_stream callback function */
+int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx,
+                               grpc_transport *transport, grpc_stream *stream,
+                               grpc_stream_refcount *refcount,
+                               const void *server_data);
+
+void grpc_transport_set_pollset(grpc_exec_ctx *exec_ctx,
+                                grpc_transport *transport, grpc_stream *stream,
+                                grpc_pollset *pollset);
+
+/* Destroy transport data for a stream.
+
+   Requires: a recv_batch with final_state == GRPC_STREAM_CLOSED has been
+   received by the up-layer. Must not be called in the same call stack as
+   recv_frame.
+
+   Arguments:
+     transport - the transport on which to create this stream
+     stream    - the grpc_stream to destroy (memory is still owned by the
+                 caller, but any child memory must be cleaned up) */
+void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
+                                   grpc_transport *transport,
+                                   grpc_stream *stream);
+
+void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
+                                                  grpc_transport_stream_op *op);
+
+void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
+                                               grpc_status_code status);
+
+void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
+                                        grpc_status_code status,
+                                        gpr_slice *optional_message);
+
+char *grpc_transport_stream_op_string(grpc_transport_stream_op *op);
+
+/* Send a batch of operations on a transport
+
+   Takes ownership of any objects contained in ops.
+
+   Arguments:
+     transport - the transport on which to initiate the stream
+     stream    - the stream on which to send the operations. This must be
+                 non-NULL and previously initialized by the same transport.
+     op        - a grpc_transport_stream_op specifying the op to perform */
+void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx,
+                                      grpc_transport *transport,
+                                      grpc_stream *stream,
+                                      grpc_transport_stream_op *op);
+
+void grpc_transport_perform_op(grpc_exec_ctx *exec_ctx,
+                               grpc_transport *transport,
+                               grpc_transport_op *op);
+
+/* Send a ping on a transport
+
+   Calls cb with user data when a response is received. */
+void grpc_transport_ping(grpc_transport *transport, grpc_closure *cb);
+
+/* Advise peer of pending connection termination. */
+void grpc_transport_goaway(grpc_transport *transport, grpc_status_code status,
+                           gpr_slice debug_data);
+
+/* Close a transport. Aborts all open streams. */
+void grpc_transport_close(grpc_transport *transport);
+
+/* Destroy the transport */
+void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport);
+
+/* Get the transports peer */
+char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
+                              grpc_transport *transport);
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H */
diff --git a/src/core/lib/transport/transport_impl.h b/src/core/lib/transport/transport_impl.h
new file mode 100644
index 0000000..2ff6707
--- /dev/null
+++ b/src/core/lib/transport/transport_impl.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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_TRANSPORT_TRANSPORT_IMPL_H
+#define GRPC_CORE_LIB_TRANSPORT_TRANSPORT_IMPL_H
+
+#include "src/core/lib/transport/transport.h"
+
+typedef struct grpc_transport_vtable {
+  /* Memory required for a single stream element - this is allocated by upper
+     layers and initialized by the transport */
+  size_t sizeof_stream; /* = sizeof(transport stream) */
+
+  /* name of this transport implementation */
+  const char *name;
+
+  /* implementation of grpc_transport_init_stream */
+  int (*init_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                     grpc_stream *stream, grpc_stream_refcount *refcount,
+                     const void *server_data);
+
+  /* implementation of grpc_transport_set_pollset */
+  void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                      grpc_stream *stream, grpc_pollset *pollset);
+
+  /* implementation of grpc_transport_perform_stream_op */
+  void (*perform_stream_op)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                            grpc_stream *stream, grpc_transport_stream_op *op);
+
+  /* implementation of grpc_transport_perform_op */
+  void (*perform_op)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                     grpc_transport_op *op);
+
+  /* implementation of grpc_transport_destroy_stream */
+  void (*destroy_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                         grpc_stream *stream);
+
+  /* implementation of grpc_transport_destroy */
+  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_transport *self);
+
+  /* implementation of grpc_transport_get_peer */
+  char *(*get_peer)(grpc_exec_ctx *exec_ctx, grpc_transport *self);
+} grpc_transport_vtable;
+
+/* an instance of a grpc transport */
+struct grpc_transport {
+  /* pointer to a vtable defining operations on this transport */
+  const grpc_transport_vtable *vtable;
+};
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_IMPL_H */
diff --git a/src/core/lib/transport/transport_op_string.c b/src/core/lib/transport/transport_op_string.c
new file mode 100644
index 0000000..df04c61
--- /dev/null
+++ b/src/core/lib/transport/transport_op_string.c
@@ -0,0 +1,140 @@
+/*
+ *
+ * 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/channel/channel_stack.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
+
+/* These routines are here to facilitate debugging - they produce string
+   representations of various transport data structures */
+
+static void put_metadata(gpr_strvec *b, grpc_mdelem *md) {
+  gpr_strvec_add(b, gpr_strdup("key="));
+  gpr_strvec_add(b,
+                 gpr_dump_slice(md->key->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+
+  gpr_strvec_add(b, gpr_strdup(" value="));
+  gpr_strvec_add(
+      b, gpr_dump_slice(md->value->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+}
+
+static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {
+  grpc_linked_mdelem *m;
+  for (m = md.list.head; m != NULL; m = m->next) {
+    if (m != md.list.head) gpr_strvec_add(b, gpr_strdup(", "));
+    put_metadata(b, m->md);
+  }
+  if (gpr_time_cmp(md.deadline, gpr_inf_future(md.deadline.clock_type)) != 0) {
+    char *tmp;
+    gpr_asprintf(&tmp, " deadline=%lld.%09d", (long long)md.deadline.tv_sec,
+                 (int)md.deadline.tv_nsec);
+    gpr_strvec_add(b, tmp);
+  }
+}
+
+char *grpc_transport_stream_op_string(grpc_transport_stream_op *op) {
+  char *tmp;
+  char *out;
+  int first = 1;
+
+  gpr_strvec b;
+  gpr_strvec_init(&b);
+
+  if (op->send_initial_metadata != NULL) {
+    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
+    first = 0;
+    gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA{"));
+    put_metadata_list(&b, *op->send_initial_metadata);
+    gpr_strvec_add(&b, gpr_strdup("}"));
+  }
+
+  if (op->send_message != NULL) {
+    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
+    first = 0;
+    gpr_asprintf(&tmp, "SEND_MESSAGE:flags=0x%08x:len=%d",
+                 op->send_message->flags, op->send_message->length);
+    gpr_strvec_add(&b, tmp);
+  }
+
+  if (op->send_trailing_metadata != NULL) {
+    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
+    first = 0;
+    gpr_strvec_add(&b, gpr_strdup("SEND_TRAILING_METADATA{"));
+    put_metadata_list(&b, *op->send_trailing_metadata);
+    gpr_strvec_add(&b, gpr_strdup("}"));
+  }
+
+  if (op->recv_initial_metadata != NULL) {
+    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
+    first = 0;
+    gpr_strvec_add(&b, gpr_strdup("RECV_INITIAL_METADATA"));
+  }
+
+  if (op->recv_message != NULL) {
+    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
+    first = 0;
+    gpr_strvec_add(&b, gpr_strdup("RECV_MESSAGE"));
+  }
+
+  if (op->recv_trailing_metadata != NULL) {
+    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
+    first = 0;
+    gpr_strvec_add(&b, gpr_strdup("RECV_TRAILING_METADATA"));
+  }
+
+  if (op->cancel_with_status != GRPC_STATUS_OK) {
+    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
+    first = 0;
+    gpr_asprintf(&tmp, "CANCEL:%d", op->cancel_with_status);
+    gpr_strvec_add(&b, tmp);
+  }
+
+  out = gpr_strvec_flatten(&b, NULL);
+  gpr_strvec_destroy(&b);
+
+  return out;
+}
+
+void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
+                      grpc_call_element *elem, grpc_transport_stream_op *op) {
+  char *str = grpc_transport_stream_op_string(op);
+  gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem, str);
+  gpr_free(str);
+}
diff --git a/src/core/lib/tsi/fake_transport_security.c b/src/core/lib/tsi/fake_transport_security.c
new file mode 100644
index 0000000..0e20d6f
--- /dev/null
+++ b/src/core/lib/tsi/fake_transport_security.c
@@ -0,0 +1,529 @@
+/*
+ *
+ * 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/tsi/fake_transport_security.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/tsi/transport_security.h"
+
+/* --- Constants. ---*/
+#define TSI_FAKE_FRAME_HEADER_SIZE 4
+#define TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE 64
+#define TSI_FAKE_DEFAULT_FRAME_SIZE 16384
+
+/* --- Structure definitions. ---*/
+
+/* a frame is encoded like this:
+   | size |     data    |
+   where the size field value is the size of the size field plus the size of
+   the data encoded in little endian on 4 bytes.  */
+typedef struct {
+  unsigned char *data;
+  size_t size;
+  size_t allocated_size;
+  size_t offset;
+  int needs_draining;
+} tsi_fake_frame;
+
+typedef enum {
+  TSI_FAKE_CLIENT_INIT = 0,
+  TSI_FAKE_SERVER_INIT = 1,
+  TSI_FAKE_CLIENT_FINISHED = 2,
+  TSI_FAKE_SERVER_FINISHED = 3,
+  TSI_FAKE_HANDSHAKE_MESSAGE_MAX = 4
+} tsi_fake_handshake_message;
+
+typedef struct {
+  tsi_handshaker base;
+  int is_client;
+  tsi_fake_handshake_message next_message_to_send;
+  int needs_incoming_message;
+  tsi_fake_frame incoming;
+  tsi_fake_frame outgoing;
+  tsi_result result;
+} tsi_fake_handshaker;
+
+typedef struct {
+  tsi_frame_protector base;
+  tsi_fake_frame protect_frame;
+  tsi_fake_frame unprotect_frame;
+  size_t max_frame_size;
+} tsi_fake_frame_protector;
+
+/* --- Utils. ---*/
+
+static const char *tsi_fake_handshake_message_strings[] = {
+    "CLIENT_INIT", "SERVER_INIT", "CLIENT_FINISHED", "SERVER_FINISHED"};
+
+static const char *tsi_fake_handshake_message_to_string(int msg) {
+  if (msg < 0 || msg >= TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
+    gpr_log(GPR_ERROR, "Invalid message %d", msg);
+    return "UNKNOWN";
+  }
+  return tsi_fake_handshake_message_strings[msg];
+}
+
+static tsi_result tsi_fake_handshake_message_from_string(
+    const char *msg_string, tsi_fake_handshake_message *msg) {
+  tsi_fake_handshake_message i;
+  for (i = 0; i < TSI_FAKE_HANDSHAKE_MESSAGE_MAX; i++) {
+    if (strncmp(msg_string, tsi_fake_handshake_message_strings[i],
+                strlen(tsi_fake_handshake_message_strings[i])) == 0) {
+      *msg = i;
+      return TSI_OK;
+    }
+  }
+  gpr_log(GPR_ERROR, "Invalid handshake message.");
+  return TSI_DATA_CORRUPTED;
+}
+
+static uint32_t load32_little_endian(const unsigned char *buf) {
+  return ((uint32_t)(buf[0]) | (uint32_t)(buf[1] << 8) |
+          (uint32_t)(buf[2] << 16) | (uint32_t)(buf[3] << 24));
+}
+
+static void store32_little_endian(uint32_t value, unsigned char *buf) {
+  buf[3] = (unsigned char)((value >> 24) & 0xFF);
+  buf[2] = (unsigned char)((value >> 16) & 0xFF);
+  buf[1] = (unsigned char)((value >> 8) & 0xFF);
+  buf[0] = (unsigned char)((value)&0xFF);
+}
+
+static void tsi_fake_frame_reset(tsi_fake_frame *frame, int needs_draining) {
+  frame->offset = 0;
+  frame->needs_draining = needs_draining;
+  if (!needs_draining) frame->size = 0;
+}
+
+/* Returns 1 if successful, 0 otherwise. */
+static int tsi_fake_frame_ensure_size(tsi_fake_frame *frame) {
+  if (frame->data == NULL) {
+    frame->allocated_size = frame->size;
+    frame->data = gpr_malloc(frame->allocated_size);
+    if (frame->data == NULL) return 0;
+  } else if (frame->size > frame->allocated_size) {
+    unsigned char *new_data = gpr_realloc(frame->data, frame->size);
+    if (new_data == NULL) {
+      gpr_free(frame->data);
+      frame->data = NULL;
+      return 0;
+    }
+    frame->data = new_data;
+    frame->allocated_size = frame->size;
+  }
+  return 1;
+}
+
+/* This method should not be called if frame->needs_framing is not 0.  */
+static tsi_result fill_frame_from_bytes(const unsigned char *incoming_bytes,
+                                        size_t *incoming_bytes_size,
+                                        tsi_fake_frame *frame) {
+  size_t available_size = *incoming_bytes_size;
+  size_t to_read_size = 0;
+  const unsigned char *bytes_cursor = incoming_bytes;
+
+  if (frame->needs_draining) return TSI_INTERNAL_ERROR;
+  if (frame->data == NULL) {
+    frame->allocated_size = TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE;
+    frame->data = gpr_malloc(frame->allocated_size);
+    if (frame->data == NULL) return TSI_OUT_OF_RESOURCES;
+  }
+
+  if (frame->offset < TSI_FAKE_FRAME_HEADER_SIZE) {
+    to_read_size = TSI_FAKE_FRAME_HEADER_SIZE - frame->offset;
+    if (to_read_size > available_size) {
+      /* Just fill what we can and exit. */
+      memcpy(frame->data + frame->offset, bytes_cursor, available_size);
+      bytes_cursor += available_size;
+      frame->offset += available_size;
+      *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
+      return TSI_INCOMPLETE_DATA;
+    }
+    memcpy(frame->data + frame->offset, bytes_cursor, to_read_size);
+    bytes_cursor += to_read_size;
+    frame->offset += to_read_size;
+    available_size -= to_read_size;
+    frame->size = load32_little_endian(frame->data);
+    if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES;
+  }
+
+  to_read_size = frame->size - frame->offset;
+  if (to_read_size > available_size) {
+    memcpy(frame->data + frame->offset, bytes_cursor, available_size);
+    frame->offset += available_size;
+    bytes_cursor += available_size;
+    *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
+    return TSI_INCOMPLETE_DATA;
+  }
+  memcpy(frame->data + frame->offset, bytes_cursor, to_read_size);
+  bytes_cursor += to_read_size;
+  *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
+  tsi_fake_frame_reset(frame, 1 /* needs_draining */);
+  return TSI_OK;
+}
+
+/* This method should not be called if frame->needs_framing is 0.  */
+static tsi_result drain_frame_to_bytes(unsigned char *outgoing_bytes,
+                                       size_t *outgoing_bytes_size,
+                                       tsi_fake_frame *frame) {
+  size_t to_write_size = frame->size - frame->offset;
+  if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
+  if (*outgoing_bytes_size < to_write_size) {
+    memcpy(outgoing_bytes, frame->data + frame->offset, *outgoing_bytes_size);
+    frame->offset += *outgoing_bytes_size;
+    return TSI_INCOMPLETE_DATA;
+  }
+  memcpy(outgoing_bytes, frame->data + frame->offset, to_write_size);
+  *outgoing_bytes_size = to_write_size;
+  tsi_fake_frame_reset(frame, 0 /* needs_draining */);
+  return TSI_OK;
+}
+
+static tsi_result bytes_to_frame(unsigned char *bytes, size_t bytes_size,
+                                 tsi_fake_frame *frame) {
+  frame->offset = 0;
+  frame->size = bytes_size + TSI_FAKE_FRAME_HEADER_SIZE;
+  if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES;
+  store32_little_endian((uint32_t)frame->size, frame->data);
+  memcpy(frame->data + TSI_FAKE_FRAME_HEADER_SIZE, bytes, bytes_size);
+  tsi_fake_frame_reset(frame, 1 /* needs draining */);
+  return TSI_OK;
+}
+
+static void tsi_fake_frame_destruct(tsi_fake_frame *frame) {
+  if (frame->data != NULL) gpr_free(frame->data);
+}
+
+/* --- tsi_frame_protector methods implementation. ---*/
+
+static tsi_result fake_protector_protect(tsi_frame_protector *self,
+                                         const unsigned char *unprotected_bytes,
+                                         size_t *unprotected_bytes_size,
+                                         unsigned char *protected_output_frames,
+                                         size_t *protected_output_frames_size) {
+  tsi_result result = TSI_OK;
+  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
+  unsigned char frame_header[TSI_FAKE_FRAME_HEADER_SIZE];
+  tsi_fake_frame *frame = &impl->protect_frame;
+  size_t saved_output_size = *protected_output_frames_size;
+  size_t drained_size = 0;
+  size_t *num_bytes_written = protected_output_frames_size;
+  *num_bytes_written = 0;
+
+  /* Try to drain first. */
+  if (frame->needs_draining) {
+    drained_size = saved_output_size - *num_bytes_written;
+    result =
+        drain_frame_to_bytes(protected_output_frames, &drained_size, frame);
+    *num_bytes_written += drained_size;
+    protected_output_frames += drained_size;
+    if (result != TSI_OK) {
+      if (result == TSI_INCOMPLETE_DATA) {
+        *unprotected_bytes_size = 0;
+        result = TSI_OK;
+      }
+      return result;
+    }
+  }
+
+  /* Now process the unprotected_bytes. */
+  if (frame->needs_draining) return TSI_INTERNAL_ERROR;
+  if (frame->size == 0) {
+    /* New frame, create a header. */
+    size_t written_in_frame_size = 0;
+    store32_little_endian((uint32_t)impl->max_frame_size, frame_header);
+    written_in_frame_size = TSI_FAKE_FRAME_HEADER_SIZE;
+    result = fill_frame_from_bytes(frame_header, &written_in_frame_size, frame);
+    if (result != TSI_INCOMPLETE_DATA) {
+      gpr_log(GPR_ERROR, "fill_frame_from_bytes returned %s",
+              tsi_result_to_string(result));
+      return result;
+    }
+  }
+  result =
+      fill_frame_from_bytes(unprotected_bytes, unprotected_bytes_size, frame);
+  if (result != TSI_OK) {
+    if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
+    return result;
+  }
+
+  /* Try to drain again. */
+  if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
+  if (frame->offset != 0) return TSI_INTERNAL_ERROR;
+  drained_size = saved_output_size - *num_bytes_written;
+  result = drain_frame_to_bytes(protected_output_frames, &drained_size, frame);
+  *num_bytes_written += drained_size;
+  if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
+  return result;
+}
+
+static tsi_result fake_protector_protect_flush(
+    tsi_frame_protector *self, unsigned char *protected_output_frames,
+    size_t *protected_output_frames_size, size_t *still_pending_size) {
+  tsi_result result = TSI_OK;
+  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
+  tsi_fake_frame *frame = &impl->protect_frame;
+  if (!frame->needs_draining) {
+    /* Create a short frame. */
+    frame->size = frame->offset;
+    frame->offset = 0;
+    frame->needs_draining = 1;
+    store32_little_endian((uint32_t)frame->size,
+                          frame->data); /* Overwrite header. */
+  }
+  result = drain_frame_to_bytes(protected_output_frames,
+                                protected_output_frames_size, frame);
+  if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
+  *still_pending_size = frame->size - frame->offset;
+  return result;
+}
+
+static tsi_result fake_protector_unprotect(
+    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
+    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
+    size_t *unprotected_bytes_size) {
+  tsi_result result = TSI_OK;
+  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
+  tsi_fake_frame *frame = &impl->unprotect_frame;
+  size_t saved_output_size = *unprotected_bytes_size;
+  size_t drained_size = 0;
+  size_t *num_bytes_written = unprotected_bytes_size;
+  *num_bytes_written = 0;
+
+  /* Try to drain first. */
+  if (frame->needs_draining) {
+    /* Go past the header if needed. */
+    if (frame->offset == 0) frame->offset = TSI_FAKE_FRAME_HEADER_SIZE;
+    drained_size = saved_output_size - *num_bytes_written;
+    result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame);
+    unprotected_bytes += drained_size;
+    *num_bytes_written += drained_size;
+    if (result != TSI_OK) {
+      if (result == TSI_INCOMPLETE_DATA) {
+        *protected_frames_bytes_size = 0;
+        result = TSI_OK;
+      }
+      return result;
+    }
+  }
+
+  /* Now process the protected_bytes. */
+  if (frame->needs_draining) return TSI_INTERNAL_ERROR;
+  result = fill_frame_from_bytes(protected_frames_bytes,
+                                 protected_frames_bytes_size, frame);
+  if (result != TSI_OK) {
+    if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
+    return result;
+  }
+
+  /* Try to drain again. */
+  if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
+  if (frame->offset != 0) return TSI_INTERNAL_ERROR;
+  frame->offset = TSI_FAKE_FRAME_HEADER_SIZE; /* Go past the header. */
+  drained_size = saved_output_size - *num_bytes_written;
+  result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame);
+  *num_bytes_written += drained_size;
+  if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
+  return result;
+}
+
+static void fake_protector_destroy(tsi_frame_protector *self) {
+  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
+  tsi_fake_frame_destruct(&impl->protect_frame);
+  tsi_fake_frame_destruct(&impl->unprotect_frame);
+  gpr_free(self);
+}
+
+static const tsi_frame_protector_vtable frame_protector_vtable = {
+    fake_protector_protect, fake_protector_protect_flush,
+    fake_protector_unprotect, fake_protector_destroy,
+};
+
+/* --- tsi_handshaker methods implementation. ---*/
+
+static tsi_result fake_handshaker_get_bytes_to_send_to_peer(
+    tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size) {
+  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
+  tsi_result result = TSI_OK;
+  if (impl->needs_incoming_message || impl->result == TSI_OK) {
+    *bytes_size = 0;
+    return TSI_OK;
+  }
+  if (!impl->outgoing.needs_draining) {
+    tsi_fake_handshake_message next_message_to_send =
+        impl->next_message_to_send + 2;
+    const char *msg_string =
+        tsi_fake_handshake_message_to_string(impl->next_message_to_send);
+    result = bytes_to_frame((unsigned char *)msg_string, strlen(msg_string),
+                            &impl->outgoing);
+    if (result != TSI_OK) return result;
+    if (next_message_to_send > TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
+      next_message_to_send = TSI_FAKE_HANDSHAKE_MESSAGE_MAX;
+    }
+    if (tsi_tracing_enabled) {
+      gpr_log(GPR_INFO, "%s prepared %s.",
+              impl->is_client ? "Client" : "Server",
+              tsi_fake_handshake_message_to_string(impl->next_message_to_send));
+    }
+    impl->next_message_to_send = next_message_to_send;
+  }
+  result = drain_frame_to_bytes(bytes, bytes_size, &impl->outgoing);
+  if (result != TSI_OK) return result;
+  if (!impl->is_client &&
+      impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
+    /* We're done. */
+    if (tsi_tracing_enabled) {
+      gpr_log(GPR_INFO, "Server is done.");
+    }
+    impl->result = TSI_OK;
+  } else {
+    impl->needs_incoming_message = 1;
+  }
+  return TSI_OK;
+}
+
+static tsi_result fake_handshaker_process_bytes_from_peer(
+    tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
+  tsi_result result = TSI_OK;
+  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
+  tsi_fake_handshake_message expected_msg = impl->next_message_to_send - 1;
+  tsi_fake_handshake_message received_msg;
+
+  if (!impl->needs_incoming_message || impl->result == TSI_OK) {
+    *bytes_size = 0;
+    return TSI_OK;
+  }
+  result = fill_frame_from_bytes(bytes, bytes_size, &impl->incoming);
+  if (result != TSI_OK) return result;
+
+  /* We now have a complete frame. */
+  result = tsi_fake_handshake_message_from_string(
+      (const char *)impl->incoming.data + TSI_FAKE_FRAME_HEADER_SIZE,
+      &received_msg);
+  if (result != TSI_OK) {
+    impl->result = result;
+    return result;
+  }
+  if (received_msg != expected_msg) {
+    gpr_log(GPR_ERROR, "Invalid received message (%s instead of %s)",
+            tsi_fake_handshake_message_to_string(received_msg),
+            tsi_fake_handshake_message_to_string(expected_msg));
+  }
+  if (tsi_tracing_enabled) {
+    gpr_log(GPR_INFO, "%s received %s.", impl->is_client ? "Client" : "Server",
+            tsi_fake_handshake_message_to_string(received_msg));
+  }
+  tsi_fake_frame_reset(&impl->incoming, 0 /* needs_draining */);
+  impl->needs_incoming_message = 0;
+  if (impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
+    /* We're done. */
+    if (tsi_tracing_enabled) {
+      gpr_log(GPR_INFO, "%s is done.", impl->is_client ? "Client" : "Server");
+    }
+    impl->result = TSI_OK;
+  }
+  return TSI_OK;
+}
+
+static tsi_result fake_handshaker_get_result(tsi_handshaker *self) {
+  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
+  return impl->result;
+}
+
+static tsi_result fake_handshaker_extract_peer(tsi_handshaker *self,
+                                               tsi_peer *peer) {
+  tsi_result result = tsi_construct_peer(1, peer);
+  if (result != TSI_OK) return result;
+  result = tsi_construct_string_peer_property_from_cstring(
+      TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_FAKE_CERTIFICATE_TYPE,
+      &peer->properties[0]);
+  if (result != TSI_OK) tsi_peer_destruct(peer);
+  return result;
+}
+
+static tsi_result fake_handshaker_create_frame_protector(
+    tsi_handshaker *self, size_t *max_protected_frame_size,
+    tsi_frame_protector **protector) {
+  *protector = tsi_create_fake_protector(max_protected_frame_size);
+  if (*protector == NULL) return TSI_OUT_OF_RESOURCES;
+  return TSI_OK;
+}
+
+static void fake_handshaker_destroy(tsi_handshaker *self) {
+  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
+  tsi_fake_frame_destruct(&impl->incoming);
+  tsi_fake_frame_destruct(&impl->outgoing);
+  gpr_free(self);
+}
+
+static const tsi_handshaker_vtable handshaker_vtable = {
+    fake_handshaker_get_bytes_to_send_to_peer,
+    fake_handshaker_process_bytes_from_peer,
+    fake_handshaker_get_result,
+    fake_handshaker_extract_peer,
+    fake_handshaker_create_frame_protector,
+    fake_handshaker_destroy,
+};
+
+tsi_handshaker *tsi_create_fake_handshaker(int is_client) {
+  tsi_fake_handshaker *impl = gpr_malloc(sizeof(*impl));
+  memset(impl, 0, sizeof(*impl));
+  impl->base.vtable = &handshaker_vtable;
+  impl->is_client = is_client;
+  impl->result = TSI_HANDSHAKE_IN_PROGRESS;
+  if (is_client) {
+    impl->needs_incoming_message = 0;
+    impl->next_message_to_send = TSI_FAKE_CLIENT_INIT;
+  } else {
+    impl->needs_incoming_message = 1;
+    impl->next_message_to_send = TSI_FAKE_SERVER_INIT;
+  }
+  return &impl->base;
+}
+
+tsi_frame_protector *tsi_create_fake_protector(
+    size_t *max_protected_frame_size) {
+  tsi_fake_frame_protector *impl = gpr_malloc(sizeof(*impl));
+  memset(impl, 0, sizeof(*impl));
+  impl->max_frame_size = (max_protected_frame_size == NULL)
+                             ? TSI_FAKE_DEFAULT_FRAME_SIZE
+                             : *max_protected_frame_size;
+  impl->base.vtable = &frame_protector_vtable;
+  return &impl->base;
+}
diff --git a/src/core/lib/tsi/fake_transport_security.h b/src/core/lib/tsi/fake_transport_security.h
new file mode 100644
index 0000000..54a9469
--- /dev/null
+++ b/src/core/lib/tsi/fake_transport_security.h
@@ -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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_TSI_FAKE_TRANSPORT_SECURITY_H
+#define GRPC_CORE_LIB_TSI_FAKE_TRANSPORT_SECURITY_H
+
+#include "src/core/lib/tsi/transport_security_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for FAKE certs. */
+#define TSI_FAKE_CERTIFICATE_TYPE "FAKE"
+
+/* Creates a fake handshaker that will create a fake frame protector.
+
+   No cryptography is performed in these objects. They just simulate handshake
+   messages going back and forth for the handshaker and do some framing on
+   cleartext data for the protector.  */
+tsi_handshaker *tsi_create_fake_handshaker(int is_client);
+
+/* Creates a protector directly without going through the handshake phase. */
+tsi_frame_protector *tsi_create_fake_protector(
+    size_t *max_protected_frame_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_TSI_FAKE_TRANSPORT_SECURITY_H */
diff --git a/src/core/lib/tsi/ssl_transport_security.c b/src/core/lib/tsi/ssl_transport_security.c
new file mode 100644
index 0000000..e91c631
--- /dev/null
+++ b/src/core/lib/tsi/ssl_transport_security.c
@@ -0,0 +1,1579 @@
+/*
+ *
+ * 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/tsi/ssl_transport_security.h"
+
+#include <grpc/support/port_platform.h>
+
+#include <limits.h>
+#include <string.h>
+
+/* TODO(jboeuf): refactor inet_ntop into a portability header. */
+#ifdef GPR_WINSOCK_SOCKET
+#include <ws2tcpip.h>
+#else
+#include <arpa/inet.h>
+#endif
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h> /* For OPENSSL_free */
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "src/core/lib/tsi/ssl_types.h"
+#include "src/core/lib/tsi/transport_security.h"
+
+/* --- Constants. ---*/
+
+#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384
+#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024
+
+/* Putting a macro like this and littering the source file with #if is really
+   bad practice.
+   TODO(jboeuf): refactor all the #if / #endif in a separate module. */
+#ifndef TSI_OPENSSL_ALPN_SUPPORT
+#define TSI_OPENSSL_ALPN_SUPPORT 1
+#endif
+
+/* TODO(jboeuf): I have not found a way to get this number dynamically from the
+   SSL structure. This is what we would ultimately want though... */
+#define TSI_SSL_MAX_PROTECTION_OVERHEAD 100
+
+/* --- Structure definitions. ---*/
+
+struct tsi_ssl_handshaker_factory {
+  tsi_result (*create_handshaker)(tsi_ssl_handshaker_factory *self,
+                                  const char *server_name_indication,
+                                  tsi_handshaker **handshaker);
+  void (*destroy)(tsi_ssl_handshaker_factory *self);
+};
+
+typedef struct {
+  tsi_ssl_handshaker_factory base;
+  SSL_CTX *ssl_context;
+  unsigned char *alpn_protocol_list;
+  size_t alpn_protocol_list_length;
+} tsi_ssl_client_handshaker_factory;
+
+typedef struct {
+  tsi_ssl_handshaker_factory base;
+
+  /* Several contexts to support SNI.
+     The tsi_peer array contains the subject names of the server certificates
+     associated with the contexts at the same index.  */
+  SSL_CTX **ssl_contexts;
+  tsi_peer *ssl_context_x509_subject_names;
+  size_t ssl_context_count;
+  unsigned char *alpn_protocol_list;
+  size_t alpn_protocol_list_length;
+} tsi_ssl_server_handshaker_factory;
+
+typedef struct {
+  tsi_handshaker base;
+  SSL *ssl;
+  BIO *into_ssl;
+  BIO *from_ssl;
+  tsi_result result;
+} tsi_ssl_handshaker;
+
+typedef struct {
+  tsi_frame_protector base;
+  SSL *ssl;
+  BIO *into_ssl;
+  BIO *from_ssl;
+  unsigned char *buffer;
+  size_t buffer_size;
+  size_t buffer_offset;
+} tsi_ssl_frame_protector;
+
+/* --- Library Initialization. ---*/
+
+static gpr_once init_openssl_once = GPR_ONCE_INIT;
+static gpr_mu *openssl_mutexes = NULL;
+
+static void openssl_locking_cb(int mode, int type, const char *file, int line) {
+  if (mode & CRYPTO_LOCK) {
+    gpr_mu_lock(&openssl_mutexes[type]);
+  } else {
+    gpr_mu_unlock(&openssl_mutexes[type]);
+  }
+}
+
+static unsigned long openssl_thread_id_cb(void) {
+  return (unsigned long)gpr_thd_currentid();
+}
+
+static void init_openssl(void) {
+  int i;
+  int num_locks;
+  SSL_library_init();
+  SSL_load_error_strings();
+  OpenSSL_add_all_algorithms();
+  num_locks = CRYPTO_num_locks();
+  GPR_ASSERT(num_locks > 0);
+  openssl_mutexes = gpr_malloc((size_t)num_locks * sizeof(gpr_mu));
+  for (i = 0; i < CRYPTO_num_locks(); i++) {
+    gpr_mu_init(&openssl_mutexes[i]);
+  }
+  CRYPTO_set_locking_callback(openssl_locking_cb);
+  CRYPTO_set_id_callback(openssl_thread_id_cb);
+}
+
+/* --- Ssl utils. ---*/
+
+static const char *ssl_error_string(int error) {
+  switch (error) {
+    case SSL_ERROR_NONE:
+      return "SSL_ERROR_NONE";
+    case SSL_ERROR_ZERO_RETURN:
+      return "SSL_ERROR_ZERO_RETURN";
+    case SSL_ERROR_WANT_READ:
+      return "SSL_ERROR_WANT_READ";
+    case SSL_ERROR_WANT_WRITE:
+      return "SSL_ERROR_WANT_WRITE";
+    case SSL_ERROR_WANT_CONNECT:
+      return "SSL_ERROR_WANT_CONNECT";
+    case SSL_ERROR_WANT_ACCEPT:
+      return "SSL_ERROR_WANT_ACCEPT";
+    case SSL_ERROR_WANT_X509_LOOKUP:
+      return "SSL_ERROR_WANT_X509_LOOKUP";
+    case SSL_ERROR_SYSCALL:
+      return "SSL_ERROR_SYSCALL";
+    case SSL_ERROR_SSL:
+      return "SSL_ERROR_SSL";
+    default:
+      return "Unknown error";
+  }
+}
+
+/* TODO(jboeuf): Remove when we are past the debugging phase with this code. */
+static void ssl_log_where_info(const SSL *ssl, int where, int flag,
+                               const char *msg) {
+  if ((where & flag) && tsi_tracing_enabled) {
+    gpr_log(GPR_INFO, "%20.20s - %30.30s  - %5.10s", msg,
+            SSL_state_string_long(ssl), SSL_state_string(ssl));
+  }
+}
+
+/* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
+static void ssl_info_callback(const SSL *ssl, int where, int ret) {
+  if (ret == 0) {
+    gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
+    return;
+  }
+
+  ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP");
+  ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
+  ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
+}
+
+/* Returns 1 if name looks like an IP address, 0 otherwise.
+   This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */
+static int looks_like_ip_address(const char *name) {
+  size_t i;
+  size_t dot_count = 0;
+  size_t num_size = 0;
+  for (i = 0; i < strlen(name); i++) {
+    if (name[i] == ':') {
+      /* IPv6 Address in hexadecimal form, : is not allowed in DNS names. */
+      return 1;
+    }
+    if (name[i] >= '0' && name[i] <= '9') {
+      if (num_size > 3) return 0;
+      num_size++;
+    } else if (name[i] == '.') {
+      if (dot_count > 3 || num_size == 0) return 0;
+      dot_count++;
+      num_size = 0;
+    } else {
+      return 0;
+    }
+  }
+  if (dot_count < 3 || num_size == 0) return 0;
+  return 1;
+}
+
+/* Gets the subject CN from an X509 cert. */
+static tsi_result ssl_get_x509_common_name(X509 *cert, unsigned char **utf8,
+                                           size_t *utf8_size) {
+  int common_name_index = -1;
+  X509_NAME_ENTRY *common_name_entry = NULL;
+  ASN1_STRING *common_name_asn1 = NULL;
+  X509_NAME *subject_name = X509_get_subject_name(cert);
+  int utf8_returned_size = 0;
+  if (subject_name == NULL) {
+    gpr_log(GPR_ERROR, "Could not get subject name from certificate.");
+    return TSI_NOT_FOUND;
+  }
+  common_name_index =
+      X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
+  if (common_name_index == -1) {
+    gpr_log(GPR_ERROR,
+            "Could not get common name of subject from certificate.");
+    return TSI_NOT_FOUND;
+  }
+  common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
+  if (common_name_entry == NULL) {
+    gpr_log(GPR_ERROR, "Could not get common name entry from certificate.");
+    return TSI_INTERNAL_ERROR;
+  }
+  common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
+  if (common_name_asn1 == NULL) {
+    gpr_log(GPR_ERROR,
+            "Could not get common name entry asn1 from certificate.");
+    return TSI_INTERNAL_ERROR;
+  }
+  utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
+  if (utf8_returned_size < 0) {
+    gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string.");
+    return TSI_OUT_OF_RESOURCES;
+  }
+  *utf8_size = (size_t)utf8_returned_size;
+  return TSI_OK;
+}
+
+/* Gets the subject CN of an X509 cert as a tsi_peer_property. */
+static tsi_result peer_property_from_x509_common_name(
+    X509 *cert, tsi_peer_property *property) {
+  unsigned char *common_name;
+  size_t common_name_size;
+  tsi_result result =
+      ssl_get_x509_common_name(cert, &common_name, &common_name_size);
+  if (result != TSI_OK) {
+    if (result == TSI_NOT_FOUND) {
+      common_name = NULL;
+      common_name_size = 0;
+    } else {
+      return result;
+    }
+  }
+  result = tsi_construct_string_peer_property(
+      TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
+      common_name == NULL ? "" : (const char *)common_name, common_name_size,
+      property);
+  OPENSSL_free(common_name);
+  return result;
+}
+
+/* Gets the X509 cert in PEM format as a tsi_peer_property. */
+static tsi_result add_pem_certificate(X509 *cert, tsi_peer_property *property) {
+  BIO *bio = BIO_new(BIO_s_mem());
+  if (!PEM_write_bio_X509(bio, cert)) {
+    BIO_free(bio);
+    return TSI_INTERNAL_ERROR;
+  }
+  char *contents;
+  long len = BIO_get_mem_data(bio, &contents);
+  if (len <= 0) {
+    BIO_free(bio);
+    return TSI_INTERNAL_ERROR;
+  }
+  tsi_result result = tsi_construct_string_peer_property(
+      TSI_X509_PEM_CERT_PROPERTY, (const char *)contents, (size_t)len,
+      property);
+  BIO_free(bio);
+  return result;
+}
+
+/* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
+static tsi_result add_subject_alt_names_properties_to_peer(
+    tsi_peer *peer, GENERAL_NAMES *subject_alt_names,
+    size_t subject_alt_name_count) {
+  size_t i;
+  tsi_result result = TSI_OK;
+
+  /* Reset for DNS entries filtering. */
+  peer->property_count -= subject_alt_name_count;
+
+  for (i = 0; i < subject_alt_name_count; i++) {
+    GENERAL_NAME *subject_alt_name =
+        sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
+    /* Filter out the non-dns entries names. */
+    if (subject_alt_name->type == GEN_DNS) {
+      unsigned char *name = NULL;
+      int name_size;
+      name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName);
+      if (name_size < 0) {
+        gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
+        result = TSI_INTERNAL_ERROR;
+        break;
+      }
+      result = tsi_construct_string_peer_property(
+          TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *)name,
+          (size_t)name_size, &peer->properties[peer->property_count++]);
+      OPENSSL_free(name);
+    } else if (subject_alt_name->type == GEN_IPADD) {
+      char ntop_buf[INET6_ADDRSTRLEN];
+      int af;
+
+      if (subject_alt_name->d.iPAddress->length == 4) {
+        af = AF_INET;
+      } else if (subject_alt_name->d.iPAddress->length == 16) {
+        af = AF_INET6;
+      } else {
+        gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP");
+        result = TSI_INTERNAL_ERROR;
+        break;
+      }
+      const char *name = inet_ntop(af, subject_alt_name->d.iPAddress->data,
+                                   ntop_buf, INET6_ADDRSTRLEN);
+      if (name == NULL) {
+        gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet.");
+        result = TSI_INTERNAL_ERROR;
+        break;
+      }
+
+      result = tsi_construct_string_peer_property_from_cstring(
+          TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name,
+          &peer->properties[peer->property_count++]);
+    }
+    if (result != TSI_OK) break;
+  }
+  return result;
+}
+
+/* Gets information about the peer's X509 cert as a tsi_peer object. */
+static tsi_result peer_from_x509(X509 *cert, int include_certificate_type,
+                                 tsi_peer *peer) {
+  /* TODO(jboeuf): Maybe add more properties. */
+  GENERAL_NAMES *subject_alt_names =
+      X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
+  int subject_alt_name_count = (subject_alt_names != NULL)
+                                   ? (int)sk_GENERAL_NAME_num(subject_alt_names)
+                                   : 0;
+  size_t property_count;
+  tsi_result result;
+  GPR_ASSERT(subject_alt_name_count >= 0);
+  property_count = (include_certificate_type ? (size_t)1 : 0) +
+                   2 /* common name, certificate */ +
+                   (size_t)subject_alt_name_count;
+  result = tsi_construct_peer(property_count, peer);
+  if (result != TSI_OK) return result;
+  do {
+    if (include_certificate_type) {
+      result = tsi_construct_string_peer_property_from_cstring(
+          TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
+          &peer->properties[0]);
+      if (result != TSI_OK) break;
+    }
+    result = peer_property_from_x509_common_name(
+        cert, &peer->properties[include_certificate_type ? 1 : 0]);
+    if (result != TSI_OK) break;
+
+    result = add_pem_certificate(
+        cert, &peer->properties[include_certificate_type ? 2 : 1]);
+    if (result != TSI_OK) break;
+
+    if (subject_alt_name_count != 0) {
+      result = add_subject_alt_names_properties_to_peer(
+          peer, subject_alt_names, (size_t)subject_alt_name_count);
+      if (result != TSI_OK) break;
+    }
+  } while (0);
+
+  if (subject_alt_names != NULL) {
+    sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
+  }
+  if (result != TSI_OK) tsi_peer_destruct(peer);
+  return result;
+}
+
+/* Logs the SSL error stack. */
+static void log_ssl_error_stack(void) {
+  unsigned long err;
+  while ((err = ERR_get_error()) != 0) {
+    char details[256];
+    ERR_error_string_n((uint32_t)err, details, sizeof(details));
+    gpr_log(GPR_ERROR, "%s", details);
+  }
+}
+
+/* Performs an SSL_read and handle errors. */
+static tsi_result do_ssl_read(SSL *ssl, unsigned char *unprotected_bytes,
+                              size_t *unprotected_bytes_size) {
+  int read_from_ssl;
+  GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
+  read_from_ssl =
+      SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size);
+  if (read_from_ssl == 0) {
+    gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly.");
+    return TSI_INTERNAL_ERROR;
+  }
+  if (read_from_ssl < 0) {
+    read_from_ssl = SSL_get_error(ssl, read_from_ssl);
+    switch (read_from_ssl) {
+      case SSL_ERROR_WANT_READ:
+        /* We need more data to finish the frame. */
+        *unprotected_bytes_size = 0;
+        return TSI_OK;
+      case SSL_ERROR_WANT_WRITE:
+        gpr_log(
+            GPR_ERROR,
+            "Peer tried to renegotiate SSL connection. This is unsupported.");
+        return TSI_UNIMPLEMENTED;
+      case SSL_ERROR_SSL:
+        gpr_log(GPR_ERROR, "Corruption detected.");
+        log_ssl_error_stack();
+        return TSI_DATA_CORRUPTED;
+      default:
+        gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
+                ssl_error_string(read_from_ssl));
+        return TSI_PROTOCOL_FAILURE;
+    }
+  }
+  *unprotected_bytes_size = (size_t)read_from_ssl;
+  return TSI_OK;
+}
+
+/* Performs an SSL_write and handle errors. */
+static tsi_result do_ssl_write(SSL *ssl, unsigned char *unprotected_bytes,
+                               size_t unprotected_bytes_size) {
+  int ssl_write_result;
+  GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
+  ssl_write_result =
+      SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size);
+  if (ssl_write_result < 0) {
+    ssl_write_result = SSL_get_error(ssl, ssl_write_result);
+    if (ssl_write_result == SSL_ERROR_WANT_READ) {
+      gpr_log(GPR_ERROR,
+              "Peer tried to renegotiate SSL connection. This is unsupported.");
+      return TSI_UNIMPLEMENTED;
+    } else {
+      gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
+              ssl_error_string(ssl_write_result));
+      return TSI_INTERNAL_ERROR;
+    }
+  }
+  return TSI_OK;
+}
+
+/* Loads an in-memory PEM certificate chain into the SSL context. */
+static tsi_result ssl_ctx_use_certificate_chain(
+    SSL_CTX *context, const unsigned char *pem_cert_chain,
+    size_t pem_cert_chain_size) {
+  tsi_result result = TSI_OK;
+  X509 *certificate = NULL;
+  BIO *pem;
+  GPR_ASSERT(pem_cert_chain_size <= INT_MAX);
+  pem = BIO_new_mem_buf((void *)pem_cert_chain, (int)pem_cert_chain_size);
+  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
+
+  do {
+    certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
+    if (certificate == NULL) {
+      result = TSI_INVALID_ARGUMENT;
+      break;
+    }
+    if (!SSL_CTX_use_certificate(context, certificate)) {
+      result = TSI_INVALID_ARGUMENT;
+      break;
+    }
+    while (1) {
+      X509 *certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, "");
+      if (certificate_authority == NULL) {
+        ERR_clear_error();
+        break; /* Done reading. */
+      }
+      if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) {
+        X509_free(certificate_authority);
+        result = TSI_INVALID_ARGUMENT;
+        break;
+      }
+      /* We don't need to free certificate_authority as its ownership has been
+         transfered to the context. That is not the case for certificate though.
+       */
+    }
+  } while (0);
+
+  if (certificate != NULL) X509_free(certificate);
+  BIO_free(pem);
+  return result;
+}
+
+/* Loads an in-memory PEM private key into the SSL context. */
+static tsi_result ssl_ctx_use_private_key(SSL_CTX *context,
+                                          const unsigned char *pem_key,
+                                          size_t pem_key_size) {
+  tsi_result result = TSI_OK;
+  EVP_PKEY *private_key = NULL;
+  BIO *pem;
+  GPR_ASSERT(pem_key_size <= INT_MAX);
+  pem = BIO_new_mem_buf((void *)pem_key, (int)pem_key_size);
+  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
+  do {
+    private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
+    if (private_key == NULL) {
+      result = TSI_INVALID_ARGUMENT;
+      break;
+    }
+    if (!SSL_CTX_use_PrivateKey(context, private_key)) {
+      result = TSI_INVALID_ARGUMENT;
+      break;
+    }
+  } while (0);
+  if (private_key != NULL) EVP_PKEY_free(private_key);
+  BIO_free(pem);
+  return result;
+}
+
+/* Loads in-memory PEM verification certs into the SSL context and optionally
+   returns the verification cert names (root_names can be NULL). */
+static tsi_result ssl_ctx_load_verification_certs(
+    SSL_CTX *context, const unsigned char *pem_roots, size_t pem_roots_size,
+    STACK_OF(X509_NAME) * *root_names) {
+  tsi_result result = TSI_OK;
+  size_t num_roots = 0;
+  X509 *root = NULL;
+  X509_NAME *root_name = NULL;
+  BIO *pem;
+  X509_STORE *root_store;
+  GPR_ASSERT(pem_roots_size <= INT_MAX);
+  pem = BIO_new_mem_buf((void *)pem_roots, (int)pem_roots_size);
+  root_store = SSL_CTX_get_cert_store(context);
+  if (root_store == NULL) return TSI_INVALID_ARGUMENT;
+  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
+  if (root_names != NULL) {
+    *root_names = sk_X509_NAME_new_null();
+    if (*root_names == NULL) return TSI_OUT_OF_RESOURCES;
+  }
+
+  while (1) {
+    root = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
+    if (root == NULL) {
+      ERR_clear_error();
+      break; /* We're at the end of stream. */
+    }
+    if (root_names != NULL) {
+      root_name = X509_get_subject_name(root);
+      if (root_name == NULL) {
+        gpr_log(GPR_ERROR, "Could not get name from root certificate.");
+        result = TSI_INVALID_ARGUMENT;
+        break;
+      }
+      root_name = X509_NAME_dup(root_name);
+      if (root_name == NULL) {
+        result = TSI_OUT_OF_RESOURCES;
+        break;
+      }
+      sk_X509_NAME_push(*root_names, root_name);
+      root_name = NULL;
+    }
+    if (!X509_STORE_add_cert(root_store, root)) {
+      gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
+      result = TSI_INTERNAL_ERROR;
+      break;
+    }
+    X509_free(root);
+    num_roots++;
+  }
+
+  if (num_roots == 0) {
+    gpr_log(GPR_ERROR, "Could not load any root certificate.");
+    result = TSI_INVALID_ARGUMENT;
+  }
+
+  if (result != TSI_OK) {
+    if (root != NULL) X509_free(root);
+    if (root_names != NULL) {
+      sk_X509_NAME_pop_free(*root_names, X509_NAME_free);
+      *root_names = NULL;
+      if (root_name != NULL) X509_NAME_free(root_name);
+    }
+  }
+  BIO_free(pem);
+  return result;
+}
+
+/* Populates the SSL context with a private key and a cert chain, and sets the
+   cipher list and the ephemeral ECDH key. */
+static tsi_result populate_ssl_context(
+    SSL_CTX *context, const unsigned char *pem_private_key,
+    size_t pem_private_key_size, const unsigned char *pem_certificate_chain,
+    size_t pem_certificate_chain_size, const char *cipher_list) {
+  tsi_result result = TSI_OK;
+  if (pem_certificate_chain != NULL) {
+    result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain,
+                                           pem_certificate_chain_size);
+    if (result != TSI_OK) {
+      gpr_log(GPR_ERROR, "Invalid cert chain file.");
+      return result;
+    }
+  }
+  if (pem_private_key != NULL) {
+    result =
+        ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size);
+    if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
+      gpr_log(GPR_ERROR, "Invalid private key.");
+      return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
+    }
+  }
+  if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) {
+    gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
+    return TSI_INVALID_ARGUMENT;
+  }
+  {
+    EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+    if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
+      gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
+      EC_KEY_free(ecdh);
+      return TSI_INTERNAL_ERROR;
+    }
+    SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
+    EC_KEY_free(ecdh);
+  }
+  return TSI_OK;
+}
+
+/* Extracts the CN and the SANs from an X509 cert as a peer object. */
+static tsi_result extract_x509_subject_names_from_pem_cert(
+    const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer *peer) {
+  tsi_result result = TSI_OK;
+  X509 *cert = NULL;
+  BIO *pem;
+  GPR_ASSERT(pem_cert_size <= INT_MAX);
+  pem = BIO_new_mem_buf((void *)pem_cert, (int)pem_cert_size);
+  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
+
+  cert = PEM_read_bio_X509(pem, NULL, NULL, "");
+  if (cert == NULL) {
+    gpr_log(GPR_ERROR, "Invalid certificate");
+    result = TSI_INVALID_ARGUMENT;
+  } else {
+    result = peer_from_x509(cert, 0, peer);
+  }
+  if (cert != NULL) X509_free(cert);
+  BIO_free(pem);
+  return result;
+}
+
+/* Builds the alpn protocol name list according to rfc 7301. */
+static tsi_result build_alpn_protocol_name_list(
+    const unsigned char **alpn_protocols,
+    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+    unsigned char **protocol_name_list, size_t *protocol_name_list_length) {
+  uint16_t i;
+  unsigned char *current;
+  *protocol_name_list = NULL;
+  *protocol_name_list_length = 0;
+  if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
+  for (i = 0; i < num_alpn_protocols; i++) {
+    if (alpn_protocols_lengths[i] == 0) {
+      gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
+      return TSI_INVALID_ARGUMENT;
+    }
+    *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1;
+  }
+  *protocol_name_list = gpr_malloc(*protocol_name_list_length);
+  if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES;
+  current = *protocol_name_list;
+  for (i = 0; i < num_alpn_protocols; i++) {
+    *(current++) = alpn_protocols_lengths[i];
+    memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]);
+    current += alpn_protocols_lengths[i];
+  }
+  /* Safety check. */
+  if ((current < *protocol_name_list) ||
+      ((uintptr_t)(current - *protocol_name_list) !=
+       *protocol_name_list_length)) {
+    return TSI_INTERNAL_ERROR;
+  }
+  return TSI_OK;
+}
+
+// The verification callback is used for clients that don't really care about
+// the server's certificate, but we need to pull it anyway, in case a higher
+// layer wants to look at it. In this case the verification may fail, but
+// we don't really care.
+static int NullVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) {
+  return 1;
+}
+
+/* --- tsi_frame_protector methods implementation. ---*/
+
+static tsi_result ssl_protector_protect(tsi_frame_protector *self,
+                                        const unsigned char *unprotected_bytes,
+                                        size_t *unprotected_bytes_size,
+                                        unsigned char *protected_output_frames,
+                                        size_t *protected_output_frames_size) {
+  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
+  int read_from_ssl;
+  size_t available;
+  tsi_result result = TSI_OK;
+
+  /* First see if we have some pending data in the SSL BIO. */
+  int pending_in_ssl = (int)BIO_pending(impl->from_ssl);
+  if (pending_in_ssl > 0) {
+    *unprotected_bytes_size = 0;
+    GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
+    read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
+                             (int)*protected_output_frames_size);
+    if (read_from_ssl < 0) {
+      gpr_log(GPR_ERROR,
+              "Could not read from BIO even though some data is pending");
+      return TSI_INTERNAL_ERROR;
+    }
+    *protected_output_frames_size = (size_t)read_from_ssl;
+    return TSI_OK;
+  }
+
+  /* Now see if we can send a complete frame. */
+  available = impl->buffer_size - impl->buffer_offset;
+  if (available > *unprotected_bytes_size) {
+    /* If we cannot, just copy the data in our internal buffer. */
+    memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes,
+           *unprotected_bytes_size);
+    impl->buffer_offset += *unprotected_bytes_size;
+    *protected_output_frames_size = 0;
+    return TSI_OK;
+  }
+
+  /* If we can, prepare the buffer, send it to SSL_write and read. */
+  memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available);
+  result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size);
+  if (result != TSI_OK) return result;
+
+  GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
+  read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
+                           (int)*protected_output_frames_size);
+  if (read_from_ssl < 0) {
+    gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
+    return TSI_INTERNAL_ERROR;
+  }
+  *protected_output_frames_size = (size_t)read_from_ssl;
+  *unprotected_bytes_size = available;
+  impl->buffer_offset = 0;
+  return TSI_OK;
+}
+
+static tsi_result ssl_protector_protect_flush(
+    tsi_frame_protector *self, unsigned char *protected_output_frames,
+    size_t *protected_output_frames_size, size_t *still_pending_size) {
+  tsi_result result = TSI_OK;
+  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
+  int read_from_ssl = 0;
+  int pending;
+
+  if (impl->buffer_offset != 0) {
+    result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset);
+    if (result != TSI_OK) return result;
+    impl->buffer_offset = 0;
+  }
+
+  pending = (int)BIO_pending(impl->from_ssl);
+  GPR_ASSERT(pending >= 0);
+  *still_pending_size = (size_t)pending;
+  if (*still_pending_size == 0) return TSI_OK;
+
+  GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
+  read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
+                           (int)*protected_output_frames_size);
+  if (read_from_ssl <= 0) {
+    gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
+    return TSI_INTERNAL_ERROR;
+  }
+  *protected_output_frames_size = (size_t)read_from_ssl;
+  pending = (int)BIO_pending(impl->from_ssl);
+  GPR_ASSERT(pending >= 0);
+  *still_pending_size = (size_t)pending;
+  return TSI_OK;
+}
+
+static tsi_result ssl_protector_unprotect(
+    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
+    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
+    size_t *unprotected_bytes_size) {
+  tsi_result result = TSI_OK;
+  int written_into_ssl = 0;
+  size_t output_bytes_size = *unprotected_bytes_size;
+  size_t output_bytes_offset = 0;
+  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
+
+  /* First, try to read remaining data from ssl. */
+  result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
+  if (result != TSI_OK) return result;
+  if (*unprotected_bytes_size == output_bytes_size) {
+    /* We have read everything we could and cannot process any more input. */
+    *protected_frames_bytes_size = 0;
+    return TSI_OK;
+  }
+  output_bytes_offset = *unprotected_bytes_size;
+  unprotected_bytes += output_bytes_offset;
+  *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
+
+  /* Then, try to write some data to ssl. */
+  GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
+  written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes,
+                               (int)*protected_frames_bytes_size);
+  if (written_into_ssl < 0) {
+    gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
+            written_into_ssl);
+    return TSI_INTERNAL_ERROR;
+  }
+  *protected_frames_bytes_size = (size_t)written_into_ssl;
+
+  /* Now try to read some data again. */
+  result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
+  if (result == TSI_OK) {
+    /* Don't forget to output the total number of bytes read. */
+    *unprotected_bytes_size += output_bytes_offset;
+  }
+  return result;
+}
+
+static void ssl_protector_destroy(tsi_frame_protector *self) {
+  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
+  if (impl->buffer != NULL) gpr_free(impl->buffer);
+  if (impl->ssl != NULL) SSL_free(impl->ssl);
+  gpr_free(self);
+}
+
+static const tsi_frame_protector_vtable frame_protector_vtable = {
+    ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
+    ssl_protector_destroy,
+};
+
+/* --- tsi_handshaker methods implementation. ---*/
+
+static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
+                                                           unsigned char *bytes,
+                                                           size_t *bytes_size) {
+  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
+  int bytes_read_from_ssl = 0;
+  if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
+      *bytes_size > INT_MAX) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  GPR_ASSERT(*bytes_size <= INT_MAX);
+  bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size);
+  if (bytes_read_from_ssl < 0) {
+    *bytes_size = 0;
+    if (!BIO_should_retry(impl->from_ssl)) {
+      impl->result = TSI_INTERNAL_ERROR;
+      return impl->result;
+    } else {
+      return TSI_OK;
+    }
+  }
+  *bytes_size = (size_t)bytes_read_from_ssl;
+  return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
+}
+
+static tsi_result ssl_handshaker_get_result(tsi_handshaker *self) {
+  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
+  if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
+      SSL_is_init_finished(impl->ssl)) {
+    impl->result = TSI_OK;
+  }
+  return impl->result;
+}
+
+static tsi_result ssl_handshaker_process_bytes_from_peer(
+    tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
+  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
+  int bytes_written_into_ssl_size = 0;
+  if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  GPR_ASSERT(*bytes_size <= INT_MAX);
+  bytes_written_into_ssl_size =
+      BIO_write(impl->into_ssl, bytes, (int)*bytes_size);
+  if (bytes_written_into_ssl_size < 0) {
+    gpr_log(GPR_ERROR, "Could not write to memory BIO.");
+    impl->result = TSI_INTERNAL_ERROR;
+    return impl->result;
+  }
+  *bytes_size = (size_t)bytes_written_into_ssl_size;
+
+  if (!tsi_handshaker_is_in_progress(self)) {
+    impl->result = TSI_OK;
+    return impl->result;
+  } else {
+    /* Get ready to get some bytes from SSL. */
+    int ssl_result = SSL_do_handshake(impl->ssl);
+    ssl_result = SSL_get_error(impl->ssl, ssl_result);
+    switch (ssl_result) {
+      case SSL_ERROR_WANT_READ:
+        if (BIO_pending(impl->from_ssl) == 0) {
+          /* We need more data. */
+          return TSI_INCOMPLETE_DATA;
+        } else {
+          return TSI_OK;
+        }
+      case SSL_ERROR_NONE:
+        return TSI_OK;
+      default: {
+        char err_str[256];
+        ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
+        gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
+                ssl_error_string(ssl_result), err_str);
+        impl->result = TSI_PROTOCOL_FAILURE;
+        return impl->result;
+      }
+    }
+  }
+}
+
+static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self,
+                                              tsi_peer *peer) {
+  tsi_result result = TSI_OK;
+  const unsigned char *alpn_selected = NULL;
+  unsigned int alpn_selected_len;
+  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
+  X509 *peer_cert = SSL_get_peer_certificate(impl->ssl);
+  if (peer_cert != NULL) {
+    result = peer_from_x509(peer_cert, 1, peer);
+    X509_free(peer_cert);
+    if (result != TSI_OK) return result;
+  }
+#if TSI_OPENSSL_ALPN_SUPPORT
+  SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len);
+#endif /* TSI_OPENSSL_ALPN_SUPPORT */
+  if (alpn_selected == NULL) {
+    /* Try npn. */
+    SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
+                                   &alpn_selected_len);
+  }
+  if (alpn_selected != NULL) {
+    size_t i;
+    tsi_peer_property *new_properties =
+        gpr_malloc(sizeof(*new_properties) * (peer->property_count + 1));
+    memset(new_properties, 0,
+           sizeof(*new_properties) * (peer->property_count + 1));
+    for (i = 0; i < peer->property_count; i++) {
+      new_properties[i] = peer->properties[i];
+    }
+    result = tsi_construct_string_peer_property(
+        TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *)alpn_selected,
+        alpn_selected_len, &new_properties[peer->property_count]);
+    if (result != TSI_OK) {
+      gpr_free(new_properties);
+      return result;
+    }
+    if (peer->properties != NULL) gpr_free(peer->properties);
+    peer->property_count++;
+    peer->properties = new_properties;
+  }
+  return result;
+}
+
+static tsi_result ssl_handshaker_create_frame_protector(
+    tsi_handshaker *self, size_t *max_output_protected_frame_size,
+    tsi_frame_protector **protector) {
+  size_t actual_max_output_protected_frame_size =
+      TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
+  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
+  tsi_ssl_frame_protector *protector_impl = gpr_malloc(sizeof(*protector_impl));
+  memset(protector_impl, 0, sizeof(*protector_impl));
+
+  if (max_output_protected_frame_size != NULL) {
+    if (*max_output_protected_frame_size >
+        TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) {
+      *max_output_protected_frame_size =
+          TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
+    } else if (*max_output_protected_frame_size <
+               TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) {
+      *max_output_protected_frame_size =
+          TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
+    }
+    actual_max_output_protected_frame_size = *max_output_protected_frame_size;
+  }
+  protector_impl->buffer_size =
+      actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
+  protector_impl->buffer = gpr_malloc(protector_impl->buffer_size);
+  if (protector_impl->buffer == NULL) {
+    gpr_log(GPR_ERROR,
+            "Could not allocated buffer for tsi_ssl_frame_protector.");
+    gpr_free(protector_impl);
+    return TSI_INTERNAL_ERROR;
+  }
+
+  /* Transfer ownership of ssl to the frame protector. It is OK as the caller
+   * cannot call anything else but destroy on the handshaker after this call. */
+  protector_impl->ssl = impl->ssl;
+  impl->ssl = NULL;
+  protector_impl->into_ssl = impl->into_ssl;
+  protector_impl->from_ssl = impl->from_ssl;
+
+  protector_impl->base.vtable = &frame_protector_vtable;
+  *protector = &protector_impl->base;
+  return TSI_OK;
+}
+
+static void ssl_handshaker_destroy(tsi_handshaker *self) {
+  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
+  SSL_free(impl->ssl); /* The BIO objects are owned by ssl */
+  gpr_free(impl);
+}
+
+static const tsi_handshaker_vtable handshaker_vtable = {
+    ssl_handshaker_get_bytes_to_send_to_peer,
+    ssl_handshaker_process_bytes_from_peer,
+    ssl_handshaker_get_result,
+    ssl_handshaker_extract_peer,
+    ssl_handshaker_create_frame_protector,
+    ssl_handshaker_destroy,
+};
+
+/* --- tsi_ssl_handshaker_factory common methods. --- */
+
+tsi_result tsi_ssl_handshaker_factory_create_handshaker(
+    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
+    tsi_handshaker **handshaker) {
+  if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
+  return self->create_handshaker(self, server_name_indication, handshaker);
+}
+
+void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self) {
+  if (self == NULL) return;
+  self->destroy(self);
+}
+
+static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
+                                            const char *server_name_indication,
+                                            tsi_handshaker **handshaker) {
+  SSL *ssl = SSL_new(ctx);
+  BIO *into_ssl = NULL;
+  BIO *from_ssl = NULL;
+  tsi_ssl_handshaker *impl = NULL;
+  *handshaker = NULL;
+  if (ctx == NULL) {
+    gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
+    return TSI_INTERNAL_ERROR;
+  }
+  if (ssl == NULL) {
+    return TSI_OUT_OF_RESOURCES;
+  }
+  SSL_set_info_callback(ssl, ssl_info_callback);
+
+  into_ssl = BIO_new(BIO_s_mem());
+  from_ssl = BIO_new(BIO_s_mem());
+  if (into_ssl == NULL || from_ssl == NULL) {
+    gpr_log(GPR_ERROR, "BIO_new failed.");
+    SSL_free(ssl);
+    if (into_ssl != NULL) BIO_free(into_ssl);
+    if (from_ssl != NULL) BIO_free(into_ssl);
+    return TSI_OUT_OF_RESOURCES;
+  }
+  SSL_set_bio(ssl, into_ssl, from_ssl);
+  if (is_client) {
+    int ssl_result;
+    SSL_set_connect_state(ssl);
+    if (server_name_indication != NULL) {
+      if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) {
+        gpr_log(GPR_ERROR, "Invalid server name indication %s.",
+                server_name_indication);
+        SSL_free(ssl);
+        return TSI_INTERNAL_ERROR;
+      }
+    }
+    ssl_result = SSL_do_handshake(ssl);
+    ssl_result = SSL_get_error(ssl, ssl_result);
+    if (ssl_result != SSL_ERROR_WANT_READ) {
+      gpr_log(GPR_ERROR,
+              "Unexpected error received from first SSL_do_handshake call: %s",
+              ssl_error_string(ssl_result));
+      SSL_free(ssl);
+      return TSI_INTERNAL_ERROR;
+    }
+  } else {
+    SSL_set_accept_state(ssl);
+  }
+
+  impl = gpr_malloc(sizeof(*impl));
+  memset(impl, 0, sizeof(*impl));
+  impl->ssl = ssl;
+  impl->into_ssl = into_ssl;
+  impl->from_ssl = from_ssl;
+  impl->result = TSI_HANDSHAKE_IN_PROGRESS;
+  impl->base.vtable = &handshaker_vtable;
+  *handshaker = &impl->base;
+  return TSI_OK;
+}
+
+static int select_protocol_list(const unsigned char **out,
+                                unsigned char *outlen,
+                                const unsigned char *client_list,
+                                size_t client_list_len,
+                                const unsigned char *server_list,
+                                size_t server_list_len) {
+  const unsigned char *client_current = client_list;
+  while ((unsigned int)(client_current - client_list) < client_list_len) {
+    unsigned char client_current_len = *(client_current++);
+    const unsigned char *server_current = server_list;
+    while ((server_current >= server_list) &&
+           (uintptr_t)(server_current - server_list) < server_list_len) {
+      unsigned char server_current_len = *(server_current++);
+      if ((client_current_len == server_current_len) &&
+          !memcmp(client_current, server_current, server_current_len)) {
+        *out = server_current;
+        *outlen = server_current_len;
+        return SSL_TLSEXT_ERR_OK;
+      }
+      server_current += server_current_len;
+    }
+    client_current += client_current_len;
+  }
+  return SSL_TLSEXT_ERR_NOACK;
+}
+
+/* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
+
+static tsi_result ssl_client_handshaker_factory_create_handshaker(
+    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
+    tsi_handshaker **handshaker) {
+  tsi_ssl_client_handshaker_factory *impl =
+      (tsi_ssl_client_handshaker_factory *)self;
+  return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
+                                   handshaker);
+}
+
+static void ssl_client_handshaker_factory_destroy(
+    tsi_ssl_handshaker_factory *self) {
+  tsi_ssl_client_handshaker_factory *impl =
+      (tsi_ssl_client_handshaker_factory *)self;
+  if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
+  if (impl->alpn_protocol_list != NULL) gpr_free(impl->alpn_protocol_list);
+  gpr_free(impl);
+}
+
+static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out,
+                                                  unsigned char *outlen,
+                                                  const unsigned char *in,
+                                                  unsigned int inlen,
+                                                  void *arg) {
+  tsi_ssl_client_handshaker_factory *factory =
+      (tsi_ssl_client_handshaker_factory *)arg;
+  return select_protocol_list((const unsigned char **)out, outlen,
+                              factory->alpn_protocol_list,
+                              factory->alpn_protocol_list_length, in, inlen);
+}
+
+/* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
+
+static tsi_result ssl_server_handshaker_factory_create_handshaker(
+    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
+    tsi_handshaker **handshaker) {
+  tsi_ssl_server_handshaker_factory *impl =
+      (tsi_ssl_server_handshaker_factory *)self;
+  if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  /* Create the handshaker with the first context. We will switch if needed
+     because of SNI in ssl_server_handshaker_factory_servername_callback.  */
+  return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
+}
+
+static void ssl_server_handshaker_factory_destroy(
+    tsi_ssl_handshaker_factory *self) {
+  tsi_ssl_server_handshaker_factory *impl =
+      (tsi_ssl_server_handshaker_factory *)self;
+  size_t i;
+  for (i = 0; i < impl->ssl_context_count; i++) {
+    if (impl->ssl_contexts[i] != NULL) {
+      SSL_CTX_free(impl->ssl_contexts[i]);
+      tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
+    }
+  }
+  if (impl->ssl_contexts != NULL) gpr_free(impl->ssl_contexts);
+  if (impl->ssl_context_x509_subject_names != NULL) {
+    gpr_free(impl->ssl_context_x509_subject_names);
+  }
+  if (impl->alpn_protocol_list != NULL) gpr_free(impl->alpn_protocol_list);
+  gpr_free(impl);
+}
+
+static int does_entry_match_name(const char *entry, size_t entry_length,
+                                 const char *name) {
+  const char *dot;
+  const char *name_subdomain = NULL;
+  size_t name_length = strlen(name);
+  size_t name_subdomain_length;
+  if (entry_length == 0) return 0;
+
+  /* Take care of '.' terminations. */
+  if (name[name_length - 1] == '.') {
+    name_length--;
+  }
+  if (entry[entry_length - 1] == '.') {
+    entry_length--;
+    if (entry_length == 0) return 0;
+  }
+
+  if ((name_length == entry_length) &&
+      strncmp(name, entry, entry_length) == 0) {
+    return 1; /* Perfect match. */
+  }
+  if (entry[0] != '*') return 0;
+
+  /* Wildchar subdomain matching. */
+  if (entry_length < 3 || entry[1] != '.') { /* At least *.x */
+    gpr_log(GPR_ERROR, "Invalid wildchar entry.");
+    return 0;
+  }
+  name_subdomain = strchr(name, '.');
+  if (name_subdomain == NULL) return 0;
+  name_subdomain_length = strlen(name_subdomain);
+  if (name_subdomain_length < 2) return 0;
+  name_subdomain++; /* Starts after the dot. */
+  name_subdomain_length--;
+  entry += 2; /* Remove *. */
+  entry_length -= 2;
+  dot = strchr(name_subdomain, '.');
+  if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
+    gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
+    return 0;
+  }
+  if (name_subdomain[name_subdomain_length - 1] == '.') {
+    name_subdomain_length--;
+  }
+  return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
+          strncmp(entry, name_subdomain, entry_length) == 0);
+}
+
+static int ssl_server_handshaker_factory_servername_callback(SSL *ssl, int *ap,
+                                                             void *arg) {
+  tsi_ssl_server_handshaker_factory *impl =
+      (tsi_ssl_server_handshaker_factory *)arg;
+  size_t i = 0;
+  const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+  if (servername == NULL || strlen(servername) == 0) {
+    return SSL_TLSEXT_ERR_NOACK;
+  }
+
+  for (i = 0; i < impl->ssl_context_count; i++) {
+    if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i],
+                                  servername)) {
+      SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]);
+      return SSL_TLSEXT_ERR_OK;
+    }
+  }
+  gpr_log(GPR_ERROR, "No match found for server name: %s.", servername);
+  return SSL_TLSEXT_ERR_ALERT_WARNING;
+}
+
+#if TSI_OPENSSL_ALPN_SUPPORT
+static int server_handshaker_factory_alpn_callback(
+    SSL *ssl, const unsigned char **out, unsigned char *outlen,
+    const unsigned char *in, unsigned int inlen, void *arg) {
+  tsi_ssl_server_handshaker_factory *factory =
+      (tsi_ssl_server_handshaker_factory *)arg;
+  return select_protocol_list(out, outlen, in, inlen,
+                              factory->alpn_protocol_list,
+                              factory->alpn_protocol_list_length);
+}
+#endif /* TSI_OPENSSL_ALPN_SUPPORT */
+
+static int server_handshaker_factory_npn_advertised_callback(
+    SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) {
+  tsi_ssl_server_handshaker_factory *factory =
+      (tsi_ssl_server_handshaker_factory *)arg;
+  *out = factory->alpn_protocol_list;
+  GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX);
+  *outlen = (unsigned int)factory->alpn_protocol_list_length;
+  return SSL_TLSEXT_ERR_OK;
+}
+
+/* --- tsi_ssl_handshaker_factory constructors. --- */
+
+tsi_result tsi_create_ssl_client_handshaker_factory(
+    const unsigned char *pem_private_key, size_t pem_private_key_size,
+    const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
+    const unsigned char *pem_root_certs, size_t pem_root_certs_size,
+    const char *cipher_list, const unsigned char **alpn_protocols,
+    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+    tsi_ssl_handshaker_factory **factory) {
+  SSL_CTX *ssl_context = NULL;
+  tsi_ssl_client_handshaker_factory *impl = NULL;
+  tsi_result result = TSI_OK;
+
+  gpr_once_init(&init_openssl_once, init_openssl);
+
+  if (factory == NULL) return TSI_INVALID_ARGUMENT;
+  *factory = NULL;
+  if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT;
+
+  ssl_context = SSL_CTX_new(TLSv1_2_method());
+  if (ssl_context == NULL) {
+    gpr_log(GPR_ERROR, "Could not create ssl context.");
+    return TSI_INVALID_ARGUMENT;
+  }
+
+  impl = gpr_malloc(sizeof(*impl));
+  memset(impl, 0, sizeof(*impl));
+  impl->ssl_context = ssl_context;
+
+  do {
+    result =
+        populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size,
+                             pem_cert_chain, pem_cert_chain_size, cipher_list);
+    if (result != TSI_OK) break;
+    result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
+                                             pem_root_certs_size, NULL);
+    if (result != TSI_OK) {
+      gpr_log(GPR_ERROR, "Cannot load server root certificates.");
+      break;
+    }
+
+    if (num_alpn_protocols != 0) {
+      result = build_alpn_protocol_name_list(
+          alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
+          &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
+      if (result != TSI_OK) {
+        gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
+                tsi_result_to_string(result));
+        break;
+      }
+#if TSI_OPENSSL_ALPN_SUPPORT
+      GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX);
+      if (SSL_CTX_set_alpn_protos(
+              ssl_context, impl->alpn_protocol_list,
+              (unsigned int)impl->alpn_protocol_list_length)) {
+        gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
+        result = TSI_INVALID_ARGUMENT;
+        break;
+      }
+#endif /* TSI_OPENSSL_ALPN_SUPPORT */
+      SSL_CTX_set_next_proto_select_cb(
+          ssl_context, client_handshaker_factory_npn_callback, impl);
+    }
+  } while (0);
+  if (result != TSI_OK) {
+    ssl_client_handshaker_factory_destroy(&impl->base);
+    return result;
+  }
+  SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
+  /* TODO(jboeuf): Add revocation verification. */
+
+  impl->base.create_handshaker =
+      ssl_client_handshaker_factory_create_handshaker;
+  impl->base.destroy = ssl_client_handshaker_factory_destroy;
+  *factory = &impl->base;
+  return TSI_OK;
+}
+
+tsi_result tsi_create_ssl_server_handshaker_factory(
+    const unsigned char **pem_private_keys,
+    const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
+    const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
+    const unsigned char *pem_client_root_certs,
+    size_t pem_client_root_certs_size, int force_client_auth,
+    const char *cipher_list, const unsigned char **alpn_protocols,
+    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+    tsi_ssl_handshaker_factory **factory) {
+  return tsi_create_ssl_server_handshaker_factory_ex(
+      pem_private_keys, pem_private_keys_sizes, pem_cert_chains,
+      pem_cert_chains_sizes, key_cert_pair_count, pem_client_root_certs,
+      pem_client_root_certs_size,
+      force_client_auth ? TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+                        : TSI_DONT_REQUEST_CLIENT_CERTIFICATE,
+      cipher_list, alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
+      factory);
+}
+
+tsi_result tsi_create_ssl_server_handshaker_factory_ex(
+    const unsigned char **pem_private_keys,
+    const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
+    const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
+    const unsigned char *pem_client_root_certs,
+    size_t pem_client_root_certs_size,
+    tsi_client_certificate_request_type client_certificate_request,
+    const char *cipher_list, const unsigned char **alpn_protocols,
+    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+    tsi_ssl_handshaker_factory **factory) {
+  tsi_ssl_server_handshaker_factory *impl = NULL;
+  tsi_result result = TSI_OK;
+  size_t i = 0;
+
+  gpr_once_init(&init_openssl_once, init_openssl);
+
+  if (factory == NULL) return TSI_INVALID_ARGUMENT;
+  *factory = NULL;
+  if (key_cert_pair_count == 0 || pem_private_keys == NULL ||
+      pem_cert_chains == NULL) {
+    return TSI_INVALID_ARGUMENT;
+  }
+
+  impl = gpr_malloc(sizeof(*impl));
+  memset(impl, 0, sizeof(*impl));
+  impl->base.create_handshaker =
+      ssl_server_handshaker_factory_create_handshaker;
+  impl->base.destroy = ssl_server_handshaker_factory_destroy;
+  impl->ssl_contexts = gpr_malloc(key_cert_pair_count * sizeof(SSL_CTX *));
+  memset(impl->ssl_contexts, 0, key_cert_pair_count * sizeof(SSL_CTX *));
+  impl->ssl_context_x509_subject_names =
+      gpr_malloc(key_cert_pair_count * sizeof(tsi_peer));
+  memset(impl->ssl_context_x509_subject_names, 0,
+         key_cert_pair_count * sizeof(tsi_peer));
+  if (impl->ssl_contexts == NULL ||
+      impl->ssl_context_x509_subject_names == NULL) {
+    tsi_ssl_handshaker_factory_destroy(&impl->base);
+    return TSI_OUT_OF_RESOURCES;
+  }
+  impl->ssl_context_count = key_cert_pair_count;
+
+  if (num_alpn_protocols > 0) {
+    result = build_alpn_protocol_name_list(
+        alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
+        &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
+    if (result != TSI_OK) {
+      tsi_ssl_handshaker_factory_destroy(&impl->base);
+      return result;
+    }
+  }
+
+  for (i = 0; i < key_cert_pair_count; i++) {
+    do {
+      impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
+      if (impl->ssl_contexts[i] == NULL) {
+        gpr_log(GPR_ERROR, "Could not create ssl context.");
+        result = TSI_OUT_OF_RESOURCES;
+        break;
+      }
+      result = populate_ssl_context(
+          impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i],
+          pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
+      if (result != TSI_OK) break;
+
+      if (pem_client_root_certs != NULL) {
+        STACK_OF(X509_NAME) *root_names = NULL;
+        result = ssl_ctx_load_verification_certs(
+            impl->ssl_contexts[i], pem_client_root_certs,
+            pem_client_root_certs_size, &root_names);
+        if (result != TSI_OK) {
+          gpr_log(GPR_ERROR, "Invalid verification certs.");
+          break;
+        }
+        SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
+        switch (client_certificate_request) {
+          case TSI_DONT_REQUEST_CLIENT_CERTIFICATE:
+            SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_NONE, NULL);
+            break;
+          case TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+            SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER,
+                               NullVerifyCallback);
+            break;
+          case TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY:
+            SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, NULL);
+            break;
+          case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+            SSL_CTX_set_verify(
+                impl->ssl_contexts[i],
+                SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+                NullVerifyCallback);
+            break;
+          case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY:
+            SSL_CTX_set_verify(
+                impl->ssl_contexts[i],
+                SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+            break;
+        }
+        /* TODO(jboeuf): Add revocation verification. */
+      }
+
+      result = extract_x509_subject_names_from_pem_cert(
+          pem_cert_chains[i], pem_cert_chains_sizes[i],
+          &impl->ssl_context_x509_subject_names[i]);
+      if (result != TSI_OK) break;
+
+      SSL_CTX_set_tlsext_servername_callback(
+          impl->ssl_contexts[i],
+          ssl_server_handshaker_factory_servername_callback);
+      SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl);
+#if TSI_OPENSSL_ALPN_SUPPORT
+      SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i],
+                                 server_handshaker_factory_alpn_callback, impl);
+#endif /* TSI_OPENSSL_ALPN_SUPPORT */
+      SSL_CTX_set_next_protos_advertised_cb(
+          impl->ssl_contexts[i],
+          server_handshaker_factory_npn_advertised_callback, impl);
+    } while (0);
+
+    if (result != TSI_OK) {
+      tsi_ssl_handshaker_factory_destroy(&impl->base);
+      return result;
+    }
+  }
+  *factory = &impl->base;
+  return TSI_OK;
+}
+
+/* --- tsi_ssl utils. --- */
+
+int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
+  size_t i = 0;
+  size_t san_count = 0;
+  const tsi_peer_property *cn_property = NULL;
+  int like_ip = looks_like_ip_address(name);
+
+  /* Check the SAN first. */
+  for (i = 0; i < peer->property_count; i++) {
+    const tsi_peer_property *property = &peer->properties[i];
+    if (property->name == NULL) continue;
+    if (strcmp(property->name,
+               TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
+      san_count++;
+
+      if (!like_ip && does_entry_match_name(property->value.data,
+                                            property->value.length, name)) {
+        return 1;
+      } else if (like_ip &&
+                 strncmp(name, property->value.data, property->value.length) ==
+                     0 &&
+                 strlen(name) == property->value.length) {
+        /* IP Addresses are exact matches only. */
+        return 1;
+      }
+    } else if (strcmp(property->name,
+                      TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
+      cn_property = property;
+    }
+  }
+
+  /* If there's no SAN, try the CN, but only if its not like an IP Address */
+  if (san_count == 0 && cn_property != NULL && !like_ip) {
+    if (does_entry_match_name(cn_property->value.data,
+                              cn_property->value.length, name)) {
+      return 1;
+    }
+  }
+
+  return 0; /* Not found. */
+}
diff --git a/src/core/lib/tsi/ssl_transport_security.h b/src/core/lib/tsi/ssl_transport_security.h
new file mode 100644
index 0000000..7407246
--- /dev/null
+++ b/src/core/lib/tsi/ssl_transport_security.h
@@ -0,0 +1,191 @@
+/*
+ *
+ * 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_TSI_SSL_TRANSPORT_SECURITY_H
+#define GRPC_CORE_LIB_TSI_SSL_TRANSPORT_SECURITY_H
+
+#include "src/core/lib/tsi/transport_security_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for X509 certs. */
+#define TSI_X509_CERTIFICATE_TYPE "X509"
+
+/* This property is of type TSI_PEER_PROPERTY_STRING.  */
+#define TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY "x509_subject_common_name"
+#define TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY \
+  "x509_subject_alternative_name"
+
+#define TSI_X509_PEM_CERT_PROPERTY "x509_pem_cert"
+
+#define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol"
+
+/* --- tsi_ssl_handshaker_factory object ---
+
+   This object creates tsi_handshaker objects implemented in terms of the
+   TLS 1.2 specificiation.  */
+
+typedef struct tsi_ssl_handshaker_factory tsi_ssl_handshaker_factory;
+
+/* Creates a client handshaker factory.
+   - pem_private_key is the buffer containing the PEM encoding of the client's
+     private key. This parameter can be NULL if the client does not have a
+     private key.
+   - pem_private_key_size is the size of the associated buffer.
+   - pem_cert_chain is the buffer containing the PEM encoding of the client's
+     certificate chain. This parameter can be NULL if the client does not have
+     a certificate chain.
+   - pem_cert_chain_size is the size of the associated buffer.
+   - pem_roots_cert is the buffer containing the PEM encoding of the server
+     root certificates. This parameter cannot be NULL.
+   - pem_roots_cert_size is the size of the associated buffer.
+   - cipher_suites contains an optional list of the ciphers that the client
+     supports. The format of this string is described in:
+     https://www.openssl.org/docs/apps/ciphers.html.
+     This parameter can be set to NULL to use the default set of ciphers.
+     TODO(jboeuf): Revisit the format of this parameter.
+   - alpn_protocols is an array containing the protocol names that the
+     handshakers created with this factory support. This parameter can be NULL.
+   - alpn_protocols_lengths is an array containing the lengths of the alpn
+     protocols specified in alpn_protocols. This parameter can be NULL.
+   - num_alpn_protocols is the number of alpn protocols and associated lengths
+     specified. If this parameter is 0, the other alpn parameters must be NULL.
+   - factory is the address of the factory pointer to be created.
+
+   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
+     where a parameter is invalid.  */
+tsi_result tsi_create_ssl_client_handshaker_factory(
+    const unsigned char *pem_private_key, size_t pem_private_key_size,
+    const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
+    const unsigned char *pem_root_certs, size_t pem_root_certs_size,
+    const char *cipher_suites, const unsigned char **alpn_protocols,
+    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+    tsi_ssl_handshaker_factory **factory);
+
+/* Creates a server handshaker factory.
+   - version indicates which version of the specification to use.
+   - pem_private_keys is an array containing the PEM encoding of the server's
+     private keys.  This parameter cannot be NULL. The size of the array is
+     given by the key_cert_pair_count parameter.
+   - pem_private_keys_sizes is the array containing the sizes of the associated
+     buffers.
+   - pem_cert_chains is an array containing the PEM encoding of the server's
+     cert chains.  This parameter cannot be NULL. The size of the array is
+     given by the key_cert_pair_count parameter.
+   - pem_cert_chains_sizes is the array containing the sizes of the associated
+     buffers.
+   - key_cert_pair_count indicates the number of items in the private_key_files
+     and cert_chain_files parameters.
+   - pem_client_roots is the buffer containing the PEM encoding of the client
+     root certificates. This parameter may be NULL in which case the server will
+     not authenticate the client. If not NULL, the force_client_auth parameter
+     specifies if the server will accept only authenticated clients or both
+     authenticated and non-authenticated clients.
+   - pem_client_root_certs_size is the size of the associated buffer.
+   - force_client_auth, if set to non-zero will force the client to authenticate
+     with an SSL cert. Note that this option is ignored if pem_client_root_certs
+     is NULL or pem_client_roots_certs_size is 0
+   - cipher_suites contains an optional list of the ciphers that the server
+     supports. The format of this string is described in:
+     https://www.openssl.org/docs/apps/ciphers.html.
+     This parameter can be set to NULL to use the default set of ciphers.
+     TODO(jboeuf): Revisit the format of this parameter.
+   - alpn_protocols is an array containing the protocol names that the
+     handshakers created with this factory support. This parameter can be NULL.
+   - alpn_protocols_lengths is an array containing the lengths of the alpn
+     protocols specified in alpn_protocols. This parameter can be NULL.
+   - num_alpn_protocols is the number of alpn protocols and associated lengths
+     specified. If this parameter is 0, the other alpn parameters must be NULL.
+   - factory is the address of the factory pointer to be created.
+
+   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
+     where a parameter is invalid.  */
+tsi_result tsi_create_ssl_server_handshaker_factory(
+    const unsigned char **pem_private_keys,
+    const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
+    const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
+    const unsigned char *pem_client_root_certs,
+    size_t pem_client_root_certs_size, int force_client_auth,
+    const char *cipher_suites, const unsigned char **alpn_protocols,
+    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+    tsi_ssl_handshaker_factory **factory);
+
+/* Same as tsi_create_ssl_server_handshaker_factory method except uses
+   tsi_client_certificate_request_type to support more ways to handle client
+   certificate authentication.
+   - client_certificate_request, if set to non-zero will force the client to
+     authenticate with an SSL cert. Note that this option is ignored if
+     pem_client_root_certs is NULL or pem_client_roots_certs_size is 0 */
+tsi_result tsi_create_ssl_server_handshaker_factory_ex(
+    const unsigned char **pem_private_keys,
+    const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
+    const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
+    const unsigned char *pem_client_root_certs,
+    size_t pem_client_root_certs_size,
+    tsi_client_certificate_request_type client_certificate_request,
+    const char *cipher_suites, const unsigned char **alpn_protocols,
+    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+    tsi_ssl_handshaker_factory **factory);
+
+/* Creates a handshaker.
+  - self is the factory from which the handshaker will be created.
+  - server_name_indication indicates the name of the server the client is
+    trying to connect to which will be relayed to the server using the SNI
+    extension.
+    This parameter must be NULL for a server handshaker factory.
+  - handhshaker is the address of the handshaker pointer to be created.
+
+  - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
+    where a parameter is invalid.  */
+tsi_result tsi_ssl_handshaker_factory_create_handshaker(
+    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
+    tsi_handshaker **handshaker);
+
+/* Destroys the handshaker factory. WARNING: it is unsafe to destroy a factory
+   while handshakers created with this factory are still in use.  */
+void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self);
+
+/* Util that checks that an ssl peer matches a specific name.
+   Still TODO(jboeuf):
+   - handle mixed case.
+   - handle %encoded chars.
+   - handle public suffix wildchar more strictly (e.g. *.co.uk) */
+int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_TSI_SSL_TRANSPORT_SECURITY_H */
diff --git a/src/core/lib/tsi/ssl_types.h b/src/core/lib/tsi/ssl_types.h
new file mode 100644
index 0000000..0a988ef
--- /dev/null
+++ b/src/core/lib/tsi/ssl_types.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_TSI_SSL_TYPES_H
+#define GRPC_CORE_LIB_TSI_SSL_TYPES_H
+
+/* A collection of macros to cast between various integer types that are
+ * used differently between BoringSSL and OpenSSL:
+ * TSI_INT_AS_SIZE(x):  convert 'int x' to a length parameter for an OpenSSL
+ *                      function
+ * TSI_SIZE_AS_SIZE(x): convert 'size_t x' to a length parameter for an OpenSSL
+ *                      function
+ */
+
+#include <openssl/ssl.h>
+
+#ifdef OPENSSL_IS_BORINGSSL
+#define TSI_INT_AS_SIZE(x) ((size_t)(x))
+#define TSI_SIZE_AS_SIZE(x) (x)
+#else
+#define TSI_INT_AS_SIZE(x) (x)
+#define TSI_SIZE_AS_SIZE(x) ((int)(x))
+#endif
+
+#endif /* GRPC_CORE_LIB_TSI_SSL_TYPES_H */
diff --git a/src/core/tsi/test_creds/README b/src/core/lib/tsi/test_creds/README
similarity index 100%
rename from src/core/tsi/test_creds/README
rename to src/core/lib/tsi/test_creds/README
diff --git a/src/core/tsi/test_creds/badclient.key b/src/core/lib/tsi/test_creds/badclient.key
similarity index 100%
rename from src/core/tsi/test_creds/badclient.key
rename to src/core/lib/tsi/test_creds/badclient.key
diff --git a/src/core/tsi/test_creds/badclient.pem b/src/core/lib/tsi/test_creds/badclient.pem
similarity index 100%
rename from src/core/tsi/test_creds/badclient.pem
rename to src/core/lib/tsi/test_creds/badclient.pem
diff --git a/src/core/tsi/test_creds/badserver.key b/src/core/lib/tsi/test_creds/badserver.key
similarity index 100%
rename from src/core/tsi/test_creds/badserver.key
rename to src/core/lib/tsi/test_creds/badserver.key
diff --git a/src/core/tsi/test_creds/badserver.pem b/src/core/lib/tsi/test_creds/badserver.pem
similarity index 100%
rename from src/core/tsi/test_creds/badserver.pem
rename to src/core/lib/tsi/test_creds/badserver.pem
diff --git a/src/core/tsi/test_creds/ca-openssl.cnf b/src/core/lib/tsi/test_creds/ca-openssl.cnf
similarity index 100%
rename from src/core/tsi/test_creds/ca-openssl.cnf
rename to src/core/lib/tsi/test_creds/ca-openssl.cnf
diff --git a/src/core/tsi/test_creds/ca.key b/src/core/lib/tsi/test_creds/ca.key
similarity index 100%
rename from src/core/tsi/test_creds/ca.key
rename to src/core/lib/tsi/test_creds/ca.key
diff --git a/src/core/tsi/test_creds/ca.pem b/src/core/lib/tsi/test_creds/ca.pem
similarity index 100%
rename from src/core/tsi/test_creds/ca.pem
rename to src/core/lib/tsi/test_creds/ca.pem
diff --git a/src/core/tsi/test_creds/client.key b/src/core/lib/tsi/test_creds/client.key
similarity index 100%
rename from src/core/tsi/test_creds/client.key
rename to src/core/lib/tsi/test_creds/client.key
diff --git a/src/core/tsi/test_creds/client.pem b/src/core/lib/tsi/test_creds/client.pem
similarity index 100%
rename from src/core/tsi/test_creds/client.pem
rename to src/core/lib/tsi/test_creds/client.pem
diff --git a/src/core/tsi/test_creds/server0.key b/src/core/lib/tsi/test_creds/server0.key
similarity index 100%
rename from src/core/tsi/test_creds/server0.key
rename to src/core/lib/tsi/test_creds/server0.key
diff --git a/src/core/tsi/test_creds/server0.pem b/src/core/lib/tsi/test_creds/server0.pem
similarity index 100%
rename from src/core/tsi/test_creds/server0.pem
rename to src/core/lib/tsi/test_creds/server0.pem
diff --git a/src/core/tsi/test_creds/server1-openssl.cnf b/src/core/lib/tsi/test_creds/server1-openssl.cnf
similarity index 100%
rename from src/core/tsi/test_creds/server1-openssl.cnf
rename to src/core/lib/tsi/test_creds/server1-openssl.cnf
diff --git a/src/core/tsi/test_creds/server1.key b/src/core/lib/tsi/test_creds/server1.key
similarity index 100%
rename from src/core/tsi/test_creds/server1.key
rename to src/core/lib/tsi/test_creds/server1.key
diff --git a/src/core/tsi/test_creds/server1.pem b/src/core/lib/tsi/test_creds/server1.pem
similarity index 100%
rename from src/core/tsi/test_creds/server1.pem
rename to src/core/lib/tsi/test_creds/server1.pem
diff --git a/src/core/lib/tsi/transport_security.c b/src/core/lib/tsi/transport_security.c
new file mode 100644
index 0000000..830cf09
--- /dev/null
+++ b/src/core/lib/tsi/transport_security.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 "src/core/lib/tsi/transport_security.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+/* --- Tracing. --- */
+
+int tsi_tracing_enabled = 0;
+
+/* --- tsi_result common implementation. --- */
+
+const char *tsi_result_to_string(tsi_result result) {
+  switch (result) {
+    case TSI_OK:
+      return "TSI_OK";
+    case TSI_UNKNOWN_ERROR:
+      return "TSI_UNKNOWN_ERROR";
+    case TSI_INVALID_ARGUMENT:
+      return "TSI_INVALID_ARGUMENT";
+    case TSI_PERMISSION_DENIED:
+      return "TSI_PERMISSION_DENIED";
+    case TSI_INCOMPLETE_DATA:
+      return "TSI_INCOMPLETE_DATA";
+    case TSI_FAILED_PRECONDITION:
+      return "TSI_FAILED_PRECONDITION";
+    case TSI_UNIMPLEMENTED:
+      return "TSI_UNIMPLEMENTED";
+    case TSI_INTERNAL_ERROR:
+      return "TSI_INTERNAL_ERROR";
+    case TSI_DATA_CORRUPTED:
+      return "TSI_DATA_CORRUPTED";
+    case TSI_NOT_FOUND:
+      return "TSI_NOT_FOUND";
+    case TSI_PROTOCOL_FAILURE:
+      return "TSI_PROTOCOL_FAILURE";
+    case TSI_HANDSHAKE_IN_PROGRESS:
+      return "TSI_HANDSHAKE_IN_PROGRESS";
+    case TSI_OUT_OF_RESOURCES:
+      return "TSI_OUT_OF_RESOURCES";
+    default:
+      return "UNKNOWN";
+  }
+}
+
+/* --- tsi_frame_protector common implementation. ---
+
+   Calls specific implementation after state/input validation. */
+
+tsi_result tsi_frame_protector_protect(tsi_frame_protector *self,
+                                       const unsigned char *unprotected_bytes,
+                                       size_t *unprotected_bytes_size,
+                                       unsigned char *protected_output_frames,
+                                       size_t *protected_output_frames_size) {
+  if (self == NULL || unprotected_bytes == NULL ||
+      unprotected_bytes_size == NULL || protected_output_frames == NULL ||
+      protected_output_frames_size == NULL) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  return self->vtable->protect(self, unprotected_bytes, unprotected_bytes_size,
+                               protected_output_frames,
+                               protected_output_frames_size);
+}
+
+tsi_result tsi_frame_protector_protect_flush(
+    tsi_frame_protector *self, unsigned char *protected_output_frames,
+    size_t *protected_output_frames_size, size_t *still_pending_size) {
+  if (self == NULL || protected_output_frames == NULL ||
+      protected_output_frames == NULL || still_pending_size == NULL) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  return self->vtable->protect_flush(self, protected_output_frames,
+                                     protected_output_frames_size,
+                                     still_pending_size);
+}
+
+tsi_result tsi_frame_protector_unprotect(
+    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
+    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
+    size_t *unprotected_bytes_size) {
+  if (self == NULL || protected_frames_bytes == NULL ||
+      protected_frames_bytes_size == NULL || unprotected_bytes == NULL ||
+      unprotected_bytes_size == NULL) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  return self->vtable->unprotect(self, protected_frames_bytes,
+                                 protected_frames_bytes_size, unprotected_bytes,
+                                 unprotected_bytes_size);
+}
+
+void tsi_frame_protector_destroy(tsi_frame_protector *self) {
+  if (self == NULL) return;
+  self->vtable->destroy(self);
+}
+
+/* --- tsi_handshaker common implementation. ---
+
+   Calls specific implementation after state/input validation. */
+
+tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
+                                                    unsigned char *bytes,
+                                                    size_t *bytes_size) {
+  if (self == NULL || bytes == NULL || bytes_size == NULL) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size);
+}
+
+tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self,
+                                                  const unsigned char *bytes,
+                                                  size_t *bytes_size) {
+  if (self == NULL || bytes == NULL || bytes_size == NULL) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  return self->vtable->process_bytes_from_peer(self, bytes, bytes_size);
+}
+
+tsi_result tsi_handshaker_get_result(tsi_handshaker *self) {
+  if (self == NULL) return TSI_INVALID_ARGUMENT;
+  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  return self->vtable->get_result(self);
+}
+
+tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) {
+  if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT;
+  memset(peer, 0, sizeof(tsi_peer));
+  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  if (tsi_handshaker_get_result(self) != TSI_OK) {
+    return TSI_FAILED_PRECONDITION;
+  }
+  return self->vtable->extract_peer(self, peer);
+}
+
+tsi_result tsi_handshaker_create_frame_protector(
+    tsi_handshaker *self, size_t *max_protected_frame_size,
+    tsi_frame_protector **protector) {
+  tsi_result result;
+  if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT;
+  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  if (tsi_handshaker_get_result(self) != TSI_OK) {
+    return TSI_FAILED_PRECONDITION;
+  }
+  result = self->vtable->create_frame_protector(self, max_protected_frame_size,
+                                                protector);
+  if (result == TSI_OK) {
+    self->frame_protector_created = 1;
+  }
+  return result;
+}
+
+void tsi_handshaker_destroy(tsi_handshaker *self) {
+  if (self == NULL) return;
+  self->vtable->destroy(self);
+}
+
+/* --- tsi_peer implementation. --- */
+
+tsi_peer_property tsi_init_peer_property(void) {
+  tsi_peer_property property;
+  memset(&property, 0, sizeof(tsi_peer_property));
+  return property;
+}
+
+static void tsi_peer_destroy_list_property(tsi_peer_property *children,
+                                           size_t child_count) {
+  size_t i;
+  for (i = 0; i < child_count; i++) {
+    tsi_peer_property_destruct(&children[i]);
+  }
+  gpr_free(children);
+}
+
+void tsi_peer_property_destruct(tsi_peer_property *property) {
+  if (property->name != NULL) {
+    gpr_free(property->name);
+  }
+  if (property->value.data != NULL) {
+    gpr_free(property->value.data);
+  }
+  *property = tsi_init_peer_property(); /* Reset everything to 0. */
+}
+
+void tsi_peer_destruct(tsi_peer *self) {
+  if (self == NULL) return;
+  if (self->properties != NULL) {
+    tsi_peer_destroy_list_property(self->properties, self->property_count);
+    self->properties = NULL;
+  }
+  self->property_count = 0;
+}
+
+tsi_result tsi_construct_allocated_string_peer_property(
+    const char *name, size_t value_length, tsi_peer_property *property) {
+  *property = tsi_init_peer_property();
+  if (name != NULL) property->name = gpr_strdup(name);
+  if (value_length > 0) {
+    property->value.data = gpr_malloc(value_length);
+    memset(property->value.data, 0, value_length);
+    property->value.length = value_length;
+  }
+  return TSI_OK;
+}
+
+tsi_result tsi_construct_string_peer_property_from_cstring(
+    const char *name, const char *value, tsi_peer_property *property) {
+  return tsi_construct_string_peer_property(name, value, strlen(value),
+                                            property);
+}
+
+tsi_result tsi_construct_string_peer_property(const char *name,
+                                              const char *value,
+                                              size_t value_length,
+                                              tsi_peer_property *property) {
+  tsi_result result = tsi_construct_allocated_string_peer_property(
+      name, value_length, property);
+  if (result != TSI_OK) return result;
+  if (value_length > 0) {
+    memcpy(property->value.data, value, value_length);
+  }
+  return TSI_OK;
+}
+
+tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer) {
+  memset(peer, 0, sizeof(tsi_peer));
+  if (property_count > 0) {
+    peer->properties = gpr_malloc(property_count * sizeof(tsi_peer_property));
+    memset(peer->properties, 0, property_count * sizeof(tsi_peer_property));
+    peer->property_count = property_count;
+  }
+  return TSI_OK;
+}
diff --git a/src/core/lib/tsi/transport_security.h b/src/core/lib/tsi/transport_security.h
new file mode 100644
index 0000000..aaf110e
--- /dev/null
+++ b/src/core/lib/tsi/transport_security.h
@@ -0,0 +1,111 @@
+/*
+ *
+ * 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_TSI_TRANSPORT_SECURITY_H
+#define GRPC_CORE_LIB_TSI_TRANSPORT_SECURITY_H
+
+#include "src/core/lib/tsi/transport_security_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int tsi_tracing_enabled;
+
+/* Base for tsi_frame_protector implementations.
+   See transport_security_interface.h for documentation. */
+typedef struct {
+  tsi_result (*protect)(tsi_frame_protector *self,
+                        const unsigned char *unprotected_bytes,
+                        size_t *unprotected_bytes_size,
+                        unsigned char *protected_output_frames,
+                        size_t *protected_output_frames_size);
+  tsi_result (*protect_flush)(tsi_frame_protector *self,
+                              unsigned char *protected_output_frames,
+                              size_t *protected_output_frames_size,
+                              size_t *still_pending_size);
+  tsi_result (*unprotect)(tsi_frame_protector *self,
+                          const unsigned char *protected_frames_bytes,
+                          size_t *protected_frames_bytes_size,
+                          unsigned char *unprotected_bytes,
+                          size_t *unprotected_bytes_size);
+  void (*destroy)(tsi_frame_protector *self);
+} tsi_frame_protector_vtable;
+
+struct tsi_frame_protector {
+  const tsi_frame_protector_vtable *vtable;
+};
+
+/* Base for tsi_handshaker implementations.
+   See transport_security_interface.h for documentation. */
+typedef struct {
+  tsi_result (*get_bytes_to_send_to_peer)(tsi_handshaker *self,
+                                          unsigned char *bytes,
+                                          size_t *bytes_size);
+  tsi_result (*process_bytes_from_peer)(tsi_handshaker *self,
+                                        const unsigned char *bytes,
+                                        size_t *bytes_size);
+  tsi_result (*get_result)(tsi_handshaker *self);
+  tsi_result (*extract_peer)(tsi_handshaker *self, tsi_peer *peer);
+  tsi_result (*create_frame_protector)(tsi_handshaker *self,
+                                       size_t *max_protected_frame_size,
+                                       tsi_frame_protector **protector);
+  void (*destroy)(tsi_handshaker *self);
+} tsi_handshaker_vtable;
+
+struct tsi_handshaker {
+  const tsi_handshaker_vtable *vtable;
+  int frame_protector_created;
+};
+
+/* Peer and property construction/destruction functions. */
+tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer);
+tsi_peer_property tsi_init_peer_property(void);
+void tsi_peer_property_destruct(tsi_peer_property *property);
+tsi_result tsi_construct_string_peer_property(const char *name,
+                                              const char *value,
+                                              size_t value_length,
+                                              tsi_peer_property *property);
+tsi_result tsi_construct_allocated_string_peer_property(
+    const char *name, size_t value_length, tsi_peer_property *property);
+tsi_result tsi_construct_string_peer_property_from_cstring(
+    const char *name, const char *value, tsi_peer_property *property);
+
+/* Utils. */
+char *tsi_strdup(const char *src); /* Sadly, no strdup in C89. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_TSI_TRANSPORT_SECURITY_H */
diff --git a/src/core/lib/tsi/transport_security_interface.h b/src/core/lib/tsi/transport_security_interface.h
new file mode 100644
index 0000000..3e8c9d7
--- /dev/null
+++ b/src/core/lib/tsi/transport_security_interface.h
@@ -0,0 +1,353 @@
+/*
+ *
+ * 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_TSI_TRANSPORT_SECURITY_INTERFACE_H
+#define GRPC_CORE_LIB_TSI_TRANSPORT_SECURITY_INTERFACE_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* --- tsi result ---  */
+
+typedef enum {
+  TSI_OK = 0,
+  TSI_UNKNOWN_ERROR = 1,
+  TSI_INVALID_ARGUMENT = 2,
+  TSI_PERMISSION_DENIED = 3,
+  TSI_INCOMPLETE_DATA = 4,
+  TSI_FAILED_PRECONDITION = 5,
+  TSI_UNIMPLEMENTED = 6,
+  TSI_INTERNAL_ERROR = 7,
+  TSI_DATA_CORRUPTED = 8,
+  TSI_NOT_FOUND = 9,
+  TSI_PROTOCOL_FAILURE = 10,
+  TSI_HANDSHAKE_IN_PROGRESS = 11,
+  TSI_OUT_OF_RESOURCES = 12
+} tsi_result;
+
+typedef enum {
+  // Default option
+  TSI_DONT_REQUEST_CLIENT_CERTIFICATE,
+  TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+  TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY,
+  TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+  TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY,
+} tsi_client_certificate_request_type;
+
+const char *tsi_result_to_string(tsi_result result);
+
+/* --- tsi tracing --- */
+
+/* Set this early to avoid races */
+extern int tsi_tracing_enabled;
+
+/* --- tsi_frame_protector object ---
+
+  This object protects and unprotects buffers once the handshake is done.
+  Implementations of this object must be thread compatible.  */
+
+typedef struct tsi_frame_protector tsi_frame_protector;
+
+/* Outputs protected frames.
+   - unprotected_bytes is an input only parameter and points to the data
+     to be protected.
+   - unprotected_bytes_size is an input/output parameter used by the caller to
+     specify how many bytes are available in unprotected_bytes. The output
+     value is the number of bytes consumed during the call.
+   - protected_output_frames points to a buffer allocated by the caller that
+     will be written.
+   - protected_output_frames_size is an input/output parameter used by the
+     caller to specify how many bytes are available in protected_output_frames.
+     As an output, this value indicates the number of bytes written.
+   - This method returns TSI_OK in case of success or a specific error code in
+     case of failure. Note that even if all the input unprotected bytes are
+     consumed, they may not have been processed into the returned protected
+     output frames. The caller should call the protect_flush method
+     to make sure that there are no more protected bytes buffered in the
+     protector.
+
+   A typical way to call this method would be:
+
+   ------------------------------------------------------------------------
+   unsigned char protected_buffer[4096];
+   size_t protected_buffer_size = sizeof(protected_buffer);
+   tsi_result result = TSI_OK;
+   while (message_size > 0) {
+     size_t protected_buffer_size_to_send = protected_buffer_size;
+     size_t processed_message_size = message_size;
+     result = tsi_frame_protector_protect(protector,
+                                          message_bytes,
+                                          &processed_message_size,
+                                          protected_buffer,
+                                          &protected_buffer_size_to_send);
+     if (result != TSI_OK) break;
+     send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
+     message_bytes += processed_message_size;
+     message_size -= processed_message_size;
+
+     // Don't forget to flush.
+     if (message_size == 0) {
+       size_t still_pending_size;
+       do {
+         protected_buffer_size_to_send = protected_buffer_size;
+         result = tsi_frame_protector_protect_flush(
+             protector, protected_buffer,
+             &protected_buffer_size_to_send, &still_pending_size);
+         if (result != TSI_OK) break;
+         send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
+       } while (still_pending_size > 0);
+     }
+   }
+
+   if (result != TSI_OK) HandleError(result);
+   ------------------------------------------------------------------------  */
+tsi_result tsi_frame_protector_protect(tsi_frame_protector *self,
+                                       const unsigned char *unprotected_bytes,
+                                       size_t *unprotected_bytes_size,
+                                       unsigned char *protected_output_frames,
+                                       size_t *protected_output_frames_size);
+
+/* Indicates that we need to flush the bytes buffered in the protector and get
+   the resulting frame.
+   - protected_output_frames points to a buffer allocated by the caller that
+     will be written.
+   - protected_output_frames_size is an input/output parameter used by the
+     caller to specify how many bytes are available in protected_output_frames.
+   - still_pending_bytes is an output parameter indicating the number of bytes
+     that still need to be flushed from the protector.*/
+tsi_result tsi_frame_protector_protect_flush(
+    tsi_frame_protector *self, unsigned char *protected_output_frames,
+    size_t *protected_output_frames_size, size_t *still_pending_size);
+
+/* Outputs unprotected bytes.
+   - protected_frames_bytes is an input only parameter and points to the
+     protected frames to be unprotected.
+   - protected_frames_bytes_size is an input/output only parameter used by the
+     caller to specify how many bytes are available in protected_bytes. The
+     output value is the number of bytes consumed during the call.
+     Implementations will buffer up to a frame of protected data.
+   - unprotected_bytes points to a buffer allocated by the caller that will be
+     written.
+   - unprotected_bytes_size is an input/output parameter used by the caller to
+     specify how many bytes are available in unprotected_bytes. This
+     value is expected to be at most max_protected_frame_size minus overhead
+     which means that max_protected_frame_size is a safe bet. The output value
+     is the number of bytes actually written.
+     If *unprotected_bytes_size is unchanged, there may be more data remaining
+     to unprotect, and the caller should call this function again.
+
+   - This method returns TSI_OK in case of success. Success includes cases where
+     there is not enough data to output a frame in which case
+     unprotected_bytes_size will be set to 0 and cases where the internal buffer
+     needs to be read before new protected data can be processed in which case
+     protected_frames_size will be set to 0.  */
+tsi_result tsi_frame_protector_unprotect(
+    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
+    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
+    size_t *unprotected_bytes_size);
+
+/* Destroys the tsi_frame_protector object.  */
+void tsi_frame_protector_destroy(tsi_frame_protector *self);
+
+/* --- tsi_peer objects ---
+
+   tsi_peer objects are a set of properties. The peer owns the properties.  */
+
+/* This property is of type TSI_PEER_PROPERTY_STRING.  */
+#define TSI_CERTIFICATE_TYPE_PEER_PROPERTY "certificate_type"
+
+/* Property values may contain NULL characters just like C++ strings.
+   The length field gives the length of the string. */
+typedef struct tsi_peer_property {
+  char *name;
+  struct {
+    char *data;
+    size_t length;
+  } value;
+} tsi_peer_property;
+
+typedef struct {
+  tsi_peer_property *properties;
+  size_t property_count;
+} tsi_peer;
+
+/* Destructs the tsi_peer object. */
+void tsi_peer_destruct(tsi_peer *self);
+
+/* --- tsi_handshaker objects ----
+
+   Implementations of this object must be thread compatible.
+
+   A typical usage of this object would be:
+
+   ------------------------------------------------------------------------
+   tsi_result result = TSI_OK;
+   unsigned char buf[4096];
+   size_t buf_offset;
+   size_t buf_size;
+   while (1) {
+     // See if we need to send some bytes to the peer.
+     do {
+       size_t buf_size_to_send = sizeof(buf);
+       result = tsi_handshaker_get_bytes_to_send_to_peer(handshaker, buf,
+                                                         &buf_size_to_send);
+       if (buf_size_to_send > 0) send_bytes_to_peer(buf, buf_size_to_send);
+     } while (result == TSI_INCOMPLETE_DATA);
+     if (result != TSI_OK) return result;
+     if (!tsi_handshaker_is_in_progress(handshaker)) break;
+
+     do {
+       // Read bytes from the peer.
+       buf_size = sizeof(buf);
+       buf_offset = 0;
+       read_bytes_from_peer(buf, &buf_size);
+       if (buf_size == 0) break;
+
+       // Process the bytes from the peer. We have to be careful as these bytes
+       // may contain non-handshake data (protected data). If this is the case,
+       // we will exit from the loop with buf_size > 0.
+       size_t consumed_by_handshaker = buf_size;
+       result = tsi_handshaker_process_bytes_from_peer(
+           handshaker, buf, &consumed_by_handshaker);
+       buf_size -= consumed_by_handshaker;
+       buf_offset += consumed_by_handshaker;
+     } while (result == TSI_INCOMPLETE_DATA);
+
+     if (result != TSI_OK) return result;
+     if (!tsi_handshaker_is_in_progress(handshaker)) break;
+   }
+
+   // Check the Peer.
+   tsi_peer peer;
+   do {
+     result = tsi_handshaker_extract_peer(handshaker, &peer);
+     if (result != TSI_OK) break;
+     result = check_peer(&peer);
+   } while (0);
+   tsi_peer_destruct(&peer);
+   if (result != TSI_OK) return result;
+
+   // Create the protector.
+   tsi_frame_protector* protector = NULL;
+   result = tsi_handshaker_create_frame_protector(handshaker, NULL,
+                                                  &protector);
+   if (result != TSI_OK) return result;
+
+   // Do not forget to unprotect outstanding data if any.
+   if (buf_size > 0) {
+     result = tsi_frame_protector_unprotect(protector, buf + buf_offset,
+                                            buf_size, ..., ...);
+     ....
+   }
+   ...
+   ------------------------------------------------------------------------   */
+typedef struct tsi_handshaker tsi_handshaker;
+
+/* Gets bytes that need to be sent to the peer.
+   - bytes is the buffer that will be written with the data to be sent to the
+     peer.
+   - bytes_size is an input/output parameter specifying the capacity of the
+     bytes parameter as input and the number of bytes written as output.
+   Returns TSI_OK if all the data to send to the peer has been written or if
+   nothing has to be sent to the peer (in which base bytes_size outputs to 0),
+   otherwise returns TSI_INCOMPLETE_DATA which indicates that this method
+   needs to be called again to get all the bytes to send to the peer (there
+   was more data to write than the specified bytes_size). In case of a fatal
+   error in the handshake, another specific error code is returned.  */
+tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
+                                                    unsigned char *bytes,
+                                                    size_t *bytes_size);
+
+/* Processes bytes received from the peer.
+   - bytes is the buffer containing the data.
+   - bytes_size is an input/output parameter specifying the size of the data as
+     input and the number of bytes consumed as output.
+   Return TSI_OK if the handshake has all the data it needs to process,
+   otherwise return TSI_INCOMPLETE_DATA which indicates that this method
+   needs to be called again to complete the data needed for processing. In
+   case of a fatal error in the handshake, another specific error code is
+   returned.  */
+tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self,
+                                                  const unsigned char *bytes,
+                                                  size_t *bytes_size);
+
+/* Gets the result of the handshaker.
+   Returns TSI_OK if the hanshake completed successfully and there has been no
+   errors. Returns TSI_HANDSHAKE_IN_PROGRESS if the handshaker is not done yet
+   but no error has been encountered so far. Otherwise the handshaker failed
+   with the returned error.  */
+tsi_result tsi_handshaker_get_result(tsi_handshaker *self);
+
+/* Returns 1 if the handshake is in progress, 0 otherwise.  */
+#define tsi_handshaker_is_in_progress(h) \
+  (tsi_handshaker_get_result((h)) == TSI_HANDSHAKE_IN_PROGRESS)
+
+/* This method may return TSI_FAILED_PRECONDITION if
+   tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise
+   assuming the handshaker is not in a fatal error state.
+   The caller is responsible for destructing the peer.  */
+tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer);
+
+/* This method creates a tsi_frame_protector object after the handshake phase
+   is done. After this method has been called successfully, the only method
+   that can be called on this object is Destroy.
+   - max_output_protected_frame_size is an input/output parameter specifying the
+     desired max output protected frame size as input and outputing the actual
+     max output frame size as the output. Passing NULL is OK and will result in
+     the implementation choosing the default maximum protected frame size. Note
+     that this size only applies to outgoing frames (generated with
+     tsi_frame_protector_protect) and not incoming frames (input of
+     tsi_frame_protector_unprotect).
+   - protector is an output parameter pointing to the newly created
+     tsi_frame_protector object.
+   This method may return TSI_FAILED_PRECONDITION if
+   tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming
+   the handshaker is not in a fatal error state.
+   The caller is responsible for destroying the protector.  */
+tsi_result tsi_handshaker_create_frame_protector(
+    tsi_handshaker *self, size_t *max_output_protected_frame_size,
+    tsi_frame_protector **protector);
+
+/* This method releases the tsi_handshaker object. After this method is called,
+   no other method can be called on the object.  */
+void tsi_handshaker_destroy(tsi_handshaker *self);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_TSI_TRANSPORT_SECURITY_INTERFACE_H */
diff --git a/src/core/plugin_registry/grpc_plugin_registry.c b/src/core/plugin_registry/grpc_plugin_registry.c
new file mode 100644
index 0000000..822aa6d
--- /dev/null
+++ b/src/core/plugin_registry/grpc_plugin_registry.c
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/grpc.h>
+
+extern void grpc_chttp2_plugin_init(void);
+extern void grpc_chttp2_plugin_shutdown(void);
+extern void grpc_client_config_init(void);
+extern void grpc_client_config_shutdown(void);
+extern void grpc_lb_policy_pick_first_init(void);
+extern void grpc_lb_policy_pick_first_shutdown(void);
+extern void grpc_lb_policy_round_robin_init(void);
+extern void grpc_lb_policy_round_robin_shutdown(void);
+extern void grpc_resolver_dns_native_init(void);
+extern void grpc_resolver_dns_native_shutdown(void);
+extern void grpc_resolver_sockaddr_init(void);
+extern void grpc_resolver_sockaddr_shutdown(void);
+extern void census_grpc_plugin_init(void);
+extern void census_grpc_plugin_shutdown(void);
+
+void grpc_register_built_in_plugins(void) {
+  grpc_register_plugin(grpc_chttp2_plugin_init,
+                       grpc_chttp2_plugin_shutdown);
+  grpc_register_plugin(grpc_client_config_init,
+                       grpc_client_config_shutdown);
+  grpc_register_plugin(grpc_lb_policy_pick_first_init,
+                       grpc_lb_policy_pick_first_shutdown);
+  grpc_register_plugin(grpc_lb_policy_round_robin_init,
+                       grpc_lb_policy_round_robin_shutdown);
+  grpc_register_plugin(grpc_resolver_dns_native_init,
+                       grpc_resolver_dns_native_shutdown);
+  grpc_register_plugin(grpc_resolver_sockaddr_init,
+                       grpc_resolver_sockaddr_shutdown);
+  grpc_register_plugin(census_grpc_plugin_init,
+                       census_grpc_plugin_shutdown);
+}
diff --git a/src/core/plugin_registry/grpc_unsecure_plugin_registry.c b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
new file mode 100644
index 0000000..a6108ae
--- /dev/null
+++ b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/grpc.h>
+
+extern void grpc_chttp2_plugin_init(void);
+extern void grpc_chttp2_plugin_shutdown(void);
+extern void grpc_client_config_init(void);
+extern void grpc_client_config_shutdown(void);
+extern void grpc_resolver_dns_native_init(void);
+extern void grpc_resolver_dns_native_shutdown(void);
+extern void grpc_resolver_sockaddr_init(void);
+extern void grpc_resolver_sockaddr_shutdown(void);
+extern void grpc_lb_policy_pick_first_init(void);
+extern void grpc_lb_policy_pick_first_shutdown(void);
+extern void grpc_lb_policy_round_robin_init(void);
+extern void grpc_lb_policy_round_robin_shutdown(void);
+extern void census_grpc_plugin_init(void);
+extern void census_grpc_plugin_shutdown(void);
+
+void grpc_register_built_in_plugins(void) {
+  grpc_register_plugin(grpc_chttp2_plugin_init,
+                       grpc_chttp2_plugin_shutdown);
+  grpc_register_plugin(grpc_client_config_init,
+                       grpc_client_config_shutdown);
+  grpc_register_plugin(grpc_resolver_dns_native_init,
+                       grpc_resolver_dns_native_shutdown);
+  grpc_register_plugin(grpc_resolver_sockaddr_init,
+                       grpc_resolver_sockaddr_shutdown);
+  grpc_register_plugin(grpc_lb_policy_pick_first_init,
+                       grpc_lb_policy_pick_first_shutdown);
+  grpc_register_plugin(grpc_lb_policy_round_robin_init,
+                       grpc_lb_policy_round_robin_shutdown);
+  grpc_register_plugin(census_grpc_plugin_init,
+                       census_grpc_plugin_shutdown);
+}
diff --git a/src/core/profiling/basic_timers.c b/src/core/profiling/basic_timers.c
deleted file mode 100644
index df32472..0000000
--- a/src/core/profiling/basic_timers.c
+++ /dev/null
@@ -1,274 +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 GRPC_BASIC_PROFILER
-
-#include "src/core/profiling/timers.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include <stdio.h>
-
-typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
-
-typedef struct gpr_timer_entry {
-  gpr_timespec tm;
-  const char *tagstr;
-  const char *file;
-  short line;
-  char type;
-  uint8_t important;
-  int thd;
-} gpr_timer_entry;
-
-#define MAX_COUNT 1000000
-
-typedef struct gpr_timer_log {
-  size_t num_entries;
-  struct gpr_timer_log *next;
-  struct gpr_timer_log *prev;
-  gpr_timer_entry log[MAX_COUNT];
-} gpr_timer_log;
-
-typedef struct gpr_timer_log_list {
-  gpr_timer_log *head;
-  /* valid iff head!=NULL */
-  gpr_timer_log *tail;
-} gpr_timer_log_list;
-
-static __thread gpr_timer_log *g_thread_log;
-static gpr_once g_once_init = GPR_ONCE_INIT;
-static FILE *output_file;
-static const char *output_filename = "latency_trace.txt";
-static pthread_mutex_t g_mu;
-static pthread_cond_t g_cv;
-static gpr_timer_log_list g_in_progress_logs;
-static gpr_timer_log_list g_done_logs;
-static int g_shutdown;
-static gpr_thd_id g_writing_thread;
-static __thread int g_thread_id;
-static int g_next_thread_id;
-
-static int timer_log_push_back(gpr_timer_log_list *list, gpr_timer_log *log) {
-  if (list->head == NULL) {
-    list->head = list->tail = log;
-    log->next = log->prev = NULL;
-    return 1;
-  } else {
-    log->prev = list->tail;
-    log->next = NULL;
-    list->tail->next = log;
-    list->tail = log;
-    return 0;
-  }
-}
-
-static gpr_timer_log *timer_log_pop_front(gpr_timer_log_list *list) {
-  gpr_timer_log *out = list->head;
-  if (out != NULL) {
-    list->head = out->next;
-    if (list->head != NULL) {
-      list->head->prev = NULL;
-    } else {
-      list->tail = NULL;
-    }
-  }
-  return out;
-}
-
-static void timer_log_remove(gpr_timer_log_list *list, gpr_timer_log *log) {
-  if (log->prev == NULL) {
-    list->head = log->next;
-    if (list->head != NULL) {
-      list->head->prev = NULL;
-    }
-  } else {
-    log->prev->next = log->next;
-  }
-  if (log->next == NULL) {
-    list->tail = log->prev;
-    if (list->tail != NULL) {
-      list->tail->next = NULL;
-    }
-  } else {
-    log->next->prev = log->prev;
-  }
-}
-
-static void write_log(gpr_timer_log *log) {
-  size_t i;
-  if (output_file == NULL) {
-    output_file = fopen(output_filename, "w");
-  }
-  for (i = 0; i < log->num_entries; i++) {
-    gpr_timer_entry *entry = &(log->log[i]);
-    if (gpr_time_cmp(entry->tm, gpr_time_0(entry->tm.clock_type)) < 0) {
-      entry->tm = gpr_time_0(entry->tm.clock_type);
-    }
-    fprintf(output_file,
-            "{\"t\": %lld.%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": "
-            "\"%s\", \"file\": \"%s\", \"line\": %d, \"imp\": %d}\n",
-            (long long)entry->tm.tv_sec, (int)entry->tm.tv_nsec, entry->thd,
-            entry->type, entry->tagstr, entry->file, entry->line,
-            entry->important);
-  }
-}
-
-static void writing_thread(void *unused) {
-  gpr_timer_log *log;
-  pthread_mutex_lock(&g_mu);
-  for (;;) {
-    while ((log = timer_log_pop_front(&g_done_logs)) == NULL && !g_shutdown) {
-      pthread_cond_wait(&g_cv, &g_mu);
-    }
-    if (log != NULL) {
-      pthread_mutex_unlock(&g_mu);
-      write_log(log);
-      free(log);
-      pthread_mutex_lock(&g_mu);
-    }
-    if (g_shutdown) {
-      pthread_mutex_unlock(&g_mu);
-      return;
-    }
-  }
-}
-
-static void flush_logs(gpr_timer_log_list *list) {
-  gpr_timer_log *log;
-  while ((log = timer_log_pop_front(list)) != NULL) {
-    write_log(log);
-    free(log);
-  }
-}
-
-static void finish_writing() {
-  pthread_mutex_lock(&g_mu);
-  g_shutdown = 1;
-  pthread_cond_signal(&g_cv);
-  pthread_mutex_unlock(&g_mu);
-  gpr_thd_join(g_writing_thread);
-
-  gpr_log(GPR_INFO, "flushing logs");
-
-  pthread_mutex_lock(&g_mu);
-  flush_logs(&g_done_logs);
-  flush_logs(&g_in_progress_logs);
-  pthread_mutex_unlock(&g_mu);
-
-  if (output_file) {
-    fclose(output_file);
-  }
-}
-
-void gpr_timers_set_log_filename(const char *filename) {
-  output_filename = filename;
-}
-
-static void init_output() {
-  gpr_thd_options options = gpr_thd_options_default();
-  gpr_thd_options_set_joinable(&options);
-  gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options);
-  atexit(finish_writing);
-}
-
-static void rotate_log() {
-  gpr_timer_log *new = malloc(sizeof(*new));
-  gpr_once_init(&g_once_init, init_output);
-  new->num_entries = 0;
-  pthread_mutex_lock(&g_mu);
-  if (g_thread_log != NULL) {
-    timer_log_remove(&g_in_progress_logs, g_thread_log);
-    if (timer_log_push_back(&g_done_logs, g_thread_log)) {
-      pthread_cond_signal(&g_cv);
-    }
-  } else {
-    g_thread_id = g_next_thread_id++;
-  }
-  timer_log_push_back(&g_in_progress_logs, new);
-  pthread_mutex_unlock(&g_mu);
-  g_thread_log = new;
-}
-
-static void gpr_timers_log_add(const char *tagstr, marker_type type,
-                               int important, const char *file, int line) {
-  gpr_timer_entry *entry;
-
-  if (g_thread_log == NULL || g_thread_log->num_entries == MAX_COUNT) {
-    rotate_log();
-  }
-
-  entry = &g_thread_log->log[g_thread_log->num_entries++];
-
-  entry->tm = gpr_now(GPR_CLOCK_PRECISE);
-  entry->tagstr = tagstr;
-  entry->type = type;
-  entry->file = file;
-  entry->line = (short)line;
-  entry->important = important != 0;
-  entry->thd = g_thread_id;
-}
-
-/* Latency profiler API implementation. */
-void gpr_timer_add_mark(const char *tagstr, int important, const char *file,
-                        int line) {
-  gpr_timers_log_add(tagstr, MARK, important, file, line);
-}
-
-void gpr_timer_begin(const char *tagstr, int important, const char *file,
-                     int line) {
-  gpr_timers_log_add(tagstr, BEGIN, important, file, line);
-}
-
-void gpr_timer_end(const char *tagstr, int important, const char *file,
-                   int line) {
-  gpr_timers_log_add(tagstr, END, important, file, line);
-}
-
-/* Basic profiler specific API functions. */
-void gpr_timers_global_init(void) {}
-
-void gpr_timers_global_destroy(void) {}
-
-#else  /* !GRPC_BASIC_PROFILER */
-void gpr_timers_global_init(void) {}
-
-void gpr_timers_global_destroy(void) {}
-
-void gpr_timers_set_log_filename(const char *filename) {}
-#endif /* GRPC_BASIC_PROFILER */
diff --git a/src/core/profiling/stap_timers.c b/src/core/profiling/stap_timers.c
deleted file mode 100644
index efcd1af..0000000
--- a/src/core/profiling/stap_timers.c
+++ /dev/null
@@ -1,65 +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 GRPC_STAP_PROFILER
-
-#include "src/core/profiling/timers.h"
-
-#include <sys/sdt.h>
-/* Generated from src/core/profiling/stap_probes.d */
-#include "src/core/profiling/stap_probes.h"
-
-/* Latency profiler API implementation. */
-void gpr_timer_add_mark(int tag, const char *tagstr, void *id, const char *file,
-                        int line) {
-  _STAP_ADD_MARK(tag);
-}
-
-void gpr_timer_add_important_mark(int tag, const char *tagstr, void *id,
-                                  const char *file, int line) {
-  _STAP_ADD_IMPORTANT_MARK(tag);
-}
-
-void gpr_timer_begin(int tag, const char *tagstr, void *id, const char *file,
-                     int line) {
-  _STAP_TIMING_NS_BEGIN(tag);
-}
-
-void gpr_timer_end(int tag, const char *tagstr, void *id, const char *file,
-                   int line) {
-  _STAP_TIMING_NS_END(tag);
-}
-
-#endif /* GRPC_STAP_PROFILER */
diff --git a/src/core/profiling/timers.h b/src/core/profiling/timers.h
deleted file mode 100644
index 6a188dc..0000000
--- a/src/core/profiling/timers.h
+++ /dev/null
@@ -1,119 +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_PROFILING_TIMERS_H
-#define GRPC_CORE_PROFILING_TIMERS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void gpr_timers_global_init(void);
-void gpr_timers_global_destroy(void);
-
-void gpr_timer_add_mark(const char *tagstr, int important, const char *file,
-                        int line);
-void gpr_timer_begin(const char *tagstr, int important, const char *file,
-                     int line);
-void gpr_timer_end(const char *tagstr, int important, const char *file,
-                   int line);
-
-void gpr_timers_set_log_filename(const char *filename);
-
-#if !(defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
-/* No profiling. No-op all the things. */
-#define GPR_TIMER_MARK(tag, important) \
-  do {                                 \
-  } while (0)
-
-#define GPR_TIMER_BEGIN(tag, important) \
-  do {                                  \
-  } while (0)
-
-#define GPR_TIMER_END(tag, important) \
-  do {                                \
-  } while (0)
-
-#else /* at least one profiler requested... */
-/* ... hopefully only one. */
-#if defined(GRPC_STAP_PROFILER) && defined(GRPC_BASIC_PROFILER)
-#error "GRPC_STAP_PROFILER and GRPC_BASIC_PROFILER are mutually exclusive."
-#endif
-
-/* Generic profiling interface. */
-#define GPR_TIMER_MARK(tag, important) \
-  gpr_timer_add_mark(tag, important, __FILE__, __LINE__);
-
-#define GPR_TIMER_BEGIN(tag, important) \
-  gpr_timer_begin(tag, important, __FILE__, __LINE__);
-
-#define GPR_TIMER_END(tag, important) \
-  gpr_timer_end(tag, important, __FILE__, __LINE__);
-
-#ifdef GRPC_STAP_PROFILER
-/* Empty placeholder for now. */
-#endif /* GRPC_STAP_PROFILER */
-
-#ifdef GRPC_BASIC_PROFILER
-/* Empty placeholder for now. */
-#endif /* GRPC_BASIC_PROFILER */
-
-#endif /* at least one profiler requested. */
-
-#ifdef __cplusplus
-}
-
-#if (defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
-namespace grpc {
-class ProfileScope {
- public:
-  ProfileScope(const char *desc, bool important) : desc_(desc) {
-    GPR_TIMER_BEGIN(desc_, important ? 1 : 0);
-  }
-  ~ProfileScope() { GPR_TIMER_END(desc_, 0); }
-
- private:
-  const char *const desc_;
-};
-}
-
-#define GPR_TIMER_SCOPE(tag, important) \
-  ::grpc::ProfileScope _profile_scope_##__LINE__((tag), (important))
-#else
-#define GPR_TIMER_SCOPE(tag, important) \
-  do {                                  \
-  } while (false)
-#endif
-#endif
-
-#endif /* GRPC_CORE_PROFILING_TIMERS_H */
diff --git a/src/core/proto/grpc/lb/v0/load_balancer.pb.c b/src/core/proto/grpc/lb/v0/load_balancer.pb.c
deleted file mode 100644
index 59aae30..0000000
--- a/src/core/proto/grpc/lb/v0/load_balancer.pb.c
+++ /dev/null
@@ -1,119 +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.
- *
- */
-/* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.5-dev */
-
-#include "src/core/proto/grpc/lb/v0/load_balancer.pb.h"
-
-#if PB_PROTO_HEADER_VERSION != 30
-#error Regenerate this file with the current version of nanopb generator.
-#endif
-
-
-
-const pb_field_t grpc_lb_v0_Duration_fields[3] = {
-    PB_FIELD(  1, INT64   , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_Duration, seconds, seconds, 0),
-    PB_FIELD(  2, INT32   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Duration, nanos, seconds, 0),
-    PB_LAST_FIELD
-};
-
-const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3] = {
-    PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v0_InitialLoadBalanceRequest_fields),
-    PB_FIELD(  2, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v0_ClientStats_fields),
-    PB_LAST_FIELD
-};
-
-const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2] = {
-    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_InitialLoadBalanceRequest, name, name, 0),
-    PB_LAST_FIELD
-};
-
-const pb_field_t grpc_lb_v0_ClientStats_fields[4] = {
-    PB_FIELD(  1, INT64   , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_ClientStats, total_requests, total_requests, 0),
-    PB_FIELD(  2, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ClientStats, client_rpc_errors, total_requests, 0),
-    PB_FIELD(  3, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ClientStats, dropped_requests, client_rpc_errors, 0),
-    PB_LAST_FIELD
-};
-
-const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3] = {
-    PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v0_InitialLoadBalanceResponse_fields),
-    PB_FIELD(  2, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v0_ServerList_fields),
-    PB_LAST_FIELD
-};
-
-const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4] = {
-    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_InitialLoadBalanceResponse, client_config, client_config, 0),
-    PB_FIELD(  2, STRING  , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, load_balancer_delegate, client_config, 0),
-    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v0_Duration_fields),
-    PB_LAST_FIELD
-};
-
-const pb_field_t grpc_lb_v0_ServerList_fields[3] = {
-    PB_FIELD(  1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v0_ServerList, servers, servers, &grpc_lb_v0_Server_fields),
-    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ServerList, expiration_interval, servers, &grpc_lb_v0_Duration_fields),
-    PB_LAST_FIELD
-};
-
-const pb_field_t grpc_lb_v0_Server_fields[5] = {
-    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_Server, ip_address, ip_address, 0),
-    PB_FIELD(  2, INT32   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, port, ip_address, 0),
-    PB_FIELD(  3, BYTES   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, load_balance_token, port, 0),
-    PB_FIELD(  4, BOOL    , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, drop_request, load_balance_token, 0),
-    PB_LAST_FIELD
-};
-
-
-/* Check that field information fits in pb_field_t */
-#if !defined(PB_FIELD_32BIT)
-/* If you get an error here, it means that you need to define PB_FIELD_32BIT
- * compile-time option. You can do that in pb.h or on compiler command line.
- * 
- * The reason you need to do this is that some of your messages contain tag
- * numbers or field sizes that are larger than what can fit in 8 or 16 bit
- * field descriptors.
- */
-PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v0_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
-#endif
-
-#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
-/* If you get an error here, it means that you need to define PB_FIELD_16BIT
- * compile-time option. You can do that in pb.h or on compiler command line.
- * 
- * The reason you need to do this is that some of your messages contain tag
- * numbers or field sizes that are larger than what can fit in the default
- * 8 bit descriptors.
- */
-PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v0_ServerList, servers) < 256 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
-#endif
-
-
diff --git a/src/core/security/auth_filters.h b/src/core/security/auth_filters.h
deleted file mode 100644
index 1154a1d..0000000
--- a/src/core/security/auth_filters.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_AUTH_FILTERS_H
-#define GRPC_CORE_SECURITY_AUTH_FILTERS_H
-
-#include "src/core/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_SECURITY_AUTH_FILTERS_H */
diff --git a/src/core/security/b64.c b/src/core/security/b64.c
deleted file mode 100644
index c40b528..0000000
--- a/src/core/security/b64.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- *
- * 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/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/security/b64.h b/src/core/security/b64.h
deleted file mode 100644
index d18f695..0000000
--- a/src/core/security/b64.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_B64_H
-#define GRPC_CORE_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_SECURITY_B64_H */
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
deleted file mode 100644
index 332d425..0000000
--- a/src/core/security/client_auth_filter.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- *
- * 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/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/channel/channel_stack.h"
-#include "src/core/security/credentials.h"
-#include "src/core/security/security_connector.h"
-#include "src/core/security/security_context.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/call.h"
-#include "src/core/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 bound to this call; if we need to make external
-     network requests, they should be done under this pollset
-     so that work can progress when this call wants work to
-     progress */
-  grpc_pollset *pollset;
-  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_INVALID_ARGUMENT,
-                      "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->pollset);
-  grpc_call_credentials_get_request_metadata(
-      exec_ctx, calld->creds, calld->pollset, 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_INVALID_ARGUMENT, 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(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                        grpc_pollset *pollset) {
-  call_data *calld = elem->call_data;
-  calld->pollset = pollset;
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {
-  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, destroy_call_elem, sizeof(channel_data),
-    init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
-    "client-auth"};
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
deleted file mode 100644
index b4fa616..0000000
--- a/src/core/security/credentials.c
+++ /dev/null
@@ -1,1280 +0,0 @@
-/*
- *
- * 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/security/credentials.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/http_client_filter.h"
-#include "src/core/httpcli/httpcli.h"
-#include "src/core/iomgr/executor.h"
-#include "src/core/json/json.h"
-#include "src/core/support/string.h"
-#include "src/core/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_pollset *pollset, 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, pollset, 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, int force_client_auth,
-    grpc_ssl_server_config *config) {
-  size_t i;
-  config->force_client_auth = force_client_auth;
-  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) {
-  grpc_ssl_server_credentials *c =
-      gpr_malloc(sizeof(grpc_ssl_server_credentials));
-  GRPC_API_TRACE(
-      "grpc_ssl_server_credentials_create("
-      "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
-      "force_client_auth=%d, reserved=%p)",
-      5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
-          force_client_auth, 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, force_client_auth, &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_pollset *pollset,
-                                     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_httpcli_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_httpcli_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_pollset *pollset, 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, pollset, 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_pollset *pollset,
-    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
-  grpc_httpcli_header header = {"Metadata-Flavor", "Google"};
-  grpc_httpcli_request request;
-  memset(&request, 0, sizeof(grpc_httpcli_request));
-  request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
-  request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
-  request.hdr_count = 1;
-  request.hdrs = &header;
-  grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &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_pollset *pollset,
-    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
-  grpc_google_refresh_token_credentials *c =
-      (grpc_google_refresh_token_credentials *)metadata_req->creds;
-  grpc_httpcli_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.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
-  request.hdr_count = 1;
-  request.hdrs = &header;
-  request.handshaker = &grpc_httpcli_ssl;
-  grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &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_pollset *pollset, 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_pollset *pollset, 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_pollset *pollset;
-  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->pollset, 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_pollset *pollset, 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->pollset = pollset;
-  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++], pollset,
-      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_pollset *pollset,
-                                     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_pollset *pollset,
-                                        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/security/credentials.h b/src/core/security/credentials.h
deleted file mode 100644
index 133aa9d..0000000
--- a/src/core/security/credentials.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_CREDENTIALS_H
-#define GRPC_CORE_SECURITY_CREDENTIALS_H
-
-#include "src/core/transport/metadata_batch.h"
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
-#include <grpc/support/sync.h>
-
-#include "src/core/httpcli/httpcli.h"
-#include "src/core/security/json_token.h"
-#include "src/core/security/security_connector.h"
-
-struct grpc_httpcli_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_pollset *pollset,
-                               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_pollset *pollset, 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_httpcli_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_pollset *pollset,
-                                       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_SECURITY_CREDENTIALS_H */
diff --git a/src/core/security/credentials_metadata.c b/src/core/security/credentials_metadata.c
deleted file mode 100644
index b8a132f..0000000
--- a/src/core/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/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/security/credentials_posix.c b/src/core/security/credentials_posix.c
deleted file mode 100644
index 0c92bd4..0000000
--- a/src/core/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/security/credentials.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/support/env.h"
-#include "src/core/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/security/credentials_win32.c b/src/core/security/credentials_win32.c
deleted file mode 100644
index 8ee9f70..0000000
--- a/src/core/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/security/credentials.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/support/env.h"
-#include "src/core/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/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
deleted file mode 100644
index 1f4f3e4..0000000
--- a/src/core/security/google_default_credentials.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- *
- * 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/security/credentials.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-
-#include "src/core/httpcli/httpcli.h"
-#include "src/core/support/env.h"
-#include "src/core/support/load_file.h"
-#include "src/core/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_pollset *pollset;
-  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_httpcli_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_httpcli_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(detector->pollset, 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);
-
-  detector.pollset = gpr_malloc(grpc_pollset_size());
-  grpc_pollset_init(detector.pollset, &g_polling_mu);
-  detector.is_done = 0;
-  detector.success = 0;
-
-  memset(&request, 0, sizeof(grpc_httpcli_request));
-  request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
-  request.path = "/";
-
-  grpc_httpcli_context_init(&context);
-
-  grpc_httpcli_get(
-      &exec_ctx, &context, detector.pollset, &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, detector.pollset, &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, detector.pollset);
-  grpc_pollset_shutdown(&exec_ctx, detector.pollset, &destroy_closure);
-  grpc_exec_ctx_finish(&exec_ctx);
-  g_polling_mu = NULL;
-
-  gpr_free(detector.pollset);
-
-  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/security/handshake.c b/src/core/security/handshake.c
deleted file mode 100644
index b5bb666..0000000
--- a/src/core/security/handshake.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- *
- * 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/security/handshake.h"
-
-#include <stdbool.h>
-#include <string.h>
-
-#include "src/core/security/security_context.h"
-#include "src/core/security/secure_endpoint.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.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/security/handshake.h b/src/core/security/handshake.h
deleted file mode 100644
index 4872045..0000000
--- a/src/core/security/handshake.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_HANDSHAKE_H
-#define GRPC_CORE_SECURITY_HANDSHAKE_H
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/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_SECURITY_HANDSHAKE_H */
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
deleted file mode 100644
index 372e5bf..0000000
--- a/src/core/security/json_token.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- *
- * 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/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/security/b64.h"
-#include "src/core/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/security/json_token.h b/src/core/security/json_token.h
deleted file mode 100644
index d183f9b..0000000
--- a/src/core/security/json_token.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_JSON_TOKEN_H
-#define GRPC_CORE_SECURITY_JSON_TOKEN_H
-
-#include <grpc/support/slice.h>
-#include <openssl/rsa.h>
-
-#include "src/core/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_SECURITY_JSON_TOKEN_H */
diff --git a/src/core/security/jwt_verifier.c b/src/core/security/jwt_verifier.c
deleted file mode 100644
index 928c6c1..0000000
--- a/src/core/security/jwt_verifier.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- *
- * 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/security/jwt_verifier.h"
-
-#include <limits.h>
-#include <string.h>
-
-#include "src/core/httpcli/httpcli.h"
-#include "src/core/security/b64.h"
-#include "src/core/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_pollset *pollset;
-  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) {
-  verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
-  memset(ctx, 0, sizeof(verifier_cb_ctx));
-  ctx->verifier = verifier;
-  ctx->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;
-  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.path = strchr(jwks_uri, '/');
-  if (req.path == NULL) {
-    req.path = "";
-  } else {
-    *(req.host + (req.path - jwks_uri)) = '\0';
-  }
-  grpc_httpcli_get(
-      exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &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.path, "/%s", iss);
-    } else {
-      *(path_prefix++) = '\0';
-      gpr_asprintf(&req.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.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX);
-    } else {
-      *(path_prefix++) = 0;
-      gpr_asprintf(&req.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->pollset, &req,
-      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
-      http_cb, ctx);
-  gpr_free(req.host);
-  gpr_free(req.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/security/jwt_verifier.h b/src/core/security/jwt_verifier.h
deleted file mode 100644
index d898d21..0000000
--- a/src/core/security/jwt_verifier.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_JWT_VERIFIER_H
-#define GRPC_CORE_SECURITY_JWT_VERIFIER_H
-
-#include "src/core/iomgr/pollset.h"
-#include "src/core/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_SECURITY_JWT_VERIFIER_H */
diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c
deleted file mode 100644
index d11c43b..0000000
--- a/src/core/security/secure_endpoint.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- *
- * 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/security/secure_endpoint.h"
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/sync.h>
-#include "src/core/tsi/transport_security_interface.h"
-#include "src/core/debug/trace.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/security/secure_endpoint.h b/src/core/security/secure_endpoint.h
deleted file mode 100644
index 5176ef2..0000000
--- a/src/core/security/secure_endpoint.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_SECURE_ENDPOINT_H
-#define GRPC_CORE_SECURITY_SECURE_ENDPOINT_H
-
-#include "src/core/iomgr/endpoint.h"
-#include <grpc/support/slice.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_SECURITY_SECURE_ENDPOINT_H */
diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c
deleted file mode 100644
index fbec263..0000000
--- a/src/core/security/security_connector.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- *
- * 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/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/security/credentials.h"
-#include "src/core/security/handshake.h"
-#include "src/core/security/secure_endpoint.h"
-#include "src/core/security/security_context.h"
-#include "src/core/support/env.h"
-#include "src/core/support/load_file.h"
-#include "src/core/support/string.h"
-#include "src/core/transport/chttp2/alpn.h"
-#include "src/core/tsi/fake_transport_security.h"
-#include "src/core/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();
-}
-
-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(
-      (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,
-      config->force_client_auth, 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/security/security_connector.h b/src/core/security/security_connector.h
deleted file mode 100644
index 6f915eb..0000000
--- a/src/core/security/security_connector.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_SECURITY_CONNECTOR_H
-#define GRPC_CORE_SECURITY_SECURITY_CONNECTOR_H
-
-#include <grpc/grpc_security.h>
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/tcp_server.h"
-#include "src/core/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;
-  int force_client_auth;
-} 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_SECURITY_SECURITY_CONNECTOR_H */
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
deleted file mode 100644
index a71b3bc..0000000
--- a/src/core/security/security_context.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- *
- * 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 <string.h>
-
-#include "src/core/security/security_context.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/call.h"
-#include "src/core/support/string.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/security/security_context.h b/src/core/security/security_context.h
deleted file mode 100644
index 61601f5..0000000
--- a/src/core/security/security_context.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SECURITY_SECURITY_CONTEXT_H
-#define GRPC_CORE_SECURITY_SECURITY_CONTEXT_H
-
-#include "src/core/iomgr/pollset.h"
-#include "src/core/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_SECURITY_SECURITY_CONTEXT_H */
diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c
deleted file mode 100644
index 3d8e5e8..0000000
--- a/src/core/security/server_auth_filter.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- *
- * 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 <string.h>
-
-#include "src/core/security/auth_filters.h"
-#include "src/core/security/credentials.h"
-#include "src/core/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;
-}
-
-static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                        grpc_pollset *pollset) {}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {}
-
-/* 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, set_pollset, destroy_call_elem, sizeof(channel_data),
-    init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
-    "server-auth"};
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
deleted file mode 100644
index 009ec95..0000000
--- a/src/core/security/server_secure_chttp2.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- *
- * 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 <grpc/grpc.h>
-
-#include <string.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/tcp_server.h"
-#include "src/core/security/auth_filters.h"
-#include "src/core/security/credentials.h"
-#include "src/core/security/security_connector.h"
-#include "src/core/security/security_context.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/useful.h>
-
-typedef struct grpc_server_secure_state {
-  grpc_server *server;
-  grpc_tcp_server *tcp;
-  grpc_server_security_connector *sc;
-  grpc_server_credentials *creds;
-  int is_shutdown;
-  gpr_mu mu;
-  gpr_refcount refcount;
-  grpc_closure destroy_closure;
-  grpc_closure *destroy_callback;
-} grpc_server_secure_state;
-
-static void state_ref(grpc_server_secure_state *state) {
-  gpr_ref(&state->refcount);
-}
-
-static void state_unref(grpc_server_secure_state *state) {
-  if (gpr_unref(&state->refcount)) {
-    /* ensure all threads have unlocked */
-    gpr_mu_lock(&state->mu);
-    gpr_mu_unlock(&state->mu);
-    /* clean up */
-    GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server");
-    grpc_server_credentials_unref(state->creds);
-    gpr_free(state);
-  }
-}
-
-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;
-  grpc_transport *transport;
-  if (status == GRPC_SECURITY_OK) {
-    if (secure_endpoint) {
-      gpr_mu_lock(&state->mu);
-      if (!state->is_shutdown) {
-        transport = grpc_create_chttp2_transport(
-            exec_ctx, grpc_server_get_channel_args(state->server),
-            secure_endpoint, 0);
-        setup_transport(exec_ctx, state, transport, auth_context);
-        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);
-    }
-  } else {
-    gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
-  }
-  state_unref(state);
-}
-
-static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
-                      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 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;
-  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;
-  if (state->destroy_callback != NULL) {
-    state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
-                                success);
-  }
-  grpc_server_security_connector_shutdown(exec_ctx, state->sc);
-  state_unref(state);
-}
-
-/* Server callback: destroy the tcp listener (so we don't generate further
-   callbacks) */
-static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
-                    grpc_closure *callback) {
-  grpc_server_secure_state *state = statep;
-  grpc_tcp_server *tcp;
-  gpr_mu_lock(&state->mu);
-  state->is_shutdown = 1;
-  state->destroy_callback = callback;
-  tcp = state->tcp;
-  gpr_mu_unlock(&state->mu);
-  grpc_tcp_server_unref(exec_ctx, tcp);
-}
-
-int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
-                                      grpc_server_credentials *creds) {
-  grpc_resolved_addresses *resolved = NULL;
-  grpc_tcp_server *tcp = NULL;
-  grpc_server_secure_state *state = NULL;
-  size_t i;
-  unsigned count = 0;
-  int port_num = -1;
-  int port_temp;
-  grpc_security_status status = GRPC_SECURITY_ERROR;
-  grpc_server_security_connector *sc = NULL;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_API_TRACE(
-      "grpc_server_add_secure_http2_port("
-      "server=%p, addr=%s, creds=%p)",
-      3, (server, addr, creds));
-
-  /* create security context */
-  if (creds == NULL) goto error;
-  status = grpc_server_credentials_create_security_connector(creds, &sc);
-  if (status != GRPC_SECURITY_OK) {
-    gpr_log(GPR_ERROR,
-            "Unable to create secure server with credentials of type %s.",
-            creds->type);
-    goto error;
-  }
-  sc->channel_args = grpc_server_get_channel_args(server);
-
-  /* resolve address */
-  resolved = grpc_blocking_resolve_address(addr, "https");
-  if (!resolved) {
-    goto error;
-  }
-  state = gpr_malloc(sizeof(*state));
-  memset(state, 0, sizeof(*state));
-  grpc_closure_init(&state->destroy_closure, destroy_done, state);
-  tcp = grpc_tcp_server_create(&state->destroy_closure);
-  if (!tcp) {
-    goto error;
-  }
-
-  state->server = server;
-  state->tcp = tcp;
-  state->sc = sc;
-  state->creds = grpc_server_credentials_ref(creds);
-  state->is_shutdown = 0;
-  gpr_mu_init(&state->mu);
-  gpr_ref_init(&state->refcount, 1);
-
-  for (i = 0; i < resolved->naddrs; i++) {
-    port_temp = grpc_tcp_server_add_port(
-        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
-        resolved->addrs[i].len);
-    if (port_temp > 0) {
-      if (port_num == -1) {
-        port_num = port_temp;
-      } else {
-        GPR_ASSERT(port_num == port_temp);
-      }
-      count++;
-    }
-  }
-  if (count == 0) {
-    gpr_log(GPR_ERROR, "No address added out of total %d resolved",
-            resolved->naddrs);
-    goto error;
-  }
-  if (count != resolved->naddrs) {
-    gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved",
-            count, resolved->naddrs);
-    /* if it's an error, don't we want to goto error; here ? */
-  }
-  grpc_resolved_addresses_destroy(resolved);
-
-  /* Register with the server only upon success */
-  grpc_server_add_listener(&exec_ctx, server, state, start, destroy);
-
-  grpc_exec_ctx_finish(&exec_ctx);
-  return port_num;
-
-/* Error path: cleanup and return */
-error:
-  if (resolved) {
-    grpc_resolved_addresses_destroy(resolved);
-  }
-  if (tcp) {
-    grpc_tcp_server_unref(&exec_ctx, tcp);
-  } else {
-    if (sc) {
-      GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server");
-    }
-    if (state) {
-      gpr_free(state);
-    }
-  }
-  grpc_exec_ctx_finish(&exec_ctx);
-  return 0;
-}
diff --git a/src/core/statistics/census_init.c b/src/core/statistics/census_init.c
deleted file mode 100644
index b6a962f..0000000
--- a/src/core/statistics/census_init.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * 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/statistics/census_interface.h"
-
-#include <grpc/support/log.h>
-#include "src/core/statistics/census_rpc_stats.h"
-#include "src/core/statistics/census_tracing.h"
-
-void census_init(void) {
-  census_tracing_init();
-  census_stats_store_init();
-}
-
-void census_shutdown(void) {
-  census_stats_store_shutdown();
-  census_tracing_shutdown();
-}
diff --git a/src/core/statistics/census_interface.h b/src/core/statistics/census_interface.h
deleted file mode 100644
index ce8ff92..0000000
--- a/src/core/statistics/census_interface.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_STATISTICS_CENSUS_INTERFACE_H
-#define GRPC_CORE_STATISTICS_CENSUS_INTERFACE_H
-
-#include <grpc/support/port_platform.h>
-
-/* Maximum length of an individual census trace annotation. */
-#define CENSUS_MAX_ANNOTATION_LENGTH 200
-
-/* Structure of a census op id. Define as structure because 64bit integer is not
-   available on every platform for C89. */
-typedef struct census_op_id {
-  uint32_t upper;
-  uint32_t lower;
-} census_op_id;
-
-typedef struct census_rpc_stats census_rpc_stats;
-
-/* Initializes Census library. No-op if Census is already initialized. */
-void census_init(void);
-
-/* Shutdown Census Library. */
-void census_shutdown(void);
-
-/* Annotates grpc method name on a census_op_id. The method name has the format
-   of <full quantified rpc service name>/<rpc function name>. Returns 0 iff
-   op_id and method_name are all valid. op_id is valid after its creation and
-   before calling census_tracing_end_op().
-
-   TODO(hongyu): Figure out valid characters set for service name and command
-   name and document requirements here.*/
-int census_add_method_tag(census_op_id op_id, const char *method_name);
-
-/* Annotates tracing information to a specific op_id.
-   Up to CENSUS_MAX_ANNOTATION_LENGTH bytes are recorded. */
-void census_tracing_print(census_op_id op_id, const char *annotation);
-
-/* Starts tracing for an RPC. Returns a locally unique census_op_id */
-census_op_id census_tracing_start_op(void);
-
-/* Ends tracing. Calling this function will invalidate the input op_id. */
-void census_tracing_end_op(census_op_id op_id);
-
-#endif /* GRPC_CORE_STATISTICS_CENSUS_INTERFACE_H */
diff --git a/src/core/statistics/census_log.c b/src/core/statistics/census_log.c
deleted file mode 100644
index 257ba58..0000000
--- a/src/core/statistics/census_log.c
+++ /dev/null
@@ -1,603 +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.
- *
- */
-
-/* Available log space is divided up in blocks of
-   CENSUS_LOG_2_MAX_RECORD_SIZE bytes. A block can be in one of the
-   following three data structures:
-   - Free blocks (free_block_list)
-   - Blocks with unread data (dirty_block_list)
-   - Blocks currently attached to cores (core_local_blocks[])
-
-   census_log_start_write() moves a block from core_local_blocks[] to the
-   end of dirty_block_list when block:
-   - is out-of-space OR
-   - has an incomplete record (an incomplete record occurs when a thread calls
-     census_log_start_write() and is context-switched before calling
-     census_log_end_write()
-   So, blocks in dirty_block_list are ordered, from oldest to newest, by time
-   when block is detached from the core.
-
-   census_log_read_next() first iterates over dirty_block_list and then
-   core_local_blocks[]. It moves completely read blocks from dirty_block_list
-   to free_block_list. Blocks in core_local_blocks[] are not freed, even when
-   completely read.
-
-   If log is configured to discard old records and free_block_list is empty,
-   census_log_start_write() iterates over dirty_block_list to allocate a
-   new block. It moves the oldest available block (no pending read/write) to
-   core_local_blocks[].
-
-   core_local_block_struct is used to implement a map from core id to the block
-   associated with that core. This mapping is advisory. It is possible that the
-   block returned by this mapping is no longer associated with that core. This
-   mapping is updated, lazily, by census_log_start_write().
-
-   Locking in block struct:
-
-   Exclusive g_log.lock must be held before calling any functions operatong on
-   block structs except census_log_start_write() and
-   census_log_end_write().
-
-   Writes to a block are serialized via writer_lock.
-   census_log_start_write() acquires this lock and
-   census_log_end_write() releases it. On failure to acquire the lock,
-   writer allocates a new block for the current core and updates
-   core_local_block accordingly.
-
-   Simultaneous read and write access is allowed. Reader can safely read up to
-   committed bytes (bytes_committed).
-
-   reader_lock protects the block, currently being read, from getting recycled.
-   start_read() acquires reader_lock and end_read() releases the lock.
-
-   Read/write access to a block is disabled via try_disable_access(). It returns
-   with both writer_lock and reader_lock held. These locks are subsequently
-   released by enable_access() to enable access to the block.
-
-   A note on naming: Most function/struct names are prepended by cl_
-   (shorthand for census_log). Further, functions that manipulate structures
-   include the name of the structure, which will be passed as the first
-   argument. E.g. cl_block_initialize() will initialize a cl_block.
-*/
-#include "src/core/statistics/census_log.h"
-#include <string.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/cpu.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/useful.h>
-
-/* End of platform specific code */
-
-typedef struct census_log_block_list_struct {
-  struct census_log_block_list_struct *next;
-  struct census_log_block_list_struct *prev;
-  struct census_log_block *block;
-} cl_block_list_struct;
-
-typedef struct census_log_block {
-  /* Pointer to underlying buffer */
-  char *buffer;
-  gpr_atm writer_lock;
-  gpr_atm reader_lock;
-  /* Keeps completely written bytes. Declared atomic because accessed
-     simultaneously by reader and writer. */
-  gpr_atm bytes_committed;
-  /* Bytes already read */
-  int32_t bytes_read;
-  /* Links for list */
-  cl_block_list_struct link;
-/* We want this structure to be cacheline aligned. We assume the following
-   sizes for the various parts on 32/64bit systems:
-   type                 32b size    64b size
-   char*                   4           8
-   3x gpr_atm             12          24
-   int32_t               4           8 (assumes padding)
-   cl_block_list_struct   12          24
-   TOTAL                  32          64
-
-   Depending on the size of our cacheline and the architecture, we
-   selectively add char buffering to this structure. The size is checked
-   via assert in census_log_initialize(). */
-#if defined(GPR_ARCH_64)
-#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 64)
-#else
-#if defined(GPR_ARCH_32)
-#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 32)
-#else
-#error "Unknown architecture"
-#endif
-#endif
-#if CL_BLOCK_PAD_SIZE > 0
-  char padding[CL_BLOCK_PAD_SIZE];
-#endif
-} cl_block;
-
-/* A list of cl_blocks, doubly-linked through cl_block::link. */
-typedef struct census_log_block_list {
-  int32_t count;           /* Number of items in list. */
-  cl_block_list_struct ht; /* head/tail of linked list. */
-} cl_block_list;
-
-/* Cacheline aligned block pointers to avoid false sharing. Block pointer must
-   be initialized via set_block(), before calling other functions */
-typedef struct census_log_core_local_block {
-  gpr_atm block;
-/* Ensure cachline alignment: we assume sizeof(gpr_atm) == 4 or 8 */
-#if defined(GPR_ARCH_64)
-#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 8)
-#else
-#if defined(GPR_ARCH_32)
-#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 4)
-#else
-#error "Unknown architecture"
-#endif
-#endif
-#if CL_CORE_LOCAL_BLOCK_PAD_SIZE > 0
-  char padding[CL_CORE_LOCAL_BLOCK_PAD_SIZE];
-#endif
-} cl_core_local_block;
-
-struct census_log {
-  int discard_old_records;
-  /* Number of cores (aka hardware-contexts) */
-  unsigned num_cores;
-  /* number of CENSUS_LOG_2_MAX_RECORD_SIZE blocks in log */
-  int32_t num_blocks;
-  cl_block *blocks;                       /* Block metadata. */
-  cl_core_local_block *core_local_blocks; /* Keeps core to block mappings. */
-  gpr_mu lock;
-  int initialized; /* has log been initialized? */
-  /* Keeps the state of the reader iterator. A value of 0 indicates that
-     iterator has reached the end. census_log_init_reader() resets the
-     value to num_core to restart iteration. */
-  uint32_t read_iterator_state;
-  /* Points to the block being read. If non-NULL, the block is locked for
-     reading (block_being_read_->reader_lock is held). */
-  cl_block *block_being_read;
-  /* A non-zero value indicates that log is full. */
-  gpr_atm is_full;
-  char *buffer;
-  cl_block_list free_block_list;
-  cl_block_list dirty_block_list;
-  gpr_atm out_of_space_count;
-};
-
-/* Single internal log */
-static struct census_log g_log;
-
-/* Functions that operate on an atomic memory location used as a lock */
-
-/* Returns non-zero if lock is acquired */
-static int cl_try_lock(gpr_atm *lock) { return gpr_atm_acq_cas(lock, 0, 1); }
-
-static void cl_unlock(gpr_atm *lock) { gpr_atm_rel_store(lock, 0); }
-
-/* Functions that operate on cl_core_local_block's */
-
-static void cl_core_local_block_set_block(cl_core_local_block *clb,
-                                          cl_block *block) {
-  gpr_atm_rel_store(&clb->block, (gpr_atm)block);
-}
-
-static cl_block *cl_core_local_block_get_block(cl_core_local_block *clb) {
-  return (cl_block *)gpr_atm_acq_load(&clb->block);
-}
-
-/* Functions that operate on cl_block_list_struct's */
-
-static void cl_block_list_struct_initialize(cl_block_list_struct *bls,
-                                            cl_block *block) {
-  bls->next = bls->prev = bls;
-  bls->block = block;
-}
-
-/* Functions that operate on cl_block_list's */
-
-static void cl_block_list_initialize(cl_block_list *list) {
-  list->count = 0;
-  cl_block_list_struct_initialize(&list->ht, NULL);
-}
-
-/* Returns head of *this, or NULL if empty. */
-static cl_block *cl_block_list_head(cl_block_list *list) {
-  return list->ht.next->block;
-}
-
-/* Insert element *e after *pos. */
-static void cl_block_list_insert(cl_block_list *list, cl_block_list_struct *pos,
-                                 cl_block_list_struct *e) {
-  list->count++;
-  e->next = pos->next;
-  e->prev = pos;
-  e->next->prev = e;
-  e->prev->next = e;
-}
-
-/* Insert block at the head of the list */
-static void cl_block_list_insert_at_head(cl_block_list *list, cl_block *block) {
-  cl_block_list_insert(list, &list->ht, &block->link);
-}
-
-/* Insert block at the tail of the list */
-static void cl_block_list_insert_at_tail(cl_block_list *list, cl_block *block) {
-  cl_block_list_insert(list, list->ht.prev, &block->link);
-}
-
-/* Removes block *b. Requires *b be in the list. */
-static void cl_block_list_remove(cl_block_list *list, cl_block *b) {
-  list->count--;
-  b->link.next->prev = b->link.prev;
-  b->link.prev->next = b->link.next;
-}
-
-/* Functions that operate on cl_block's */
-
-static void cl_block_initialize(cl_block *block, char *buffer) {
-  block->buffer = buffer;
-  gpr_atm_rel_store(&block->writer_lock, 0);
-  gpr_atm_rel_store(&block->reader_lock, 0);
-  gpr_atm_rel_store(&block->bytes_committed, 0);
-  block->bytes_read = 0;
-  cl_block_list_struct_initialize(&block->link, block);
-}
-
-/* Guards against exposing partially written buffer to the reader. */
-static void cl_block_set_bytes_committed(cl_block *block,
-                                         int32_t bytes_committed) {
-  gpr_atm_rel_store(&block->bytes_committed, bytes_committed);
-}
-
-static int32_t cl_block_get_bytes_committed(cl_block *block) {
-  return gpr_atm_acq_load(&block->bytes_committed);
-}
-
-/* Tries to disable future read/write access to this block. Succeeds if:
-   - no in-progress write AND
-   - no in-progress read AND
-   - 'discard_data' set to true OR no unread data
-   On success, clears the block state and returns with writer_lock_ and
-   reader_lock_ held. These locks are released by a subsequent
-   cl_block_access_enable() call. */
-static int cl_block_try_disable_access(cl_block *block, int discard_data) {
-  if (!cl_try_lock(&block->writer_lock)) {
-    return 0;
-  }
-  if (!cl_try_lock(&block->reader_lock)) {
-    cl_unlock(&block->writer_lock);
-    return 0;
-  }
-  if (!discard_data &&
-      (block->bytes_read != cl_block_get_bytes_committed(block))) {
-    cl_unlock(&block->reader_lock);
-    cl_unlock(&block->writer_lock);
-    return 0;
-  }
-  cl_block_set_bytes_committed(block, 0);
-  block->bytes_read = 0;
-  return 1;
-}
-
-static void cl_block_enable_access(cl_block *block) {
-  cl_unlock(&block->reader_lock);
-  cl_unlock(&block->writer_lock);
-}
-
-/* Returns with writer_lock held. */
-static void *cl_block_start_write(cl_block *block, size_t size) {
-  int32_t bytes_committed;
-  if (!cl_try_lock(&block->writer_lock)) {
-    return NULL;
-  }
-  bytes_committed = cl_block_get_bytes_committed(block);
-  if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) {
-    cl_unlock(&block->writer_lock);
-    return NULL;
-  }
-  return block->buffer + bytes_committed;
-}
-
-/* Releases writer_lock and increments committed bytes by 'bytes_written'.
-  'bytes_written' must be <= 'size' specified in the corresponding
-  StartWrite() call. This function is thread-safe. */
-static void cl_block_end_write(cl_block *block, size_t bytes_written) {
-  cl_block_set_bytes_committed(
-      block, cl_block_get_bytes_committed(block) + bytes_written);
-  cl_unlock(&block->writer_lock);
-}
-
-/* Returns a pointer to the first unread byte in buffer. The number of bytes
-   available are returned in 'bytes_available'. Acquires reader lock that is
-   released by a subsequent cl_block_end_read() call. Returns NULL if:
-   - read in progress
-   - no data available */
-static void *cl_block_start_read(cl_block *block, size_t *bytes_available) {
-  void *record;
-  if (!cl_try_lock(&block->reader_lock)) {
-    return NULL;
-  }
-  /* bytes_committed may change from under us. Use bytes_available to update
-     bytes_read below. */
-  *bytes_available = cl_block_get_bytes_committed(block) - block->bytes_read;
-  if (*bytes_available == 0) {
-    cl_unlock(&block->reader_lock);
-    return NULL;
-  }
-  record = block->buffer + block->bytes_read;
-  block->bytes_read += *bytes_available;
-  return record;
-}
-
-static void cl_block_end_read(cl_block *block) {
-  cl_unlock(&block->reader_lock);
-}
-
-/* Internal functions operating on g_log */
-
-/* Allocates a new free block (or recycles an available dirty block if log is
-   configured to discard old records). Returns NULL if out-of-space. */
-static cl_block *cl_allocate_block(void) {
-  cl_block *block = cl_block_list_head(&g_log.free_block_list);
-  if (block != NULL) {
-    cl_block_list_remove(&g_log.free_block_list, block);
-    return block;
-  }
-  if (!g_log.discard_old_records) {
-    /* No free block and log is configured to keep old records. */
-    return NULL;
-  }
-  /* Recycle dirty block. Start from the oldest. */
-  for (block = cl_block_list_head(&g_log.dirty_block_list); block != NULL;
-       block = block->link.next->block) {
-    if (cl_block_try_disable_access(block, 1 /* discard data */)) {
-      cl_block_list_remove(&g_log.dirty_block_list, block);
-      return block;
-    }
-  }
-  return NULL;
-}
-
-/* Allocates a new block and updates core id => block mapping. 'old_block'
-   points to the block that the caller thinks is attached to
-   'core_id'. 'old_block' may be NULL. Returns non-zero if:
-   - allocated a new block OR
-   - 'core_id' => 'old_block' mapping changed (another thread allocated a
-     block before lock was acquired). */
-static int cl_allocate_core_local_block(int32_t core_id, cl_block *old_block) {
-  /* Now that we have the lock, check if core-local mapping has changed. */
-  cl_core_local_block *core_local_block = &g_log.core_local_blocks[core_id];
-  cl_block *block = cl_core_local_block_get_block(core_local_block);
-  if ((block != NULL) && (block != old_block)) {
-    return 1;
-  }
-  if (block != NULL) {
-    cl_core_local_block_set_block(core_local_block, NULL);
-    cl_block_list_insert_at_tail(&g_log.dirty_block_list, block);
-  }
-  block = cl_allocate_block();
-  if (block == NULL) {
-    gpr_atm_rel_store(&g_log.is_full, 1);
-    return 0;
-  }
-  cl_core_local_block_set_block(core_local_block, block);
-  cl_block_enable_access(block);
-  return 1;
-}
-
-static cl_block *cl_get_block(void *record) {
-  uintptr_t p = (uintptr_t)((char *)record - g_log.buffer);
-  uintptr_t index = p >> CENSUS_LOG_2_MAX_RECORD_SIZE;
-  return &g_log.blocks[index];
-}
-
-/* Gets the next block to read and tries to free 'prev' block (if not NULL).
-   Returns NULL if reached the end. */
-static cl_block *cl_next_block_to_read(cl_block *prev) {
-  cl_block *block = NULL;
-  if (g_log.read_iterator_state == g_log.num_cores) {
-    /* We are traversing dirty list; find the next dirty block. */
-    if (prev != NULL) {
-      /* Try to free the previous block if there is no unread data. This block
-         may have unread data if previously incomplete record completed between
-         read_next() calls. */
-      block = prev->link.next->block;
-      if (cl_block_try_disable_access(prev, 0 /* do not discard data */)) {
-        cl_block_list_remove(&g_log.dirty_block_list, prev);
-        cl_block_list_insert_at_head(&g_log.free_block_list, prev);
-        gpr_atm_rel_store(&g_log.is_full, 0);
-      }
-    } else {
-      block = cl_block_list_head(&g_log.dirty_block_list);
-    }
-    if (block != NULL) {
-      return block;
-    }
-    /* We are done with the dirty list; moving on to core-local blocks. */
-  }
-  while (g_log.read_iterator_state > 0) {
-    g_log.read_iterator_state--;
-    block = cl_core_local_block_get_block(
-        &g_log.core_local_blocks[g_log.read_iterator_state]);
-    if (block != NULL) {
-      return block;
-    }
-  }
-  return NULL;
-}
-
-/* External functions: primary stats_log interface */
-void census_log_initialize(size_t size_in_mb, int discard_old_records) {
-  int32_t ix;
-  /* Check cacheline alignment. */
-  GPR_ASSERT(sizeof(cl_block) % GPR_CACHELINE_SIZE == 0);
-  GPR_ASSERT(sizeof(cl_core_local_block) % GPR_CACHELINE_SIZE == 0);
-  GPR_ASSERT(!g_log.initialized);
-  g_log.discard_old_records = discard_old_records;
-  g_log.num_cores = gpr_cpu_num_cores();
-  /* Ensure at least as many blocks as there are cores. */
-  g_log.num_blocks = GPR_MAX(
-      g_log.num_cores, (size_in_mb << 20) >> CENSUS_LOG_2_MAX_RECORD_SIZE);
-  gpr_mu_init(&g_log.lock);
-  g_log.read_iterator_state = 0;
-  g_log.block_being_read = NULL;
-  gpr_atm_rel_store(&g_log.is_full, 0);
-  g_log.core_local_blocks = (cl_core_local_block *)gpr_malloc_aligned(
-      g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG);
-  memset(g_log.core_local_blocks, 0,
-         g_log.num_cores * sizeof(cl_core_local_block));
-  g_log.blocks = (cl_block *)gpr_malloc_aligned(
-      g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG);
-  memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block));
-  g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
-  memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
-  cl_block_list_initialize(&g_log.free_block_list);
-  cl_block_list_initialize(&g_log.dirty_block_list);
-  for (ix = 0; ix < g_log.num_blocks; ++ix) {
-    cl_block *block = g_log.blocks + ix;
-    cl_block_initialize(block,
-                        g_log.buffer + (CENSUS_LOG_MAX_RECORD_SIZE * ix));
-    cl_block_try_disable_access(block, 1 /* discard data */);
-    cl_block_list_insert_at_tail(&g_log.free_block_list, block);
-  }
-  gpr_atm_rel_store(&g_log.out_of_space_count, 0);
-  g_log.initialized = 1;
-}
-
-void census_log_shutdown(void) {
-  GPR_ASSERT(g_log.initialized);
-  gpr_mu_destroy(&g_log.lock);
-  gpr_free_aligned(g_log.core_local_blocks);
-  g_log.core_local_blocks = NULL;
-  gpr_free_aligned(g_log.blocks);
-  g_log.blocks = NULL;
-  gpr_free(g_log.buffer);
-  g_log.buffer = NULL;
-  g_log.initialized = 0;
-}
-
-void *census_log_start_write(size_t size) {
-  /* Used to bound number of times block allocation is attempted. */
-  int32_t attempts_remaining = g_log.num_blocks;
-  /* TODO(aveitch): move this inside the do loop when current_cpu is fixed */
-  int32_t core_id = gpr_cpu_current_cpu();
-  GPR_ASSERT(g_log.initialized);
-  if (size > CENSUS_LOG_MAX_RECORD_SIZE) {
-    return NULL;
-  }
-  do {
-    int allocated;
-    void *record = NULL;
-    cl_block *block =
-        cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]);
-    if (block && (record = cl_block_start_write(block, size))) {
-      return record;
-    }
-    /* Need to allocate a new block. We are here if:
-       - No block associated with the core OR
-       - Write in-progress on the block OR
-       - block is out of space */
-    if (gpr_atm_acq_load(&g_log.is_full)) {
-      gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
-      return NULL;
-    }
-    gpr_mu_lock(&g_log.lock);
-    allocated = cl_allocate_core_local_block(core_id, block);
-    gpr_mu_unlock(&g_log.lock);
-    if (!allocated) {
-      gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
-      return NULL;
-    }
-  } while (attempts_remaining--);
-  /* Give up. */
-  gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
-  return NULL;
-}
-
-void census_log_end_write(void *record, size_t bytes_written) {
-  GPR_ASSERT(g_log.initialized);
-  cl_block_end_write(cl_get_block(record), bytes_written);
-}
-
-void census_log_init_reader(void) {
-  GPR_ASSERT(g_log.initialized);
-  gpr_mu_lock(&g_log.lock);
-  /* If a block is locked for reading unlock it. */
-  if (g_log.block_being_read != NULL) {
-    cl_block_end_read(g_log.block_being_read);
-    g_log.block_being_read = NULL;
-  }
-  g_log.read_iterator_state = g_log.num_cores;
-  gpr_mu_unlock(&g_log.lock);
-}
-
-const void *census_log_read_next(size_t *bytes_available) {
-  GPR_ASSERT(g_log.initialized);
-  gpr_mu_lock(&g_log.lock);
-  if (g_log.block_being_read != NULL) {
-    cl_block_end_read(g_log.block_being_read);
-  }
-  do {
-    g_log.block_being_read = cl_next_block_to_read(g_log.block_being_read);
-    if (g_log.block_being_read != NULL) {
-      void *record =
-          cl_block_start_read(g_log.block_being_read, bytes_available);
-      if (record != NULL) {
-        gpr_mu_unlock(&g_log.lock);
-        return record;
-      }
-    }
-  } while (g_log.block_being_read != NULL);
-  gpr_mu_unlock(&g_log.lock);
-  return NULL;
-}
-
-size_t census_log_remaining_space(void) {
-  size_t space;
-  GPR_ASSERT(g_log.initialized);
-  gpr_mu_lock(&g_log.lock);
-  if (g_log.discard_old_records) {
-    /* Remaining space is not meaningful; just return the entire log space. */
-    space = g_log.num_blocks << CENSUS_LOG_2_MAX_RECORD_SIZE;
-  } else {
-    space = g_log.free_block_list.count * CENSUS_LOG_MAX_RECORD_SIZE;
-  }
-  gpr_mu_unlock(&g_log.lock);
-  return space;
-}
-
-int census_log_out_of_space_count(void) {
-  GPR_ASSERT(g_log.initialized);
-  return gpr_atm_acq_load(&g_log.out_of_space_count);
-}
diff --git a/src/core/statistics/census_log.h b/src/core/statistics/census_log.h
deleted file mode 100644
index e7ce0d4..0000000
--- a/src/core/statistics/census_log.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_STATISTICS_CENSUS_LOG_H
-#define GRPC_CORE_STATISTICS_CENSUS_LOG_H
-
-#include <stddef.h>
-
-/* Maximum record size, in bytes. */
-#define CENSUS_LOG_2_MAX_RECORD_SIZE 14 /* 2^14 = 16KB */
-#define CENSUS_LOG_MAX_RECORD_SIZE (1 << CENSUS_LOG_2_MAX_RECORD_SIZE)
-
-/* Initialize the statistics logging subsystem with the given log size. A log
-   size of 0 will result in the smallest possible log for the platform
-   (approximately CENSUS_LOG_MAX_RECORD_SIZE * gpr_cpu_num_cores()). If
-   discard_old_records is non-zero, then new records will displace older ones
-   when the log is full. This function must be called before any other
-   census_log functions.
-*/
-void census_log_initialize(size_t size_in_mb, int discard_old_records);
-
-/* Shutdown the logging subsystem. Caller must ensure that:
-   - no in progress or future call to any census_log functions
-   - no incomplete records
-*/
-void census_log_shutdown(void);
-
-/* Allocates and returns a 'size' bytes record and marks it in use. A
-   subsequent census_log_end_write() marks the record complete. The
-   'bytes_written' census_log_end_write() argument must be <=
-   'size'. Returns NULL if out-of-space AND:
-       - log is configured to keep old records OR
-       - all blocks are pinned by incomplete records.
-*/
-void *census_log_start_write(size_t size);
-
-void census_log_end_write(void *record, size_t bytes_written);
-
-/* census_log_read_next() iterates over blocks with data and for each block
-   returns a pointer to the first unread byte. The number of bytes that can be
-   read are returned in 'bytes_available'. Reader is expected to read all
-   available data. Reading the data consumes it i.e. it cannot be read again.
-   census_log_read_next() returns NULL if the end is reached i.e last block
-   is read. census_log_init_reader() starts the iteration or aborts the
-   current iteration.
-*/
-void census_log_init_reader(void);
-const void *census_log_read_next(size_t *bytes_available);
-
-/* Returns estimated remaining space across all blocks, in bytes. If log is
-   configured to discard old records, returns total log space. Otherwise,
-   returns space available in empty blocks (partially filled blocks are
-   treated as full).
-*/
-size_t census_log_remaining_space(void);
-
-/* Returns the number of times gprc_stats_log_start_write() failed due to
-   out-of-space. */
-int census_log_out_of_space_count(void);
-
-#endif /* GRPC_CORE_STATISTICS_CENSUS_LOG_H */
diff --git a/src/core/statistics/census_rpc_stats.c b/src/core/statistics/census_rpc_stats.c
deleted file mode 100644
index 524a607..0000000
--- a/src/core/statistics/census_rpc_stats.c
+++ /dev/null
@@ -1,253 +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/statistics/census_interface.h"
-#include "src/core/statistics/census_rpc_stats.h"
-#include "src/core/statistics/hash_table.h"
-#include "src/core/statistics/census_tracing.h"
-#include "src/core/statistics/window_stats.h"
-#include "src/core/support/murmur_hash.h"
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-
-#define NUM_INTERVALS 3
-#define MINUTE_INTERVAL 0
-#define HOUR_INTERVAL 1
-#define TOTAL_INTERVAL 2
-
-/* for easier typing */
-typedef census_per_method_rpc_stats per_method_stats;
-
-/* Ensure mu is only initialized once. */
-static gpr_once g_stats_store_mu_init = GPR_ONCE_INIT;
-/* Guards two stats stores. */
-static gpr_mu g_mu;
-static census_ht *g_client_stats_store = NULL;
-static census_ht *g_server_stats_store = NULL;
-
-static void init_mutex(void) { gpr_mu_init(&g_mu); }
-
-static void init_mutex_once(void) {
-  gpr_once_init(&g_stats_store_mu_init, init_mutex);
-}
-
-static int cmp_str_keys(const void *k1, const void *k2) {
-  return strcmp((const char *)k1, (const char *)k2);
-}
-
-/* TODO(hongyu): replace it with cityhash64 */
-static uint64_t simple_hash(const void *k) {
-  size_t len = strlen(k);
-  uint64_t higher = gpr_murmur_hash3((const char *)k, len / 2, 0);
-  return higher << 32 |
-         gpr_murmur_hash3((const char *)k + len / 2, len - len / 2, 0);
-}
-
-static void delete_stats(void *stats) {
-  census_window_stats_destroy((struct census_window_stats *)stats);
-}
-
-static void delete_key(void *key) { gpr_free(key); }
-
-static const census_ht_option ht_opt = {
-    CENSUS_HT_POINTER /* key type */, 1999 /* n_of_buckets */,
-    simple_hash /* hash function */, cmp_str_keys /* key comparator */,
-    delete_stats /* data deleter */, delete_key /* key deleter */
-};
-
-static void init_rpc_stats(void *stats) {
-  memset(stats, 0, sizeof(census_rpc_stats));
-}
-
-static void stat_add_proportion(double p, void *base, const void *addme) {
-  census_rpc_stats *b = (census_rpc_stats *)base;
-  census_rpc_stats *a = (census_rpc_stats *)addme;
-  b->cnt += p * a->cnt;
-  b->rpc_error_cnt += p * a->rpc_error_cnt;
-  b->app_error_cnt += p * a->app_error_cnt;
-  b->elapsed_time_ms += p * a->elapsed_time_ms;
-  b->api_request_bytes += p * a->api_request_bytes;
-  b->wire_request_bytes += p * a->wire_request_bytes;
-  b->api_response_bytes += p * a->api_response_bytes;
-  b->wire_response_bytes += p * a->wire_response_bytes;
-}
-
-static void stat_add(void *base, const void *addme) {
-  stat_add_proportion(1.0, base, addme);
-}
-
-static gpr_timespec min_hour_total_intervals[3] = {
-    {60, 0}, {3600, 0}, {36000000, 0}};
-
-static const census_window_stats_stat_info window_stats_settings = {
-    sizeof(census_rpc_stats), init_rpc_stats, stat_add, stat_add_proportion};
-
-census_rpc_stats *census_rpc_stats_create_empty(void) {
-  census_rpc_stats *ret =
-      (census_rpc_stats *)gpr_malloc(sizeof(census_rpc_stats));
-  memset(ret, 0, sizeof(census_rpc_stats));
-  return ret;
-}
-
-void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats *data) {
-  int i = 0;
-  for (i = 0; i < data->num_entries; i++) {
-    if (data->stats[i].method != NULL) {
-      gpr_free((void *)data->stats[i].method);
-    }
-  }
-  if (data->stats != NULL) {
-    gpr_free(data->stats);
-  }
-  data->num_entries = 0;
-  data->stats = NULL;
-}
-
-static void record_stats(census_ht *store, census_op_id op_id,
-                         const census_rpc_stats *stats) {
-  gpr_mu_lock(&g_mu);
-  if (store != NULL) {
-    census_trace_obj *trace = NULL;
-    census_internal_lock_trace_store();
-    trace = census_get_trace_obj_locked(op_id);
-    if (trace != NULL) {
-      const char *method_name = census_get_trace_method_name(trace);
-      struct census_window_stats *window_stats = NULL;
-      census_ht_key key;
-      key.ptr = (void *)method_name;
-      window_stats = census_ht_find(store, key);
-      census_internal_unlock_trace_store();
-      if (window_stats == NULL) {
-        window_stats = census_window_stats_create(3, min_hour_total_intervals,
-                                                  30, &window_stats_settings);
-        key.ptr = gpr_strdup(key.ptr);
-        census_ht_insert(store, key, (void *)window_stats);
-      }
-      census_window_stats_add(window_stats, gpr_now(GPR_CLOCK_REALTIME), stats);
-    } else {
-      census_internal_unlock_trace_store();
-    }
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-void census_record_rpc_client_stats(census_op_id op_id,
-                                    const census_rpc_stats *stats) {
-  record_stats(g_client_stats_store, op_id, stats);
-}
-
-void census_record_rpc_server_stats(census_op_id op_id,
-                                    const census_rpc_stats *stats) {
-  record_stats(g_server_stats_store, op_id, stats);
-}
-
-/* Get stats from input stats store */
-static void get_stats(census_ht *store, census_aggregated_rpc_stats *data) {
-  GPR_ASSERT(data != NULL);
-  if (data->num_entries != 0) {
-    census_aggregated_rpc_stats_set_empty(data);
-  }
-  gpr_mu_lock(&g_mu);
-  if (store != NULL) {
-    size_t n;
-    unsigned i, j;
-    gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
-    census_ht_kv *kv = census_ht_get_all_elements(store, &n);
-    if (kv != NULL) {
-      data->num_entries = n;
-      data->stats =
-          (per_method_stats *)gpr_malloc(sizeof(per_method_stats) * n);
-      for (i = 0; i < n; i++) {
-        census_window_stats_sums sums[NUM_INTERVALS];
-        for (j = 0; j < NUM_INTERVALS; j++) {
-          sums[j].statistic = (void *)census_rpc_stats_create_empty();
-        }
-        data->stats[i].method = gpr_strdup(kv[i].k.ptr);
-        census_window_stats_get_sums(kv[i].v, now, sums);
-        data->stats[i].minute_stats =
-            *(census_rpc_stats *)sums[MINUTE_INTERVAL].statistic;
-        data->stats[i].hour_stats =
-            *(census_rpc_stats *)sums[HOUR_INTERVAL].statistic;
-        data->stats[i].total_stats =
-            *(census_rpc_stats *)sums[TOTAL_INTERVAL].statistic;
-        for (j = 0; j < NUM_INTERVALS; j++) {
-          gpr_free(sums[j].statistic);
-        }
-      }
-      gpr_free(kv);
-    }
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-void census_get_client_stats(census_aggregated_rpc_stats *data) {
-  get_stats(g_client_stats_store, data);
-}
-
-void census_get_server_stats(census_aggregated_rpc_stats *data) {
-  get_stats(g_server_stats_store, data);
-}
-
-void census_stats_store_init(void) {
-  init_mutex_once();
-  gpr_mu_lock(&g_mu);
-  if (g_client_stats_store == NULL && g_server_stats_store == NULL) {
-    g_client_stats_store = census_ht_create(&ht_opt);
-    g_server_stats_store = census_ht_create(&ht_opt);
-  } else {
-    gpr_log(GPR_ERROR, "Census stats store already initialized.");
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-void census_stats_store_shutdown(void) {
-  init_mutex_once();
-  gpr_mu_lock(&g_mu);
-  if (g_client_stats_store != NULL) {
-    census_ht_destroy(g_client_stats_store);
-    g_client_stats_store = NULL;
-  } else {
-    gpr_log(GPR_ERROR, "Census server stats store not initialized.");
-  }
-  if (g_server_stats_store != NULL) {
-    census_ht_destroy(g_server_stats_store);
-    g_server_stats_store = NULL;
-  } else {
-    gpr_log(GPR_ERROR, "Census client stats store not initialized.");
-  }
-  gpr_mu_unlock(&g_mu);
-}
diff --git a/src/core/statistics/census_rpc_stats.h b/src/core/statistics/census_rpc_stats.h
deleted file mode 100644
index 4cf17d2..0000000
--- a/src/core/statistics/census_rpc_stats.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_STATISTICS_CENSUS_RPC_STATS_H
-#define GRPC_CORE_STATISTICS_CENSUS_RPC_STATS_H
-
-#include "src/core/statistics/census_interface.h"
-#include <grpc/support/port_platform.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct census_rpc_stats {
-  uint64_t cnt;
-  uint64_t rpc_error_cnt;
-  uint64_t app_error_cnt;
-  double elapsed_time_ms;
-  double api_request_bytes;
-  double wire_request_bytes;
-  double api_response_bytes;
-  double wire_response_bytes;
-};
-
-/* Creates an empty rpc stats object on heap. */
-census_rpc_stats *census_rpc_stats_create_empty(void);
-
-typedef struct census_per_method_rpc_stats {
-  const char *method;
-  census_rpc_stats minute_stats; /* cumulative stats in the past minute */
-  census_rpc_stats hour_stats;   /* cumulative stats in the past hour */
-  census_rpc_stats total_stats;  /* cumulative stats from last gc */
-} census_per_method_rpc_stats;
-
-typedef struct census_aggregated_rpc_stats {
-  int num_entries;
-  census_per_method_rpc_stats *stats;
-} census_aggregated_rpc_stats;
-
-/* Initializes an aggregated rpc stats object to an empty state. */
-void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats *data);
-
-/* Records client side stats of a rpc. */
-void census_record_rpc_client_stats(census_op_id op_id,
-                                    const census_rpc_stats *stats);
-
-/* Records server side stats of a rpc. */
-void census_record_rpc_server_stats(census_op_id op_id,
-                                    const census_rpc_stats *stats);
-
-/* The following two functions are intended for inprocess query of
-   per-service per-method stats from grpc implementations. */
-
-/* Populates *data_map with server side aggregated per-service per-method
-   stats.
-   DO NOT CALL from outside of grpc code. */
-void census_get_server_stats(census_aggregated_rpc_stats *data_map);
-
-/* Populates *data_map with client side aggregated per-service per-method
-   stats.
-   DO NOT CALL from outside of grpc code. */
-void census_get_client_stats(census_aggregated_rpc_stats *data_map);
-
-void census_stats_store_init(void);
-void census_stats_store_shutdown(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_STATISTICS_CENSUS_RPC_STATS_H */
diff --git a/src/core/statistics/census_tracing.c b/src/core/statistics/census_tracing.c
deleted file mode 100644
index dc0f8a2..0000000
--- a/src/core/statistics/census_tracing.c
+++ /dev/null
@@ -1,238 +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/statistics/census_interface.h"
-#include "src/core/statistics/census_tracing.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "src/core/statistics/hash_table.h"
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/sync.h>
-
-void census_trace_obj_destroy(census_trace_obj *obj) {
-  census_trace_annotation *p = obj->annotations;
-  while (p != NULL) {
-    census_trace_annotation *next = p->next;
-    gpr_free(p);
-    p = next;
-  }
-  gpr_free(obj->method);
-  gpr_free(obj);
-}
-
-static void delete_trace_obj(void *obj) {
-  census_trace_obj_destroy((census_trace_obj *)obj);
-}
-
-static const census_ht_option ht_opt = {
-    CENSUS_HT_UINT64 /* key type */, 571 /* n_of_buckets */, NULL /* hash */,
-    NULL /* compare_keys */, delete_trace_obj /* delete data */,
-    NULL /* delete key */
-};
-
-static gpr_once g_init_mutex_once = GPR_ONCE_INIT;
-static gpr_mu g_mu; /* Guards following two static variables. */
-static census_ht *g_trace_store = NULL;
-static uint64_t g_id = 0;
-
-static census_ht_key op_id_as_key(census_op_id *id) {
-  return *(census_ht_key *)id;
-}
-
-static uint64_t op_id_2_uint64(census_op_id *id) {
-  uint64_t ret;
-  memcpy(&ret, id, sizeof(census_op_id));
-  return ret;
-}
-
-static void init_mutex(void) { gpr_mu_init(&g_mu); }
-
-static void init_mutex_once(void) {
-  gpr_once_init(&g_init_mutex_once, init_mutex);
-}
-
-census_op_id census_tracing_start_op(void) {
-  gpr_mu_lock(&g_mu);
-  {
-    census_trace_obj *ret = gpr_malloc(sizeof(census_trace_obj));
-    memset(ret, 0, sizeof(census_trace_obj));
-    g_id++;
-    memcpy(&ret->id, &g_id, sizeof(census_op_id));
-    ret->rpc_stats.cnt = 1;
-    ret->ts = gpr_now(GPR_CLOCK_REALTIME);
-    census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void *)ret);
-    gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id);
-    gpr_mu_unlock(&g_mu);
-    return ret->id;
-  }
-}
-
-int census_add_method_tag(census_op_id op_id, const char *method) {
-  int ret = 0;
-  census_trace_obj *trace = NULL;
-  gpr_mu_lock(&g_mu);
-  trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
-  if (trace == NULL) {
-    ret = 1;
-  } else {
-    trace->method = gpr_strdup(method);
-  }
-  gpr_mu_unlock(&g_mu);
-  return ret;
-}
-
-void census_tracing_print(census_op_id op_id, const char *anno_txt) {
-  census_trace_obj *trace = NULL;
-  gpr_mu_lock(&g_mu);
-  trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
-  if (trace != NULL) {
-    census_trace_annotation *anno = gpr_malloc(sizeof(census_trace_annotation));
-    anno->ts = gpr_now(GPR_CLOCK_REALTIME);
-    {
-      char *d = anno->txt;
-      const char *s = anno_txt;
-      int n = 0;
-      for (; n < CENSUS_MAX_ANNOTATION_LENGTH && *s != '\0'; ++n) {
-        *d++ = *s++;
-      }
-      *d = '\0';
-    }
-    anno->next = trace->annotations;
-    trace->annotations = anno;
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-void census_tracing_end_op(census_op_id op_id) {
-  census_trace_obj *trace = NULL;
-  gpr_mu_lock(&g_mu);
-  trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
-  if (trace != NULL) {
-    trace->rpc_stats.elapsed_time_ms = gpr_timespec_to_micros(
-        gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), trace->ts));
-    gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us",
-            op_id_2_uint64(&op_id), trace->method,
-            trace->rpc_stats.elapsed_time_ms);
-    census_ht_erase(g_trace_store, op_id_as_key(&op_id));
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-void census_tracing_init(void) {
-  init_mutex_once();
-  gpr_mu_lock(&g_mu);
-  if (g_trace_store == NULL) {
-    g_id = 1;
-    g_trace_store = census_ht_create(&ht_opt);
-  } else {
-    gpr_log(GPR_ERROR, "Census trace store already initialized.");
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-void census_tracing_shutdown(void) {
-  gpr_mu_lock(&g_mu);
-  if (g_trace_store != NULL) {
-    census_ht_destroy(g_trace_store);
-    g_trace_store = NULL;
-  } else {
-    gpr_log(GPR_ERROR, "Census trace store is not initialized.");
-  }
-  gpr_mu_unlock(&g_mu);
-}
-
-void census_internal_lock_trace_store(void) { gpr_mu_lock(&g_mu); }
-
-void census_internal_unlock_trace_store(void) { gpr_mu_unlock(&g_mu); }
-
-census_trace_obj *census_get_trace_obj_locked(census_op_id op_id) {
-  if (g_trace_store == NULL) {
-    gpr_log(GPR_ERROR, "Census trace store is not initialized.");
-    return NULL;
-  }
-  return (census_trace_obj *)census_ht_find(g_trace_store,
-                                            op_id_as_key(&op_id));
-}
-
-const char *census_get_trace_method_name(const census_trace_obj *trace) {
-  return trace->method;
-}
-
-static census_trace_annotation *dup_annotation_chain(
-    census_trace_annotation *from) {
-  census_trace_annotation *ret = NULL;
-  census_trace_annotation **to = &ret;
-  for (; from != NULL; from = from->next) {
-    *to = gpr_malloc(sizeof(census_trace_annotation));
-    memcpy(*to, from, sizeof(census_trace_annotation));
-    to = &(*to)->next;
-  }
-  return ret;
-}
-
-static census_trace_obj *trace_obj_dup(census_trace_obj *from) {
-  census_trace_obj *to = NULL;
-  GPR_ASSERT(from != NULL);
-  to = gpr_malloc(sizeof(census_trace_obj));
-  to->id = from->id;
-  to->ts = from->ts;
-  to->rpc_stats = from->rpc_stats;
-  to->method = gpr_strdup(from->method);
-  to->annotations = dup_annotation_chain(from->annotations);
-  return to;
-}
-
-census_trace_obj **census_get_active_ops(int *num_active_ops) {
-  census_trace_obj **ret = NULL;
-  gpr_mu_lock(&g_mu);
-  if (g_trace_store != NULL) {
-    size_t n = 0;
-    census_ht_kv *all_kvs = census_ht_get_all_elements(g_trace_store, &n);
-    *num_active_ops = (int)n;
-    if (n != 0) {
-      size_t i = 0;
-      ret = gpr_malloc(sizeof(census_trace_obj *) * n);
-      for (i = 0; i < n; i++) {
-        ret[i] = trace_obj_dup((census_trace_obj *)all_kvs[i].v);
-      }
-    }
-    gpr_free(all_kvs);
-  }
-  gpr_mu_unlock(&g_mu);
-  return ret;
-}
diff --git a/src/core/statistics/census_tracing.h b/src/core/statistics/census_tracing.h
deleted file mode 100644
index b611e95..0000000
--- a/src/core/statistics/census_tracing.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_STATISTICS_CENSUS_TRACING_H
-#define GRPC_CORE_STATISTICS_CENSUS_TRACING_H
-
-#include <grpc/support/time.h>
-#include "src/core/statistics/census_rpc_stats.h"
-
-/* WARNING: The data structures and APIs provided by this file are for GRPC
-   library's internal use ONLY. They might be changed in backward-incompatible
-   ways and are not subject to any deprecation policy.
-   They are not recommended for external use.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Struct for a trace annotation. */
-typedef struct census_trace_annotation {
-  gpr_timespec ts;                            /* timestamp of the annotation */
-  char txt[CENSUS_MAX_ANNOTATION_LENGTH + 1]; /* actual txt annotation */
-  struct census_trace_annotation *next;
-} census_trace_annotation;
-
-typedef struct census_trace_obj {
-  census_op_id id;
-  gpr_timespec ts;
-  census_rpc_stats rpc_stats;
-  char *method;
-  census_trace_annotation *annotations;
-} census_trace_obj;
-
-/* Deletes trace object. */
-void census_trace_obj_destroy(census_trace_obj *obj);
-
-/* Initializes trace store. This function is thread safe. */
-void census_tracing_init(void);
-
-/* Shutsdown trace store. This function is thread safe. */
-void census_tracing_shutdown(void);
-
-/* Gets trace obj corresponding to the input op_id. Returns NULL if trace store
-   is not initialized or trace obj is not found. Requires trace store being
-   locked before calling this function. */
-census_trace_obj *census_get_trace_obj_locked(census_op_id op_id);
-
-/* The following two functions acquire and release the trace store global lock.
-   They are for census internal use only. */
-void census_internal_lock_trace_store(void);
-void census_internal_unlock_trace_store(void);
-
-/* Gets method name associated with the input trace object. */
-const char *census_get_trace_method_name(const census_trace_obj *trace);
-
-/* Returns an array of pointers to trace objects of currently active operations
-   and fills in number of active operations. Returns NULL if there are no active
-   operations.
-   Caller owns the returned objects. */
-census_trace_obj **census_get_active_ops(int *num_active_ops);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_STATISTICS_CENSUS_TRACING_H */
diff --git a/src/core/statistics/hash_table.c b/src/core/statistics/hash_table.c
deleted file mode 100644
index 0cadcd4..0000000
--- a/src/core/statistics/hash_table.c
+++ /dev/null
@@ -1,303 +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/statistics/hash_table.h"
-
-#include <stdio.h>
-#include <stddef.h>
-
-#include <grpc/support/log.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/port_platform.h>
-
-#define CENSUS_HT_NUM_BUCKETS 1999
-
-/* A single hash table data entry */
-typedef struct ht_entry {
-  census_ht_key key;
-  void *data;
-  struct ht_entry *next;
-} ht_entry;
-
-/* hash table bucket */
-typedef struct bucket {
-  /* NULL if bucket is empty */
-  ht_entry *next;
-  /* -1 if all buckets are empty. */
-  int32_t prev_non_empty_bucket;
-  /* -1 if all buckets are empty. */
-  int32_t next_non_empty_bucket;
-} bucket;
-
-struct unresizable_hash_table {
-  /* Number of entries in the table */
-  size_t size;
-  /* Number of buckets */
-  uint32_t num_buckets;
-  /* Array of buckets initialized at creation time. Memory consumption is
-     16 bytes per bucket on a 64-bit platform. */
-  bucket *buckets;
-  /* Index of the first non-empty bucket. -1 iff size == 0. */
-  int32_t first_non_empty_bucket;
-  /* Index of the last non_empty bucket. -1 iff size == 0. */
-  int32_t last_non_empty_bucket;
-  /* Immutable options of this hash table, initialized at creation time. */
-  census_ht_option options;
-};
-
-typedef struct entry_locator {
-  int32_t bucket_idx;
-  int is_first_in_chain;
-  int found;
-  ht_entry *prev_entry;
-} entry_locator;
-
-/* Asserts if option is not valid. */
-void check_options(const census_ht_option *option) {
-  GPR_ASSERT(option != NULL);
-  GPR_ASSERT(option->num_buckets > 0);
-  GPR_ASSERT(option->key_type == CENSUS_HT_UINT64 ||
-             option->key_type == CENSUS_HT_POINTER);
-  if (option->key_type == CENSUS_HT_UINT64) {
-    GPR_ASSERT(option->hash == NULL);
-  } else if (option->key_type == CENSUS_HT_POINTER) {
-    GPR_ASSERT(option->hash != NULL);
-    GPR_ASSERT(option->compare_keys != NULL);
-  }
-}
-
-#define REMOVE_NEXT(options, ptr) \
-  do {                            \
-    ht_entry *tmp = (ptr)->next;  \
-    (ptr)->next = tmp->next;      \
-    delete_entry(options, tmp);   \
-  } while (0)
-
-static void delete_entry(const census_ht_option *opt, ht_entry *p) {
-  if (opt->delete_data != NULL) {
-    opt->delete_data(p->data);
-  }
-  if (opt->delete_key != NULL) {
-    opt->delete_key(p->key.ptr);
-  }
-  gpr_free(p);
-}
-
-static uint64_t hash(const census_ht_option *opt, census_ht_key key) {
-  return opt->key_type == CENSUS_HT_UINT64 ? key.val : opt->hash(key.ptr);
-}
-
-census_ht *census_ht_create(const census_ht_option *option) {
-  int i;
-  census_ht *ret = NULL;
-  check_options(option);
-  ret = (census_ht *)gpr_malloc(sizeof(census_ht));
-  ret->size = 0;
-  ret->num_buckets = option->num_buckets;
-  ret->buckets = (bucket *)gpr_malloc(sizeof(bucket) * ret->num_buckets);
-  ret->options = *option;
-  /* initialize each bucket */
-  for (i = 0; i < ret->options.num_buckets; i++) {
-    ret->buckets[i].prev_non_empty_bucket = -1;
-    ret->buckets[i].next_non_empty_bucket = -1;
-    ret->buckets[i].next = NULL;
-  }
-  return ret;
-}
-
-static int32_t find_bucket_idx(const census_ht *ht, census_ht_key key) {
-  return hash(&ht->options, key) % ht->num_buckets;
-}
-
-static int keys_match(const census_ht_option *opt, const ht_entry *p,
-                      const census_ht_key key) {
-  GPR_ASSERT(opt->key_type == CENSUS_HT_UINT64 ||
-             opt->key_type == CENSUS_HT_POINTER);
-  if (opt->key_type == CENSUS_HT_UINT64) return p->key.val == key.val;
-  return !opt->compare_keys((p->key).ptr, key.ptr);
-}
-
-static entry_locator ht_find(const census_ht *ht, census_ht_key key) {
-  entry_locator loc = {0, 0, 0, NULL};
-  int32_t idx = 0;
-  ht_entry *ptr = NULL;
-  GPR_ASSERT(ht != NULL);
-  idx = find_bucket_idx(ht, key);
-  ptr = ht->buckets[idx].next;
-  if (ptr == NULL) {
-    /* bucket is empty */
-    return loc;
-  }
-  if (keys_match(&ht->options, ptr, key)) {
-    loc.bucket_idx = idx;
-    loc.is_first_in_chain = 1;
-    loc.found = 1;
-    return loc;
-  } else {
-    for (; ptr->next != NULL; ptr = ptr->next) {
-      if (keys_match(&ht->options, ptr->next, key)) {
-        loc.bucket_idx = idx;
-        loc.is_first_in_chain = 0;
-        loc.found = 1;
-        loc.prev_entry = ptr;
-        return loc;
-      }
-    }
-  }
-  /* Could not find the key */
-  return loc;
-}
-
-void *census_ht_find(const census_ht *ht, census_ht_key key) {
-  entry_locator loc = ht_find(ht, key);
-  if (loc.found == 0) {
-    return NULL;
-  }
-  return loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next->data
-                               : loc.prev_entry->next->data;
-}
-
-void census_ht_insert(census_ht *ht, census_ht_key key, void *data) {
-  int32_t idx = find_bucket_idx(ht, key);
-  ht_entry *ptr = NULL;
-  entry_locator loc = ht_find(ht, key);
-  if (loc.found) {
-    /* Replace old value with new value. */
-    ptr = loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next
-                                : loc.prev_entry->next;
-    if (ht->options.delete_data != NULL) {
-      ht->options.delete_data(ptr->data);
-    }
-    ptr->data = data;
-    return;
-  }
-
-  /* first entry in the table. */
-  if (ht->size == 0) {
-    ht->buckets[idx].next_non_empty_bucket = -1;
-    ht->buckets[idx].prev_non_empty_bucket = -1;
-    ht->first_non_empty_bucket = idx;
-    ht->last_non_empty_bucket = idx;
-  } else if (ht->buckets[idx].next == NULL) {
-    /* first entry in the bucket. */
-    ht->buckets[ht->last_non_empty_bucket].next_non_empty_bucket = idx;
-    ht->buckets[idx].prev_non_empty_bucket = ht->last_non_empty_bucket;
-    ht->buckets[idx].next_non_empty_bucket = -1;
-    ht->last_non_empty_bucket = idx;
-  }
-  ptr = (ht_entry *)gpr_malloc(sizeof(ht_entry));
-  ptr->key = key;
-  ptr->data = data;
-  ptr->next = ht->buckets[idx].next;
-  ht->buckets[idx].next = ptr;
-  ht->size++;
-}
-
-void census_ht_erase(census_ht *ht, census_ht_key key) {
-  entry_locator loc = ht_find(ht, key);
-  if (loc.found == 0) {
-    /* noop if not found */
-    return;
-  }
-  ht->size--;
-  if (loc.is_first_in_chain) {
-    bucket *b = &ht->buckets[loc.bucket_idx];
-    GPR_ASSERT(b->next != NULL);
-    /* The only entry in the bucket */
-    if (b->next->next == NULL) {
-      int prev = b->prev_non_empty_bucket;
-      int next = b->next_non_empty_bucket;
-      if (prev != -1) {
-        ht->buckets[prev].next_non_empty_bucket = next;
-      } else {
-        ht->first_non_empty_bucket = next;
-      }
-      if (next != -1) {
-        ht->buckets[next].prev_non_empty_bucket = prev;
-      } else {
-        ht->last_non_empty_bucket = prev;
-      }
-    }
-    REMOVE_NEXT(&ht->options, b);
-  } else {
-    GPR_ASSERT(loc.prev_entry->next != NULL);
-    REMOVE_NEXT(&ht->options, loc.prev_entry);
-  }
-}
-
-/* Returns NULL if input table is empty. */
-census_ht_kv *census_ht_get_all_elements(const census_ht *ht, size_t *num) {
-  census_ht_kv *ret = NULL;
-  int i = 0;
-  int32_t idx = -1;
-  GPR_ASSERT(ht != NULL && num != NULL);
-  *num = ht->size;
-  if (*num == 0) {
-    return NULL;
-  }
-
-  ret = (census_ht_kv *)gpr_malloc(sizeof(census_ht_kv) * ht->size);
-  idx = ht->first_non_empty_bucket;
-  while (idx >= 0) {
-    ht_entry *ptr = ht->buckets[idx].next;
-    for (; ptr != NULL; ptr = ptr->next) {
-      ret[i].k = ptr->key;
-      ret[i].v = ptr->data;
-      i++;
-    }
-    idx = ht->buckets[idx].next_non_empty_bucket;
-  }
-  return ret;
-}
-
-static void ht_delete_entry_chain(const census_ht_option *options,
-                                  ht_entry *first) {
-  if (first == NULL) {
-    return;
-  }
-  if (first->next != NULL) {
-    ht_delete_entry_chain(options, first->next);
-  }
-  delete_entry(options, first);
-}
-
-void census_ht_destroy(census_ht *ht) {
-  unsigned i;
-  for (i = 0; i < ht->num_buckets; ++i) {
-    ht_delete_entry_chain(&ht->options, ht->buckets[i].next);
-  }
-  gpr_free(ht->buckets);
-  gpr_free(ht);
-}
-
-size_t census_ht_get_size(const census_ht *ht) { return ht->size; }
diff --git a/src/core/statistics/hash_table.h b/src/core/statistics/hash_table.h
deleted file mode 100644
index f4bf2ba..0000000
--- a/src/core/statistics/hash_table.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_STATISTICS_HASH_TABLE_H
-#define GRPC_CORE_STATISTICS_HASH_TABLE_H
-
-#include <stddef.h>
-
-#include <grpc/support/port_platform.h>
-
-/* A chain based hash table with fixed number of buckets.
-   Your probably shouldn't use this code directly. It is implemented for the
-   use case in census trace store and stats store, where number of entries in
-   the table is in the scale of upto several thousands, entries are added and
-   removed from the table very frequently (~100k/s), the frequency of find()
-   operations is roughly several times of the frequency of insert() and erase()
-   Comparing to find(), the insert(), erase() and get_all_entries() operations
-   are much less freqent (<1/s).
-
-   Per bucket memory overhead is about (8 + sizeof(intptr_t) bytes.
-   Per entry memory overhead is about (8 + 2 * sizeof(intptr_t) bytes.
-
-   All functions are not thread-safe. Synchronization will be provided in the
-   upper layer (in trace store and stats store).
-*/
-
-/* Opaque hash table struct */
-typedef struct unresizable_hash_table census_ht;
-
-/* Currently, the hash_table can take two types of keys. (uint64 for trace
-   store and const char* for stats store). */
-typedef union {
-  uint64_t val;
-  void *ptr;
-} census_ht_key;
-
-typedef enum census_ht_key_type {
-  CENSUS_HT_UINT64 = 0,
-  CENSUS_HT_POINTER = 1
-} census_ht_key_type;
-
-typedef struct census_ht_option {
-  /* Type of hash key */
-  census_ht_key_type key_type;
-  /* Desired number of buckets, preferably a prime number */
-  int32_t num_buckets;
-  /* Fucntion to calculate uint64 hash value of the key. Only takes effect if
-     key_type is POINTER. */
-  uint64_t (*hash)(const void *);
-  /* Function to compare two keys, returns 0 iff equal. Only takes effect if
-     key_type is POINTER */
-  int (*compare_keys)(const void *k1, const void *k2);
-  /* Value deleter. NULL if no specialized delete function is needed. */
-  void (*delete_data)(void *);
-  /* Key deleter. NULL if table does not own the key. (e.g. key is part of the
-     value or key is not owned by the table.) */
-  void (*delete_key)(void *);
-} census_ht_option;
-
-/* Creates a hashtable with fixed number of buckets according to the settings
-   specified in 'options' arg. Function pointers "hash" and "compare_keys" must
-   be provided if key_type is POINTER. Asserts if fail to create. */
-census_ht *census_ht_create(const census_ht_option *options);
-
-/* Deletes hash table instance. Frees all dynamic memory owned by ht.*/
-void census_ht_destroy(census_ht *ht);
-
-/* Inserts the input key-val pair into hash_table. If an entry with the same key
-   exists in the table, the corresponding value will be overwritten by the input
-   val. */
-void census_ht_insert(census_ht *ht, census_ht_key key, void *val);
-
-/* Returns pointer to data, returns NULL if not found. */
-void *census_ht_find(const census_ht *ht, census_ht_key key);
-
-/* Erase hash table entry with input key. Noop if key is not found. */
-void census_ht_erase(census_ht *ht, census_ht_key key);
-
-typedef struct census_ht_kv {
-  census_ht_key k;
-  void *v;
-} census_ht_kv;
-
-/* Returns an array of pointers to all values in the hash table. Order of the
-   elements can be arbitrary. Sets 'num' to the size of returned array. Caller
-   owns returned array. */
-census_ht_kv *census_ht_get_all_elements(const census_ht *ht, size_t *num);
-
-/* Returns number of elements kept. */
-size_t census_ht_get_size(const census_ht *ht);
-
-/* Functor applied on each key-value pair while iterating through entries in the
-   table. The functor should not mutate data. */
-typedef void (*census_ht_itr_cb)(census_ht_key key, const void *val_ptr,
-                                 void *state);
-
-/* Iterates through all key-value pairs in the hash_table. The callback function
-   should not invalidate data entries. */
-uint64_t census_ht_for_all(const census_ht *ht, census_ht_itr_cb);
-
-#endif /* GRPC_CORE_STATISTICS_HASH_TABLE_H */
diff --git a/src/core/statistics/window_stats.c b/src/core/statistics/window_stats.c
deleted file mode 100644
index 3f29408..0000000
--- a/src/core/statistics/window_stats.c
+++ /dev/null
@@ -1,316 +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/statistics/window_stats.h"
-#include <math.h>
-#include <stddef.h>
-#include <string.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include <grpc/support/useful.h>
-
-/* typedefs make typing long names easier. Use cws (for census_window_stats) */
-typedef census_window_stats_stat_info cws_stat_info;
-typedef struct census_window_stats_sum cws_sum;
-
-/* Each interval is composed of a number of buckets, which hold a count of
-   entries and a single statistic */
-typedef struct census_window_stats_bucket {
-  int64_t count;
-  void *statistic;
-} cws_bucket;
-
-/* Each interval has a set of buckets, and the variables needed to keep
-   track of their current state */
-typedef struct census_window_stats_interval_stats {
-  /* The buckets. There will be 'granularity' + 1 of these. */
-  cws_bucket *buckets;
-  /* Index of the bucket containing the smallest time interval. */
-  int bottom_bucket;
-  /* The smallest time storable in the current window. */
-  int64_t bottom;
-  /* The largest time storable in the current window + 1ns */
-  int64_t top;
-  /* The width of each bucket in ns. */
-  int64_t width;
-} cws_interval_stats;
-
-typedef struct census_window_stats {
-  /* Number of intervals. */
-  int nintervals;
-  /* Number of buckets in each interval. 'granularity' + 1. */
-  int nbuckets;
-  /* Record of stat_info. */
-  cws_stat_info stat_info;
-  /* Stats for each interval. */
-  cws_interval_stats *interval_stats;
-  /* The time the newset stat was recorded. */
-  int64_t newest_time;
-} window_stats;
-
-/* Calculate an actual bucket index from a logical index 'IDX'. Other
-   parameters supply information on the interval struct and overall stats. */
-#define BUCKET_IDX(IS, IDX, WSTATS) \
-  ((IS->bottom_bucket + (IDX)) % WSTATS->nbuckets)
-
-/* The maximum seconds value we can have in a valid timespec. More than this
-   will result in overflow in timespec_to_ns(). This works out to ~292 years.
-   TODO: consider using doubles instead of int64. */
-static int64_t max_seconds = (GPR_INT64_MAX - GPR_NS_PER_SEC) / GPR_NS_PER_SEC;
-
-static int64_t timespec_to_ns(const gpr_timespec ts) {
-  if (ts.tv_sec > max_seconds) {
-    return GPR_INT64_MAX - 1;
-  }
-  return ts.tv_sec * GPR_NS_PER_SEC + ts.tv_nsec;
-}
-
-static void cws_initialize_statistic(void *statistic,
-                                     const cws_stat_info *stat_info) {
-  if (stat_info->stat_initialize == NULL) {
-    memset(statistic, 0, stat_info->stat_size);
-  } else {
-    stat_info->stat_initialize(statistic);
-  }
-}
-
-/* Create and initialize a statistic */
-static void *cws_create_statistic(const cws_stat_info *stat_info) {
-  void *stat = gpr_malloc(stat_info->stat_size);
-  cws_initialize_statistic(stat, stat_info);
-  return stat;
-}
-
-window_stats *census_window_stats_create(int nintervals,
-                                         const gpr_timespec intervals[],
-                                         int granularity,
-                                         const cws_stat_info *stat_info) {
-  window_stats *ret;
-  int i;
-  /* validate inputs */
-  GPR_ASSERT(nintervals > 0 && granularity > 2 && intervals != NULL &&
-             stat_info != NULL);
-  for (i = 0; i < nintervals; i++) {
-    int64_t ns = timespec_to_ns(intervals[i]);
-    GPR_ASSERT(intervals[i].tv_sec >= 0 && intervals[i].tv_nsec >= 0 &&
-               intervals[i].tv_nsec < GPR_NS_PER_SEC && ns >= 100 &&
-               granularity * 10 <= ns);
-  }
-  /* Allocate and initialize relevant data structures */
-  ret = (window_stats *)gpr_malloc(sizeof(window_stats));
-  ret->nintervals = nintervals;
-  ret->nbuckets = granularity + 1;
-  ret->stat_info = *stat_info;
-  ret->interval_stats =
-      (cws_interval_stats *)gpr_malloc(nintervals * sizeof(cws_interval_stats));
-  for (i = 0; i < nintervals; i++) {
-    int64_t size_ns = timespec_to_ns(intervals[i]);
-    cws_interval_stats *is = ret->interval_stats + i;
-    cws_bucket *buckets = is->buckets =
-        (cws_bucket *)gpr_malloc(ret->nbuckets * sizeof(cws_bucket));
-    int b;
-    for (b = 0; b < ret->nbuckets; b++) {
-      buckets[b].statistic = cws_create_statistic(stat_info);
-      buckets[b].count = 0;
-    }
-    is->bottom_bucket = 0;
-    is->bottom = 0;
-    is->width = size_ns / granularity;
-    /* Check for possible overflow issues, and maximize interval size if the
-       user requested something large enough. */
-    if ((GPR_INT64_MAX - is->width) > size_ns) {
-      is->top = size_ns + is->width;
-    } else {
-      is->top = GPR_INT64_MAX;
-      is->width = GPR_INT64_MAX / (granularity + 1);
-    }
-    /* If size doesn't divide evenly, we can have a width slightly too small;
-       better to have it slightly large. */
-    if ((size_ns - (granularity + 1) * is->width) > 0) {
-      is->width += 1;
-    }
-  }
-  ret->newest_time = 0;
-  return ret;
-}
-
-/* When we try adding a measurement above the current interval range, we
-   need to "shift" the buckets sufficiently to cover the new range. */
-static void cws_shift_buckets(const window_stats *wstats,
-                              cws_interval_stats *is, int64_t when_ns) {
-  int i;
-  /* number of bucket time widths to "shift" */
-  int shift;
-  /* number of buckets to clear */
-  int nclear;
-  GPR_ASSERT(when_ns >= is->top);
-  /* number of bucket time widths to "shift" */
-  shift = ((when_ns - is->top) / is->width) + 1;
-  /* number of buckets to clear - limited by actual number of buckets */
-  nclear = GPR_MIN(shift, wstats->nbuckets);
-  for (i = 0; i < nclear; i++) {
-    int b = BUCKET_IDX(is, i, wstats);
-    is->buckets[b].count = 0;
-    cws_initialize_statistic(is->buckets[b].statistic, &wstats->stat_info);
-  }
-  /* adjust top/bottom times and current bottom bucket */
-  is->bottom_bucket = BUCKET_IDX(is, shift, wstats);
-  is->top += shift * is->width;
-  is->bottom += shift * is->width;
-}
-
-void census_window_stats_add(window_stats *wstats, const gpr_timespec when,
-                             const void *stat_value) {
-  int i;
-  int64_t when_ns = timespec_to_ns(when);
-  GPR_ASSERT(wstats->interval_stats != NULL);
-  for (i = 0; i < wstats->nintervals; i++) {
-    cws_interval_stats *is = wstats->interval_stats + i;
-    cws_bucket *bucket;
-    if (when_ns < is->bottom) { /* Below smallest time in interval: drop */
-      continue;
-    }
-    if (when_ns >= is->top) { /* above limit: shift buckets */
-      cws_shift_buckets(wstats, is, when_ns);
-    }
-    /* Add the stat. */
-    GPR_ASSERT(is->bottom <= when_ns && when_ns < is->top);
-    bucket = is->buckets +
-             BUCKET_IDX(is, (when_ns - is->bottom) / is->width, wstats);
-    bucket->count++;
-    wstats->stat_info.stat_add(bucket->statistic, stat_value);
-  }
-  if (when_ns > wstats->newest_time) {
-    wstats->newest_time = when_ns;
-  }
-}
-
-/* Add a specific bucket contents to an accumulating total. */
-static void cws_add_bucket_to_sum(cws_sum *sum, const cws_bucket *bucket,
-                                  const cws_stat_info *stat_info) {
-  sum->count += bucket->count;
-  stat_info->stat_add(sum->statistic, bucket->statistic);
-}
-
-/* Add a proportion to an accumulating sum. */
-static void cws_add_proportion_to_sum(double p, cws_sum *sum,
-                                      const cws_bucket *bucket,
-                                      const cws_stat_info *stat_info) {
-  sum->count += p * bucket->count;
-  stat_info->stat_add_proportion(p, sum->statistic, bucket->statistic);
-}
-
-void census_window_stats_get_sums(const window_stats *wstats,
-                                  const gpr_timespec when, cws_sum sums[]) {
-  int i;
-  int64_t when_ns = timespec_to_ns(when);
-  GPR_ASSERT(wstats->interval_stats != NULL);
-  for (i = 0; i < wstats->nintervals; i++) {
-    int when_bucket;
-    int new_bucket;
-    double last_proportion = 1.0;
-    double bottom_proportion;
-    cws_interval_stats *is = wstats->interval_stats + i;
-    cws_sum *sum = sums + i;
-    sum->count = 0;
-    cws_initialize_statistic(sum->statistic, &wstats->stat_info);
-    if (when_ns < is->bottom) {
-      continue;
-    }
-    if (when_ns >= is->top) {
-      cws_shift_buckets(wstats, is, when_ns);
-    }
-    /* Calculating the appropriate amount of which buckets to use can get
-       complicated. Essentially there are two cases:
-       1) if the "top" bucket (new_bucket, where the newest additions to the
-       stats recorded are entered) corresponds to 'when', then we need
-       to take a proportion of it - (if when < newest_time) or the full
-       thing. We also (possibly) need to take a corresponding
-       proportion of the bottom bucket.
-       2) Other cases, we just take a straight proportion.
-     */
-    when_bucket = (when_ns - is->bottom) / is->width;
-    new_bucket = (wstats->newest_time - is->bottom) / is->width;
-    if (new_bucket == when_bucket) {
-      int64_t bottom_bucket_time = is->bottom + when_bucket * is->width;
-      if (when_ns < wstats->newest_time) {
-        last_proportion = (double)(when_ns - bottom_bucket_time) /
-                          (double)(wstats->newest_time - bottom_bucket_time);
-        bottom_proportion =
-            (double)(is->width - (when_ns - bottom_bucket_time)) / is->width;
-      } else {
-        bottom_proportion =
-            (double)(is->width - (wstats->newest_time - bottom_bucket_time)) /
-            is->width;
-      }
-    } else {
-      last_proportion =
-          (double)(when_ns + 1 - is->bottom - when_bucket * is->width) /
-          is->width;
-      bottom_proportion = 1.0 - last_proportion;
-    }
-    cws_add_proportion_to_sum(last_proportion, sum,
-                              is->buckets + BUCKET_IDX(is, when_bucket, wstats),
-                              &wstats->stat_info);
-    if (when_bucket != 0) { /* last bucket isn't also bottom bucket */
-      int b;
-      /* Add all of "bottom" bucket if we are looking at a subset of the
-         full interval, or a proportion if we are adding full interval. */
-      cws_add_proportion_to_sum(
-          (when_bucket == wstats->nbuckets - 1 ? bottom_proportion : 1.0), sum,
-          is->buckets + is->bottom_bucket, &wstats->stat_info);
-      /* Add all the remaining buckets (everything but top and bottom). */
-      for (b = 1; b < when_bucket; b++) {
-        cws_add_bucket_to_sum(sum, is->buckets + BUCKET_IDX(is, b, wstats),
-                              &wstats->stat_info);
-      }
-    }
-  }
-}
-
-void census_window_stats_destroy(window_stats *wstats) {
-  int i;
-  GPR_ASSERT(wstats->interval_stats != NULL);
-  for (i = 0; i < wstats->nintervals; i++) {
-    int b;
-    for (b = 0; b < wstats->nbuckets; b++) {
-      gpr_free(wstats->interval_stats[i].buckets[b].statistic);
-    }
-    gpr_free(wstats->interval_stats[i].buckets);
-  }
-  gpr_free(wstats->interval_stats);
-  /* Ensure any use-after free triggers assert. */
-  wstats->interval_stats = NULL;
-  gpr_free(wstats);
-}
diff --git a/src/core/statistics/window_stats.h b/src/core/statistics/window_stats.h
deleted file mode 100644
index 7742771..0000000
--- a/src/core/statistics/window_stats.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_STATISTICS_WINDOW_STATS_H
-#define GRPC_CORE_STATISTICS_WINDOW_STATS_H
-
-#include <grpc/support/time.h>
-
-/* Keep rolling sums of a user-defined statistic (containing a number of
-   measurements) over a a number of time intervals ("windows"). For example,
-   you can use a window_stats object to answer questions such as
-   "Approximately how many RPCs/s did I receive over the past minute, and
-   approximately how many bytes did I send out over that period?".
-
-   The type of data to record, and the time intervals to keep are specified
-   when creating the object via a call to census_window_stats_create().
-
-   A window's interval is divided into one or more "buckets"; the interval
-   must be divisible by the number of buckets. Internally, these buckets
-   control the granularity of window_stats' measurements. Increasing the
-   number of buckets lets the object respond more quickly to changes in the
-   overall rate of data added into the object, at the cost of additional
-   memory usage.
-
-   Here's some code which keeps one minute/hour measurements for two values
-   (latency in seconds and bytes transferred), with each interval divided into
-   4 buckets.
-
-    typedef struct my_stat {
-      double latency;
-      int bytes;
-    } my_stat;
-
-    void add_my_stat(void* base, const void* addme) {
-      my_stat* b = (my_stat*)base;
-      const my_stat* a = (const my_stat*)addme;
-      b->latency += a->latency;
-      b->bytes += a->bytes;
-    }
-
-    void add_proportion_my_stat(double p, void* base, const void* addme) {
-      (my_stat*)result->latency += p * (const my_stat*)base->latency;
-      (my_stat*)result->bytes += p * (const my_stat*)base->bytes;
-    }
-
-    #define kNumIntervals 2
-    #define kMinInterval 0
-    #define kHourInterval 1
-    #define kNumBuckets 4
-
-    const struct census_window_stats_stat_info kMyStatInfo
-        = { sizeof(my_stat), NULL, add_my_stat, add_proportion_my_stat };
-    gpr_timespec intervals[kNumIntervals] = {{60, 0}, {3600, 0}};
-    my_stat stat;
-    my_stat sums[kNumIntervals];
-    census_window_stats_sums result[kNumIntervals];
-    struct census_window_stats* stats
-        = census_window_stats_create(kNumIntervals, intervals, kNumBuckets,
-                                     &kMyStatInfo);
-    // Record a new event, taking 15.3ms, transferring 1784 bytes.
-    stat.latency = 0.153;
-    stat.bytes = 1784;
-    census_window_stats_add(stats, gpr_now(GPR_CLOCK_REALTIME), &stat);
-    // Get sums and print them out
-    result[kMinInterval].statistic = &sums[kMinInterval];
-    result[kHourInterval].statistic = &sums[kHourInterval];
-    census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), result);
-    printf("%d events/min, average time %gs, average bytes %g\n",
-           result[kMinInterval].count,
-           (my_stat*)result[kMinInterval].statistic->latency /
-             result[kMinInterval].count,
-           (my_stat*)result[kMinInterval].statistic->bytes /
-             result[kMinInterval].count
-          );
-    printf("%d events/hr, average time %gs, average bytes %g\n",
-           result[kHourInterval].count,
-           (my_stat*)result[kHourInterval].statistic->latency /
-             result[kHourInterval].count,
-           (my_stat*)result[kHourInterval].statistic->bytes /
-             result[kHourInterval].count
-          );
-*/
-
-/* Opaque structure for representing window_stats object */
-struct census_window_stats;
-
-/* Information provided by API user on the information they want to record */
-typedef struct census_window_stats_stat_info {
-  /* Number of bytes in user-defined object. */
-  size_t stat_size;
-  /* Function to initialize a user-defined statistics object. If this is set
-   * to NULL, then the object will be zero-initialized. */
-  void (*stat_initialize)(void *stat);
-  /* Function to add one user-defined statistics object ('addme') to 'base' */
-  void (*stat_add)(void *base, const void *addme);
-  /* As for previous function, but only add a proportion 'p'. This API will
-     currently only use 'p' values in the range [0,1], but other values are
-     possible in the future, and should be supported. */
-  void (*stat_add_proportion)(double p, void *base, const void *addme);
-} census_window_stats_stat_info;
-
-/* Create a new window_stats object. 'nintervals' is the number of
-   'intervals', and must be >=1. 'granularity' is the number of buckets, with
-   a larger number using more memory, but providing greater accuracy of
-   results. 'granularity should be > 2. We also require that each interval be
-   at least 10 * 'granularity' nanoseconds in size. 'stat_info' contains
-   information about the statistic to be gathered. Intervals greater than ~192
-   years will be treated as essentially infinite in size. This function will
-   GPR_ASSERT() if the object cannot be created or any of the parameters have
-   invalid values. This function is thread-safe. */
-struct census_window_stats *census_window_stats_create(
-    int nintervals, const gpr_timespec intervals[], int granularity,
-    const census_window_stats_stat_info *stat_info);
-
-/* Add a new measurement (in 'stat_value'), as of a given time ('when').
-   This function is thread-compatible. */
-void census_window_stats_add(struct census_window_stats *wstats,
-                             const gpr_timespec when, const void *stat_value);
-
-/* Structure used to record a single intervals sum for a given statistic */
-typedef struct census_window_stats_sum {
-  /* Total count of samples. Note that because some internal interpolation
-     is performed, the count of samples returned for each interval may not be an
-     integral value. */
-  double count;
-  /* Sum for statistic */
-  void *statistic;
-} census_window_stats_sums;
-
-/* Retrieve a set of all values stored in a window_stats object 'wstats'. The
-   number of 'sums' MUST be the same as the number 'nintervals' used in
-   census_window_stats_create(). This function is thread-compatible. */
-void census_window_stats_get_sums(const struct census_window_stats *wstats,
-                                  const gpr_timespec when,
-                                  struct census_window_stats_sum sums[]);
-
-/* Destroy a window_stats object. Once this function has been called, the
-   object will no longer be usable from any of the above functions (and
-   calling them will most likely result in a NULL-pointer dereference or
-   assertion failure). This function is thread-compatible. */
-void census_window_stats_destroy(struct census_window_stats *wstats);
-
-#endif /* GRPC_CORE_STATISTICS_WINDOW_STATS_H */
diff --git a/src/core/support/alloc.c b/src/core/support/alloc.c
deleted file mode 100644
index b99584b..0000000
--- a/src/core/support/alloc.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *
- * 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 <grpc/support/alloc.h>
-
-#include <stdlib.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include "src/core/profiling/timers.h"
-
-static gpr_allocation_functions g_alloc_functions = {malloc, realloc, free};
-
-gpr_allocation_functions gpr_get_allocation_functions() {
-  return g_alloc_functions;
-}
-
-void gpr_set_allocation_functions(gpr_allocation_functions functions) {
-  GPR_ASSERT(functions.malloc_fn != NULL);
-  GPR_ASSERT(functions.realloc_fn != NULL);
-  GPR_ASSERT(functions.free_fn != NULL);
-  g_alloc_functions = functions;
-}
-
-void *gpr_malloc(size_t size) {
-  void *p;
-  GPR_TIMER_BEGIN("gpr_malloc", 0);
-  p = g_alloc_functions.malloc_fn(size);
-  if (!p) {
-    abort();
-  }
-  GPR_TIMER_END("gpr_malloc", 0);
-  return p;
-}
-
-void gpr_free(void *p) {
-  GPR_TIMER_BEGIN("gpr_free", 0);
-  g_alloc_functions.free_fn(p);
-  GPR_TIMER_END("gpr_free", 0);
-}
-
-void *gpr_realloc(void *p, size_t size) {
-  GPR_TIMER_BEGIN("gpr_realloc", 0);
-  p = g_alloc_functions.realloc_fn(p, size);
-  if (!p) {
-    abort();
-  }
-  GPR_TIMER_END("gpr_realloc", 0);
-  return p;
-}
-
-void *gpr_malloc_aligned(size_t size, size_t alignment_log) {
-  size_t alignment = ((size_t)1) << alignment_log;
-  size_t extra = alignment - 1 + sizeof(void *);
-  void *p = gpr_malloc(size + extra);
-  void **ret = (void **)(((uintptr_t)p + extra) & ~(alignment - 1));
-  ret[-1] = p;
-  return (void *)ret;
-}
-
-void gpr_free_aligned(void *ptr) { gpr_free(((void **)ptr)[-1]); }
diff --git a/src/core/support/avl.c b/src/core/support/avl.c
deleted file mode 100644
index f378b3e..0000000
--- a/src/core/support/avl.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- *
- * 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 <grpc/support/avl.h>
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-gpr_avl gpr_avl_create(const gpr_avl_vtable *vtable) {
-  gpr_avl out;
-  out.vtable = vtable;
-  out.root = NULL;
-  return out;
-}
-
-static gpr_avl_node *ref_node(gpr_avl_node *node) {
-  if (node) {
-    gpr_ref(&node->refs);
-  }
-  return node;
-}
-
-static void unref_node(const gpr_avl_vtable *vtable, gpr_avl_node *node) {
-  if (node == NULL) {
-    return;
-  }
-  if (gpr_unref(&node->refs)) {
-    vtable->destroy_key(node->key);
-    vtable->destroy_value(node->value);
-    unref_node(vtable, node->left);
-    unref_node(vtable, node->right);
-    gpr_free(node);
-  }
-}
-
-static long node_height(gpr_avl_node *node) {
-  return node == NULL ? 0 : node->height;
-}
-
-#ifndef NDEBUG
-static long calculate_height(gpr_avl_node *node) {
-  return node == NULL ? 0 : 1 + GPR_MAX(calculate_height(node->left),
-                                        calculate_height(node->right));
-}
-
-static gpr_avl_node *assert_invariants(gpr_avl_node *n) {
-  if (n == NULL) return NULL;
-  assert_invariants(n->left);
-  assert_invariants(n->right);
-  assert(calculate_height(n) == n->height);
-  assert(labs(node_height(n->left) - node_height(n->right)) <= 1);
-  return n;
-}
-#else
-static gpr_avl_node *assert_invariants(gpr_avl_node *n) { return n; }
-#endif
-
-gpr_avl_node *new_node(void *key, void *value, gpr_avl_node *left,
-                       gpr_avl_node *right) {
-  gpr_avl_node *node = gpr_malloc(sizeof(*node));
-  gpr_ref_init(&node->refs, 1);
-  node->key = key;
-  node->value = value;
-  node->left = assert_invariants(left);
-  node->right = assert_invariants(right);
-  node->height = 1 + GPR_MAX(node_height(left), node_height(right));
-  return node;
-}
-
-static gpr_avl_node *get(const gpr_avl_vtable *vtable, gpr_avl_node *node,
-                         void *key) {
-  long cmp;
-
-  if (node == NULL) {
-    return NULL;
-  }
-
-  cmp = vtable->compare_keys(node->key, key);
-  if (cmp == 0) {
-    return node;
-  } else if (cmp > 0) {
-    return get(vtable, node->left, key);
-  } else {
-    return get(vtable, node->right, key);
-  }
-}
-
-void *gpr_avl_get(gpr_avl avl, void *key) {
-  gpr_avl_node *node = get(avl.vtable, avl.root, key);
-  return node ? node->value : NULL;
-}
-
-static gpr_avl_node *rotate_left(const gpr_avl_vtable *vtable, void *key,
-                                 void *value, gpr_avl_node *left,
-                                 gpr_avl_node *right) {
-  gpr_avl_node *n =
-      new_node(vtable->copy_key(right->key), vtable->copy_value(right->value),
-               new_node(key, value, left, ref_node(right->left)),
-               ref_node(right->right));
-  unref_node(vtable, right);
-  return n;
-}
-
-static gpr_avl_node *rotate_right(const gpr_avl_vtable *vtable, void *key,
-                                  void *value, gpr_avl_node *left,
-                                  gpr_avl_node *right) {
-  gpr_avl_node *n = new_node(
-      vtable->copy_key(left->key), vtable->copy_value(left->value),
-      ref_node(left->left), new_node(key, value, ref_node(left->right), right));
-  unref_node(vtable, left);
-  return n;
-}
-
-static gpr_avl_node *rotate_left_right(const gpr_avl_vtable *vtable, void *key,
-                                       void *value, gpr_avl_node *left,
-                                       gpr_avl_node *right) {
-  /* rotate_right(..., rotate_left(left), right) */
-  gpr_avl_node *n = new_node(
-      vtable->copy_key(left->right->key),
-      vtable->copy_value(left->right->value),
-      new_node(vtable->copy_key(left->key), vtable->copy_value(left->value),
-               ref_node(left->left), ref_node(left->right->left)),
-      new_node(key, value, ref_node(left->right->right), right));
-  unref_node(vtable, left);
-  return n;
-}
-
-static gpr_avl_node *rotate_right_left(const gpr_avl_vtable *vtable, void *key,
-                                       void *value, gpr_avl_node *left,
-                                       gpr_avl_node *right) {
-  /* rotate_left(..., left, rotate_right(right)) */
-  gpr_avl_node *n = new_node(
-      vtable->copy_key(right->left->key),
-      vtable->copy_value(right->left->value),
-      new_node(key, value, left, ref_node(right->left->left)),
-      new_node(vtable->copy_key(right->key), vtable->copy_value(right->value),
-               ref_node(right->left->right), ref_node(right->right)));
-  unref_node(vtable, right);
-  return n;
-}
-
-static gpr_avl_node *rebalance(const gpr_avl_vtable *vtable, void *key,
-                               void *value, gpr_avl_node *left,
-                               gpr_avl_node *right) {
-  switch (node_height(left) - node_height(right)) {
-    case 2:
-      if (node_height(left->left) - node_height(left->right) == -1) {
-        return assert_invariants(
-            rotate_left_right(vtable, key, value, left, right));
-      } else {
-        return assert_invariants(rotate_right(vtable, key, value, left, right));
-      }
-    case -2:
-      if (node_height(right->left) - node_height(right->right) == 1) {
-        return assert_invariants(
-            rotate_right_left(vtable, key, value, left, right));
-      } else {
-        return assert_invariants(rotate_left(vtable, key, value, left, right));
-      }
-    default:
-      return assert_invariants(new_node(key, value, left, right));
-  }
-}
-
-static gpr_avl_node *add(const gpr_avl_vtable *vtable, gpr_avl_node *node,
-                         void *key, void *value) {
-  long cmp;
-  if (node == NULL) {
-    return new_node(key, value, NULL, NULL);
-  }
-  cmp = vtable->compare_keys(node->key, key);
-  if (cmp == 0) {
-    return new_node(key, value, ref_node(node->left), ref_node(node->right));
-  } else if (cmp > 0) {
-    return rebalance(
-        vtable, vtable->copy_key(node->key), vtable->copy_value(node->value),
-        add(vtable, node->left, key, value), ref_node(node->right));
-  } else {
-    return rebalance(vtable, vtable->copy_key(node->key),
-                     vtable->copy_value(node->value), ref_node(node->left),
-                     add(vtable, node->right, key, value));
-  }
-}
-
-gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value) {
-  gpr_avl_node *old_root = avl.root;
-  avl.root = add(avl.vtable, avl.root, key, value);
-  assert_invariants(avl.root);
-  unref_node(avl.vtable, old_root);
-  return avl;
-}
-
-static gpr_avl_node *in_order_head(gpr_avl_node *node) {
-  while (node->left != NULL) {
-    node = node->left;
-  }
-  return node;
-}
-
-static gpr_avl_node *in_order_tail(gpr_avl_node *node) {
-  while (node->right != NULL) {
-    node = node->right;
-  }
-  return node;
-}
-
-static gpr_avl_node *remove(const gpr_avl_vtable *vtable, gpr_avl_node *node,
-                            void *key) {
-  long cmp;
-  if (node == NULL) {
-    return NULL;
-  }
-  cmp = vtable->compare_keys(node->key, key);
-  if (cmp == 0) {
-    if (node->left == NULL) {
-      return ref_node(node->right);
-    } else if (node->right == NULL) {
-      return ref_node(node->left);
-    } else if (node->left->height < node->right->height) {
-      gpr_avl_node *h = in_order_head(node->right);
-      return rebalance(vtable, vtable->copy_key(h->key),
-                       vtable->copy_value(h->value), ref_node(node->left),
-                       remove(vtable, node->right, h->key));
-    } else {
-      gpr_avl_node *h = in_order_tail(node->left);
-      return rebalance(
-          vtable, vtable->copy_key(h->key), vtable->copy_value(h->value),
-          remove(vtable, node->left, h->key), ref_node(node->right));
-    }
-  } else if (cmp > 0) {
-    return rebalance(vtable, vtable->copy_key(node->key),
-                     vtable->copy_value(node->value),
-                     remove(vtable, node->left, key), ref_node(node->right));
-  } else {
-    return rebalance(vtable, vtable->copy_key(node->key),
-                     vtable->copy_value(node->value), ref_node(node->left),
-                     remove(vtable, node->right, key));
-  }
-}
-
-gpr_avl gpr_avl_remove(gpr_avl avl, void *key) {
-  gpr_avl_node *old_root = avl.root;
-  avl.root = remove(avl.vtable, avl.root, key);
-  assert_invariants(avl.root);
-  unref_node(avl.vtable, old_root);
-  return avl;
-}
-
-gpr_avl gpr_avl_ref(gpr_avl avl) {
-  ref_node(avl.root);
-  return avl;
-}
-
-void gpr_avl_unref(gpr_avl avl) { unref_node(avl.vtable, avl.root); }
diff --git a/src/core/support/backoff.c b/src/core/support/backoff.c
deleted file mode 100644
index 7458219..0000000
--- a/src/core/support/backoff.c
+++ /dev/null
@@ -1,71 +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 "src/core/support/backoff.h"
-
-#include <grpc/support/useful.h>
-
-void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
-                      int64_t min_timeout_millis, int64_t max_timeout_millis) {
-  backoff->multiplier = multiplier;
-  backoff->jitter = jitter;
-  backoff->min_timeout_millis = min_timeout_millis;
-  backoff->max_timeout_millis = max_timeout_millis;
-  backoff->rng_state = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
-}
-
-gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) {
-  backoff->current_timeout_millis = backoff->min_timeout_millis;
-  return gpr_time_add(
-      now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
-}
-
-/* Generate a random number between 0 and 1. */
-static double generate_uniform_random_number(uint32_t *rng_state) {
-  *rng_state = (1103515245 * *rng_state + 12345) % ((uint32_t)1 << 31);
-  return *rng_state / (double)((uint32_t)1 << 31);
-}
-
-gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) {
-  double new_timeout_millis =
-      backoff->multiplier * (double)backoff->current_timeout_millis;
-  double jitter_range = backoff->jitter * new_timeout_millis;
-  double jitter =
-      (2 * generate_uniform_random_number(&backoff->rng_state) - 1) *
-      jitter_range;
-  backoff->current_timeout_millis =
-      GPR_CLAMP((int64_t)(new_timeout_millis + jitter),
-                backoff->min_timeout_millis, backoff->max_timeout_millis);
-  return gpr_time_add(
-      now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
-}
diff --git a/src/core/support/backoff.h b/src/core/support/backoff.h
deleted file mode 100644
index f7730fd..0000000
--- a/src/core/support/backoff.h
+++ /dev/null
@@ -1,65 +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_CORE_SUPPORT_BACKOFF_H
-#define GRPC_CORE_SUPPORT_BACKOFF_H
-
-#include <grpc/support/time.h>
-
-typedef struct {
-  /// const: multiplier between retry attempts
-  double multiplier;
-  /// const: amount to randomize backoffs
-  double jitter;
-  /// const: minimum time between retries in milliseconds
-  int64_t min_timeout_millis;
-  /// const: maximum time between retries in milliseconds
-  int64_t max_timeout_millis;
-
-  /// random number generator
-  uint32_t rng_state;
-
-  /// current retry timeout in milliseconds
-  int64_t current_timeout_millis;
-} gpr_backoff;
-
-/// Initialize backoff machinery - does not need to be destroyed
-void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
-                      int64_t min_timeout_millis, int64_t max_timeout_millis);
-
-/// Begin retry loop: returns a timespec for the NEXT retry
-gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now);
-/// Step a retry loop: returns a timespec for the NEXT retry
-gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now);
-
-#endif /* GRPC_CORE_SUPPORT_BACKOFF_H */
diff --git a/src/core/support/block_annotate.h b/src/core/support/block_annotate.h
deleted file mode 100644
index 79a1803..0000000
--- a/src/core/support/block_annotate.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_BLOCK_ANNOTATE_H
-#define GRPC_CORE_SUPPORT_BLOCK_ANNOTATE_H
-
-/* These annotations identify the beginning and end of regions where
-   the code may block for reasons other than synchronization functions.
-   These include poll, epoll, and getaddrinfo. */
-
-#define GRPC_SCHEDULING_START_BLOCKING_REGION \
-  do {                                        \
-  } while (0)
-#define GRPC_SCHEDULING_END_BLOCKING_REGION \
-  do {                                      \
-  } while (0)
-
-#endif /* GRPC_CORE_SUPPORT_BLOCK_ANNOTATE_H */
diff --git a/src/core/support/cmdline.c b/src/core/support/cmdline.c
deleted file mode 100644
index b517f30..0000000
--- a/src/core/support/cmdline.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 <grpc/support/cmdline.h>
-
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-typedef enum { ARGTYPE_INT, ARGTYPE_BOOL, ARGTYPE_STRING } argtype;
-
-typedef struct arg {
-  const char *name;
-  const char *help;
-  argtype type;
-  void *value;
-  struct arg *next;
-} arg;
-
-struct gpr_cmdline {
-  const char *description;
-  arg *args;
-  const char *argv0;
-
-  const char *extra_arg_name;
-  const char *extra_arg_help;
-  void (*extra_arg)(void *user_data, const char *arg);
-  void *extra_arg_user_data;
-
-  int (*state)(gpr_cmdline *cl, char *arg);
-  arg *cur_arg;
-
-  int survive_failure;
-};
-
-static int normal_state(gpr_cmdline *cl, char *arg);
-
-gpr_cmdline *gpr_cmdline_create(const char *description) {
-  gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline));
-  memset(cl, 0, sizeof(gpr_cmdline));
-
-  cl->description = description;
-  cl->state = normal_state;
-
-  return cl;
-}
-
-void gpr_cmdline_set_survive_failure(gpr_cmdline *cl) {
-  cl->survive_failure = 1;
-}
-
-void gpr_cmdline_destroy(gpr_cmdline *cl) {
-  while (cl->args) {
-    arg *a = cl->args;
-    cl->args = a->next;
-    gpr_free(a);
-  }
-  gpr_free(cl);
-}
-
-static void add_arg(gpr_cmdline *cl, const char *name, const char *help,
-                    argtype type, void *value) {
-  arg *a;
-
-  for (a = cl->args; a; a = a->next) {
-    GPR_ASSERT(0 != strcmp(a->name, name));
-  }
-
-  a = gpr_malloc(sizeof(arg));
-  memset(a, 0, sizeof(arg));
-  a->name = name;
-  a->help = help;
-  a->type = type;
-  a->value = value;
-  a->next = cl->args;
-  cl->args = a;
-}
-
-void gpr_cmdline_add_int(gpr_cmdline *cl, const char *name, const char *help,
-                         int *value) {
-  add_arg(cl, name, help, ARGTYPE_INT, value);
-}
-
-void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name, const char *help,
-                          int *value) {
-  add_arg(cl, name, help, ARGTYPE_BOOL, value);
-}
-
-void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help,
-                            char **value) {
-  add_arg(cl, name, help, ARGTYPE_STRING, value);
-}
-
-void gpr_cmdline_on_extra_arg(
-    gpr_cmdline *cl, const char *name, const char *help,
-    void (*on_extra_arg)(void *user_data, const char *arg), void *user_data) {
-  GPR_ASSERT(!cl->extra_arg);
-  GPR_ASSERT(on_extra_arg);
-
-  cl->extra_arg = on_extra_arg;
-  cl->extra_arg_user_data = user_data;
-  cl->extra_arg_name = name;
-  cl->extra_arg_help = help;
-}
-
-/* recursively descend argument list, adding the last element
-   to s first - so that arguments are added in the order they were
-   added to the list by api calls */
-static void add_args_to_usage(gpr_strvec *s, arg *a) {
-  char *tmp;
-
-  if (!a) return;
-  add_args_to_usage(s, a->next);
-
-  switch (a->type) {
-    case ARGTYPE_BOOL:
-      gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name);
-      gpr_strvec_add(s, tmp);
-      break;
-    case ARGTYPE_STRING:
-      gpr_asprintf(&tmp, " [--%s=string]", a->name);
-      gpr_strvec_add(s, tmp);
-      break;
-    case ARGTYPE_INT:
-      gpr_asprintf(&tmp, " [--%s=int]", a->name);
-      gpr_strvec_add(s, tmp);
-      break;
-  }
-}
-
-char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) {
-  /* TODO(ctiller): make this prettier */
-  gpr_strvec s;
-  char *tmp;
-  const char *name = strrchr(argv0, '/');
-
-  if (name) {
-    name++;
-  } else {
-    name = argv0;
-  }
-
-  gpr_strvec_init(&s);
-
-  gpr_asprintf(&tmp, "Usage: %s", name);
-  gpr_strvec_add(&s, tmp);
-  add_args_to_usage(&s, cl->args);
-  if (cl->extra_arg) {
-    gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name);
-    gpr_strvec_add(&s, tmp);
-  }
-  gpr_strvec_add(&s, gpr_strdup("\n"));
-
-  tmp = gpr_strvec_flatten(&s, NULL);
-  gpr_strvec_destroy(&s);
-  return tmp;
-}
-
-static int print_usage_and_die(gpr_cmdline *cl) {
-  char *usage = gpr_cmdline_usage_string(cl, cl->argv0);
-  fprintf(stderr, "%s", usage);
-  gpr_free(usage);
-  if (!cl->survive_failure) {
-    exit(1);
-  }
-  return 0;
-}
-
-static int extra_state(gpr_cmdline *cl, char *str) {
-  if (!cl->extra_arg) {
-    return print_usage_and_die(cl);
-  }
-  cl->extra_arg(cl->extra_arg_user_data, str);
-  return 1;
-}
-
-static arg *find_arg(gpr_cmdline *cl, char *name) {
-  arg *a;
-
-  for (a = cl->args; a; a = a->next) {
-    if (0 == strcmp(a->name, name)) {
-      break;
-    }
-  }
-
-  if (!a) {
-    fprintf(stderr, "Unknown argument: %s\n", name);
-    return NULL;
-  }
-
-  return a;
-}
-
-static int value_state(gpr_cmdline *cl, char *str) {
-  long intval;
-  char *end;
-
-  GPR_ASSERT(cl->cur_arg);
-
-  switch (cl->cur_arg->type) {
-    case ARGTYPE_INT:
-      intval = strtol(str, &end, 0);
-      if (*end || intval < INT_MIN || intval > INT_MAX) {
-        fprintf(stderr, "expected integer, got '%s' for %s\n", str,
-                cl->cur_arg->name);
-        return print_usage_and_die(cl);
-      }
-      *(int *)cl->cur_arg->value = (int)intval;
-      break;
-    case ARGTYPE_BOOL:
-      if (0 == strcmp(str, "1") || 0 == strcmp(str, "true")) {
-        *(int *)cl->cur_arg->value = 1;
-      } else if (0 == strcmp(str, "0") || 0 == strcmp(str, "false")) {
-        *(int *)cl->cur_arg->value = 0;
-      } else {
-        fprintf(stderr, "expected boolean, got '%s' for %s\n", str,
-                cl->cur_arg->name);
-        return print_usage_and_die(cl);
-      }
-      break;
-    case ARGTYPE_STRING:
-      *(char **)cl->cur_arg->value = str;
-      break;
-  }
-
-  cl->state = normal_state;
-  return 1;
-}
-
-static int normal_state(gpr_cmdline *cl, char *str) {
-  char *eq = NULL;
-  char *tmp = NULL;
-  char *arg_name = NULL;
-  int r = 1;
-
-  if (0 == strcmp(str, "-help") || 0 == strcmp(str, "--help") ||
-      0 == strcmp(str, "-h")) {
-    return print_usage_and_die(cl);
-  }
-
-  cl->cur_arg = NULL;
-
-  if (str[0] == '-') {
-    if (str[1] == '-') {
-      if (str[2] == 0) {
-        /* handle '--' to move to just extra args */
-        cl->state = extra_state;
-        return 1;
-      }
-      str += 2;
-    } else {
-      str += 1;
-    }
-    /* first byte of str is now past the leading '-' or '--' */
-    if (str[0] == 'n' && str[1] == 'o' && str[2] == '-') {
-      /* str is of the form '--no-foo' - it's a flag disable */
-      str += 3;
-      cl->cur_arg = find_arg(cl, str);
-      if (cl->cur_arg == NULL) {
-        return print_usage_and_die(cl);
-      }
-      if (cl->cur_arg->type != ARGTYPE_BOOL) {
-        fprintf(stderr, "%s is not a flag argument\n", str);
-        return print_usage_and_die(cl);
-      }
-      *(int *)cl->cur_arg->value = 0;
-      return 1; /* early out */
-    }
-    eq = strchr(str, '=');
-    if (eq != NULL) {
-      /* copy the string into a temp buffer and extract the name */
-      tmp = arg_name = gpr_malloc((size_t)(eq - str + 1));
-      memcpy(arg_name, str, (size_t)(eq - str));
-      arg_name[eq - str] = 0;
-    } else {
-      arg_name = str;
-    }
-    cl->cur_arg = find_arg(cl, arg_name);
-    if (cl->cur_arg == NULL) {
-      return print_usage_and_die(cl);
-    }
-    if (eq != NULL) {
-      /* str was of the type --foo=value, parse the value */
-      r = value_state(cl, eq + 1);
-    } else if (cl->cur_arg->type != ARGTYPE_BOOL) {
-      /* flag types don't have a '--foo value' variant, other types do */
-      cl->state = value_state;
-    } else {
-      /* flag parameter: just set the value */
-      *(int *)cl->cur_arg->value = 1;
-    }
-  } else {
-    r = extra_state(cl, str);
-  }
-
-  gpr_free(tmp);
-  return r;
-}
-
-int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) {
-  int i;
-
-  GPR_ASSERT(argc >= 1);
-  cl->argv0 = argv[0];
-
-  for (i = 1; i < argc; i++) {
-    if (!cl->state(cl, argv[i])) {
-      return 0;
-    }
-  }
-  return 1;
-}
diff --git a/src/core/support/cpu_linux.c b/src/core/support/cpu_linux.c
deleted file mode 100644
index 7af6a8f..0000000
--- a/src/core/support/cpu_linux.c
+++ /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.
- *
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif /* _GNU_SOURCE */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_CPU_LINUX
-
-#include <sched.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <grpc/support/cpu.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-
-static int ncpus = 0;
-
-static void init_num_cpus() {
-  /* This must be signed. sysconf returns -1 when the number cannot be
-     determined */
-  ncpus = (int)sysconf(_SC_NPROCESSORS_ONLN);
-  if (ncpus < 1) {
-    gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1");
-    ncpus = 1;
-  }
-}
-
-unsigned gpr_cpu_num_cores(void) {
-  static gpr_once once = GPR_ONCE_INIT;
-  gpr_once_init(&once, init_num_cpus);
-  return (unsigned)ncpus;
-}
-
-unsigned gpr_cpu_current_cpu(void) {
-  int cpu = sched_getcpu();
-  if (cpu < 0) {
-    gpr_log(GPR_ERROR, "Error determining current CPU: %s\n", strerror(errno));
-    return 0;
-  }
-  return (unsigned)cpu;
-}
-
-#endif /* GPR_CPU_LINUX */
diff --git a/src/core/support/cpu_posix.c b/src/core/support/cpu_posix.c
deleted file mode 100644
index 8f01c28..0000000
--- a/src/core/support/cpu_posix.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_CPU_POSIX
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-
-static __thread char magic_thread_local;
-
-static long ncpus = 0;
-
-static void init_ncpus() {
-  ncpus = sysconf(_SC_NPROCESSORS_ONLN);
-  if (ncpus < 1 || ncpus > INT32_MAX) {
-    gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1");
-    ncpus = 1;
-  }
-}
-
-unsigned gpr_cpu_num_cores(void) {
-  static gpr_once once = GPR_ONCE_INIT;
-  gpr_once_init(&once, init_ncpus);
-  return (unsigned)ncpus;
-}
-
-/* This is a cheap, but good enough, pointer hash for sharding things: */
-static size_t shard_ptr(const void *info) {
-  size_t x = (size_t)info;
-  return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) % gpr_cpu_num_cores();
-}
-
-unsigned gpr_cpu_current_cpu(void) {
-  /* NOTE: there's no way I know to return the actual cpu index portably...
-     most code that's using this is using it to shard across work queues though,
-     so here we use thread identity instead to achieve a similar though not
-     identical effect */
-  return (unsigned)shard_ptr(&magic_thread_local);
-}
-
-#endif /* GPR_CPU_POSIX */
diff --git a/src/core/support/env.h b/src/core/support/env.h
deleted file mode 100644
index 2902456..0000000
--- a/src/core/support/env.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_ENV_H
-#define GRPC_CORE_SUPPORT_ENV_H
-
-#include <stdio.h>
-
-#include <grpc/support/slice.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Env utility functions */
-
-/* Gets the environment variable value with the specified name.
-   Returns a newly allocated string. It is the responsability of the caller to
-   gpr_free the return value if not NULL (which means that the environment
-   variable exists). */
-char *gpr_getenv(const char *name);
-
-/* Sets the the environment with the specified name to the specified value. */
-void gpr_setenv(const char *name, const char *value);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_SUPPORT_ENV_H */
diff --git a/src/core/support/env_linux.c b/src/core/support/env_linux.c
deleted file mode 100644
index fe51f84..0000000
--- a/src/core/support/env_linux.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* for secure_getenv. */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_LINUX_ENV
-
-#include "src/core/support/env.h"
-
-#include <dlfcn.h>
-#include <features.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/support/string.h"
-
-char *gpr_getenv(const char *name) {
-#if defined(GPR_BACKWARDS_COMPATIBILITY_MODE)
-  typedef char *(*getenv_type)(const char *);
-  static getenv_type getenv_func = NULL;
-  /* Check to see which getenv variant is supported (go from most
-   * to least secure) */
-  const char *names[] = {"secure_getenv", "__secure_getenv", "getenv"};
-  for (size_t i = 0; getenv_func == NULL && i < GPR_ARRAY_SIZE(names); i++) {
-    getenv_func = (getenv_type)dlsym(RTLD_DEFAULT, names[i]);
-    if (getenv_func != NULL && strstr(names[i], "secure") == NULL) {
-      gpr_log(GPR_DEBUG,
-              "Warning: insecure environment read function '%s' used",
-              names[i]);
-    }
-  }
-  char *result = getenv_func(name);
-  return result == NULL ? result : gpr_strdup(result);
-#elif __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17)
-  char *result = secure_getenv(name);
-  return result == NULL ? result : gpr_strdup(result);
-#else
-  gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used",
-          "getenv");
-  char *result = getenv(name);
-  return result == NULL ? result : gpr_strdup(result);
-#endif
-}
-
-void gpr_setenv(const char *name, const char *value) {
-  int res = setenv(name, value, 1);
-  GPR_ASSERT(res == 0);
-}
-
-#endif /* GPR_LINUX_ENV */
diff --git a/src/core/support/env_posix.c b/src/core/support/env_posix.c
deleted file mode 100644
index 1dd2af5..0000000
--- a/src/core/support/env_posix.c
+++ /dev/null
@@ -1,57 +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_ENV
-
-#include "src/core/support/env.h"
-
-#include <stdlib.h>
-
-#include <grpc/support/log.h>
-
-#include "src/core/support/string.h"
-#include <grpc/support/string_util.h>
-
-char *gpr_getenv(const char *name) {
-  char *result = getenv(name);
-  return result == NULL ? result : gpr_strdup(result);
-}
-
-void gpr_setenv(const char *name, const char *value) {
-  int res = setenv(name, value, 1);
-  GPR_ASSERT(res == 0);
-}
-
-#endif /* GPR_POSIX_ENV */
diff --git a/src/core/support/env_win32.c b/src/core/support/env_win32.c
deleted file mode 100644
index 1025828..0000000
--- a/src/core/support/env_win32.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include "src/core/support/env.h"
-#include "src/core/support/string.h"
-
-#ifdef __MINGW32__
-errno_t getenv_s(size_t *size_needed, char *buffer, size_t size,
-                 const char *varname);
-#else
-#include <stdlib.h>
-#endif
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-char *gpr_getenv(const char *name) {
-  size_t size;
-  char *result = NULL;
-  errno_t err;
-
-  err = getenv_s(&size, NULL, 0, name);
-  if (err || (size == 0)) return NULL;
-  result = gpr_malloc(size);
-  err = getenv_s(&size, result, size, name);
-  if (err) {
-    gpr_free(result);
-    return NULL;
-  }
-  return result;
-}
-
-void gpr_setenv(const char *name, const char *value) {
-  errno_t res = _putenv_s(name, value);
-  GPR_ASSERT(res == 0);
-}
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/support/histogram.c b/src/core/support/histogram.c
deleted file mode 100644
index 20ed2b1..0000000
--- a/src/core/support/histogram.c
+++ /dev/null
@@ -1,244 +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/histogram.h>
-
-#include <math.h>
-#include <stddef.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-/* Histograms are stored with exponentially increasing bucket sizes.
-   The first bucket is [0, m) where m = 1 + resolution
-   Bucket n (n>=1) contains [m**n, m**(n+1))
-   There are sufficient buckets to reach max_bucket_start */
-
-struct gpr_histogram {
-  /* Sum of all values seen so far */
-  double sum;
-  /* Sum of squares of all values seen so far */
-  double sum_of_squares;
-  /* number of values seen so far */
-  double count;
-  /* m in the description */
-  double multiplier;
-  double one_on_log_multiplier;
-  /* minimum value seen */
-  double min_seen;
-  /* maximum value seen */
-  double max_seen;
-  /* maximum representable value */
-  double max_possible;
-  /* number of buckets */
-  size_t num_buckets;
-  /* the buckets themselves */
-  uint32_t *buckets;
-};
-
-/* determine a bucket index given a value - does no bounds checking */
-static size_t bucket_for_unchecked(gpr_histogram *h, double x) {
-  return (size_t)(log(x) * h->one_on_log_multiplier);
-}
-
-/* bounds checked version of the above */
-static size_t bucket_for(gpr_histogram *h, double x) {
-  size_t bucket = bucket_for_unchecked(h, GPR_CLAMP(x, 1.0, h->max_possible));
-  GPR_ASSERT(bucket < h->num_buckets);
-  return bucket;
-}
-
-/* at what value does a bucket start? */
-static double bucket_start(gpr_histogram *h, double x) {
-  return pow(h->multiplier, x);
-}
-
-gpr_histogram *gpr_histogram_create(double resolution,
-                                    double max_bucket_start) {
-  gpr_histogram *h = gpr_malloc(sizeof(gpr_histogram));
-  GPR_ASSERT(resolution > 0.0);
-  GPR_ASSERT(max_bucket_start > resolution);
-  h->sum = 0.0;
-  h->sum_of_squares = 0.0;
-  h->multiplier = 1.0 + resolution;
-  h->one_on_log_multiplier = 1.0 / log(1.0 + resolution);
-  h->max_possible = max_bucket_start;
-  h->count = 0.0;
-  h->min_seen = max_bucket_start;
-  h->max_seen = 0.0;
-  h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
-  GPR_ASSERT(h->num_buckets > 1);
-  GPR_ASSERT(h->num_buckets < 100000000);
-  h->buckets = gpr_malloc(sizeof(uint32_t) * h->num_buckets);
-  memset(h->buckets, 0, sizeof(uint32_t) * h->num_buckets);
-  return h;
-}
-
-void gpr_histogram_destroy(gpr_histogram *h) {
-  gpr_free(h->buckets);
-  gpr_free(h);
-}
-
-void gpr_histogram_add(gpr_histogram *h, double x) {
-  h->sum += x;
-  h->sum_of_squares += x * x;
-  h->count++;
-  if (x < h->min_seen) {
-    h->min_seen = x;
-  }
-  if (x > h->max_seen) {
-    h->max_seen = x;
-  }
-  h->buckets[bucket_for(h, x)]++;
-}
-
-int gpr_histogram_merge(gpr_histogram *dst, const gpr_histogram *src) {
-  if ((dst->num_buckets != src->num_buckets) ||
-      (dst->multiplier != src->multiplier)) {
-    /* Fail because these histograms don't match */
-    return 0;
-  }
-  gpr_histogram_merge_contents(dst, src->buckets, src->num_buckets,
-                               src->min_seen, src->max_seen, src->sum,
-                               src->sum_of_squares, src->count);
-  return 1;
-}
-
-void gpr_histogram_merge_contents(gpr_histogram *dst, const uint32_t *data,
-                                  size_t data_count, double min_seen,
-                                  double max_seen, double sum,
-                                  double sum_of_squares, double count) {
-  size_t i;
-  GPR_ASSERT(dst->num_buckets == data_count);
-  dst->sum += sum;
-  dst->sum_of_squares += sum_of_squares;
-  dst->count += count;
-  if (min_seen < dst->min_seen) {
-    dst->min_seen = min_seen;
-  }
-  if (max_seen > dst->max_seen) {
-    dst->max_seen = max_seen;
-  }
-  for (i = 0; i < dst->num_buckets; i++) {
-    dst->buckets[i] += data[i];
-  }
-}
-
-static double threshold_for_count_below(gpr_histogram *h, double count_below) {
-  double count_so_far;
-  double lower_bound;
-  double upper_bound;
-  size_t lower_idx;
-  size_t upper_idx;
-
-  if (h->count == 0) {
-    return 0.0;
-  }
-
-  if (count_below <= 0) {
-    return h->min_seen;
-  }
-  if (count_below >= h->count) {
-    return h->max_seen;
-  }
-
-  /* find the lowest bucket that gets us above count_below */
-  count_so_far = 0.0;
-  for (lower_idx = 0; lower_idx < h->num_buckets; lower_idx++) {
-    count_so_far += h->buckets[lower_idx];
-    if (count_so_far >= count_below) {
-      break;
-    }
-  }
-  if (count_so_far == count_below) {
-    /* this bucket hits the threshold exactly... we should be midway through
-       any run of zero values following the bucket */
-    for (upper_idx = lower_idx + 1; upper_idx < h->num_buckets; upper_idx++) {
-      if (h->buckets[upper_idx]) {
-        break;
-      }
-    }
-    return (bucket_start(h, (double)lower_idx) +
-            bucket_start(h, (double)upper_idx)) /
-           2.0;
-  } else {
-    /* treat values as uniform throughout the bucket, and find where this value
-       should lie */
-    lower_bound = bucket_start(h, (double)lower_idx);
-    upper_bound = bucket_start(h, (double)(lower_idx + 1));
-    return GPR_CLAMP(upper_bound -
-                         (upper_bound - lower_bound) *
-                             (count_so_far - count_below) /
-                             h->buckets[lower_idx],
-                     h->min_seen, h->max_seen);
-  }
-}
-
-double gpr_histogram_percentile(gpr_histogram *h, double percentile) {
-  return threshold_for_count_below(h, h->count * percentile / 100.0);
-}
-
-double gpr_histogram_mean(gpr_histogram *h) {
-  GPR_ASSERT(h->count != 0);
-  return h->sum / h->count;
-}
-
-double gpr_histogram_stddev(gpr_histogram *h) {
-  return sqrt(gpr_histogram_variance(h));
-}
-
-double gpr_histogram_variance(gpr_histogram *h) {
-  if (h->count == 0) return 0.0;
-  return (h->sum_of_squares * h->count - h->sum * h->sum) /
-         (h->count * h->count);
-}
-
-double gpr_histogram_maximum(gpr_histogram *h) { return h->max_seen; }
-
-double gpr_histogram_minimum(gpr_histogram *h) { return h->min_seen; }
-
-double gpr_histogram_count(gpr_histogram *h) { return h->count; }
-
-double gpr_histogram_sum(gpr_histogram *h) { return h->sum; }
-
-double gpr_histogram_sum_of_squares(gpr_histogram *h) {
-  return h->sum_of_squares;
-}
-
-const uint32_t *gpr_histogram_get_contents(gpr_histogram *h, size_t *size) {
-  *size = h->num_buckets;
-  return h->buckets;
-}
diff --git a/src/core/support/host_port.c b/src/core/support/host_port.c
deleted file mode 100644
index 23f65b1..0000000
--- a/src/core/support/host_port.c
+++ /dev/null
@@ -1,110 +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/host_port.h>
-
-#include <string.h>
-
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-int gpr_join_host_port(char **out, const char *host, int port) {
-  if (host[0] != '[' && strchr(host, ':') != NULL) {
-    /* IPv6 literals must be enclosed in brackets. */
-    return gpr_asprintf(out, "[%s]:%d", host, port);
-  } else {
-    /* Ordinary non-bracketed host:port. */
-    return gpr_asprintf(out, "%s:%d", host, port);
-  }
-}
-
-int gpr_split_host_port(const char *name, char **host, char **port) {
-  const char *host_start;
-  size_t host_len;
-  const char *port_start;
-
-  *host = NULL;
-  *port = NULL;
-
-  if (name[0] == '[') {
-    /* Parse a bracketed host, typically an IPv6 literal. */
-    const char *rbracket = strchr(name, ']');
-    if (rbracket == NULL) {
-      /* Unmatched [ */
-      return 0;
-    }
-    if (rbracket[1] == '\0') {
-      /* ]<end> */
-      port_start = NULL;
-    } else if (rbracket[1] == ':') {
-      /* ]:<port?> */
-      port_start = rbracket + 2;
-    } else {
-      /* ]<invalid> */
-      return 0;
-    }
-    host_start = name + 1;
-    host_len = (size_t)(rbracket - host_start);
-    if (memchr(host_start, ':', host_len) == NULL) {
-      /* Require all bracketed hosts to contain a colon, because a hostname or
-         IPv4 address should never use brackets. */
-      return 0;
-    }
-  } else {
-    const char *colon = strchr(name, ':');
-    if (colon != NULL && strchr(colon + 1, ':') == NULL) {
-      /* Exactly 1 colon.  Split into host:port. */
-      host_start = name;
-      host_len = (size_t)(colon - name);
-      port_start = colon + 1;
-    } else {
-      /* 0 or 2+ colons.  Bare hostname or IPv6 litearal. */
-      host_start = name;
-      host_len = strlen(name);
-      port_start = NULL;
-    }
-  }
-
-  /* Allocate return values. */
-  *host = gpr_malloc(host_len + 1);
-  memcpy(*host, host_start, host_len);
-  (*host)[host_len] = '\0';
-
-  if (port_start != NULL) {
-    *port = gpr_strdup(port_start);
-  }
-
-  return 1;
-}
diff --git a/src/core/support/load_file.c b/src/core/support/load_file.c
deleted file mode 100644
index 650bd62..0000000
--- a/src/core/support/load_file.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *
- * 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/support/load_file.h"
-
-#include <errno.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/support/block_annotate.h"
-#include "src/core/support/string.h"
-
-gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
-                        int *success) {
-  unsigned char *contents = NULL;
-  size_t contents_size = 0;
-  char *error_msg = NULL;
-  gpr_slice result = gpr_empty_slice();
-  FILE *file;
-  size_t bytes_read = 0;
-
-  GRPC_SCHEDULING_START_BLOCKING_REGION;
-  file = fopen(filename, "rb");
-  if (file == NULL) {
-    gpr_asprintf(&error_msg, "Could not open file %s (error = %s).", filename,
-                 strerror(errno));
-    GPR_ASSERT(error_msg != NULL);
-    goto end;
-  }
-  fseek(file, 0, SEEK_END);
-  /* Converting to size_t on the assumption that it will not fail */
-  contents_size = (size_t)ftell(file);
-  fseek(file, 0, SEEK_SET);
-  contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0));
-  bytes_read = fread(contents, 1, contents_size, file);
-  if (bytes_read < contents_size) {
-    GPR_ASSERT(ferror(file));
-    gpr_asprintf(&error_msg, "Error %s occured while reading file %s.",
-                 strerror(errno), filename);
-    GPR_ASSERT(error_msg != NULL);
-    goto end;
-  }
-  if (success != NULL) *success = 1;
-  if (add_null_terminator) {
-    contents[contents_size++] = 0;
-  }
-  result = gpr_slice_new(contents, contents_size, gpr_free);
-
-end:
-  if (error_msg != NULL) {
-    gpr_log(GPR_ERROR, "%s", error_msg);
-    gpr_free(error_msg);
-    if (success != NULL) *success = 0;
-  }
-  if (file != NULL) fclose(file);
-  GRPC_SCHEDULING_END_BLOCKING_REGION;
-  return result;
-}
diff --git a/src/core/support/load_file.h b/src/core/support/load_file.h
deleted file mode 100644
index 5896654..0000000
--- a/src/core/support/load_file.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_LOAD_FILE_H
-#define GRPC_CORE_SUPPORT_LOAD_FILE_H
-
-#include <stdio.h>
-
-#include <grpc/support/slice.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Loads the content of a file into a slice. add_null_terminator will add
-   a NULL terminator if non-zero. The success parameter, if not NULL,
-   will be set to 1 in case of success and 0 in case of failure. */
-gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
-                        int *success);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_SUPPORT_LOAD_FILE_H */
diff --git a/src/core/support/log.c b/src/core/support/log.c
deleted file mode 100644
index 04156a5..0000000
--- a/src/core/support/log.c
+++ /dev/null
@@ -1,66 +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/log.h>
-#include <grpc/support/port_platform.h>
-
-#include <stdio.h>
-#include <string.h>
-
-extern void gpr_default_log(gpr_log_func_args *args);
-static gpr_log_func g_log_func = gpr_default_log;
-
-const char *gpr_log_severity_string(gpr_log_severity severity) {
-  switch (severity) {
-    case GPR_LOG_SEVERITY_DEBUG:
-      return "D";
-    case GPR_LOG_SEVERITY_INFO:
-      return "I";
-    case GPR_LOG_SEVERITY_ERROR:
-      return "E";
-  }
-  GPR_UNREACHABLE_CODE(return "UNKNOWN");
-}
-
-void gpr_log_message(const char *file, int line, gpr_log_severity severity,
-                     const char *message) {
-  gpr_log_func_args lfargs;
-  memset(&lfargs, 0, sizeof(lfargs));
-  lfargs.file = file;
-  lfargs.line = line;
-  lfargs.severity = severity;
-  lfargs.message = message;
-  g_log_func(&lfargs);
-}
-
-void gpr_set_log_function(gpr_log_func f) { g_log_func = f; }
diff --git a/src/core/support/log_android.c b/src/core/support/log_android.c
deleted file mode 100644
index 5d0c7d8..0000000
--- a/src/core/support/log_android.c
+++ /dev/null
@@ -1,87 +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_ANDROID
-
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <android/log.h>
-
-static android_LogPriority severity_to_log_priority(gpr_log_severity severity) {
-  switch (severity) {
-    case GPR_LOG_SEVERITY_DEBUG:
-      return ANDROID_LOG_DEBUG;
-    case GPR_LOG_SEVERITY_INFO:
-      return ANDROID_LOG_INFO;
-    case GPR_LOG_SEVERITY_ERROR:
-      return ANDROID_LOG_ERROR;
-  }
-  return ANDROID_LOG_DEFAULT;
-}
-
-void gpr_log(const char *file, int line, gpr_log_severity severity,
-             const char *format, ...) {
-  char *message = NULL;
-  va_list args;
-  va_start(args, format);
-  vasprintf(&message, format, args);
-  va_end(args);
-  gpr_log_message(file, line, severity, message);
-  free(message);
-}
-
-void gpr_default_log(gpr_log_func_args *args) {
-  char *final_slash;
-  const char *display_file;
-  char *output = NULL;
-
-  final_slash = strrchr(args->file, '/');
-  if (final_slash == NULL)
-    display_file = args->file;
-  else
-    display_file = final_slash + 1;
-
-  asprintf(&output, "%s:%d] %s", display_file, args->line, args->message);
-
-  __android_log_write(severity_to_log_priority(args->severity), "GRPC", output);
-
-  /* allocated by asprintf => use free, not gpr_free */
-  free(output);
-}
-
-#endif /* GPR_ANDROID */
diff --git a/src/core/support/log_linux.c b/src/core/support/log_linux.c
deleted file mode 100644
index d66b7a3..0000000
--- a/src/core/support/log_linux.c
+++ /dev/null
@@ -1,105 +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 _POSIX_SOURCE
-#define _POSIX_SOURCE
-#endif
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_LINUX
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/time.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <linux/unistd.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-static long gettid(void) { return syscall(__NR_gettid); }
-
-void gpr_log(const char *file, int line, gpr_log_severity severity,
-             const char *format, ...) {
-  char *message = NULL;
-  va_list args;
-  va_start(args, format);
-  if (vasprintf(&message, format, args) == -1) {
-    va_end(args);
-    return;
-  }
-  va_end(args);
-  gpr_log_message(file, line, severity, message);
-  free(message);
-}
-
-void gpr_default_log(gpr_log_func_args *args) {
-  char *final_slash;
-  char *prefix;
-  const char *display_file;
-  char time_buffer[64];
-  time_t timer;
-  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
-  struct tm tm;
-
-  timer = (time_t)now.tv_sec;
-  final_slash = strrchr(args->file, '/');
-  if (final_slash == NULL)
-    display_file = args->file;
-  else
-    display_file = final_slash + 1;
-
-  if (!localtime_r(&timer, &tm)) {
-    strcpy(time_buffer, "error:localtime");
-  } else if (0 ==
-             strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
-    strcpy(time_buffer, "error:strftime");
-  }
-
-  gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]",
-               gpr_log_severity_string(args->severity), time_buffer,
-               (int)(now.tv_nsec), gettid(), display_file, args->line);
-
-  fprintf(stderr, "%-60s %s\n", prefix, args->message);
-  gpr_free(prefix);
-}
-
-#endif
diff --git a/src/core/support/log_posix.c b/src/core/support/log_posix.c
deleted file mode 100644
index 3ff171f..0000000
--- a/src/core/support/log_posix.c
+++ /dev/null
@@ -1,102 +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>
-
-#if defined(GPR_POSIX_LOG)
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-#include <pthread.h>
-
-static intptr_t gettid(void) { return (intptr_t)pthread_self(); }
-
-void gpr_log(const char *file, int line, gpr_log_severity severity,
-             const char *format, ...) {
-  char buf[64];
-  char *allocated = NULL;
-  char *message = NULL;
-  int ret;
-  va_list args;
-  va_start(args, format);
-  ret = vsnprintf(buf, sizeof(buf), format, args);
-  va_end(args);
-  if (ret < 0) {
-    message = NULL;
-  } else if ((size_t)ret <= sizeof(buf) - 1) {
-    message = buf;
-  } else {
-    message = allocated = gpr_malloc((size_t)ret + 1);
-    va_start(args, format);
-    vsnprintf(message, (size_t)(ret + 1), format, args);
-    va_end(args);
-  }
-  gpr_log_message(file, line, severity, message);
-  gpr_free(allocated);
-}
-
-void gpr_default_log(gpr_log_func_args *args) {
-  char *final_slash;
-  const char *display_file;
-  char time_buffer[64];
-  time_t timer;
-  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
-  struct tm tm;
-
-  timer = (time_t)now.tv_sec;
-  final_slash = strrchr(args->file, '/');
-  if (final_slash == NULL)
-    display_file = args->file;
-  else
-    display_file = final_slash + 1;
-
-  if (!localtime_r(&timer, &tm)) {
-    strcpy(time_buffer, "error:localtime");
-  } else if (0 ==
-             strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
-    strcpy(time_buffer, "error:strftime");
-  }
-
-  fprintf(stderr, "%s%s.%09d %7tu %s:%d] %s\n",
-          gpr_log_severity_string(args->severity), time_buffer,
-          (int)(now.tv_nsec), gettid(), display_file, args->line,
-          args->message);
-}
-
-#endif /* defined(GPR_POSIX_LOG) */
diff --git a/src/core/support/log_win32.c b/src/core/support/log_win32.c
deleted file mode 100644
index e18e667..0000000
--- a/src/core/support/log_win32.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log_win32.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/support/string.h"
-#include "src/core/support/string_win32.h"
-
-void gpr_log(const char *file, int line, gpr_log_severity severity,
-             const char *format, ...) {
-  char *message = NULL;
-  va_list args;
-  int ret;
-
-  /* Determine the length. */
-  va_start(args, format);
-  ret = _vscprintf(format, args);
-  va_end(args);
-  if (ret < 0) {
-    message = NULL;
-  } else {
-    /* Allocate a new buffer, with space for the NUL terminator. */
-    size_t strp_buflen = (size_t)ret + 1;
-    message = gpr_malloc(strp_buflen);
-
-    /* Print to the buffer. */
-    va_start(args, format);
-    ret = vsnprintf_s(message, strp_buflen, _TRUNCATE, format, args);
-    va_end(args);
-    if ((size_t)ret != strp_buflen - 1) {
-      /* This should never happen. */
-      gpr_free(message);
-      message = NULL;
-    }
-  }
-
-  gpr_log_message(file, line, severity, message);
-  gpr_free(message);
-}
-
-/* Simple starter implementation */
-void gpr_default_log(gpr_log_func_args *args) {
-  char *final_slash;
-  const char *display_file;
-  char time_buffer[64];
-  time_t timer;
-  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
-  struct tm tm;
-
-  timer = (time_t)now.tv_sec;
-  final_slash = strrchr(args->file, '\\');
-  if (final_slash == NULL)
-    display_file = args->file;
-  else
-    display_file = final_slash + 1;
-
-  if (localtime_s(&tm, &timer)) {
-    strcpy(time_buffer, "error:localtime");
-  } else if (0 ==
-             strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
-    strcpy(time_buffer, "error:strftime");
-  }
-
-  fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n",
-          gpr_log_severity_string(args->severity), time_buffer,
-          (int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line,
-          args->message);
-  fflush(stderr);
-}
-
-char *gpr_format_message(int messageid) {
-  LPTSTR tmessage;
-  char *message;
-  DWORD status = FormatMessage(
-      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
-          FORMAT_MESSAGE_IGNORE_INSERTS,
-      NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-      (LPTSTR)(&tmessage), 0, NULL);
-  if (status == 0) return gpr_strdup("Unable to retrieve error string");
-  message = gpr_tchar_to_char(tmessage);
-  LocalFree(tmessage);
-  return message;
-}
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/support/murmur_hash.c b/src/core/support/murmur_hash.c
deleted file mode 100644
index a5261c0..0000000
--- a/src/core/support/murmur_hash.c
+++ /dev/null
@@ -1,96 +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/support/murmur_hash.h"
-
-#define ROTL32(x, r) ((x) << (r)) | ((x) >> (32 - (r)))
-
-#define FMIX32(h)    \
-  (h) ^= (h) >> 16;  \
-  (h) *= 0x85ebca6b; \
-  (h) ^= (h) >> 13;  \
-  (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;
-  int i;
-
-  uint32_t h1 = seed;
-  uint32_t k1;
-
-  const uint32_t c1 = 0xcc9e2d51;
-  const uint32_t c2 = 0x1b873593;
-
-  const uint32_t *blocks = ((const uint32_t *)key) + nblocks;
-  const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
-
-  /* body */
-  for (i = -(int)nblocks; i; i++) {
-    k1 = GETBLOCK32(blocks, i);
-
-    k1 *= c1;
-    k1 = ROTL32(k1, 15);
-    k1 *= c2;
-
-    h1 ^= k1;
-    h1 = ROTL32(h1, 13);
-    h1 = h1 * 5 + 0xe6546b64;
-  }
-
-  k1 = 0;
-
-  /* tail */
-  switch (len & 3) {
-    case 3:
-      k1 ^= ((uint32_t)tail[2]) << 16;
-    case 2:
-      k1 ^= ((uint32_t)tail[1]) << 8;
-    case 1:
-      k1 ^= tail[0];
-      k1 *= c1;
-      k1 = ROTL32(k1, 15);
-      k1 *= c2;
-      h1 ^= k1;
-  };
-
-  /* finalization */
-  h1 ^= (uint32_t)len;
-  FMIX32(h1);
-  return h1;
-}
diff --git a/src/core/support/murmur_hash.h b/src/core/support/murmur_hash.h
deleted file mode 100644
index 0f0b399..0000000
--- a/src/core/support/murmur_hash.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_MURMUR_HASH_H
-#define GRPC_CORE_SUPPORT_MURMUR_HASH_H
-
-#include <grpc/support/port_platform.h>
-
-#include <stddef.h>
-
-/* compute the hash of key (length len) */
-uint32_t gpr_murmur_hash3(const void *key, size_t len, uint32_t seed);
-
-#endif /* GRPC_CORE_SUPPORT_MURMUR_HASH_H */
diff --git a/src/core/support/stack_lockfree.c b/src/core/support/stack_lockfree.c
deleted file mode 100644
index 9daecd2..0000000
--- a/src/core/support/stack_lockfree.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- *
- * 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/support/stack_lockfree.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/port_platform.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/log.h>
-
-/* The lockfree node structure is a single architecture-level
-   word that allows for an atomic CAS to set it up. */
-struct lockfree_node_contents {
-  /* next thing to look at. Actual index for head, next index otherwise */
-  uint16_t index;
-#ifdef GPR_ARCH_64
-  uint16_t pad;
-  uint32_t aba_ctr;
-#else
-#ifdef GPR_ARCH_32
-  uint16_t aba_ctr;
-#else
-#error Unsupported bit width architecture
-#endif
-#endif
-};
-
-/* Use a union to make sure that these are in the same bits as an atm word */
-typedef union lockfree_node {
-  gpr_atm atm;
-  struct lockfree_node_contents contents;
-} lockfree_node;
-
-#define ENTRY_ALIGNMENT_BITS 3 /* make sure that entries aligned to 8-bytes */
-#define INVALID_ENTRY_INDEX                        \
-  ((1 << 16) - 1) /* reserve this entry as invalid \
-                    */
-
-struct gpr_stack_lockfree {
-  lockfree_node *entries;
-  lockfree_node head; /* An atomic entry describing curr head */
-
-#ifndef NDEBUG
-  /* Bitmap of pushed entries to check for double-push or pop */
-  gpr_atm pushed[(INVALID_ENTRY_INDEX + 1) / (8 * sizeof(gpr_atm))];
-#endif
-};
-
-gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries) {
-  gpr_stack_lockfree *stack;
-  stack = gpr_malloc(sizeof(*stack));
-  /* Since we only allocate 16 bits to represent an entry number,
-   * make sure that we are within the desired range */
-  /* Reserve the highest entry number as a dummy */
-  GPR_ASSERT(entries < INVALID_ENTRY_INDEX);
-  stack->entries = gpr_malloc_aligned(entries * sizeof(stack->entries[0]),
-                                      ENTRY_ALIGNMENT_BITS);
-  /* Clear out all entries */
-  memset(stack->entries, 0, entries * sizeof(stack->entries[0]));
-  memset(&stack->head, 0, sizeof(stack->head));
-#ifndef NDEBUG
-  memset(&stack->pushed, 0, sizeof(stack->pushed));
-#endif
-
-  GPR_ASSERT(sizeof(stack->entries->atm) == sizeof(stack->entries->contents));
-
-  /* Point the head at reserved dummy entry */
-  stack->head.contents.index = INVALID_ENTRY_INDEX;
-/* Fill in the pad and aba_ctr to avoid confusing memcheck tools */
-#ifdef GPR_ARCH_64
-  stack->head.contents.pad = 0;
-#endif
-  stack->head.contents.aba_ctr = 0;
-  return stack;
-}
-
-void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack) {
-  gpr_free_aligned(stack->entries);
-  gpr_free(stack);
-}
-
-int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
-  lockfree_node head;
-  lockfree_node newhead;
-  lockfree_node curent;
-  lockfree_node newent;
-
-  /* First fill in the entry's index and aba ctr for new head */
-  newhead.contents.index = (uint16_t)entry;
-#ifdef GPR_ARCH_64
-  /* Fill in the pad to avoid confusing memcheck tools */
-  newhead.contents.pad = 0;
-#endif
-
-  /* Also post-increment the aba_ctr */
-  curent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
-  newhead.contents.aba_ctr = ++curent.contents.aba_ctr;
-  gpr_atm_no_barrier_store(&stack->entries[entry].atm, curent.atm);
-
-#ifndef NDEBUG
-  /* Check for double push */
-  {
-    int pushed_index = entry / (int)(8 * sizeof(gpr_atm));
-    int pushed_bit = entry % (int)(8 * sizeof(gpr_atm));
-    gpr_atm old_val;
-
-    old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index],
-                                           ((gpr_atm)1 << pushed_bit));
-    GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) == 0);
-  }
-#endif
-
-  do {
-    /* Atomically get the existing head value for use */
-    head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
-    /* Point to it */
-    newent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
-    newent.contents.index = head.contents.index;
-    gpr_atm_no_barrier_store(&stack->entries[entry].atm, newent.atm);
-  } while (!gpr_atm_rel_cas(&(stack->head.atm), head.atm, newhead.atm));
-  /* Use rel_cas above to make sure that entry index is set properly */
-  return head.contents.index == INVALID_ENTRY_INDEX;
-}
-
-int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) {
-  lockfree_node head;
-  lockfree_node newhead;
-
-  do {
-    head.atm = gpr_atm_acq_load(&(stack->head.atm));
-    if (head.contents.index == INVALID_ENTRY_INDEX) {
-      return -1;
-    }
-    newhead.atm =
-        gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm));
-
-  } while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm));
-#ifndef NDEBUG
-  /* Check for valid pop */
-  {
-    int pushed_index = head.contents.index / (8 * sizeof(gpr_atm));
-    int pushed_bit = head.contents.index % (8 * sizeof(gpr_atm));
-    gpr_atm old_val;
-
-    old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index],
-                                           -((gpr_atm)1 << pushed_bit));
-    GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) != 0);
-  }
-#endif
-
-  return head.contents.index;
-}
diff --git a/src/core/support/stack_lockfree.h b/src/core/support/stack_lockfree.h
deleted file mode 100644
index d6fd06d..0000000
--- a/src/core/support/stack_lockfree.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_STACK_LOCKFREE_H
-#define GRPC_CORE_SUPPORT_STACK_LOCKFREE_H
-
-#include <stddef.h>
-
-typedef struct gpr_stack_lockfree gpr_stack_lockfree;
-
-/* This stack must specify the maximum number of entries to track.
-   The current implementation only allows up to 65534 entries */
-gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries);
-void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack);
-
-/* Pass in a valid entry number for the next stack entry */
-/* Returns 1 if this is the first element on the stack, 0 otherwise */
-int gpr_stack_lockfree_push(gpr_stack_lockfree *, int entry);
-
-/* Returns -1 on empty or the actual entry number */
-int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack);
-
-#endif /* GRPC_CORE_SUPPORT_STACK_LOCKFREE_H */
diff --git a/src/core/support/string.c b/src/core/support/string.c
deleted file mode 100644
index 1f541de..0000000
--- a/src/core/support/string.c
+++ /dev/null
@@ -1,296 +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/support/string.h"
-
-#include <ctype.h>
-#include <stddef.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/useful.h>
-
-char *gpr_strdup(const char *src) {
-  char *dst;
-  size_t len;
-
-  if (!src) {
-    return NULL;
-  }
-
-  len = strlen(src) + 1;
-  dst = gpr_malloc(len);
-
-  memcpy(dst, src, len);
-
-  return dst;
-}
-
-typedef struct {
-  size_t capacity;
-  size_t length;
-  char *data;
-} dump_out;
-
-static dump_out dump_out_create(void) {
-  dump_out r = {0, 0, NULL};
-  return r;
-}
-
-static void dump_out_append(dump_out *out, char c) {
-  if (out->length == out->capacity) {
-    out->capacity = GPR_MAX(8, 2 * out->capacity);
-    out->data = gpr_realloc(out->data, out->capacity);
-  }
-  out->data[out->length++] = c;
-}
-
-static void hexdump(dump_out *out, const char *buf, size_t len) {
-  static const char hex[16] = "0123456789abcdef";
-
-  const uint8_t *const beg = (const uint8_t *)buf;
-  const uint8_t *const end = beg + len;
-  const uint8_t *cur;
-
-  for (cur = beg; cur != end; ++cur) {
-    if (cur != beg) dump_out_append(out, ' ');
-    dump_out_append(out, hex[*cur >> 4]);
-    dump_out_append(out, hex[*cur & 0xf]);
-  }
-}
-
-static void asciidump(dump_out *out, const char *buf, size_t len) {
-  const uint8_t *const beg = (const uint8_t *)buf;
-  const uint8_t *const end = beg + len;
-  const uint8_t *cur;
-  int out_was_empty = (out->length == 0);
-  if (!out_was_empty) {
-    dump_out_append(out, ' ');
-    dump_out_append(out, '\'');
-  }
-  for (cur = beg; cur != end; ++cur) {
-    dump_out_append(out, (char)(isprint(*cur) ? *(char *)cur : '.'));
-  }
-  if (!out_was_empty) {
-    dump_out_append(out, '\'');
-  }
-}
-
-char *gpr_dump(const char *buf, size_t len, uint32_t flags) {
-  dump_out out = dump_out_create();
-  if (flags & GPR_DUMP_HEX) {
-    hexdump(&out, buf, len);
-  }
-  if (flags & GPR_DUMP_ASCII) {
-    asciidump(&out, buf, len);
-  }
-  dump_out_append(&out, 0);
-  return out.data;
-}
-
-char *gpr_dump_slice(gpr_slice s, uint32_t flags) {
-  return gpr_dump((const char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s),
-                  flags);
-}
-
-int gpr_parse_bytes_to_uint32(const char *buf, size_t len, uint32_t *result) {
-  uint32_t out = 0;
-  uint32_t new;
-  size_t i;
-
-  if (len == 0) return 0; /* must have some bytes */
-
-  for (i = 0; i < len; i++) {
-    if (buf[i] < '0' || buf[i] > '9') return 0; /* bad char */
-    new = 10 * out + (uint32_t)(buf[i] - '0');
-    if (new < out) return 0; /* overflow */
-    out = new;
-  }
-
-  *result = out;
-  return 1;
-}
-
-void gpr_reverse_bytes(char *str, int len) {
-  char *p1, *p2;
-  for (p1 = str, p2 = str + len - 1; p2 > p1; ++p1, --p2) {
-    char temp = *p1;
-    *p1 = *p2;
-    *p2 = temp;
-  }
-}
-
-int gpr_ltoa(long value, char *string) {
-  long sign;
-  int i = 0;
-
-  if (value == 0) {
-    string[0] = '0';
-    string[1] = 0;
-    return 1;
-  }
-
-  sign = value < 0 ? -1 : 1;
-  while (value) {
-    string[i++] = (char)('0' + sign * (value % 10));
-    value /= 10;
-  }
-  if (sign < 0) string[i++] = '-';
-  gpr_reverse_bytes(string, i);
-  string[i] = 0;
-  return i;
-}
-
-int int64_ttoa(int64_t value, char *string) {
-  int64_t sign;
-  int i = 0;
-
-  if (value == 0) {
-    string[0] = '0';
-    string[1] = 0;
-    return 1;
-  }
-
-  sign = value < 0 ? -1 : 1;
-  while (value) {
-    string[i++] = (char)('0' + sign * (value % 10));
-    value /= 10;
-  }
-  if (sign < 0) string[i++] = '-';
-  gpr_reverse_bytes(string, i);
-  string[i] = 0;
-  return i;
-}
-
-char *gpr_strjoin(const char **strs, size_t nstrs, size_t *final_length) {
-  return gpr_strjoin_sep(strs, nstrs, "", final_length);
-}
-
-char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep,
-                      size_t *final_length) {
-  const size_t sep_len = strlen(sep);
-  size_t out_length = 0;
-  size_t i;
-  char *out;
-  for (i = 0; i < nstrs; i++) {
-    out_length += strlen(strs[i]);
-  }
-  out_length += 1; /* null terminator */
-  if (nstrs > 0) {
-    out_length += sep_len * (nstrs - 1); /* separators */
-  }
-  out = gpr_malloc(out_length);
-  out_length = 0;
-  for (i = 0; i < nstrs; i++) {
-    const size_t slen = strlen(strs[i]);
-    if (i != 0) {
-      memcpy(out + out_length, sep, sep_len);
-      out_length += sep_len;
-    }
-    memcpy(out + out_length, strs[i], slen);
-    out_length += slen;
-  }
-  out[out_length] = 0;
-  if (final_length != NULL) {
-    *final_length = out_length;
-  }
-  return out;
-}
-
-/** Finds the initial (\a begin) and final (\a end) offsets of the next
- * substring from \a str + \a read_offset until the next \a sep or the end of \a
- * str.
- *
- * Returns 1 and updates \a begin and \a end. Returns 0 otherwise. */
-static int slice_find_separator_offset(const gpr_slice str, const char *sep,
-                                       const size_t read_offset, size_t *begin,
-                                       size_t *end) {
-  size_t i;
-  const uint8_t *str_ptr = GPR_SLICE_START_PTR(str) + read_offset;
-  const size_t str_len = GPR_SLICE_LENGTH(str) - read_offset;
-  const size_t sep_len = strlen(sep);
-  if (str_len < sep_len) {
-    return 0;
-  }
-
-  for (i = 0; i <= str_len - sep_len; i++) {
-    if (memcmp(str_ptr + i, sep, sep_len) == 0) {
-      *begin = read_offset;
-      *end = read_offset + i;
-      return 1;
-    }
-  }
-  return 0;
-}
-
-void gpr_slice_split(gpr_slice str, const char *sep, gpr_slice_buffer *dst) {
-  const size_t sep_len = strlen(sep);
-  size_t begin, end;
-
-  GPR_ASSERT(sep_len > 0);
-
-  if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) {
-    do {
-      gpr_slice_buffer_add_indexed(dst, gpr_slice_sub(str, begin, end));
-    } while (slice_find_separator_offset(str, sep, end + sep_len, &begin,
-                                         &end) != 0);
-    gpr_slice_buffer_add_indexed(
-        dst, gpr_slice_sub(str, end + sep_len, GPR_SLICE_LENGTH(str)));
-  } else { /* no sep found, add whole input */
-    gpr_slice_buffer_add_indexed(dst, gpr_slice_ref(str));
-  }
-}
-
-void gpr_strvec_init(gpr_strvec *sv) { memset(sv, 0, sizeof(*sv)); }
-
-void gpr_strvec_destroy(gpr_strvec *sv) {
-  size_t i;
-  for (i = 0; i < sv->count; i++) {
-    gpr_free(sv->strs[i]);
-  }
-  gpr_free(sv->strs);
-}
-
-void gpr_strvec_add(gpr_strvec *sv, char *str) {
-  if (sv->count == sv->capacity) {
-    sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
-    sv->strs = gpr_realloc(sv->strs, sizeof(char *) * sv->capacity);
-  }
-  sv->strs[sv->count++] = str;
-}
-
-char *gpr_strvec_flatten(gpr_strvec *sv, size_t *final_length) {
-  return gpr_strjoin((const char **)sv->strs, sv->count, final_length);
-}
diff --git a/src/core/support/string.h b/src/core/support/string.h
deleted file mode 100644
index a367ed7..0000000
--- a/src/core/support/string.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_STRING_H
-#define GRPC_CORE_SUPPORT_STRING_H
-
-#include <stddef.h>
-
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/slice.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* String utility functions */
-
-/* Flags for gpr_dump function. */
-#define GPR_DUMP_HEX 0x00000001
-#define GPR_DUMP_ASCII 0x00000002
-
-/* Converts array buf, of length len, into a C string  according to the flags.
-   Result should be freed with gpr_free() */
-char *gpr_dump(const char *buf, size_t len, uint32_t flags);
-
-/* Calls gpr_dump on a slice. */
-char *gpr_dump_slice(gpr_slice slice, uint32_t flags);
-
-/* Parses an array of bytes into an integer (base 10). Returns 1 on success,
-   0 on failure. */
-int gpr_parse_bytes_to_uint32(const char *data, size_t length,
-                              uint32_t *result);
-
-/* Minimum buffer size for calling ltoa */
-#define GPR_LTOA_MIN_BUFSIZE (3 * sizeof(long))
-
-/* Convert a long to a string in base 10; returns the length of the
-   output string (or 0 on failure).
-   output must be at least GPR_LTOA_MIN_BUFSIZE bytes long. */
-int gpr_ltoa(long value, char *output);
-
-/* Minimum buffer size for calling int64toa */
-#define GPR_INT64TOA_MIN_BUFSIZE (3 * sizeof(int64_t))
-
-/* Convert an int64 to a string in base 10; returns the length of the
-output string (or 0 on failure).
-output must be at least GPR_INT64TOA_MIN_BUFSIZE bytes long.
-NOTE: This function ensures sufficient bit width even on Win x64,
-where long is 32bit is size.*/
-int int64_ttoa(int64_t value, char *output);
-
-/* Reverse a run of bytes */
-void gpr_reverse_bytes(char *str, int len);
-
-/* Join a set of strings, returning the resulting string.
-   Total combined length (excluding null terminator) is returned in total_length
-   if it is non-null. */
-char *gpr_strjoin(const char **strs, size_t nstrs, size_t *total_length);
-
-/* Join a set of strings using a separator, returning the resulting string.
-   Total combined length (excluding null terminator) is returned in total_length
-   if it is non-null. */
-char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep,
-                      size_t *total_length);
-
-/** Split \a str by the separator \a sep. Results are stored in \a dst, which
- * should be a properly initialized instance. */
-void gpr_slice_split(gpr_slice str, const char *sep, gpr_slice_buffer *dst);
-
-/* A vector of strings... for building up a final string one piece at a time */
-typedef struct {
-  char **strs;
-  size_t count;
-  size_t capacity;
-} gpr_strvec;
-
-/* Initialize/destroy */
-void gpr_strvec_init(gpr_strvec *strs);
-void gpr_strvec_destroy(gpr_strvec *strs);
-/* Add a string to a strvec, takes ownership of the string */
-void gpr_strvec_add(gpr_strvec *strs, char *add);
-/* Return a joined string with all added substrings, optionally setting
-   total_length as per gpr_strjoin */
-char *gpr_strvec_flatten(gpr_strvec *strs, size_t *total_length);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_SUPPORT_STRING_H */
diff --git a/src/core/support/string_posix.c b/src/core/support/string_posix.c
deleted file mode 100644
index 25c333d..0000000
--- a/src/core/support/string_posix.c
+++ /dev/null
@@ -1,86 +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_STRING
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-int gpr_asprintf(char **strp, const char *format, ...) {
-  va_list args;
-  int ret;
-  char buf[64];
-  size_t strp_buflen;
-
-  /* Use a constant-sized buffer to determine the length. */
-  va_start(args, format);
-  ret = vsnprintf(buf, sizeof(buf), format, args);
-  va_end(args);
-  if (ret < 0) {
-    *strp = NULL;
-    return -1;
-  }
-
-  /* Allocate a new buffer, with space for the NUL terminator. */
-  strp_buflen = (size_t)ret + 1;
-  if ((*strp = gpr_malloc(strp_buflen)) == NULL) {
-    /* This shouldn't happen, because gpr_malloc() calls abort(). */
-    return -1;
-  }
-
-  /* Return early if we have all the bytes. */
-  if (strp_buflen <= sizeof(buf)) {
-    memcpy(*strp, buf, strp_buflen);
-    return ret;
-  }
-
-  /* Try again using the larger buffer. */
-  va_start(args, format);
-  ret = vsnprintf(*strp, strp_buflen, format, args);
-  va_end(args);
-  if ((size_t)ret == strp_buflen - 1) {
-    return ret;
-  }
-
-  /* This should never happen. */
-  gpr_free(*strp);
-  *strp = NULL;
-  return -1;
-}
-
-#endif /* GPR_POSIX_STRING */
diff --git a/src/core/support/string_win32.c b/src/core/support/string_win32.c
deleted file mode 100644
index 3b1f702..0000000
--- a/src/core/support/string_win32.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Posix code for gpr snprintf support. */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-#include "src/core/support/string.h"
-
-int gpr_asprintf(char **strp, const char *format, ...) {
-  va_list args;
-  int ret;
-  size_t strp_buflen;
-
-  /* Determine the length. */
-  va_start(args, format);
-  ret = _vscprintf(format, args);
-  va_end(args);
-  if (ret < 0) {
-    *strp = NULL;
-    return -1;
-  }
-
-  /* Allocate a new buffer, with space for the NUL terminator. */
-  strp_buflen = (size_t)ret + 1;
-  if ((*strp = gpr_malloc(strp_buflen)) == NULL) {
-    /* This shouldn't happen, because gpr_malloc() calls abort(). */
-    return -1;
-  }
-
-  /* Print to the buffer. */
-  va_start(args, format);
-  ret = vsnprintf_s(*strp, strp_buflen, _TRUNCATE, format, args);
-  va_end(args);
-  if ((size_t)ret == strp_buflen - 1) {
-    return ret;
-  }
-
-  /* This should never happen. */
-  gpr_free(*strp);
-  *strp = NULL;
-  return -1;
-}
-
-#if defined UNICODE || defined _UNICODE
-LPTSTR
-gpr_char_to_tchar(LPCSTR input) {
-  LPTSTR ret;
-  int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
-  if (needed <= 0) return NULL;
-  ret = gpr_malloc((unsigned)needed * sizeof(TCHAR));
-  MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed);
-  return ret;
-}
-
-LPSTR
-gpr_tchar_to_char(LPCTSTR input) {
-  LPSTR ret;
-  int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL);
-  if (needed <= 0) return NULL;
-  ret = gpr_malloc((unsigned)needed);
-  WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL);
-  return ret;
-}
-#else
-char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); }
-
-char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); }
-#endif
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/support/string_win32.h b/src/core/support/string_win32.h
deleted file mode 100644
index c9ae8d9..0000000
--- a/src/core/support/string_win32.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_STRING_WIN32_H
-#define GRPC_CORE_SUPPORT_STRING_WIN32_H
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-/* These allocate new strings using gpr_malloc to convert from and to utf-8. */
-LPTSTR gpr_char_to_tchar(LPCSTR input);
-LPSTR gpr_tchar_to_char(LPCTSTR input);
-
-#endif /* GPR_WIN32 */
-
-#endif /* GRPC_CORE_SUPPORT_STRING_WIN32_H */
diff --git a/src/core/support/subprocess_posix.c b/src/core/support/subprocess_posix.c
deleted file mode 100644
index 171054e..0000000
--- a/src/core/support/subprocess_posix.c
+++ /dev/null
@@ -1,112 +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_SUBPROCESS
-
-#include <grpc/support/subprocess.h>
-
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-struct gpr_subprocess {
-  int pid;
-  int joined;
-};
-
-const char *gpr_subprocess_binary_extension() { return ""; }
-
-gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
-  gpr_subprocess *r;
-  int pid;
-  char **exec_args;
-
-  pid = fork();
-  if (pid == -1) {
-    return NULL;
-  } else if (pid == 0) {
-    exec_args = gpr_malloc(((size_t)argc + 1) * sizeof(char *));
-    memcpy(exec_args, argv, (size_t)argc * sizeof(char *));
-    exec_args[argc] = NULL;
-    execv(exec_args[0], exec_args);
-    /* if we reach here, an error has occurred */
-    gpr_log(GPR_ERROR, "execv '%s' failed: %s", exec_args[0], strerror(errno));
-    _exit(1);
-    return NULL;
-  } else {
-    r = gpr_malloc(sizeof(gpr_subprocess));
-    memset(r, 0, sizeof(*r));
-    r->pid = pid;
-    return r;
-  }
-}
-
-void gpr_subprocess_destroy(gpr_subprocess *p) {
-  if (!p->joined) {
-    kill(p->pid, SIGKILL);
-    gpr_subprocess_join(p);
-  }
-  gpr_free(p);
-}
-
-int gpr_subprocess_join(gpr_subprocess *p) {
-  int status;
-retry:
-  if (waitpid(p->pid, &status, 0) == -1) {
-    if (errno == EINTR) {
-      goto retry;
-    }
-    gpr_log(GPR_ERROR, "waitpid failed: %s", strerror(errno));
-    return -1;
-  }
-  return status;
-}
-
-void gpr_subprocess_interrupt(gpr_subprocess *p) {
-  if (!p->joined) {
-    kill(p->pid, SIGINT);
-  }
-}
-
-#endif /* GPR_POSIX_SUBPROCESS */
diff --git a/src/core/support/subprocess_windows.c b/src/core/support/subprocess_windows.c
deleted file mode 100644
index 2b25ef0..0000000
--- a/src/core/support/subprocess_windows.c
+++ /dev/null
@@ -1,141 +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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WINDOWS_SUBPROCESS
-
-#include <windows.h>
-#include <string.h>
-#include <tchar.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/subprocess.h>
-#include "src/core/support/string.h"
-#include "src/core/support/string_win32.h"
-
-struct gpr_subprocess {
-  PROCESS_INFORMATION pi;
-  int joined;
-  int interrupted;
-};
-
-const char *gpr_subprocess_binary_extension() { return ".exe"; }
-
-gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
-  gpr_subprocess *r;
-
-  STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-
-  char *args = gpr_strjoin_sep(argv, (size_t)argc, " ", NULL);
-  TCHAR *args_tchar;
-
-  args_tchar = gpr_char_to_tchar(args);
-  gpr_free(args);
-
-  memset(&si, 0, sizeof(si));
-  si.cb = sizeof(si);
-  memset(&pi, 0, sizeof(pi));
-
-  if (!CreateProcess(NULL, args_tchar, NULL, NULL, FALSE,
-                     CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) {
-    gpr_free(args_tchar);
-    return NULL;
-  }
-  gpr_free(args_tchar);
-
-  r = gpr_malloc(sizeof(gpr_subprocess));
-  memset(r, 0, sizeof(*r));
-  r->pi = pi;
-  return r;
-}
-
-void gpr_subprocess_destroy(gpr_subprocess *p) {
-  if (p) {
-    if (!p->joined) {
-      gpr_subprocess_interrupt(p);
-      gpr_subprocess_join(p);
-    }
-    if (p->pi.hProcess) {
-      CloseHandle(p->pi.hProcess);
-    }
-    if (p->pi.hThread) {
-      CloseHandle(p->pi.hThread);
-    }
-    gpr_free(p);
-  }
-}
-
-int gpr_subprocess_join(gpr_subprocess *p) {
-  DWORD dwExitCode;
-  if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
-    if (dwExitCode == STILL_ACTIVE) {
-      if (WaitForSingleObject(p->pi.hProcess, INFINITE) == WAIT_OBJECT_0) {
-        p->joined = 1;
-        goto getExitCode;
-      }
-      return -1;  // failed to join
-    } else {
-      goto getExitCode;
-    }
-  } else {
-    return -1;  // failed to get exit code
-  }
-
-getExitCode:
-  if (p->interrupted) {
-    return 0;
-  }
-  if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
-    return (int)dwExitCode;
-  } else {
-    return -1;  // failed to get exit code
-  }
-}
-
-void gpr_subprocess_interrupt(gpr_subprocess *p) {
-  DWORD dwExitCode;
-  if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
-    if (dwExitCode == STILL_ACTIVE) {
-      gpr_log(GPR_INFO, "sending ctrl-break");
-      GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, p->pi.dwProcessId);
-      p->joined = 1;
-      p->interrupted = 1;
-    }
-  }
-  return;
-}
-
-#endif /* GPR_WINDOWS_SUBPROCESS */
diff --git a/src/core/support/sync.c b/src/core/support/sync.c
deleted file mode 100644
index 69e3e39..0000000
--- a/src/core/support/sync.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Generic implementation of synchronization primitives. */
-
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/atm.h>
-
-/* Number of mutexes to allocate for events, to avoid lock contention.
-   Should be a prime. */
-enum { event_sync_partitions = 31 };
-
-/* Events are partitioned by address to avoid lock contention. */
-static struct sync_array_s {
-  gpr_mu mu;
-  gpr_cv cv;
-} sync_array[event_sync_partitions];
-
-/* This routine is executed once on first use, via event_once */
-static gpr_once event_once = GPR_ONCE_INIT;
-static void event_initialize(void) {
-  int i;
-  for (i = 0; i != event_sync_partitions; i++) {
-    gpr_mu_init(&sync_array[i].mu);
-    gpr_cv_init(&sync_array[i].cv);
-  }
-}
-
-/* Hash ev into an element of sync_array[]. */
-static struct sync_array_s *hash(gpr_event *ev) {
-  return &sync_array[((uintptr_t)ev) % event_sync_partitions];
-}
-
-void gpr_event_init(gpr_event *ev) {
-  gpr_once_init(&event_once, &event_initialize);
-  ev->state = 0;
-}
-
-void gpr_event_set(gpr_event *ev, void *value) {
-  struct sync_array_s *s = hash(ev);
-  gpr_mu_lock(&s->mu);
-  GPR_ASSERT(gpr_atm_acq_load(&ev->state) == 0);
-  gpr_atm_rel_store(&ev->state, (gpr_atm)value);
-  gpr_cv_broadcast(&s->cv);
-  gpr_mu_unlock(&s->mu);
-  GPR_ASSERT(value != NULL);
-}
-
-void *gpr_event_get(gpr_event *ev) {
-  return (void *)gpr_atm_acq_load(&ev->state);
-}
-
-void *gpr_event_wait(gpr_event *ev, gpr_timespec abs_deadline) {
-  void *result = (void *)gpr_atm_acq_load(&ev->state);
-  if (result == NULL) {
-    struct sync_array_s *s = hash(ev);
-    gpr_mu_lock(&s->mu);
-    do {
-      result = (void *)gpr_atm_acq_load(&ev->state);
-    } while (result == NULL && !gpr_cv_wait(&s->cv, &s->mu, abs_deadline));
-    gpr_mu_unlock(&s->mu);
-  }
-  return result;
-}
-
-void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
-
-void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
-
-void gpr_ref_non_zero(gpr_refcount *r) {
-  gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
-  GPR_ASSERT(prior > 0);
-}
-
-void gpr_refn(gpr_refcount *r, int n) {
-  gpr_atm_no_barrier_fetch_add(&r->count, n);
-}
-
-int gpr_unref(gpr_refcount *r) {
-  gpr_atm prior = gpr_atm_full_fetch_add(&r->count, -1);
-  GPR_ASSERT(prior > 0);
-  return prior == 1;
-}
-
-void gpr_stats_init(gpr_stats_counter *c, intptr_t n) {
-  gpr_atm_rel_store(&c->value, n);
-}
-
-void gpr_stats_inc(gpr_stats_counter *c, intptr_t inc) {
-  gpr_atm_no_barrier_fetch_add(&c->value, inc);
-}
-
-intptr_t gpr_stats_read(const gpr_stats_counter *c) {
-  /* don't need acquire-load, but we have no no-barrier load yet */
-  return gpr_atm_acq_load(&c->value);
-}
diff --git a/src/core/support/sync_posix.c b/src/core/support/sync_posix.c
deleted file mode 100644
index d3c483f..0000000
--- a/src/core/support/sync_posix.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SYNC
-
-#include <errno.h>
-#include <time.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-#include "src/core/profiling/timers.h"
-
-void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
-
-void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); }
-
-void gpr_mu_lock(gpr_mu* mu) {
-  GPR_TIMER_BEGIN("gpr_mu_lock", 0);
-  GPR_ASSERT(pthread_mutex_lock(mu) == 0);
-  GPR_TIMER_END("gpr_mu_lock", 0);
-}
-
-void gpr_mu_unlock(gpr_mu* mu) {
-  GPR_TIMER_BEGIN("gpr_mu_unlock", 0);
-  GPR_ASSERT(pthread_mutex_unlock(mu) == 0);
-  GPR_TIMER_END("gpr_mu_unlock", 0);
-}
-
-int gpr_mu_trylock(gpr_mu* mu) {
-  int err;
-  GPR_TIMER_BEGIN("gpr_mu_trylock", 0);
-  err = pthread_mutex_trylock(mu);
-  GPR_ASSERT(err == 0 || err == EBUSY);
-  GPR_TIMER_END("gpr_mu_trylock", 0);
-  return err == 0;
-}
-
-/*----------------------------------------*/
-
-void gpr_cv_init(gpr_cv* cv) { GPR_ASSERT(pthread_cond_init(cv, NULL) == 0); }
-
-void gpr_cv_destroy(gpr_cv* cv) { GPR_ASSERT(pthread_cond_destroy(cv) == 0); }
-
-int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) {
-  int err = 0;
-  if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) ==
-      0) {
-    err = pthread_cond_wait(cv, mu);
-  } else {
-    struct timespec abs_deadline_ts;
-    abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME);
-    abs_deadline_ts.tv_sec = (time_t)abs_deadline.tv_sec;
-    abs_deadline_ts.tv_nsec = abs_deadline.tv_nsec;
-    err = pthread_cond_timedwait(cv, mu, &abs_deadline_ts);
-  }
-  GPR_ASSERT(err == 0 || err == ETIMEDOUT || err == EAGAIN);
-  return err == ETIMEDOUT;
-}
-
-void gpr_cv_signal(gpr_cv* cv) { GPR_ASSERT(pthread_cond_signal(cv) == 0); }
-
-void gpr_cv_broadcast(gpr_cv* cv) {
-  GPR_ASSERT(pthread_cond_broadcast(cv) == 0);
-}
-
-/*----------------------------------------*/
-
-void gpr_once_init(gpr_once* once, void (*init_function)(void)) {
-  GPR_ASSERT(pthread_once(once, init_function) == 0);
-}
-
-#endif /* GRP_POSIX_SYNC */
diff --git a/src/core/support/sync_win32.c b/src/core/support/sync_win32.c
deleted file mode 100644
index 41998eb..0000000
--- a/src/core/support/sync_win32.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Win32 code for gpr synchronization support. */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-void gpr_mu_init(gpr_mu *mu) {
-  InitializeCriticalSection(&mu->cs);
-  mu->locked = 0;
-}
-
-void gpr_mu_destroy(gpr_mu *mu) { DeleteCriticalSection(&mu->cs); }
-
-void gpr_mu_lock(gpr_mu *mu) {
-  EnterCriticalSection(&mu->cs);
-  GPR_ASSERT(!mu->locked);
-  mu->locked = 1;
-}
-
-void gpr_mu_unlock(gpr_mu *mu) {
-  mu->locked = 0;
-  LeaveCriticalSection(&mu->cs);
-}
-
-int gpr_mu_trylock(gpr_mu *mu) {
-  int result = TryEnterCriticalSection(&mu->cs);
-  if (result) {
-    if (mu->locked) {                /* This thread already holds the lock. */
-      LeaveCriticalSection(&mu->cs); /* Decrement lock count. */
-      result = 0;                    /* Indicate failure */
-    }
-    mu->locked = 1;
-  }
-  return result;
-}
-
-/*----------------------------------------*/
-
-void gpr_cv_init(gpr_cv *cv) { InitializeConditionVariable(cv); }
-
-void gpr_cv_destroy(gpr_cv *cv) {
-  /* Condition variables don't need destruction in Win32. */
-}
-
-int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
-  int timeout = 0;
-  DWORD timeout_max_ms;
-  mu->locked = 0;
-  if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) ==
-      0) {
-    SleepConditionVariableCS(cv, &mu->cs, INFINITE);
-  } else {
-    abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME);
-    gpr_timespec now = gpr_now(abs_deadline.clock_type);
-    int64_t now_ms = (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000;
-    int64_t deadline_ms =
-        (int64_t)abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000;
-    if (now_ms >= deadline_ms) {
-      timeout = 1;
-    } else {
-      if ((deadline_ms - now_ms) >= INFINITE) {
-        timeout_max_ms = INFINITE - 1;
-      } else {
-        timeout_max_ms = (DWORD)(deadline_ms - now_ms);
-      }
-      timeout = (SleepConditionVariableCS(cv, &mu->cs, timeout_max_ms) == 0 &&
-                 GetLastError() == ERROR_TIMEOUT);
-    }
-  }
-  mu->locked = 1;
-  return timeout;
-}
-
-void gpr_cv_signal(gpr_cv *cv) { WakeConditionVariable(cv); }
-
-void gpr_cv_broadcast(gpr_cv *cv) { WakeAllConditionVariable(cv); }
-
-/*----------------------------------------*/
-
-static void *dummy;
-struct run_once_func_arg {
-  void (*init_function)(void);
-};
-static BOOL CALLBACK run_once_func(gpr_once *once, void *v, void **pv) {
-  struct run_once_func_arg *arg = v;
-  (*arg->init_function)();
-  return 1;
-}
-
-void gpr_once_init(gpr_once *once, void (*init_function)(void)) {
-  struct run_once_func_arg arg;
-  arg.init_function = init_function;
-  InitOnceExecuteOnce(once, run_once_func, &arg, &dummy);
-}
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/support/thd_internal.h b/src/core/support/thd_internal.h
deleted file mode 100644
index 33b904e..0000000
--- a/src/core/support/thd_internal.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_THD_INTERNAL_H
-#define GRPC_CORE_SUPPORT_THD_INTERNAL_H
-
-/* Internal interfaces between modules within the gpr support library.  */
-
-#endif /* GRPC_CORE_SUPPORT_THD_INTERNAL_H */
diff --git a/src/core/support/thd_posix.c b/src/core/support/thd_posix.c
deleted file mode 100644
index 653a1c8..0000000
--- a/src/core/support/thd_posix.c
+++ /dev/null
@@ -1,94 +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.
- *
- */
-
-/* Posix implementation for gpr threads. */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SYNC
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/useful.h>
-
-struct thd_arg {
-  void (*body)(void *arg); /* body of a thread */
-  void *arg;               /* argument to a thread */
-};
-
-/* Body of every thread started via gpr_thd_new. */
-static void *thread_body(void *v) {
-  struct thd_arg a = *(struct thd_arg *)v;
-  free(v);
-  (*a.body)(a.arg);
-  return NULL;
-}
-
-int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
-                const gpr_thd_options *options) {
-  int thread_started;
-  pthread_attr_t attr;
-  pthread_t p;
-  /* don't use gpr_malloc as we may cause an infinite recursion with
-   * the profiling code */
-  struct thd_arg *a = malloc(sizeof(*a));
-  GPR_ASSERT(a != NULL);
-  a->body = thd_body;
-  a->arg = arg;
-
-  GPR_ASSERT(pthread_attr_init(&attr) == 0);
-  if (gpr_thd_options_is_detached(options)) {
-    GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ==
-               0);
-  } else {
-    GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) ==
-               0);
-  }
-  thread_started = (pthread_create(&p, &attr, &thread_body, a) == 0);
-  GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
-  if (!thread_started) {
-    free(a);
-  }
-  *t = (gpr_thd_id)p;
-  return thread_started;
-}
-
-gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)pthread_self(); }
-
-void gpr_thd_join(gpr_thd_id t) { pthread_join((pthread_t)t, NULL); }
-
-#endif /* GPR_POSIX_SYNC */
diff --git a/src/core/support/thd_win32.c b/src/core/support/thd_win32.c
deleted file mode 100644
index a9db180..0000000
--- a/src/core/support/thd_win32.c
+++ /dev/null
@@ -1,117 +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.
- *
- */
-
-/* Windows implementation for gpr threads. */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include <string.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/thd.h>
-
-#if defined(_MSC_VER)
-#define thread_local __declspec(thread)
-#elif defined(__GNUC__)
-#define thread_local __thread
-#else
-#error "Unknown compiler - please file a bug report"
-#endif
-
-struct thd_info {
-  void (*body)(void *arg); /* body of a thread */
-  void *arg;               /* argument to a thread */
-  HANDLE join_event;       /* if joinable, the join event */
-  int joinable;            /* true if not detached */
-};
-
-static thread_local struct thd_info *g_thd_info;
-
-/* Destroys a thread info */
-static void destroy_thread(struct thd_info *t) {
-  if (t->joinable) CloseHandle(t->join_event);
-  gpr_free(t);
-}
-
-/* Body of every thread started via gpr_thd_new. */
-static DWORD WINAPI thread_body(void *v) {
-  g_thd_info = (struct thd_info *)v;
-  g_thd_info->body(g_thd_info->arg);
-  if (g_thd_info->joinable) {
-    BOOL ret = SetEvent(g_thd_info->join_event);
-    GPR_ASSERT(ret);
-  } else {
-    destroy_thread(g_thd_info);
-  }
-  return 0;
-}
-
-int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
-                const gpr_thd_options *options) {
-  HANDLE handle;
-  struct thd_info *info = gpr_malloc(sizeof(*info));
-  info->body = thd_body;
-  info->arg = arg;
-  *t = 0;
-  if (gpr_thd_options_is_joinable(options)) {
-    info->joinable = 1;
-    info->join_event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (info->join_event == NULL) {
-      gpr_free(info);
-      return 0;
-    }
-  } else {
-    info->joinable = 0;
-  }
-  handle = CreateThread(NULL, 64 * 1024, thread_body, info, 0, NULL);
-  if (handle == NULL) {
-    destroy_thread(info);
-  } else {
-    *t = (gpr_thd_id)info;
-    CloseHandle(handle);
-  }
-  return handle != NULL;
-}
-
-gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)g_thd_info; }
-
-void gpr_thd_join(gpr_thd_id t) {
-  struct thd_info *info = (struct thd_info *)t;
-  DWORD ret = WaitForSingleObject(info->join_event, INFINITE);
-  GPR_ASSERT(ret == WAIT_OBJECT_0);
-  destroy_thread(info);
-}
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/support/time.c b/src/core/support/time.c
deleted file mode 100644
index 423d12f..0000000
--- a/src/core/support/time.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Generic implementation of time calls. */
-
-#include <grpc/support/time.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <grpc/support/log.h>
-
-int gpr_time_cmp(gpr_timespec a, gpr_timespec b) {
-  int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
-  GPR_ASSERT(a.clock_type == b.clock_type);
-  if (cmp == 0) {
-    cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
-  }
-  return cmp;
-}
-
-gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b) {
-  return gpr_time_cmp(a, b) < 0 ? a : b;
-}
-
-gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b) {
-  return gpr_time_cmp(a, b) > 0 ? a : b;
-}
-
-gpr_timespec gpr_time_0(gpr_clock_type type) {
-  gpr_timespec out;
-  out.tv_sec = 0;
-  out.tv_nsec = 0;
-  out.clock_type = type;
-  return out;
-}
-
-gpr_timespec gpr_inf_future(gpr_clock_type type) {
-  gpr_timespec out;
-  out.tv_sec = INT64_MAX;
-  out.tv_nsec = 0;
-  out.clock_type = type;
-  return out;
-}
-
-gpr_timespec gpr_inf_past(gpr_clock_type type) {
-  gpr_timespec out;
-  out.tv_sec = INT64_MIN;
-  out.tv_nsec = 0;
-  out.clock_type = type;
-  return out;
-}
-
-/* TODO(ctiller): consider merging _nanos, _micros, _millis into a single
-   function for maintainability. Similarly for _seconds, _minutes, and _hours */
-
-gpr_timespec gpr_time_from_nanos(int64_t ns, gpr_clock_type type) {
-  gpr_timespec result;
-  result.clock_type = type;
-  if (ns == INT64_MAX) {
-    result = gpr_inf_future(type);
-  } else if (ns == INT64_MIN) {
-    result = gpr_inf_past(type);
-  } else if (ns >= 0) {
-    result.tv_sec = ns / GPR_NS_PER_SEC;
-    result.tv_nsec = (int32_t)(ns - result.tv_sec * GPR_NS_PER_SEC);
-  } else {
-    /* Calculation carefully formulated to avoid any possible under/overflow. */
-    result.tv_sec = (-(999999999 - (ns + GPR_NS_PER_SEC)) / GPR_NS_PER_SEC) - 1;
-    result.tv_nsec = (int32_t)(ns - result.tv_sec * GPR_NS_PER_SEC);
-  }
-  return result;
-}
-
-gpr_timespec gpr_time_from_micros(int64_t us, gpr_clock_type type) {
-  gpr_timespec result;
-  result.clock_type = type;
-  if (us == INT64_MAX) {
-    result = gpr_inf_future(type);
-  } else if (us == INT64_MIN) {
-    result = gpr_inf_past(type);
-  } else if (us >= 0) {
-    result.tv_sec = us / 1000000;
-    result.tv_nsec = (int32_t)((us - result.tv_sec * 1000000) * 1000);
-  } else {
-    /* Calculation carefully formulated to avoid any possible under/overflow. */
-    result.tv_sec = (-(999999 - (us + 1000000)) / 1000000) - 1;
-    result.tv_nsec = (int32_t)((us - result.tv_sec * 1000000) * 1000);
-  }
-  return result;
-}
-
-gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type type) {
-  gpr_timespec result;
-  result.clock_type = type;
-  if (ms == INT64_MAX) {
-    result = gpr_inf_future(type);
-  } else if (ms == INT64_MIN) {
-    result = gpr_inf_past(type);
-  } else if (ms >= 0) {
-    result.tv_sec = ms / 1000;
-    result.tv_nsec = (int32_t)((ms - result.tv_sec * 1000) * 1000000);
-  } else {
-    /* Calculation carefully formulated to avoid any possible under/overflow. */
-    result.tv_sec = (-(999 - (ms + 1000)) / 1000) - 1;
-    result.tv_nsec = (int32_t)((ms - result.tv_sec * 1000) * 1000000);
-  }
-  return result;
-}
-
-gpr_timespec gpr_time_from_seconds(int64_t s, gpr_clock_type type) {
-  gpr_timespec result;
-  result.clock_type = type;
-  if (s == INT64_MAX) {
-    result = gpr_inf_future(type);
-  } else if (s == INT64_MIN) {
-    result = gpr_inf_past(type);
-  } else {
-    result.tv_sec = s;
-    result.tv_nsec = 0;
-  }
-  return result;
-}
-
-gpr_timespec gpr_time_from_minutes(int64_t m, gpr_clock_type type) {
-  gpr_timespec result;
-  result.clock_type = type;
-  if (m >= INT64_MAX / 60) {
-    result = gpr_inf_future(type);
-  } else if (m <= INT64_MIN / 60) {
-    result = gpr_inf_past(type);
-  } else {
-    result.tv_sec = m * 60;
-    result.tv_nsec = 0;
-  }
-  return result;
-}
-
-gpr_timespec gpr_time_from_hours(int64_t h, gpr_clock_type type) {
-  gpr_timespec result;
-  result.clock_type = type;
-  if (h >= INT64_MAX / 3600) {
-    result = gpr_inf_future(type);
-  } else if (h <= INT64_MIN / 3600) {
-    result = gpr_inf_past(type);
-  } else {
-    result.tv_sec = h * 3600;
-    result.tv_nsec = 0;
-  }
-  return result;
-}
-
-gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) {
-  gpr_timespec sum;
-  int64_t inc = 0;
-  GPR_ASSERT(b.clock_type == GPR_TIMESPAN);
-  sum.clock_type = a.clock_type;
-  sum.tv_nsec = a.tv_nsec + b.tv_nsec;
-  if (sum.tv_nsec >= GPR_NS_PER_SEC) {
-    sum.tv_nsec -= GPR_NS_PER_SEC;
-    inc++;
-  }
-  if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) {
-    sum = a;
-  } else if (b.tv_sec == INT64_MAX ||
-             (b.tv_sec >= 0 && a.tv_sec >= INT64_MAX - b.tv_sec)) {
-    sum = gpr_inf_future(sum.clock_type);
-  } else if (b.tv_sec == INT64_MIN ||
-             (b.tv_sec <= 0 && a.tv_sec <= INT64_MIN - b.tv_sec)) {
-    sum = gpr_inf_past(sum.clock_type);
-  } else {
-    sum.tv_sec = a.tv_sec + b.tv_sec;
-    if (inc != 0 && sum.tv_sec == INT64_MAX - 1) {
-      sum = gpr_inf_future(sum.clock_type);
-    } else {
-      sum.tv_sec += inc;
-    }
-  }
-  return sum;
-}
-
-gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) {
-  gpr_timespec diff;
-  int64_t dec = 0;
-  if (b.clock_type == GPR_TIMESPAN) {
-    diff.clock_type = a.clock_type;
-  } else {
-    GPR_ASSERT(a.clock_type == b.clock_type);
-    diff.clock_type = GPR_TIMESPAN;
-  }
-  diff.tv_nsec = a.tv_nsec - b.tv_nsec;
-  if (diff.tv_nsec < 0) {
-    diff.tv_nsec += GPR_NS_PER_SEC;
-    dec++;
-  }
-  if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) {
-    diff = a;
-  } else if (b.tv_sec == INT64_MIN ||
-             (b.tv_sec <= 0 && a.tv_sec >= INT64_MAX + b.tv_sec)) {
-    diff = gpr_inf_future(GPR_CLOCK_REALTIME);
-  } else if (b.tv_sec == INT64_MAX ||
-             (b.tv_sec >= 0 && a.tv_sec <= INT64_MIN + b.tv_sec)) {
-    diff = gpr_inf_past(GPR_CLOCK_REALTIME);
-  } else {
-    diff.tv_sec = a.tv_sec - b.tv_sec;
-    if (dec != 0 && diff.tv_sec == INT64_MIN + 1) {
-      diff = gpr_inf_past(GPR_CLOCK_REALTIME);
-    } else {
-      diff.tv_sec -= dec;
-    }
-  }
-  return diff;
-}
-
-int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold) {
-  int cmp_ab;
-
-  GPR_ASSERT(a.clock_type == b.clock_type);
-  GPR_ASSERT(threshold.clock_type == GPR_TIMESPAN);
-
-  cmp_ab = gpr_time_cmp(a, b);
-  if (cmp_ab == 0) return 1;
-  if (cmp_ab < 0) {
-    return gpr_time_cmp(gpr_time_sub(b, a), threshold) <= 0;
-  } else {
-    return gpr_time_cmp(gpr_time_sub(a, b), threshold) <= 0;
-  }
-}
-
-int32_t gpr_time_to_millis(gpr_timespec t) {
-  if (t.tv_sec >= 2147483) {
-    if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) {
-      return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS;
-    }
-    return 2147483647;
-  } else if (t.tv_sec <= -2147483) {
-    /* TODO(ctiller): correct handling here (it's so far in the past do we
-       care?) */
-    return -2147483647;
-  } else {
-    return (int32_t)(t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS);
-  }
-}
-
-double gpr_timespec_to_micros(gpr_timespec t) {
-  return (double)t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3;
-}
-
-gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
-  if (t.clock_type == clock_type) {
-    return t;
-  }
-
-  if (t.tv_nsec == 0) {
-    if (t.tv_sec == INT64_MAX) {
-      t.clock_type = clock_type;
-      return t;
-    }
-    if (t.tv_sec == INT64_MIN) {
-      t.clock_type = clock_type;
-      return t;
-    }
-  }
-
-  if (clock_type == GPR_TIMESPAN) {
-    return gpr_time_sub(t, gpr_now(t.clock_type));
-  }
-
-  if (t.clock_type == GPR_TIMESPAN) {
-    return gpr_time_add(gpr_now(clock_type), t);
-  }
-
-  return gpr_time_add(gpr_now(clock_type),
-                      gpr_time_sub(t, gpr_now(t.clock_type)));
-}
diff --git a/src/core/support/time_posix.c b/src/core/support/time_posix.c
deleted file mode 100644
index 36d75e7..0000000
--- a/src/core/support/time_posix.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-#include <src/core/support/time_precise.h>
-
-#ifdef GPR_POSIX_TIME
-
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-#ifdef __linux__
-#include <sys/syscall.h>
-#endif
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include "src/core/support/block_annotate.h"
-
-static struct timespec timespec_from_gpr(gpr_timespec gts) {
-  struct timespec rv;
-  if (sizeof(time_t) < sizeof(int64_t)) {
-    /* fine to assert, as this is only used in gpr_sleep_until */
-    GPR_ASSERT(gts.tv_sec <= INT32_MAX && gts.tv_sec >= INT32_MIN);
-  }
-  rv.tv_sec = (time_t)gts.tv_sec;
-  rv.tv_nsec = gts.tv_nsec;
-  return rv;
-}
-
-#if _POSIX_TIMERS > 0
-static gpr_timespec gpr_from_timespec(struct timespec ts,
-                                      gpr_clock_type clock_type) {
-  /*
-   * timespec.tv_sec can have smaller size than gpr_timespec.tv_sec,
-   * but we are only using this function to implement gpr_now
-   * so there's no need to handle "infinity" values.
-   */
-  gpr_timespec rv;
-  rv.tv_sec = ts.tv_sec;
-  rv.tv_nsec = (int32_t)ts.tv_nsec;
-  rv.clock_type = clock_type;
-  return rv;
-}
-
-/** maps gpr_clock_type --> clockid_t for clock_gettime */
-static const clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC,
-                                                  CLOCK_REALTIME};
-
-void gpr_time_init(void) { gpr_precise_clock_init(); }
-
-gpr_timespec gpr_now(gpr_clock_type clock_type) {
-  struct timespec now;
-  GPR_ASSERT(clock_type != GPR_TIMESPAN);
-  if (clock_type == GPR_CLOCK_PRECISE) {
-    gpr_timespec ret;
-    gpr_precise_clock_now(&ret);
-    return ret;
-  } else {
-#if defined(GPR_BACKWARDS_COMPATIBILITY_MODE) && defined(__linux__)
-    /* avoid ABI problems by invoking syscalls directly */
-    syscall(SYS_clock_gettime, clockid_for_gpr_clock[clock_type], &now);
-#else
-    clock_gettime(clockid_for_gpr_clock[clock_type], &now);
-#endif
-    return gpr_from_timespec(now, clock_type);
-  }
-}
-#else
-/* For some reason Apple's OSes haven't implemented clock_gettime. */
-
-#include <sys/time.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-
-static double g_time_scale;
-static uint64_t g_time_start;
-
-void gpr_time_init(void) {
-  mach_timebase_info_data_t tb = {0, 1};
-  gpr_precise_clock_init();
-  mach_timebase_info(&tb);
-  g_time_scale = tb.numer;
-  g_time_scale /= tb.denom;
-  g_time_start = mach_absolute_time();
-}
-
-gpr_timespec gpr_now(gpr_clock_type clock) {
-  gpr_timespec now;
-  struct timeval now_tv;
-  double now_dbl;
-
-  now.clock_type = clock;
-  switch (clock) {
-    case GPR_CLOCK_REALTIME:
-      gettimeofday(&now_tv, NULL);
-      now.tv_sec = now_tv.tv_sec;
-      now.tv_nsec = now_tv.tv_usec * 1000;
-      break;
-    case GPR_CLOCK_MONOTONIC:
-      now_dbl = (mach_absolute_time() - g_time_start) * g_time_scale;
-      now.tv_sec = (int64_t)(now_dbl * 1e-9);
-      now.tv_nsec = (int32_t)(now_dbl - ((double)now.tv_sec) * 1e9);
-      break;
-    case GPR_CLOCK_PRECISE:
-      gpr_precise_clock_now(&now);
-      break;
-    case GPR_TIMESPAN:
-      abort();
-  }
-
-  return now;
-}
-#endif
-
-void gpr_sleep_until(gpr_timespec until) {
-  gpr_timespec now;
-  gpr_timespec delta;
-  struct timespec delta_ts;
-  int ns_result;
-
-  for (;;) {
-    /* We could simplify by using clock_nanosleep instead, but it might be
-     * slightly less portable. */
-    now = gpr_now(until.clock_type);
-    if (gpr_time_cmp(until, now) <= 0) {
-      return;
-    }
-
-    delta = gpr_time_sub(until, now);
-    delta_ts = timespec_from_gpr(delta);
-    GRPC_SCHEDULING_START_BLOCKING_REGION;
-    ns_result = nanosleep(&delta_ts, NULL);
-    GRPC_SCHEDULING_END_BLOCKING_REGION;
-    if (ns_result == 0) {
-      break;
-    }
-  }
-}
-
-#endif /* GPR_POSIX_TIME */
diff --git a/src/core/support/time_precise.h b/src/core/support/time_precise.h
deleted file mode 100644
index 871c99a..0000000
--- a/src/core/support/time_precise.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_TIME_PRECISE_H
-#define GRPC_CORE_SUPPORT_TIME_PRECISE_H
-
-#include <grpc/support/time.h>
-
-void gpr_precise_clock_init(void);
-void gpr_precise_clock_now(gpr_timespec *clk);
-
-#endif /* GRPC_CORE_SUPPORT_TIME_PRECISE_H */
diff --git a/src/core/support/time_win32.c b/src/core/support/time_win32.c
deleted file mode 100644
index 8af957e..0000000
--- a/src/core/support/time_win32.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Win32 code for gpr time support. */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-#include <src/core/support/time_precise.h>
-#include <sys/timeb.h>
-#include <process.h>
-#include <limits.h>
-
-#include "src/core/support/block_annotate.h"
-
-static LARGE_INTEGER g_start_time;
-static double g_time_scale;
-
-void gpr_time_init(void) {
-  LARGE_INTEGER frequency;
-  QueryPerformanceFrequency(&frequency);
-  QueryPerformanceCounter(&g_start_time);
-  g_time_scale = 1.0 / (double)frequency.QuadPart;
-}
-
-gpr_timespec gpr_now(gpr_clock_type clock) {
-  gpr_timespec now_tv;
-  LONGLONG diff;
-  struct _timeb now_tb;
-  LARGE_INTEGER timestamp;
-  double now_dbl;
-  now_tv.clock_type = clock;
-  switch (clock) {
-    case GPR_CLOCK_REALTIME:
-      _ftime_s(&now_tb);
-      now_tv.tv_sec = (int64_t)now_tb.time;
-      now_tv.tv_nsec = now_tb.millitm * 1000000;
-      break;
-    case GPR_CLOCK_MONOTONIC:
-    case GPR_CLOCK_PRECISE:
-      QueryPerformanceCounter(&timestamp);
-      diff = timestamp.QuadPart - g_start_time.QuadPart;
-      now_dbl = (double)diff * g_time_scale;
-      now_tv.tv_sec = (int64_t)now_dbl;
-      now_tv.tv_nsec = (int32_t)((now_dbl - (double)now_tv.tv_sec) * 1e9);
-      break;
-    case GPR_TIMESPAN:
-      abort();
-      break;
-  }
-  return now_tv;
-}
-
-void gpr_sleep_until(gpr_timespec until) {
-  gpr_timespec now;
-  gpr_timespec delta;
-  int64_t sleep_millis;
-
-  for (;;) {
-    /* We could simplify by using clock_nanosleep instead, but it might be
-     * slightly less portable. */
-    now = gpr_now(until.clock_type);
-    if (gpr_time_cmp(until, now) <= 0) {
-      return;
-    }
-
-    delta = gpr_time_sub(until, now);
-    sleep_millis =
-        delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS;
-    GPR_ASSERT((sleep_millis >= 0) && (sleep_millis <= INT_MAX));
-    GRPC_SCHEDULING_START_BLOCKING_REGION;
-    Sleep((DWORD)sleep_millis);
-    GRPC_SCHEDULING_END_BLOCKING_REGION;
-  }
-}
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/support/tmpfile.h b/src/core/support/tmpfile.h
deleted file mode 100644
index df6f869..0000000
--- a/src/core/support/tmpfile.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SUPPORT_TMPFILE_H
-#define GRPC_CORE_SUPPORT_TMPFILE_H
-
-#include <stdio.h>
-
-#include <grpc/support/slice.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Creates a temporary file from a prefix.
-   If tmp_filename is not NULL, *tmp_filename is assigned the name of the
-   created file and it is the responsibility of the caller to gpr_free it
-   unless an error occurs in which case it will be set to NULL. */
-FILE *gpr_tmpfile(const char *prefix, char **tmp_filename);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_SUPPORT_TMPFILE_H */
diff --git a/src/core/support/tmpfile_posix.c b/src/core/support/tmpfile_posix.c
deleted file mode 100644
index b16eeac..0000000
--- a/src/core/support/tmpfile_posix.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_FILE
-
-#include "src/core/support/tmpfile.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/support/string.h"
-
-FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) {
-  FILE *result = NULL;
-  char *template;
-  int fd;
-
-  if (tmp_filename != NULL) *tmp_filename = NULL;
-
-  gpr_asprintf(&template, "/tmp/%s_XXXXXX", prefix);
-  GPR_ASSERT(template != NULL);
-
-  fd = mkstemp(template);
-  if (fd == -1) {
-    gpr_log(GPR_ERROR, "mkstemp failed for template %s with error %s.",
-            template, strerror(errno));
-    goto end;
-  }
-  result = fdopen(fd, "w+");
-  if (result == NULL) {
-    gpr_log(GPR_ERROR, "Could not open file %s from fd %d (error = %s).",
-            template, fd, strerror(errno));
-    unlink(template);
-    close(fd);
-    goto end;
-  }
-
-end:
-  if (result != NULL && tmp_filename != NULL) {
-    *tmp_filename = template;
-  } else {
-    gpr_free(template);
-  }
-  return result;
-}
-
-#endif /* GPR_POSIX_FILE */
diff --git a/src/core/support/tmpfile_win32.c b/src/core/support/tmpfile_win32.c
deleted file mode 100644
index 3000f00..0000000
--- a/src/core/support/tmpfile_win32.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include <io.h>
-#include <stdio.h>
-#include <string.h>
-#include <tchar.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/support/string_win32.h"
-#include "src/core/support/tmpfile.h"
-
-FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) {
-  FILE *result = NULL;
-  LPTSTR template_string = NULL;
-  TCHAR tmp_path[MAX_PATH];
-  TCHAR tmp_filename[MAX_PATH];
-  DWORD status;
-  UINT success;
-
-  if (tmp_filename_out != NULL) *tmp_filename_out = NULL;
-
-  /* Convert our prefix to TCHAR. */
-  template_string = gpr_char_to_tchar(prefix);
-  GPR_ASSERT(template_string);
-
-  /* Get the path to the best temporary folder available. */
-  status = GetTempPath(MAX_PATH, tmp_path);
-  if (status == 0 || status > MAX_PATH) goto end;
-
-  /* Generate a unique filename with our template + temporary path. */
-  success = GetTempFileName(tmp_path, template_string, 0, tmp_filename);
-  if (!success) goto end;
-
-  /* Open a file there. */
-  if (_tfopen_s(&result, tmp_filename, TEXT("wb+")) != 0) goto end;
-
-end:
-  if (result && tmp_filename_out) {
-    *tmp_filename_out = gpr_tchar_to_char(tmp_filename);
-  }
-
-  gpr_free(template_string);
-  return result;
-}
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/surface/alarm.c b/src/core/surface/alarm.c
deleted file mode 100644
index 8169ede..0000000
--- a/src/core/surface/alarm.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *
- * 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/iomgr/timer.h"
-#include "src/core/surface/completion_queue.h"
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-
-struct grpc_alarm {
-  grpc_timer alarm;
-  grpc_cq_completion completion;
-  /** completion queue where events about this alarm will be posted */
-  grpc_completion_queue *cq;
-  /** user supplied tag */
-  void *tag;
-};
-
-static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg,
-                                      grpc_cq_completion *c) {}
-
-static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  grpc_alarm *alarm = arg;
-  grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, success,
-                 do_nothing_end_completion, NULL, &alarm->completion);
-}
-
-grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline,
-                              void *tag) {
-  grpc_alarm *alarm = gpr_malloc(sizeof(grpc_alarm));
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_CQ_INTERNAL_REF(cq, "alarm");
-  alarm->cq = cq;
-  alarm->tag = tag;
-
-  grpc_cq_begin_op(cq, tag);
-  grpc_timer_init(&exec_ctx, &alarm->alarm,
-                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
-                  alarm_cb, alarm, gpr_now(GPR_CLOCK_MONOTONIC));
-  grpc_exec_ctx_finish(&exec_ctx);
-  return alarm;
-}
-
-void grpc_alarm_cancel(grpc_alarm *alarm) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_timer_cancel(&exec_ctx, &alarm->alarm);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-void grpc_alarm_destroy(grpc_alarm *alarm) {
-  grpc_alarm_cancel(alarm);
-  GRPC_CQ_INTERNAL_UNREF(alarm->cq, "alarm");
-  gpr_free(alarm);
-}
diff --git a/src/core/surface/api_trace.c b/src/core/surface/api_trace.c
deleted file mode 100644
index 9f0b900..0000000
--- a/src/core/surface/api_trace.c
+++ /dev/null
@@ -1,36 +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/surface/api_trace.h"
-
-int grpc_api_trace = 0;
diff --git a/src/core/surface/api_trace.h b/src/core/surface/api_trace.h
deleted file mode 100644
index 29a9b2d..0000000
--- a/src/core/surface/api_trace.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_API_TRACE_H
-#define GRPC_CORE_SURFACE_API_TRACE_H
-
-#include "src/core/debug/trace.h"
-#include <grpc/support/log.h>
-
-extern int grpc_api_trace;
-
-/* Provide unwrapping macros because we're in C89 and variadic macros weren't
-   introduced until C99... */
-#define GRPC_API_TRACE_UNWRAP0()
-#define GRPC_API_TRACE_UNWRAP1(a) , a
-#define GRPC_API_TRACE_UNWRAP2(a, b) , a, b
-#define GRPC_API_TRACE_UNWRAP3(a, b, c) , a, b, c
-#define GRPC_API_TRACE_UNWRAP4(a, b, c, d) , a, b, c, d
-#define GRPC_API_TRACE_UNWRAP5(a, b, c, d, e) , a, b, c, d, e
-#define GRPC_API_TRACE_UNWRAP6(a, b, c, d, e, f) , a, b, c, d, e, f
-#define GRPC_API_TRACE_UNWRAP7(a, b, c, d, e, f, g) , a, b, c, d, e, f, g
-#define GRPC_API_TRACE_UNWRAP8(a, b, c, d, e, f, g, h) , a, b, c, d, e, f, g, h
-#define GRPC_API_TRACE_UNWRAP9(a, b, c, d, e, f, g, h, i) \
-  , a, b, c, d, e, f, g, h, i
-#define GRPC_API_TRACE_UNWRAP10(a, b, c, d, e, f, g, h, i, j) \
-  , a, b, c, d, e, f, g, h, i, j
-
-/* Due to the limitations of C89's preprocessor, the arity of the var-arg list
-   'nargs' must be specified. */
-#define GRPC_API_TRACE(fmt, nargs, args)                      \
-  if (grpc_api_trace) {                                       \
-    gpr_log(GPR_INFO, fmt GRPC_API_TRACE_UNWRAP##nargs args); \
-  }
-
-#endif /* GRPC_CORE_SURFACE_API_TRACE_H */
diff --git a/src/core/surface/byte_buffer.c b/src/core/surface/byte_buffer.c
deleted file mode 100644
index fb39c45..0000000
--- a/src/core/surface/byte_buffer.c
+++ /dev/null
@@ -1,97 +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/byte_buffer.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices,
-                                              size_t nslices) {
-  return grpc_raw_compressed_byte_buffer_create(slices, nslices,
-                                                GRPC_COMPRESS_NONE);
-}
-
-grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create(
-    gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression) {
-  size_t i;
-  grpc_byte_buffer *bb = malloc(sizeof(grpc_byte_buffer));
-  bb->type = GRPC_BB_RAW;
-  bb->data.raw.compression = compression;
-  gpr_slice_buffer_init(&bb->data.raw.slice_buffer);
-  for (i = 0; i < nslices; i++) {
-    gpr_slice_ref(slices[i]);
-    gpr_slice_buffer_add(&bb->data.raw.slice_buffer, slices[i]);
-  }
-  return bb;
-}
-
-grpc_byte_buffer *grpc_raw_byte_buffer_from_reader(
-    grpc_byte_buffer_reader *reader) {
-  grpc_byte_buffer *bb = malloc(sizeof(grpc_byte_buffer));
-  gpr_slice slice;
-  bb->type = GRPC_BB_RAW;
-  bb->data.raw.compression = GRPC_COMPRESS_NONE;
-  gpr_slice_buffer_init(&bb->data.raw.slice_buffer);
-
-  while (grpc_byte_buffer_reader_next(reader, &slice)) {
-    gpr_slice_buffer_add(&bb->data.raw.slice_buffer, slice);
-  }
-  return bb;
-}
-
-grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb) {
-  switch (bb->type) {
-    case GRPC_BB_RAW:
-      return grpc_raw_byte_buffer_create(bb->data.raw.slice_buffer.slices,
-                                         bb->data.raw.slice_buffer.count);
-  }
-  GPR_UNREACHABLE_CODE(return NULL);
-}
-
-void grpc_byte_buffer_destroy(grpc_byte_buffer *bb) {
-  if (!bb) return;
-  switch (bb->type) {
-    case GRPC_BB_RAW:
-      gpr_slice_buffer_destroy(&bb->data.raw.slice_buffer);
-      break;
-  }
-  free(bb);
-}
-
-size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) {
-  switch (bb->type) {
-    case GRPC_BB_RAW:
-      return bb->data.raw.slice_buffer.length;
-  }
-  GPR_UNREACHABLE_CODE(return 0);
-}
diff --git a/src/core/surface/byte_buffer_reader.c b/src/core/surface/byte_buffer_reader.c
deleted file mode 100644
index 4679854..0000000
--- a/src/core/surface/byte_buffer_reader.c
+++ /dev/null
@@ -1,123 +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 <grpc/byte_buffer_reader.h>
-
-#include <grpc/compression.h>
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/byte_buffer.h>
-
-#include "src/core/compression/message_compress.h"
-
-static int is_compressed(grpc_byte_buffer *buffer) {
-  switch (buffer->type) {
-    case GRPC_BB_RAW:
-      if (buffer->data.raw.compression == GRPC_COMPRESS_NONE) {
-        return 0 /* GPR_FALSE */;
-      }
-      break;
-  }
-  return 1 /* GPR_TRUE */;
-}
-
-void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
-                                  grpc_byte_buffer *buffer) {
-  gpr_slice_buffer decompressed_slices_buffer;
-  reader->buffer_in = buffer;
-  switch (reader->buffer_in->type) {
-    case GRPC_BB_RAW:
-      gpr_slice_buffer_init(&decompressed_slices_buffer);
-      if (is_compressed(reader->buffer_in)) {
-        grpc_msg_decompress(reader->buffer_in->data.raw.compression,
-                            &reader->buffer_in->data.raw.slice_buffer,
-                            &decompressed_slices_buffer);
-        reader->buffer_out =
-            grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices,
-                                        decompressed_slices_buffer.count);
-        gpr_slice_buffer_destroy(&decompressed_slices_buffer);
-      } else { /* not compressed, use the input buffer as output */
-        reader->buffer_out = reader->buffer_in;
-      }
-      reader->current.index = 0;
-      break;
-  }
-}
-
-void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) {
-  switch (reader->buffer_in->type) {
-    case GRPC_BB_RAW:
-      /* keeping the same if-else structure as in the init function */
-      if (is_compressed(reader->buffer_in)) {
-        grpc_byte_buffer_destroy(reader->buffer_out);
-      }
-      break;
-  }
-}
-
-int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
-                                 gpr_slice *slice) {
-  switch (reader->buffer_in->type) {
-    case GRPC_BB_RAW: {
-      gpr_slice_buffer *slice_buffer;
-      slice_buffer = &reader->buffer_out->data.raw.slice_buffer;
-      if (reader->current.index < slice_buffer->count) {
-        *slice = gpr_slice_ref(slice_buffer->slices[reader->current.index]);
-        reader->current.index += 1;
-        return 1;
-      }
-      break;
-    }
-  }
-  return 0;
-}
-
-gpr_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) {
-  gpr_slice in_slice;
-  size_t bytes_read = 0;
-  const size_t input_size = grpc_byte_buffer_length(reader->buffer_out);
-  gpr_slice out_slice = gpr_slice_malloc(input_size);
-  uint8_t *const outbuf = GPR_SLICE_START_PTR(out_slice); /* just an alias */
-
-  while (grpc_byte_buffer_reader_next(reader, &in_slice) != 0) {
-    const size_t slice_length = GPR_SLICE_LENGTH(in_slice);
-    memcpy(&(outbuf[bytes_read]), GPR_SLICE_START_PTR(in_slice), slice_length);
-    bytes_read += slice_length;
-    gpr_slice_unref(in_slice);
-    GPR_ASSERT(bytes_read <= input_size);
-  }
-  return out_slice;
-}
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
deleted file mode 100644
index 6f1cd1d..0000000
--- a/src/core/surface/call.c
+++ /dev/null
@@ -1,1491 +0,0 @@
-/*
- *
- * 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 <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/compression.h>
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/compression/algorithm_metadata.h"
-#include "src/core/iomgr/timer.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/call.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/completion_queue.h"
-#include "src/core/transport/static_metadata.h"
-
-/** The maximum number of concurrent batches possible.
-    Based upon the maximum number of individually queueable ops in the batch
-   api:
-      - initial metadata send
-      - message send
-      - status/close send (depending on client/server)
-      - initial metadata recv
-      - message recv
-      - status/close recv (depending on client/server) */
-#define MAX_CONCURRENT_BATCHES 6
-
-typedef struct {
-  grpc_ioreq_completion_func on_complete;
-  void *user_data;
-  int success;
-} completed_request;
-
-#define MAX_SEND_EXTRA_METADATA_COUNT 3
-
-/* Status data for a request can come from several sources; this
-   enumerates them all, and acts as a priority sorting for which
-   status to return to the application - earlier entries override
-   later ones */
-typedef enum {
-  /* Status came from the application layer overriding whatever
-     the wire says */
-  STATUS_FROM_API_OVERRIDE = 0,
-  /* Status was created by some internal channel stack operation */
-  STATUS_FROM_CORE,
-  /* Status came from 'the wire' - or somewhere below the surface
-     layer */
-  STATUS_FROM_WIRE,
-  /* Status came from the server sending status */
-  STATUS_FROM_SERVER_STATUS,
-  STATUS_SOURCE_COUNT
-} status_source;
-
-typedef struct {
-  uint8_t is_set;
-  grpc_status_code code;
-  grpc_mdstr *details;
-} received_status;
-
-/* How far through the GRPC stream have we read? */
-typedef enum {
-  /* We are still waiting for initial metadata to complete */
-  READ_STATE_INITIAL = 0,
-  /* We have gotten initial metadata, and are reading either
-     messages or trailing metadata */
-  READ_STATE_GOT_INITIAL_METADATA,
-  /* The stream is closed for reading */
-  READ_STATE_READ_CLOSED,
-  /* The stream is closed for reading & writing */
-  READ_STATE_STREAM_CLOSED
-} read_state;
-
-typedef enum {
-  WRITE_STATE_INITIAL = 0,
-  WRITE_STATE_STARTED,
-  WRITE_STATE_WRITE_CLOSED
-} write_state;
-
-typedef struct batch_control {
-  grpc_call *call;
-  grpc_cq_completion cq_completion;
-  grpc_closure finish_batch;
-  void *notify_tag;
-  gpr_refcount steps_to_complete;
-
-  uint8_t send_initial_metadata;
-  uint8_t send_message;
-  uint8_t send_final_op;
-  uint8_t recv_initial_metadata;
-  uint8_t recv_message;
-  uint8_t recv_final_op;
-  uint8_t is_notify_tag_closure;
-  uint8_t success;
-} batch_control;
-
-struct grpc_call {
-  grpc_completion_queue *cq;
-  grpc_channel *channel;
-  grpc_call *parent;
-  grpc_call *first_child;
-  /* TODO(ctiller): share with cq if possible? */
-  gpr_mu mu;
-
-  /* client or server call */
-  uint8_t is_client;
-  /* is the alarm set */
-  uint8_t have_alarm;
-  /** has grpc_call_destroy been called */
-  uint8_t destroy_called;
-  /** flag indicating that cancellation is inherited */
-  uint8_t cancellation_is_inherited;
-  /** bitmask of live batches */
-  uint8_t used_batches;
-  /** which ops are in-flight */
-  uint8_t sent_initial_metadata;
-  uint8_t sending_message;
-  uint8_t sent_final_op;
-  uint8_t received_initial_metadata;
-  uint8_t receiving_message;
-  uint8_t received_final_op;
-
-  /* have we received initial metadata */
-  bool has_initial_md_been_received;
-
-  batch_control active_batches[MAX_CONCURRENT_BATCHES];
-
-  /* first idx: is_receiving, second idx: is_trailing */
-  grpc_metadata_batch metadata_batch[2][2];
-
-  /* Buffered read metadata waiting to be returned to the application.
-     Element 0 is initial metadata, element 1 is trailing metadata. */
-  grpc_metadata_array *buffered_metadata[2];
-
-  /* Received call statuses from various sources */
-  received_status status[STATUS_SOURCE_COUNT];
-
-  /* Compression algorithm for the call */
-  grpc_compression_algorithm compression_algorithm;
-  /* Supported encodings (compression algorithms), a bitset */
-  uint32_t encodings_accepted_by_peer;
-
-  /* Contexts for various subsystems (security, tracing, ...). */
-  grpc_call_context_element context[GRPC_CONTEXT_COUNT];
-
-  /* Deadline alarm - if have_alarm is non-zero */
-  grpc_timer alarm;
-
-  /* for the client, extra metadata is initial metadata; for the
-     server, it's trailing metadata */
-  grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT];
-  int send_extra_metadata_count;
-  gpr_timespec send_deadline;
-
-  /** siblings: children of the same parent form a list, and this list is
-     protected under
-      parent->mu */
-  grpc_call *sibling_next;
-  grpc_call *sibling_prev;
-
-  grpc_slice_buffer_stream sending_stream;
-  grpc_byte_stream *receiving_stream;
-  grpc_byte_buffer **receiving_buffer;
-  gpr_slice receiving_slice;
-  grpc_closure receiving_slice_ready;
-  grpc_closure receiving_stream_ready;
-  grpc_closure receiving_initial_metadata_ready;
-  uint32_t test_only_last_message_flags;
-
-  union {
-    struct {
-      grpc_status_code *status;
-      char **status_details;
-      size_t *status_details_capacity;
-    } client;
-    struct {
-      int *cancelled;
-    } server;
-  } final_op;
-
-  struct {
-    void *bctlp;
-    bool success;
-  } saved_receiving_stream_ready_ctx;
-};
-
-#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
-#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
-#define CALL_ELEM_FROM_CALL(call, idx) \
-  grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
-#define CALL_FROM_TOP_ELEM(top_elem) \
-  CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem))
-
-static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                               gpr_timespec deadline);
-static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                       grpc_transport_stream_op *op);
-static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
-                                          grpc_status_code status,
-                                          const char *description);
-static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack,
-                         bool success);
-static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
-                                  bool success);
-
-grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
-                            uint32_t propagation_mask,
-                            grpc_completion_queue *cq,
-                            const void *server_transport_data,
-                            grpc_mdelem **add_initial_metadata,
-                            size_t add_initial_metadata_count,
-                            gpr_timespec send_deadline) {
-  size_t i, j;
-  grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_call *call;
-  GPR_TIMER_BEGIN("grpc_call_create", 0);
-  call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
-  memset(call, 0, sizeof(grpc_call));
-  gpr_mu_init(&call->mu);
-  call->channel = channel;
-  call->cq = cq;
-  call->parent = parent_call;
-  call->is_client = server_transport_data == NULL;
-  if (call->is_client) {
-    GPR_ASSERT(add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT);
-    for (i = 0; i < add_initial_metadata_count; i++) {
-      call->send_extra_metadata[i].md = add_initial_metadata[i];
-    }
-    call->send_extra_metadata_count = (int)add_initial_metadata_count;
-  } else {
-    GPR_ASSERT(add_initial_metadata_count == 0);
-    call->send_extra_metadata_count = 0;
-  }
-  for (i = 0; i < 2; i++) {
-    for (j = 0; j < 2; j++) {
-      call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
-    }
-  }
-  call->send_deadline = send_deadline;
-  GRPC_CHANNEL_INTERNAL_REF(channel, "call");
-  /* initial refcount dropped by grpc_call_destroy */
-  grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call,
-                       call->context, server_transport_data,
-                       CALL_STACK_FROM_CALL(call));
-  if (cq != NULL) {
-    GRPC_CQ_INTERNAL_REF(cq, "bind");
-    grpc_call_stack_set_pollset(&exec_ctx, CALL_STACK_FROM_CALL(call),
-                                grpc_cq_pollset(cq));
-  }
-  if (parent_call != NULL) {
-    GRPC_CALL_INTERNAL_REF(parent_call, "child");
-    GPR_ASSERT(call->is_client);
-    GPR_ASSERT(!parent_call->is_client);
-
-    gpr_mu_lock(&parent_call->mu);
-
-    if (propagation_mask & GRPC_PROPAGATE_DEADLINE) {
-      send_deadline = gpr_time_min(
-          gpr_convert_clock_type(send_deadline,
-                                 parent_call->send_deadline.clock_type),
-          parent_call->send_deadline);
-    }
-    /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with
-     * GRPC_PROPAGATE_STATS_CONTEXT */
-    /* TODO(ctiller): This should change to use the appropriate census start_op
-     * call. */
-    if (propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) {
-      GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
-      grpc_call_context_set(call, GRPC_CONTEXT_TRACING,
-                            parent_call->context[GRPC_CONTEXT_TRACING].value,
-                            NULL);
-    } else {
-      GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
-    }
-    if (propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
-      call->cancellation_is_inherited = 1;
-    }
-
-    if (parent_call->first_child == NULL) {
-      parent_call->first_child = call;
-      call->sibling_next = call->sibling_prev = call;
-    } else {
-      call->sibling_next = parent_call->first_child;
-      call->sibling_prev = parent_call->first_child->sibling_prev;
-      call->sibling_next->sibling_prev = call->sibling_prev->sibling_next =
-          call;
-    }
-
-    gpr_mu_unlock(&parent_call->mu);
-  }
-  if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) !=
-      0) {
-    set_deadline_alarm(&exec_ctx, call, send_deadline);
-  }
-  grpc_exec_ctx_finish(&exec_ctx);
-  GPR_TIMER_END("grpc_call_create", 0);
-  return call;
-}
-
-void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                                    grpc_completion_queue *cq) {
-  GPR_ASSERT(cq);
-  call->cq = cq;
-  GRPC_CQ_INTERNAL_REF(cq, "bind");
-  grpc_call_stack_set_pollset(exec_ctx, CALL_STACK_FROM_CALL(call),
-                              grpc_cq_pollset(cq));
-}
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-#define REF_REASON reason
-#define REF_ARG , const char *reason
-#else
-#define REF_REASON ""
-#define REF_ARG
-#endif
-void grpc_call_internal_ref(grpc_call *c REF_ARG) {
-  GRPC_CALL_STACK_REF(CALL_STACK_FROM_CALL(c), REF_REASON);
-}
-void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
-  GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
-}
-
-static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, bool success) {
-  size_t i;
-  int ii;
-  grpc_call *c = call;
-  GPR_TIMER_BEGIN("destroy_call", 0);
-  for (i = 0; i < 2; i++) {
-    grpc_metadata_batch_destroy(
-        &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]);
-  }
-  if (c->receiving_stream != NULL) {
-    grpc_byte_stream_destroy(exec_ctx, c->receiving_stream);
-  }
-  grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c));
-  GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->channel, "call");
-  gpr_mu_destroy(&c->mu);
-  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
-    if (c->status[i].details) {
-      GRPC_MDSTR_UNREF(c->status[i].details);
-    }
-  }
-  for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
-    GRPC_MDELEM_UNREF(c->send_extra_metadata[ii].md);
-  }
-  for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
-    if (c->context[i].destroy) {
-      c->context[i].destroy(c->context[i].value);
-    }
-  }
-  if (c->cq) {
-    GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
-  }
-  gpr_free(c);
-  GPR_TIMER_END("destroy_call", 0);
-}
-
-static void set_status_code(grpc_call *call, status_source source,
-                            uint32_t status) {
-  if (call->status[source].is_set) return;
-
-  call->status[source].is_set = 1;
-  call->status[source].code = (grpc_status_code)status;
-
-  /* TODO(ctiller): what to do about the flush that was previously here */
-}
-
-static void set_compression_algorithm(grpc_call *call,
-                                      grpc_compression_algorithm algo) {
-  call->compression_algorithm = algo;
-}
-
-grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
-    grpc_call *call) {
-  grpc_compression_algorithm algorithm;
-  gpr_mu_lock(&call->mu);
-  algorithm = call->compression_algorithm;
-  gpr_mu_unlock(&call->mu);
-  return algorithm;
-}
-
-uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
-  uint32_t flags;
-  gpr_mu_lock(&call->mu);
-  flags = call->test_only_last_message_flags;
-  gpr_mu_unlock(&call->mu);
-  return flags;
-}
-
-static void destroy_encodings_accepted_by_peer(void *p) { return; }
-
-static void set_encodings_accepted_by_peer(grpc_call *call, grpc_mdelem *mdel) {
-  size_t i;
-  grpc_compression_algorithm algorithm;
-  gpr_slice_buffer accept_encoding_parts;
-  gpr_slice accept_encoding_slice;
-  void *accepted_user_data;
-
-  accepted_user_data =
-      grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
-  if (accepted_user_data != NULL) {
-    call->encodings_accepted_by_peer =
-        (uint32_t)(((uintptr_t)accepted_user_data) - 1);
-    return;
-  }
-
-  accept_encoding_slice = mdel->value->slice;
-  gpr_slice_buffer_init(&accept_encoding_parts);
-  gpr_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
-
-  /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
-   * zeroes the whole grpc_call */
-  /* Always support no compression */
-  GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
-  for (i = 0; i < accept_encoding_parts.count; i++) {
-    const gpr_slice *accept_encoding_entry_slice =
-        &accept_encoding_parts.slices[i];
-    if (grpc_compression_algorithm_parse(
-            (const char *)GPR_SLICE_START_PTR(*accept_encoding_entry_slice),
-            GPR_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
-      GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
-    } else {
-      char *accept_encoding_entry_str =
-          gpr_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
-      gpr_log(GPR_ERROR,
-              "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
-              accept_encoding_entry_str);
-      gpr_free(accept_encoding_entry_str);
-    }
-  }
-
-  gpr_slice_buffer_destroy(&accept_encoding_parts);
-
-  grpc_mdelem_set_user_data(
-      mdel, destroy_encodings_accepted_by_peer,
-      (void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
-}
-
-uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
-  uint32_t encodings_accepted_by_peer;
-  gpr_mu_lock(&call->mu);
-  encodings_accepted_by_peer = call->encodings_accepted_by_peer;
-  gpr_mu_unlock(&call->mu);
-  return encodings_accepted_by_peer;
-}
-
-static void set_status_details(grpc_call *call, status_source source,
-                               grpc_mdstr *status) {
-  if (call->status[source].details != NULL) {
-    GRPC_MDSTR_UNREF(call->status[source].details);
-  }
-  call->status[source].details = status;
-}
-
-static void get_final_status(grpc_call *call,
-                             void (*set_value)(grpc_status_code code,
-                                               void *user_data),
-                             void *set_value_user_data) {
-  int i;
-  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
-    if (call->status[i].is_set) {
-      set_value(call->status[i].code, set_value_user_data);
-      return;
-    }
-  }
-  if (call->is_client) {
-    set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
-  } else {
-    set_value(GRPC_STATUS_OK, set_value_user_data);
-  }
-}
-
-static void get_final_details(grpc_call *call, char **out_details,
-                              size_t *out_details_capacity) {
-  int i;
-  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
-    if (call->status[i].is_set) {
-      if (call->status[i].details) {
-        gpr_slice details = call->status[i].details->slice;
-        size_t len = GPR_SLICE_LENGTH(details);
-        if (len + 1 > *out_details_capacity) {
-          *out_details_capacity =
-              GPR_MAX(len + 1, *out_details_capacity * 3 / 2);
-          *out_details = gpr_realloc(*out_details, *out_details_capacity);
-        }
-        memcpy(*out_details, GPR_SLICE_START_PTR(details), len);
-        (*out_details)[len] = 0;
-      } else {
-        goto no_details;
-      }
-      return;
-    }
-  }
-
-no_details:
-  if (0 == *out_details_capacity) {
-    *out_details_capacity = 8;
-    *out_details = gpr_malloc(*out_details_capacity);
-  }
-  **out_details = 0;
-}
-
-static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
-  return (grpc_linked_mdelem *)&md->internal_data;
-}
-
-static int prepare_application_metadata(grpc_call *call, int count,
-                                        grpc_metadata *metadata,
-                                        int is_trailing,
-                                        int prepend_extra_metadata) {
-  int i;
-  grpc_metadata_batch *batch =
-      &call->metadata_batch[0 /* is_receiving */][is_trailing];
-  if (prepend_extra_metadata) {
-    if (call->send_extra_metadata_count == 0) {
-      prepend_extra_metadata = 0;
-    } else {
-      for (i = 0; i < call->send_extra_metadata_count; i++) {
-        GRPC_MDELEM_REF(call->send_extra_metadata[i].md);
-      }
-      for (i = 1; i < call->send_extra_metadata_count; i++) {
-        call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
-      }
-      for (i = 0; i < call->send_extra_metadata_count - 1; i++) {
-        call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1];
-      }
-    }
-  }
-  for (i = 0; i < count; i++) {
-    grpc_metadata *md = &metadata[i];
-    grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
-    GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
-    l->md = grpc_mdelem_from_string_and_buffer(
-        md->key, (const uint8_t *)md->value, md->value_length);
-    if (!grpc_header_key_is_legal(grpc_mdstr_as_c_string(l->md->key),
-                                  GRPC_MDSTR_LENGTH(l->md->key))) {
-      gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
-              grpc_mdstr_as_c_string(l->md->key));
-      return 0;
-    } else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
-                                      GRPC_MDSTR_LENGTH(l->md->key)) &&
-               !grpc_header_nonbin_value_is_legal(
-                   grpc_mdstr_as_c_string(l->md->value),
-                   GRPC_MDSTR_LENGTH(l->md->value))) {
-      gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
-      return 0;
-    }
-  }
-  for (i = 1; i < count; i++) {
-    linked_from_md(&metadata[i])->prev = linked_from_md(&metadata[i - 1]);
-  }
-  for (i = 0; i < count - 1; i++) {
-    linked_from_md(&metadata[i])->next = linked_from_md(&metadata[i + 1]);
-  }
-  switch (prepend_extra_metadata * 2 + (count != 0)) {
-    case 0:
-      /* no prepend, no metadata => nothing to do */
-      batch->list.head = batch->list.tail = NULL;
-      break;
-    case 1:
-      /* metadata, but no prepend */
-      batch->list.head = linked_from_md(&metadata[0]);
-      batch->list.tail = linked_from_md(&metadata[count - 1]);
-      batch->list.head->prev = NULL;
-      batch->list.tail->next = NULL;
-      break;
-    case 2:
-      /* prepend, but no md */
-      batch->list.head = &call->send_extra_metadata[0];
-      batch->list.tail =
-          &call->send_extra_metadata[call->send_extra_metadata_count - 1];
-      batch->list.head->prev = NULL;
-      batch->list.tail->next = NULL;
-      break;
-    case 3:
-      /* prepend AND md */
-      batch->list.head = &call->send_extra_metadata[0];
-      call->send_extra_metadata[call->send_extra_metadata_count - 1].next =
-          linked_from_md(&metadata[0]);
-      linked_from_md(&metadata[0])->prev =
-          &call->send_extra_metadata[call->send_extra_metadata_count - 1];
-      batch->list.tail = linked_from_md(&metadata[count - 1]);
-      batch->list.head->prev = NULL;
-      batch->list.tail->next = NULL;
-      break;
-    default:
-      GPR_UNREACHABLE_CODE(return 0);
-  }
-
-  return 1;
-}
-
-void grpc_call_destroy(grpc_call *c) {
-  int cancel;
-  grpc_call *parent = c->parent;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GPR_TIMER_BEGIN("grpc_call_destroy", 0);
-  GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
-
-  if (parent) {
-    gpr_mu_lock(&parent->mu);
-    if (c == parent->first_child) {
-      parent->first_child = c->sibling_next;
-      if (c == parent->first_child) {
-        parent->first_child = NULL;
-      }
-      c->sibling_prev->sibling_next = c->sibling_next;
-      c->sibling_next->sibling_prev = c->sibling_prev;
-    }
-    gpr_mu_unlock(&parent->mu);
-    GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
-  }
-
-  gpr_mu_lock(&c->mu);
-  GPR_ASSERT(!c->destroy_called);
-  c->destroy_called = 1;
-  if (c->have_alarm) {
-    grpc_timer_cancel(&exec_ctx, &c->alarm);
-  }
-  cancel = !c->received_final_op;
-  gpr_mu_unlock(&c->mu);
-  if (cancel) grpc_call_cancel(c, NULL);
-  GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
-  grpc_exec_ctx_finish(&exec_ctx);
-  GPR_TIMER_END("grpc_call_destroy", 0);
-}
-
-grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
-  GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
-  GPR_ASSERT(!reserved);
-  return grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Cancelled",
-                                      NULL);
-}
-
-grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
-                                             grpc_status_code status,
-                                             const char *description,
-                                             void *reserved) {
-  grpc_call_error r;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GRPC_API_TRACE(
-      "grpc_call_cancel_with_status("
-      "c=%p, status=%d, description=%s, reserved=%p)",
-      4, (c, (int)status, description, reserved));
-  GPR_ASSERT(reserved == NULL);
-  gpr_mu_lock(&c->mu);
-  r = cancel_with_status(&exec_ctx, c, status, description);
-  gpr_mu_unlock(&c->mu);
-  grpc_exec_ctx_finish(&exec_ctx);
-  return r;
-}
-
-typedef struct cancel_closure {
-  grpc_closure closure;
-  grpc_call *call;
-  grpc_status_code status;
-} cancel_closure;
-
-static void done_cancel(grpc_exec_ctx *exec_ctx, void *ccp, bool success) {
-  cancel_closure *cc = ccp;
-  GRPC_CALL_INTERNAL_UNREF(exec_ctx, cc->call, "cancel");
-  gpr_free(cc);
-}
-
-static void send_cancel(grpc_exec_ctx *exec_ctx, void *ccp, bool success) {
-  grpc_transport_stream_op op;
-  cancel_closure *cc = ccp;
-  memset(&op, 0, sizeof(op));
-  op.cancel_with_status = cc->status;
-  /* reuse closure to catch completion */
-  grpc_closure_init(&cc->closure, done_cancel, cc);
-  op.on_complete = &cc->closure;
-  execute_op(exec_ctx, cc->call, &op);
-}
-
-static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
-                                          grpc_status_code status,
-                                          const char *description) {
-  grpc_mdstr *details =
-      description ? grpc_mdstr_from_string(description) : NULL;
-  cancel_closure *cc = gpr_malloc(sizeof(*cc));
-
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-
-  set_status_code(c, STATUS_FROM_API_OVERRIDE, (uint32_t)status);
-  set_status_details(c, STATUS_FROM_API_OVERRIDE, details);
-
-  grpc_closure_init(&cc->closure, send_cancel, cc);
-  cc->call = c;
-  cc->status = status;
-  GRPC_CALL_INTERNAL_REF(c, "cancel");
-  grpc_exec_ctx_enqueue(exec_ctx, &cc->closure, true, NULL);
-
-  return GRPC_CALL_OK;
-}
-
-static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                       grpc_transport_stream_op *op) {
-  grpc_call_element *elem;
-
-  GPR_TIMER_BEGIN("execute_op", 0);
-  elem = CALL_ELEM_FROM_CALL(call, 0);
-  op->context = call->context;
-  elem->filter->start_transport_stream_op(exec_ctx, elem, op);
-  GPR_TIMER_END("execute_op", 0);
-}
-
-char *grpc_call_get_peer(grpc_call *call) {
-  grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  char *result;
-  GRPC_API_TRACE("grpc_call_get_peer(%p)", 1, (call));
-  result = elem->filter->get_peer(&exec_ctx, elem);
-  if (result == NULL) {
-    result = grpc_channel_get_target(call->channel);
-  }
-  if (result == NULL) {
-    result = gpr_strdup("unknown");
-  }
-  grpc_exec_ctx_finish(&exec_ctx);
-  return result;
-}
-
-grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
-  return CALL_FROM_TOP_ELEM(elem);
-}
-
-static void call_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  grpc_call *call = arg;
-  gpr_mu_lock(&call->mu);
-  call->have_alarm = 0;
-  if (success) {
-    cancel_with_status(exec_ctx, call, GRPC_STATUS_DEADLINE_EXCEEDED,
-                       "Deadline Exceeded");
-  }
-  gpr_mu_unlock(&call->mu);
-  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "alarm");
-}
-
-static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                               gpr_timespec deadline) {
-  if (call->have_alarm) {
-    gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice");
-    assert(0);
-    return;
-  }
-  GRPC_CALL_INTERNAL_REF(call, "alarm");
-  call->have_alarm = 1;
-  call->send_deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
-  grpc_timer_init(exec_ctx, &call->alarm, call->send_deadline, call_alarm, call,
-                  gpr_now(GPR_CLOCK_MONOTONIC));
-}
-
-/* we offset status by a small amount when storing it into transport metadata
-   as metadata cannot store a 0 value (which is used as OK for grpc_status_codes
-   */
-#define STATUS_OFFSET 1
-static void destroy_status(void *ignored) {}
-
-static uint32_t decode_status(grpc_mdelem *md) {
-  uint32_t status;
-  void *user_data;
-  if (md == GRPC_MDELEM_GRPC_STATUS_0) return 0;
-  if (md == GRPC_MDELEM_GRPC_STATUS_1) return 1;
-  if (md == GRPC_MDELEM_GRPC_STATUS_2) return 2;
-  user_data = grpc_mdelem_get_user_data(md, destroy_status);
-  if (user_data != NULL) {
-    status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
-  } else {
-    if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
-                                   GPR_SLICE_LENGTH(md->value->slice),
-                                   &status)) {
-      status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
-    }
-    grpc_mdelem_set_user_data(md, destroy_status,
-                              (void *)(intptr_t)(status + STATUS_OFFSET));
-  }
-  return status;
-}
-
-static uint32_t decode_compression(grpc_mdelem *md) {
-  grpc_compression_algorithm algorithm =
-      grpc_compression_algorithm_from_mdstr(md->value);
-  if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
-    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
-    gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str);
-  }
-  return algorithm;
-}
-
-static grpc_mdelem *recv_common_filter(grpc_call *call, grpc_mdelem *elem) {
-  if (elem->key == GRPC_MDSTR_GRPC_STATUS) {
-    GPR_TIMER_BEGIN("status", 0);
-    set_status_code(call, STATUS_FROM_WIRE, decode_status(elem));
-    GPR_TIMER_END("status", 0);
-    return NULL;
-  } else if (elem->key == GRPC_MDSTR_GRPC_MESSAGE) {
-    GPR_TIMER_BEGIN("status-details", 0);
-    set_status_details(call, STATUS_FROM_WIRE, GRPC_MDSTR_REF(elem->value));
-    GPR_TIMER_END("status-details", 0);
-    return NULL;
-  }
-  return elem;
-}
-
-static grpc_mdelem *publish_app_metadata(grpc_call *call, grpc_mdelem *elem,
-                                         int is_trailing) {
-  grpc_metadata_array *dest;
-  grpc_metadata *mdusr;
-  GPR_TIMER_BEGIN("publish_app_metadata", 0);
-  dest = call->buffered_metadata[is_trailing];
-  if (dest->count == dest->capacity) {
-    dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2);
-    dest->metadata =
-        gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
-  }
-  mdusr = &dest->metadata[dest->count++];
-  mdusr->key = grpc_mdstr_as_c_string(elem->key);
-  mdusr->value = grpc_mdstr_as_c_string(elem->value);
-  mdusr->value_length = GPR_SLICE_LENGTH(elem->value->slice);
-  GPR_TIMER_END("publish_app_metadata", 0);
-  return elem;
-}
-
-static grpc_mdelem *recv_initial_filter(void *callp, grpc_mdelem *elem) {
-  grpc_call *call = callp;
-  elem = recv_common_filter(call, elem);
-  if (elem == NULL) {
-    return NULL;
-  } else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) {
-    GPR_TIMER_BEGIN("compression_algorithm", 0);
-    set_compression_algorithm(call, decode_compression(elem));
-    GPR_TIMER_END("compression_algorithm", 0);
-    return NULL;
-  } else if (elem->key == GRPC_MDSTR_GRPC_ACCEPT_ENCODING) {
-    GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
-    set_encodings_accepted_by_peer(call, elem);
-    GPR_TIMER_END("encodings_accepted_by_peer", 0);
-    return NULL;
-  } else {
-    return publish_app_metadata(call, elem, 0);
-  }
-}
-
-static grpc_mdelem *recv_trailing_filter(void *callp, grpc_mdelem *elem) {
-  grpc_call *call = callp;
-  elem = recv_common_filter(call, elem);
-  if (elem == NULL) {
-    return NULL;
-  } else {
-    return publish_app_metadata(call, elem, 1);
-  }
-}
-
-grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
-  return CALL_STACK_FROM_CALL(call);
-}
-
-/*
- * BATCH API IMPLEMENTATION
- */
-
-static void set_status_value_directly(grpc_status_code status, void *dest) {
-  *(grpc_status_code *)dest = status;
-}
-
-static void set_cancelled_value(grpc_status_code status, void *dest) {
-  *(int *)dest = (status != GRPC_STATUS_OK);
-}
-
-static int are_write_flags_valid(uint32_t flags) {
-  /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
-  const uint32_t allowed_write_positions =
-      (GRPC_WRITE_USED_MASK | GRPC_WRITE_INTERNAL_USED_MASK);
-  const uint32_t invalid_positions = ~allowed_write_positions;
-  return !(flags & invalid_positions);
-}
-
-static batch_control *allocate_batch_control(grpc_call *call) {
-  size_t i;
-  for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
-    if ((call->used_batches & (1 << i)) == 0) {
-      call->used_batches = (uint8_t)(call->used_batches | (uint8_t)(1 << i));
-      return &call->active_batches[i];
-    }
-  }
-  return NULL;
-}
-
-static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
-                                    grpc_cq_completion *storage) {
-  batch_control *bctl = user_data;
-  grpc_call *call = bctl->call;
-  gpr_mu_lock(&call->mu);
-  call->used_batches = (uint8_t)(
-      call->used_batches & ~(uint8_t)(1 << (bctl - call->active_batches)));
-  gpr_mu_unlock(&call->mu);
-  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
-}
-
-static void post_batch_completion(grpc_exec_ctx *exec_ctx,
-                                  batch_control *bctl) {
-  grpc_call *call = bctl->call;
-  if (bctl->is_notify_tag_closure) {
-    grpc_exec_ctx_enqueue(exec_ctx, bctl->notify_tag, bctl->success, NULL);
-    gpr_mu_lock(&call->mu);
-    bctl->call->used_batches =
-        (uint8_t)(bctl->call->used_batches &
-                  ~(uint8_t)(1 << (bctl - bctl->call->active_batches)));
-    gpr_mu_unlock(&call->mu);
-    GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
-  } else {
-    grpc_cq_end_op(exec_ctx, bctl->call->cq, bctl->notify_tag, bctl->success,
-                   finish_batch_completion, bctl, &bctl->cq_completion);
-  }
-}
-
-static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
-                                      batch_control *bctl) {
-  grpc_call *call = bctl->call;
-  for (;;) {
-    size_t remaining = call->receiving_stream->length -
-                       (*call->receiving_buffer)->data.raw.slice_buffer.length;
-    if (remaining == 0) {
-      call->receiving_message = 0;
-      grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
-      call->receiving_stream = NULL;
-      if (gpr_unref(&bctl->steps_to_complete)) {
-        post_batch_completion(exec_ctx, bctl);
-      }
-      return;
-    }
-    if (grpc_byte_stream_next(exec_ctx, call->receiving_stream,
-                              &call->receiving_slice, remaining,
-                              &call->receiving_slice_ready)) {
-      gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
-                           call->receiving_slice);
-    } else {
-      return;
-    }
-  }
-}
-
-static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
-                                  bool success) {
-  batch_control *bctl = bctlp;
-  grpc_call *call = bctl->call;
-
-  if (success) {
-    gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
-                         call->receiving_slice);
-    continue_receiving_slices(exec_ctx, bctl);
-  } else {
-    grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
-    call->receiving_stream = NULL;
-    grpc_byte_buffer_destroy(*call->receiving_buffer);
-    *call->receiving_buffer = NULL;
-    if (gpr_unref(&bctl->steps_to_complete)) {
-      post_batch_completion(exec_ctx, bctl);
-    }
-  }
-}
-
-static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl,
-                                  bool success) {
-  grpc_call *call = bctl->call;
-  if (call->receiving_stream == NULL) {
-    *call->receiving_buffer = NULL;
-    call->receiving_message = 0;
-    if (gpr_unref(&bctl->steps_to_complete)) {
-      post_batch_completion(exec_ctx, bctl);
-    }
-  } else if (call->receiving_stream->length >
-             grpc_channel_get_max_message_length(call->channel)) {
-    cancel_with_status(exec_ctx, call, GRPC_STATUS_INTERNAL,
-                       "Max message size exceeded");
-    grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
-    call->receiving_stream = NULL;
-    *call->receiving_buffer = NULL;
-    call->receiving_message = 0;
-    if (gpr_unref(&bctl->steps_to_complete)) {
-      post_batch_completion(exec_ctx, bctl);
-    }
-  } else {
-    call->test_only_last_message_flags = call->receiving_stream->flags;
-    if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&
-        (call->compression_algorithm > GRPC_COMPRESS_NONE)) {
-      *call->receiving_buffer = grpc_raw_compressed_byte_buffer_create(
-          NULL, 0, call->compression_algorithm);
-    } else {
-      *call->receiving_buffer = grpc_raw_byte_buffer_create(NULL, 0);
-    }
-    grpc_closure_init(&call->receiving_slice_ready, receiving_slice_ready,
-                      bctl);
-    continue_receiving_slices(exec_ctx, bctl);
-    /* early out */
-    return;
-  }
-}
-
-static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
-                                   bool success) {
-  batch_control *bctl = bctlp;
-  grpc_call *call = bctl->call;
-
-  gpr_mu_lock(&bctl->call->mu);
-  if (bctl->call->has_initial_md_been_received) {
-    gpr_mu_unlock(&bctl->call->mu);
-    process_data_after_md(exec_ctx, bctlp, success);
-  } else {
-    call->saved_receiving_stream_ready_ctx.bctlp = bctlp;
-    call->saved_receiving_stream_ready_ctx.success = success;
-    gpr_mu_unlock(&bctl->call->mu);
-  }
-}
-
-static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
-                                             void *bctlp, bool success) {
-  batch_control *bctl = bctlp;
-  grpc_call *call = bctl->call;
-
-  gpr_mu_lock(&call->mu);
-
-  grpc_metadata_batch *md =
-      &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
-  grpc_metadata_batch_filter(md, recv_initial_filter, call);
-  call->has_initial_md_been_received = true;
-
-  if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
-          0 &&
-      !call->is_client) {
-    GPR_TIMER_BEGIN("set_deadline_alarm", 0);
-    set_deadline_alarm(exec_ctx, call, md->deadline);
-    GPR_TIMER_END("set_deadline_alarm", 0);
-  }
-
-  if (call->saved_receiving_stream_ready_ctx.bctlp != NULL) {
-    grpc_closure *saved_rsr_closure = grpc_closure_create(
-        receiving_stream_ready, call->saved_receiving_stream_ready_ctx.bctlp);
-    grpc_exec_ctx_enqueue(exec_ctx, saved_rsr_closure,
-                          call->saved_receiving_stream_ready_ctx.success, NULL);
-    call->saved_receiving_stream_ready_ctx.bctlp = NULL;
-  }
-
-  gpr_mu_unlock(&call->mu);
-
-  if (gpr_unref(&bctl->steps_to_complete)) {
-    post_batch_completion(exec_ctx, bctl);
-  }
-}
-
-static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, bool success) {
-  batch_control *bctl = bctlp;
-  grpc_call *call = bctl->call;
-  grpc_call *child_call;
-  grpc_call *next_child_call;
-
-  gpr_mu_lock(&call->mu);
-  if (bctl->send_initial_metadata) {
-    grpc_metadata_batch_destroy(
-        &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
-  }
-  if (bctl->send_message) {
-    call->sending_message = 0;
-  }
-  if (bctl->send_final_op) {
-    grpc_metadata_batch_destroy(
-        &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
-  }
-  if (bctl->recv_final_op) {
-    grpc_metadata_batch *md =
-        &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
-    grpc_metadata_batch_filter(md, recv_trailing_filter, call);
-
-    if (call->have_alarm) {
-      grpc_timer_cancel(exec_ctx, &call->alarm);
-    }
-    /* propagate cancellation to any interested children */
-    child_call = call->first_child;
-    if (child_call != NULL) {
-      do {
-        next_child_call = child_call->sibling_next;
-        if (child_call->cancellation_is_inherited) {
-          GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
-          grpc_call_cancel(child_call, NULL);
-          GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
-        }
-        child_call = next_child_call;
-      } while (child_call != call->first_child);
-    }
-
-    if (call->is_client) {
-      get_final_status(call, set_status_value_directly,
-                       call->final_op.client.status);
-      get_final_details(call, call->final_op.client.status_details,
-                        call->final_op.client.status_details_capacity);
-    } else {
-      get_final_status(call, set_cancelled_value,
-                       call->final_op.server.cancelled);
-    }
-
-    success = 1;
-  }
-  bctl->success = success != 0;
-  gpr_mu_unlock(&call->mu);
-  if (gpr_unref(&bctl->steps_to_complete)) {
-    post_batch_completion(exec_ctx, bctl);
-  }
-}
-
-static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
-                                        grpc_call *call, const grpc_op *ops,
-                                        size_t nops, void *notify_tag,
-                                        int is_notify_tag_closure) {
-  grpc_transport_stream_op stream_op;
-  size_t i;
-  const grpc_op *op;
-  batch_control *bctl;
-  int num_completion_callbacks_needed = 1;
-  grpc_call_error error = GRPC_CALL_OK;
-
-  GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
-
-  GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
-
-  memset(&stream_op, 0, sizeof(stream_op));
-
-  /* TODO(ctiller): this feels like it could be made lock-free */
-  gpr_mu_lock(&call->mu);
-  bctl = allocate_batch_control(call);
-  memset(bctl, 0, sizeof(*bctl));
-  bctl->call = call;
-  bctl->notify_tag = notify_tag;
-  bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
-
-  if (nops == 0) {
-    GRPC_CALL_INTERNAL_REF(call, "completion");
-    bctl->success = 1;
-    if (!is_notify_tag_closure) {
-      grpc_cq_begin_op(call->cq, notify_tag);
-    }
-    gpr_mu_unlock(&call->mu);
-    post_batch_completion(exec_ctx, bctl);
-    error = GRPC_CALL_OK;
-    goto done;
-  }
-
-  /* rewrite batch ops into a transport op */
-  for (i = 0; i < nops; i++) {
-    op = &ops[i];
-    if (op->reserved != NULL) {
-      error = GRPC_CALL_ERROR;
-      goto done_with_error;
-    }
-    switch (op->op) {
-      case GRPC_OP_SEND_INITIAL_METADATA:
-        /* Flag validation: currently allow no flags */
-        if (op->flags != 0) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (call->sent_initial_metadata) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        if (op->data.send_initial_metadata.count > INT_MAX) {
-          error = GRPC_CALL_ERROR_INVALID_METADATA;
-          goto done_with_error;
-        }
-        bctl->send_initial_metadata = 1;
-        call->sent_initial_metadata = 1;
-        if (!prepare_application_metadata(
-                call, (int)op->data.send_initial_metadata.count,
-                op->data.send_initial_metadata.metadata, 0, call->is_client)) {
-          error = GRPC_CALL_ERROR_INVALID_METADATA;
-          goto done_with_error;
-        }
-        /* TODO(ctiller): just make these the same variable? */
-        call->metadata_batch[0][0].deadline = call->send_deadline;
-        stream_op.send_initial_metadata =
-            &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
-        break;
-      case GRPC_OP_SEND_MESSAGE:
-        if (!are_write_flags_valid(op->flags)) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (op->data.send_message == NULL) {
-          error = GRPC_CALL_ERROR_INVALID_MESSAGE;
-          goto done_with_error;
-        }
-        if (call->sending_message) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        bctl->send_message = 1;
-        call->sending_message = 1;
-        grpc_slice_buffer_stream_init(
-            &call->sending_stream,
-            &op->data.send_message->data.raw.slice_buffer, op->flags);
-        stream_op.send_message = &call->sending_stream.base;
-        break;
-      case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
-        /* Flag validation: currently allow no flags */
-        if (op->flags != 0) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (!call->is_client) {
-          error = GRPC_CALL_ERROR_NOT_ON_SERVER;
-          goto done_with_error;
-        }
-        if (call->sent_final_op) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        bctl->send_final_op = 1;
-        call->sent_final_op = 1;
-        stream_op.send_trailing_metadata =
-            &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
-        break;
-      case GRPC_OP_SEND_STATUS_FROM_SERVER:
-        /* Flag validation: currently allow no flags */
-        if (op->flags != 0) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (call->is_client) {
-          error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
-          goto done_with_error;
-        }
-        if (call->sent_final_op) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        if (op->data.send_status_from_server.trailing_metadata_count >
-            INT_MAX) {
-          error = GRPC_CALL_ERROR_INVALID_METADATA;
-          goto done_with_error;
-        }
-        bctl->send_final_op = 1;
-        call->sent_final_op = 1;
-        call->send_extra_metadata_count = 1;
-        call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
-            call->channel, op->data.send_status_from_server.status);
-        if (op->data.send_status_from_server.status_details != NULL) {
-          call->send_extra_metadata[1].md = grpc_mdelem_from_metadata_strings(
-              GRPC_MDSTR_GRPC_MESSAGE,
-              grpc_mdstr_from_string(
-                  op->data.send_status_from_server.status_details));
-          call->send_extra_metadata_count++;
-          set_status_details(
-              call, STATUS_FROM_API_OVERRIDE,
-              GRPC_MDSTR_REF(call->send_extra_metadata[1].md->value));
-        }
-        set_status_code(call, STATUS_FROM_API_OVERRIDE,
-                        (uint32_t)op->data.send_status_from_server.status);
-        if (!prepare_application_metadata(
-                call,
-                (int)op->data.send_status_from_server.trailing_metadata_count,
-                op->data.send_status_from_server.trailing_metadata, 1, 1)) {
-          error = GRPC_CALL_ERROR_INVALID_METADATA;
-          goto done_with_error;
-        }
-        stream_op.send_trailing_metadata =
-            &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
-        break;
-      case GRPC_OP_RECV_INITIAL_METADATA:
-        /* Flag validation: currently allow no flags */
-        if (op->flags != 0) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (call->received_initial_metadata) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        call->received_initial_metadata = 1;
-        call->buffered_metadata[0] = op->data.recv_initial_metadata;
-        grpc_closure_init(&call->receiving_initial_metadata_ready,
-                          receiving_initial_metadata_ready, bctl);
-        bctl->recv_initial_metadata = 1;
-        stream_op.recv_initial_metadata =
-            &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
-        stream_op.recv_initial_metadata_ready =
-            &call->receiving_initial_metadata_ready;
-        num_completion_callbacks_needed++;
-        break;
-      case GRPC_OP_RECV_MESSAGE:
-        /* Flag validation: currently allow no flags */
-        if (op->flags != 0) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (call->receiving_message) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        call->receiving_message = 1;
-        bctl->recv_message = 1;
-        call->receiving_buffer = op->data.recv_message;
-        stream_op.recv_message = &call->receiving_stream;
-        grpc_closure_init(&call->receiving_stream_ready, receiving_stream_ready,
-                          bctl);
-        stream_op.recv_message_ready = &call->receiving_stream_ready;
-        num_completion_callbacks_needed++;
-        break;
-      case GRPC_OP_RECV_STATUS_ON_CLIENT:
-        /* Flag validation: currently allow no flags */
-        if (op->flags != 0) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (!call->is_client) {
-          error = GRPC_CALL_ERROR_NOT_ON_SERVER;
-          goto done_with_error;
-        }
-        if (call->received_final_op) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        call->received_final_op = 1;
-        call->buffered_metadata[1] =
-            op->data.recv_status_on_client.trailing_metadata;
-        call->final_op.client.status = op->data.recv_status_on_client.status;
-        call->final_op.client.status_details =
-            op->data.recv_status_on_client.status_details;
-        call->final_op.client.status_details_capacity =
-            op->data.recv_status_on_client.status_details_capacity;
-        bctl->recv_final_op = 1;
-        stream_op.recv_trailing_metadata =
-            &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
-        break;
-      case GRPC_OP_RECV_CLOSE_ON_SERVER:
-        /* Flag validation: currently allow no flags */
-        if (op->flags != 0) {
-          error = GRPC_CALL_ERROR_INVALID_FLAGS;
-          goto done_with_error;
-        }
-        if (call->is_client) {
-          error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
-          goto done_with_error;
-        }
-        if (call->received_final_op) {
-          error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
-          goto done_with_error;
-        }
-        call->received_final_op = 1;
-        call->final_op.server.cancelled =
-            op->data.recv_close_on_server.cancelled;
-        bctl->recv_final_op = 1;
-        stream_op.recv_trailing_metadata =
-            &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
-        break;
-    }
-  }
-
-  GRPC_CALL_INTERNAL_REF(call, "completion");
-  if (!is_notify_tag_closure) {
-    grpc_cq_begin_op(call->cq, notify_tag);
-  }
-  gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
-
-  stream_op.context = call->context;
-  grpc_closure_init(&bctl->finish_batch, finish_batch, bctl);
-  stream_op.on_complete = &bctl->finish_batch;
-  gpr_mu_unlock(&call->mu);
-
-  execute_op(exec_ctx, call, &stream_op);
-
-done:
-  GPR_TIMER_END("grpc_call_start_batch", 0);
-  return error;
-
-done_with_error:
-  /* reverse any mutations that occured */
-  if (bctl->send_initial_metadata) {
-    call->sent_initial_metadata = 0;
-    grpc_metadata_batch_clear(&call->metadata_batch[0][0]);
-  }
-  if (bctl->send_message) {
-    call->sending_message = 0;
-    grpc_byte_stream_destroy(exec_ctx, &call->sending_stream.base);
-  }
-  if (bctl->send_final_op) {
-    call->sent_final_op = 0;
-    grpc_metadata_batch_clear(&call->metadata_batch[0][1]);
-  }
-  if (bctl->recv_initial_metadata) {
-    call->received_initial_metadata = 0;
-  }
-  if (bctl->recv_message) {
-    call->receiving_message = 0;
-  }
-  if (bctl->recv_final_op) {
-    call->received_final_op = 0;
-  }
-  gpr_mu_unlock(&call->mu);
-  goto done;
-}
-
-grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
-                                      size_t nops, void *tag, void *reserved) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_call_error err;
-
-  GRPC_API_TRACE(
-      "grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, reserved=%p)",
-      5, (call, ops, (unsigned long)nops, tag, reserved));
-
-  if (reserved != NULL) {
-    err = GRPC_CALL_ERROR;
-  } else {
-    err = call_start_batch(&exec_ctx, call, ops, nops, tag, 0);
-  }
-
-  grpc_exec_ctx_finish(&exec_ctx);
-  return err;
-}
-
-grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx,
-                                                  grpc_call *call,
-                                                  const grpc_op *ops,
-                                                  size_t nops,
-                                                  grpc_closure *closure) {
-  return call_start_batch(exec_ctx, call, ops, nops, closure, 1);
-}
-
-void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
-                           void *value, void (*destroy)(void *value)) {
-  if (call->context[elem].destroy) {
-    call->context[elem].destroy(call->context[elem].value);
-  }
-  call->context[elem].value = value;
-  call->context[elem].destroy = destroy;
-}
-
-void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) {
-  return call->context[elem].value;
-}
-
-uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; }
-
-grpc_compression_algorithm grpc_call_compression_for_level(
-    grpc_call *call, grpc_compression_level level) {
-  gpr_mu_lock(&call->mu);
-  const uint32_t accepted_encodings = call->encodings_accepted_by_peer;
-  gpr_mu_unlock(&call->mu);
-  return grpc_compression_algorithm_for_level(level, accepted_encodings);
-}
diff --git a/src/core/surface/call.h b/src/core/surface/call.h
deleted file mode 100644
index d2edf03..0000000
--- a/src/core/surface/call.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_CALL_H
-#define GRPC_CORE_SURFACE_CALL_H
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/channel/context.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/surface_trace.h"
-
-#include <grpc/grpc.h>
-#include <grpc/impl/codegen/compression_types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*grpc_ioreq_completion_func)(grpc_exec_ctx *exec_ctx,
-                                           grpc_call *call, int success,
-                                           void *user_data);
-
-grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
-                            uint32_t propagation_mask,
-                            grpc_completion_queue *cq,
-                            const void *server_transport_data,
-                            grpc_mdelem **add_initial_metadata,
-                            size_t add_initial_metadata_count,
-                            gpr_timespec send_deadline);
-
-void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                                    grpc_completion_queue *cq);
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-void grpc_call_internal_ref(grpc_call *call, const char *reason);
-void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                              const char *reason);
-#define GRPC_CALL_INTERNAL_REF(call, reason) \
-  grpc_call_internal_ref(call, reason)
-#define GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, reason) \
-  grpc_call_internal_unref(exec_ctx, call, reason)
-#else
-void grpc_call_internal_ref(grpc_call *call);
-void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call);
-#define GRPC_CALL_INTERNAL_REF(call, reason) grpc_call_internal_ref(call)
-#define GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, reason) \
-  grpc_call_internal_unref(exec_ctx, call)
-#endif
-
-grpc_call_stack *grpc_call_get_call_stack(grpc_call *call);
-
-grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx,
-                                                  grpc_call *call,
-                                                  const grpc_op *ops,
-                                                  size_t nops,
-                                                  grpc_closure *closure);
-
-/* Given the top call_element, get the call object. */
-grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element);
-
-void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
-                         grpc_call *call, const grpc_op *ops, size_t nops,
-                         void *tag);
-
-/* Set a context pointer.
-   No thread safety guarantees are made wrt this value. */
-void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
-                           void *value, void (*destroy)(void *value));
-/* Get a context pointer. */
-void *grpc_call_context_get(grpc_call *call, grpc_context_index elem);
-
-#define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \
-  if (grpc_api_trace) grpc_call_log_batch(sev, call, ops, nops, tag)
-
-uint8_t grpc_call_is_client(grpc_call *call);
-
-/* Return an appropriate compression algorithm for the requested compression \a
- * level in the context of \a call. */
-grpc_compression_algorithm grpc_call_compression_for_level(
-    grpc_call *call, grpc_compression_level level);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_SURFACE_CALL_H */
diff --git a/src/core/surface/call_details.c b/src/core/surface/call_details.c
deleted file mode 100644
index 60f0029..0000000
--- a/src/core/surface/call_details.c
+++ /dev/null
@@ -1,50 +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/grpc.h>
-#include <grpc/support/alloc.h>
-
-#include <string.h>
-
-#include "src/core/surface/api_trace.h"
-
-void grpc_call_details_init(grpc_call_details* cd) {
-  GRPC_API_TRACE("grpc_call_details_init(cd=%p)", 1, (cd));
-  memset(cd, 0, sizeof(*cd));
-}
-
-void grpc_call_details_destroy(grpc_call_details* cd) {
-  GRPC_API_TRACE("grpc_call_details_destroy(cd=%p)", 1, (cd));
-  gpr_free(cd->method);
-  gpr_free(cd->host);
-}
diff --git a/src/core/surface/call_log_batch.c b/src/core/surface/call_log_batch.c
deleted file mode 100644
index 46756f4..0000000
--- a/src/core/surface/call_log_batch.c
+++ /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.
- *
- */
-
-#include "src/core/surface/call.h"
-
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/string_util.h>
-
-static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) {
-  size_t i;
-  for (i = 0; i < count; i++) {
-    gpr_strvec_add(b, gpr_strdup("\nkey="));
-    gpr_strvec_add(b, gpr_strdup(md[i].key));
-
-    gpr_strvec_add(b, gpr_strdup(" value="));
-    gpr_strvec_add(b, gpr_dump(md[i].value, md[i].value_length,
-                               GPR_DUMP_HEX | GPR_DUMP_ASCII));
-  }
-}
-
-char *grpc_op_string(const grpc_op *op) {
-  char *tmp;
-  char *out;
-
-  gpr_strvec b;
-  gpr_strvec_init(&b);
-
-  switch (op->op) {
-    case GRPC_OP_SEND_INITIAL_METADATA:
-      gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA"));
-      add_metadata(&b, op->data.send_initial_metadata.metadata,
-                   op->data.send_initial_metadata.count);
-      break;
-    case GRPC_OP_SEND_MESSAGE:
-      gpr_asprintf(&tmp, "SEND_MESSAGE ptr=%p", op->data.send_message);
-      gpr_strvec_add(&b, tmp);
-      break;
-    case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
-      gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
-      break;
-    case GRPC_OP_SEND_STATUS_FROM_SERVER:
-      gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=%s",
-                   op->data.send_status_from_server.status,
-                   op->data.send_status_from_server.status_details);
-      gpr_strvec_add(&b, tmp);
-      add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
-                   op->data.send_status_from_server.trailing_metadata_count);
-      break;
-    case GRPC_OP_RECV_INITIAL_METADATA:
-      gpr_asprintf(&tmp, "RECV_INITIAL_METADATA ptr=%p",
-                   op->data.recv_initial_metadata);
-      gpr_strvec_add(&b, tmp);
-      break;
-    case GRPC_OP_RECV_MESSAGE:
-      gpr_asprintf(&tmp, "RECV_MESSAGE ptr=%p", op->data.recv_message);
-      gpr_strvec_add(&b, tmp);
-      break;
-    case GRPC_OP_RECV_STATUS_ON_CLIENT:
-      gpr_asprintf(&tmp,
-                   "RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
-                   op->data.recv_status_on_client.trailing_metadata,
-                   op->data.recv_status_on_client.status,
-                   op->data.recv_status_on_client.status_details);
-      gpr_strvec_add(&b, tmp);
-      break;
-    case GRPC_OP_RECV_CLOSE_ON_SERVER:
-      gpr_asprintf(&tmp, "RECV_CLOSE_ON_SERVER cancelled=%p",
-                   op->data.recv_close_on_server.cancelled);
-      gpr_strvec_add(&b, tmp);
-  }
-  out = gpr_strvec_flatten(&b, NULL);
-  gpr_strvec_destroy(&b);
-
-  return out;
-}
-
-void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
-                         grpc_call *call, const grpc_op *ops, size_t nops,
-                         void *tag) {
-  char *tmp;
-  size_t i;
-  for (i = 0; i < nops; i++) {
-    tmp = grpc_op_string(&ops[i]);
-    gpr_log(file, line, severity, "ops[%d]: %s", i, tmp);
-    gpr_free(tmp);
-  }
-}
diff --git a/src/core/surface/call_test_only.h b/src/core/surface/call_test_only.h
deleted file mode 100644
index fdc43a3..0000000
--- a/src/core/surface/call_test_only.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_CALL_TEST_ONLY_H
-#define GRPC_CORE_SURFACE_CALL_TEST_ONLY_H
-
-#include <grpc/grpc.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Return the compression algorithm from \a call.
- *
- * \warning This function should \b only be used in test code. */
-grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
-    grpc_call *call);
-
-/** Return the message flags from \a call.
- *
- * \warning This function should \b only be used in test code. */
-uint32_t grpc_call_test_only_get_message_flags(grpc_call *call);
-
-/** Returns a bitset for the encodings (compression algorithms) supported by \a
- * call's peer.
- *
- * To be indexed by grpc_compression_algorithm enum values. */
-uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_SURFACE_CALL_TEST_ONLY_H */
diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c
deleted file mode 100644
index 964ab34..0000000
--- a/src/core/surface/channel.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- *
- * 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/surface/channel.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/surface/channel_init.h"
-#include "src/core/client_config/resolver_registry.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/call.h"
-#include "src/core/surface/init.h"
-#include "src/core/transport/static_metadata.h"
-
-/** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
- *  Avoids needing to take a metadata context lock for sending status
- *  if the status code is <= NUM_CACHED_STATUS_ELEMS.
- *  Sized to allow the most commonly used codes to fit in
- *  (OK, Cancelled, Unknown). */
-#define NUM_CACHED_STATUS_ELEMS 3
-
-typedef struct registered_call {
-  grpc_mdelem *path;
-  grpc_mdelem *authority;
-  struct registered_call *next;
-} registered_call;
-
-struct grpc_channel {
-  int is_client;
-  uint32_t max_message_length;
-  grpc_mdelem *default_authority;
-
-  gpr_mu registered_call_mu;
-  registered_call *registered_calls;
-  char *target;
-};
-
-#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
-#define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \
-  (((grpc_channel *)(channel_stack)) - 1)
-#define CHANNEL_FROM_TOP_ELEM(top_elem) \
-  CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
-
-/* the protobuf library will (by default) start warning at 100megs */
-#define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
-
-static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, bool success);
-
-grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
-                                  const grpc_channel_args *args,
-                                  grpc_channel_stack_type channel_stack_type,
-                                  grpc_transport *optional_transport) {
-  bool is_client = grpc_channel_stack_type_is_client(channel_stack_type);
-
-  grpc_channel *channel = grpc_channel_init_create_stack(
-      exec_ctx, channel_stack_type, sizeof(grpc_channel), args, 1,
-      destroy_channel, NULL, optional_transport);
-
-  memset(channel, 0, sizeof(*channel));
-  channel->target = gpr_strdup(target);
-  channel->is_client = is_client;
-  gpr_mu_init(&channel->registered_call_mu);
-  channel->registered_calls = NULL;
-
-  channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH;
-  if (args) {
-    for (size_t i = 0; i < args->num_args; i++) {
-      if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) {
-        if (args->args[i].type != GRPC_ARG_INTEGER) {
-          gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
-                  GRPC_ARG_MAX_MESSAGE_LENGTH);
-        } else if (args->args[i].value.integer < 0) {
-          gpr_log(GPR_ERROR, "%s ignored: it must be >= 0",
-                  GRPC_ARG_MAX_MESSAGE_LENGTH);
-        } else {
-          channel->max_message_length = (uint32_t)args->args[i].value.integer;
-        }
-      } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
-        if (args->args[i].type != GRPC_ARG_STRING) {
-          gpr_log(GPR_ERROR, "%s ignored: it must be a string",
-                  GRPC_ARG_DEFAULT_AUTHORITY);
-        } else {
-          if (channel->default_authority) {
-            /* setting this takes precedence over anything else */
-            GRPC_MDELEM_UNREF(channel->default_authority);
-          }
-          channel->default_authority = grpc_mdelem_from_strings(
-              ":authority", args->args[i].value.string);
-        }
-      } else if (0 ==
-                 strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
-        if (args->args[i].type != GRPC_ARG_STRING) {
-          gpr_log(GPR_ERROR, "%s ignored: it must be a string",
-                  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-        } else {
-          if (channel->default_authority) {
-            /* other ways of setting this (notably ssl) take precedence */
-            gpr_log(GPR_ERROR,
-                    "%s ignored: default host already set some other way",
-                    GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-          } else {
-            channel->default_authority = grpc_mdelem_from_strings(
-                ":authority", args->args[i].value.string);
-          }
-        }
-      }
-    }
-  }
-
-  if (channel->is_client && channel->default_authority == NULL &&
-      target != NULL) {
-    char *default_authority = grpc_get_default_authority(target);
-    if (default_authority) {
-      channel->default_authority =
-          grpc_mdelem_from_strings(":authority", default_authority);
-    }
-    gpr_free(default_authority);
-  }
-
-  return channel;
-}
-
-char *grpc_channel_get_target(grpc_channel *channel) {
-  GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
-  return gpr_strdup(channel->target);
-}
-
-static grpc_call *grpc_channel_create_call_internal(
-    grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
-    grpc_completion_queue *cq, grpc_mdelem *path_mdelem,
-    grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
-  grpc_mdelem *send_metadata[2];
-  size_t num_metadata = 0;
-
-  GPR_ASSERT(channel->is_client);
-
-  send_metadata[num_metadata++] = path_mdelem;
-  if (authority_mdelem != NULL) {
-    send_metadata[num_metadata++] = authority_mdelem;
-  } else if (channel->default_authority != NULL) {
-    send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
-  }
-
-  return grpc_call_create(channel, parent_call, propagation_mask, cq, NULL,
-                          send_metadata, num_metadata, deadline);
-}
-
-grpc_call *grpc_channel_create_call(grpc_channel *channel,
-                                    grpc_call *parent_call,
-                                    uint32_t propagation_mask,
-                                    grpc_completion_queue *cq,
-                                    const char *method, const char *host,
-                                    gpr_timespec deadline, void *reserved) {
-  GRPC_API_TRACE(
-      "grpc_channel_create_call("
-      "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
-      "host=%s, "
-      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
-      "reserved=%p)",
-      10, (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
-           (long long)deadline.tv_sec, (int)deadline.tv_nsec,
-           (int)deadline.clock_type, reserved));
-  GPR_ASSERT(!reserved);
-  return grpc_channel_create_call_internal(
-      channel, parent_call, propagation_mask, cq,
-      grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
-                                        grpc_mdstr_from_string(method)),
-      host ? grpc_mdelem_from_metadata_strings(GRPC_MDSTR_AUTHORITY,
-                                               grpc_mdstr_from_string(host))
-           : NULL,
-      deadline);
-}
-
-void *grpc_channel_register_call(grpc_channel *channel, const char *method,
-                                 const char *host, void *reserved) {
-  registered_call *rc = gpr_malloc(sizeof(registered_call));
-  GRPC_API_TRACE(
-      "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
-      4, (channel, method, host, reserved));
-  GPR_ASSERT(!reserved);
-  rc->path = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
-                                               grpc_mdstr_from_string(method));
-  rc->authority = host ? grpc_mdelem_from_metadata_strings(
-                             GRPC_MDSTR_AUTHORITY, grpc_mdstr_from_string(host))
-                       : NULL;
-  gpr_mu_lock(&channel->registered_call_mu);
-  rc->next = channel->registered_calls;
-  channel->registered_calls = rc;
-  gpr_mu_unlock(&channel->registered_call_mu);
-  return rc;
-}
-
-grpc_call *grpc_channel_create_registered_call(
-    grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
-    grpc_completion_queue *completion_queue, void *registered_call_handle,
-    gpr_timespec deadline, void *reserved) {
-  registered_call *rc = registered_call_handle;
-  GRPC_API_TRACE(
-      "grpc_channel_create_registered_call("
-      "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
-      "registered_call_handle=%p, "
-      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
-      "reserved=%p)",
-      9, (channel, parent_call, (unsigned)propagation_mask, completion_queue,
-          registered_call_handle, (long long)deadline.tv_sec,
-          (int)deadline.tv_nsec, (int)deadline.clock_type, reserved));
-  GPR_ASSERT(!reserved);
-  return grpc_channel_create_call_internal(
-      channel, parent_call, propagation_mask, completion_queue,
-      GRPC_MDELEM_REF(rc->path),
-      rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline);
-}
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-#define REF_REASON reason
-#define REF_ARG , const char *reason
-#else
-#define REF_REASON ""
-#define REF_ARG
-#endif
-void grpc_channel_internal_ref(grpc_channel *c REF_ARG) {
-  GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON);
-}
-
-void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel *c REF_ARG) {
-  GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON);
-}
-
-static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg,
-                            bool iomgr_success) {
-  grpc_channel *channel = arg;
-  grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel));
-  while (channel->registered_calls) {
-    registered_call *rc = channel->registered_calls;
-    channel->registered_calls = rc->next;
-    GRPC_MDELEM_UNREF(rc->path);
-    if (rc->authority) {
-      GRPC_MDELEM_UNREF(rc->authority);
-    }
-    gpr_free(rc);
-  }
-  if (channel->default_authority != NULL) {
-    GRPC_MDELEM_UNREF(channel->default_authority);
-  }
-  gpr_mu_destroy(&channel->registered_call_mu);
-  gpr_free(channel->target);
-  gpr_free(channel);
-}
-
-void grpc_channel_destroy(grpc_channel *channel) {
-  grpc_transport_op op;
-  grpc_channel_element *elem;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
-  memset(&op, 0, sizeof(op));
-  op.disconnect = 1;
-  elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
-  elem->filter->start_transport_op(&exec_ctx, elem, &op);
-
-  GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel");
-
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) {
-  return CHANNEL_STACK_FROM_CHANNEL(channel);
-}
-
-grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
-  char tmp[GPR_LTOA_MIN_BUFSIZE];
-  switch (i) {
-    case 0:
-      return GRPC_MDELEM_GRPC_STATUS_0;
-    case 1:
-      return GRPC_MDELEM_GRPC_STATUS_1;
-    case 2:
-      return GRPC_MDELEM_GRPC_STATUS_2;
-  }
-  gpr_ltoa(i, tmp);
-  return grpc_mdelem_from_metadata_strings(GRPC_MDSTR_GRPC_STATUS,
-                                           grpc_mdstr_from_string(tmp));
-}
-
-uint32_t grpc_channel_get_max_message_length(grpc_channel *channel) {
-  return channel->max_message_length;
-}
diff --git a/src/core/surface/channel.h b/src/core/surface/channel.h
deleted file mode 100644
index c08988d..0000000
--- a/src/core/surface/channel.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_CHANNEL_H
-#define GRPC_CORE_SURFACE_CHANNEL_H
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/surface/channel_stack_type.h"
-#include "src/core/client_config/subchannel_factory.h"
-
-grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
-                                  const grpc_channel_args *args,
-                                  grpc_channel_stack_type channel_stack_type,
-                                  grpc_transport *optional_transport);
-
-/** Get a (borrowed) pointer to this channels underlying channel stack */
-grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel);
-
-/** Get a grpc_mdelem of grpc-status: X where X is the numeric value of
-    status_code.
-
-    The returned elem is owned by the caller. */
-grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel,
-                                                 int status_code);
-uint32_t grpc_channel_get_max_message_length(grpc_channel *channel);
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-void grpc_channel_internal_ref(grpc_channel *channel, const char *reason);
-void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
-                                 const char *reason);
-#define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \
-  grpc_channel_internal_ref(channel, reason)
-#define GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, reason) \
-  grpc_channel_internal_unref(exec_ctx, channel, reason)
-#else
-void grpc_channel_internal_ref(grpc_channel *channel);
-void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel *channel);
-#define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \
-  grpc_channel_internal_ref(channel)
-#define GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, reason) \
-  grpc_channel_internal_unref(exec_ctx, channel)
-#endif
-
-#endif /* GRPC_CORE_SURFACE_CHANNEL_H */
diff --git a/src/core/surface/channel_connectivity.c b/src/core/surface/channel_connectivity.c
deleted file mode 100644
index 2dd4fce..0000000
--- a/src/core/surface/channel_connectivity.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- *
- * 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/surface/channel.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/client_uchannel.h"
-#include "src/core/iomgr/timer.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/completion_queue.h"
-
-grpc_connectivity_state grpc_channel_check_connectivity_state(
-    grpc_channel *channel, int try_to_connect) {
-  /* forward through to the underlying client channel */
-  grpc_channel_element *client_channel_elem =
-      grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_connectivity_state state;
-  GRPC_API_TRACE(
-      "grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2,
-      (channel, try_to_connect));
-  if (client_channel_elem->filter == &grpc_client_channel_filter) {
-    state = grpc_client_channel_check_connectivity_state(
-        &exec_ctx, client_channel_elem, try_to_connect);
-    grpc_exec_ctx_finish(&exec_ctx);
-    return state;
-  }
-  if (client_channel_elem->filter == &grpc_client_uchannel_filter) {
-    state = grpc_client_uchannel_check_connectivity_state(
-        &exec_ctx, client_channel_elem, try_to_connect);
-    grpc_exec_ctx_finish(&exec_ctx);
-    return state;
-  }
-  gpr_log(GPR_ERROR,
-          "grpc_channel_check_connectivity_state called on something that is "
-          "not a (u)client channel, but '%s'",
-          client_channel_elem->filter->name);
-  grpc_exec_ctx_finish(&exec_ctx);
-  return GRPC_CHANNEL_FATAL_FAILURE;
-}
-
-typedef enum {
-  WAITING,
-  CALLING_BACK,
-  CALLING_BACK_AND_FINISHED,
-  CALLED_BACK
-} callback_phase;
-
-typedef struct {
-  gpr_mu mu;
-  callback_phase phase;
-  int success;
-  grpc_closure on_complete;
-  grpc_timer alarm;
-  grpc_connectivity_state state;
-  grpc_completion_queue *cq;
-  grpc_cq_completion completion_storage;
-  grpc_channel *channel;
-  void *tag;
-} state_watcher;
-
-static void delete_state_watcher(grpc_exec_ctx *exec_ctx, state_watcher *w) {
-  grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
-      grpc_channel_get_channel_stack(w->channel));
-  if (client_channel_elem->filter == &grpc_client_channel_filter) {
-    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->channel,
-                                "watch_channel_connectivity");
-  } else if (client_channel_elem->filter == &grpc_client_uchannel_filter) {
-    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->channel,
-                                "watch_uchannel_connectivity");
-  } else {
-    abort();
-  }
-  gpr_mu_destroy(&w->mu);
-  gpr_free(w);
-}
-
-static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
-                                grpc_cq_completion *ignored) {
-  int delete = 0;
-  state_watcher *w = pw;
-  gpr_mu_lock(&w->mu);
-  switch (w->phase) {
-    case WAITING:
-    case CALLED_BACK:
-      GPR_UNREACHABLE_CODE(return );
-    case CALLING_BACK:
-      w->phase = CALLED_BACK;
-      break;
-    case CALLING_BACK_AND_FINISHED:
-      delete = 1;
-      break;
-  }
-  gpr_mu_unlock(&w->mu);
-
-  if (delete) {
-    delete_state_watcher(exec_ctx, w);
-  }
-}
-
-static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
-                        int due_to_completion) {
-  int delete = 0;
-
-  if (due_to_completion) {
-    grpc_timer_cancel(exec_ctx, &w->alarm);
-  }
-
-  gpr_mu_lock(&w->mu);
-  if (due_to_completion) {
-    w->success = 1;
-  }
-  switch (w->phase) {
-    case WAITING:
-      w->phase = CALLING_BACK;
-      grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->success, finished_completion,
-                     w, &w->completion_storage);
-      break;
-    case CALLING_BACK:
-      w->phase = CALLING_BACK_AND_FINISHED;
-      break;
-    case CALLING_BACK_AND_FINISHED:
-      GPR_UNREACHABLE_CODE(return );
-    case CALLED_BACK:
-      delete = 1;
-      break;
-  }
-  gpr_mu_unlock(&w->mu);
-
-  if (delete) {
-    delete_state_watcher(exec_ctx, w);
-  }
-}
-
-static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
-  partly_done(exec_ctx, pw, 1);
-}
-
-static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
-  partly_done(exec_ctx, pw, 0);
-}
-
-void grpc_channel_watch_connectivity_state(
-    grpc_channel *channel, grpc_connectivity_state last_observed_state,
-    gpr_timespec deadline, grpc_completion_queue *cq, void *tag) {
-  grpc_channel_element *client_channel_elem =
-      grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  state_watcher *w = gpr_malloc(sizeof(*w));
-
-  GRPC_API_TRACE(
-      "grpc_channel_watch_connectivity_state("
-      "channel=%p, last_observed_state=%d, "
-      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
-      "cq=%p, tag=%p)",
-      7, (channel, (int)last_observed_state, (long long)deadline.tv_sec,
-          (int)deadline.tv_nsec, (int)deadline.clock_type, cq, tag));
-
-  grpc_cq_begin_op(cq, tag);
-
-  gpr_mu_init(&w->mu);
-  grpc_closure_init(&w->on_complete, watch_complete, w);
-  w->phase = WAITING;
-  w->state = last_observed_state;
-  w->success = 0;
-  w->cq = cq;
-  w->tag = tag;
-  w->channel = channel;
-
-  grpc_timer_init(&exec_ctx, &w->alarm,
-                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
-                  timeout_complete, w, gpr_now(GPR_CLOCK_MONOTONIC));
-
-  if (client_channel_elem->filter == &grpc_client_channel_filter) {
-    GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity");
-    grpc_client_channel_watch_connectivity_state(&exec_ctx, client_channel_elem,
-                                                 grpc_cq_pollset(cq), &w->state,
-                                                 &w->on_complete);
-  } else if (client_channel_elem->filter == &grpc_client_uchannel_filter) {
-    GRPC_CHANNEL_INTERNAL_REF(channel, "watch_uchannel_connectivity");
-    grpc_client_uchannel_watch_connectivity_state(
-        &exec_ctx, client_channel_elem, grpc_cq_pollset(cq), &w->state,
-        &w->on_complete);
-  }
-
-  grpc_exec_ctx_finish(&exec_ctx);
-}
diff --git a/src/core/surface/channel_create.c b/src/core/surface/channel_create.c
deleted file mode 100644
index 123447c..0000000
--- a/src/core/surface/channel_create.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *
- * 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 <grpc/grpc.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-
-#include "src/core/census/grpc_filter.h"
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/channel/http_client_filter.h"
-#include "src/core/client_config/resolver_registry.h"
-#include "src/core/iomgr/tcp_client.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/channel.h"
-#include "src/core/transport/chttp2_transport.h"
-
-typedef struct {
-  grpc_connector base;
-  gpr_refcount refs;
-
-  grpc_closure *notify;
-  grpc_connect_in_args args;
-  grpc_connect_out_args *result;
-  grpc_closure initial_string_sent;
-  gpr_slice_buffer initial_string_buffer;
-
-  grpc_endpoint *tcp;
-
-  grpc_closure connected;
-} connector;
-
-static void connector_ref(grpc_connector *con) {
-  connector *c = (connector *)con;
-  gpr_ref(&c->refs);
-}
-
-static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
-  connector *c = (connector *)con;
-  if (gpr_unref(&c->refs)) {
-    /* c->initial_string_buffer does not need to be destroyed */
-    gpr_free(c);
-  }
-}
-
-static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
-                                           bool success) {
-  connector_unref(exec_ctx, arg);
-}
-
-static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  connector *c = arg;
-  grpc_closure *notify;
-  grpc_endpoint *tcp = c->tcp;
-  if (tcp != NULL) {
-    if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
-      grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
-                        c);
-      gpr_slice_buffer_init(&c->initial_string_buffer);
-      gpr_slice_buffer_add(&c->initial_string_buffer,
-                           c->args.initial_connect_string);
-      connector_ref(arg);
-      grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
-                          &c->initial_string_sent);
-    }
-    c->result->transport =
-        grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1);
-    grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
-                                        0);
-    GPR_ASSERT(c->result->transport);
-    c->result->channel_args = c->args.channel_args;
-  } else {
-    memset(c->result, 0, sizeof(*c->result));
-  }
-  notify = c->notify;
-  c->notify = NULL;
-  notify->cb(exec_ctx, notify->cb_arg, 1);
-}
-
-static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}
-
-static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
-                              const grpc_connect_in_args *args,
-                              grpc_connect_out_args *result,
-                              grpc_closure *notify) {
-  connector *c = (connector *)con;
-  GPR_ASSERT(c->notify == NULL);
-  GPR_ASSERT(notify->cb);
-  c->notify = notify;
-  c->args = *args;
-  c->result = result;
-  c->tcp = NULL;
-  grpc_closure_init(&c->connected, connected, c);
-  grpc_tcp_client_connect(exec_ctx, &c->connected, &c->tcp,
-                          args->interested_parties, args->addr, args->addr_len,
-                          args->deadline);
-}
-
-static const grpc_connector_vtable connector_vtable = {
-    connector_ref, connector_unref, connector_shutdown, connector_connect};
-
-typedef struct {
-  grpc_subchannel_factory base;
-  gpr_refcount refs;
-  grpc_channel_args *merge_args;
-  grpc_channel *master;
-} subchannel_factory;
-
-static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  gpr_ref(&f->refs);
-}
-
-static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_factory *scf) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  if (gpr_unref(&f->refs)) {
-    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
-    grpc_channel_args_destroy(f->merge_args);
-    gpr_free(f);
-  }
-}
-
-static grpc_subchannel *subchannel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
-    grpc_subchannel_args *args) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  connector *c = gpr_malloc(sizeof(*c));
-  grpc_channel_args *final_args =
-      grpc_channel_args_merge(args->args, f->merge_args);
-  grpc_subchannel *s;
-  memset(c, 0, sizeof(*c));
-  c->base.vtable = &connector_vtable;
-  gpr_ref_init(&c->refs, 1);
-  args->args = final_args;
-  s = grpc_subchannel_create(exec_ctx, &c->base, args);
-  grpc_connector_unref(exec_ctx, &c->base);
-  grpc_channel_args_destroy(final_args);
-  return s;
-}
-
-static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
-    subchannel_factory_ref, subchannel_factory_unref,
-    subchannel_factory_create_subchannel};
-
-/* Create a client channel:
-   Asynchronously: - resolve target
-                   - connect to it (trying alternatives as presented)
-                   - perform handshakes */
-grpc_channel *grpc_insecure_channel_create(const char *target,
-                                           const grpc_channel_args *args,
-                                           void *reserved) {
-  grpc_channel *channel = NULL;
-  grpc_resolver *resolver;
-  subchannel_factory *f;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GRPC_API_TRACE(
-      "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3,
-      (target, args, reserved));
-  GPR_ASSERT(!reserved);
-
-  channel =
-      grpc_channel_create(&exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
-
-  f = gpr_malloc(sizeof(*f));
-  f->base.vtable = &subchannel_factory_vtable;
-  gpr_ref_init(&f->refs, 1);
-  f->merge_args = grpc_channel_args_copy(args);
-  f->master = channel;
-  GRPC_CHANNEL_INTERNAL_REF(f->master, "subchannel_factory");
-  resolver = grpc_resolver_create(target, &f->base);
-  if (!resolver) {
-    GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, f->master, "subchannel_factory");
-    grpc_subchannel_factory_unref(&exec_ctx, &f->base);
-    grpc_exec_ctx_finish(&exec_ctx);
-    return NULL;
-  }
-
-  grpc_client_channel_set_resolver(
-      &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
-  GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
-  grpc_subchannel_factory_unref(&exec_ctx, &f->base);
-
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  return channel;
-}
diff --git a/src/core/surface/channel_init.c b/src/core/surface/channel_init.c
deleted file mode 100644
index 538be84..0000000
--- a/src/core/surface/channel_init.c
+++ /dev/null
@@ -1,148 +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 "src/core/surface/channel_init.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/useful.h>
-
-typedef struct stage_slot {
-  grpc_channel_init_stage fn;
-  void *arg;
-  int priority;
-  size_t insertion_order;
-} stage_slot;
-
-typedef struct stage_slots {
-  stage_slot *slots;
-  size_t num_slots;
-  size_t cap_slots;
-} stage_slots;
-
-static stage_slots g_slots[GRPC_NUM_CHANNEL_STACK_TYPES];
-static bool g_finalized;
-
-void grpc_channel_init_init(void) {
-  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
-    g_slots[i].slots = NULL;
-    g_slots[i].num_slots = 0;
-    g_slots[i].cap_slots = 0;
-  }
-  g_finalized = false;
-}
-
-void grpc_channel_init_register_stage(grpc_channel_stack_type type,
-                                      int priority,
-                                      grpc_channel_init_stage stage,
-                                      void *stage_arg) {
-  GPR_ASSERT(!g_finalized);
-  if (g_slots[type].cap_slots == g_slots[type].num_slots) {
-    g_slots[type].cap_slots = GPR_MAX(8, 3 * g_slots[type].cap_slots / 2);
-    g_slots[type].slots =
-        gpr_realloc(g_slots[type].slots,
-                    g_slots[type].cap_slots * sizeof(*g_slots[type].slots));
-  }
-  stage_slot *s = &g_slots[type].slots[g_slots[type].num_slots++];
-  s->insertion_order = g_slots[type].num_slots;
-  s->priority = priority;
-  s->fn = stage;
-  s->arg = stage_arg;
-}
-
-static int compare_slots(const void *a, const void *b) {
-  const stage_slot *sa = a;
-  const stage_slot *sb = b;
-
-  int c = GPR_ICMP(sa->priority, sb->priority);
-  if (c != 0) return c;
-  return GPR_ICMP(sa->insertion_order, sb->insertion_order);
-}
-
-void grpc_channel_init_finalize(void) {
-  GPR_ASSERT(!g_finalized);
-  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
-    qsort(g_slots[i].slots, g_slots[i].num_slots, sizeof(*g_slots[i].slots),
-          compare_slots);
-  }
-  g_finalized = true;
-}
-
-void grpc_channel_init_shutdown(void) {
-  for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
-    gpr_free(g_slots[i].slots);
-    g_slots[i].slots = (void *)(uintptr_t)0xdeadbeef;
-  }
-}
-
-static const char *name_for_type(grpc_channel_stack_type type) {
-  switch (type) {
-    case GRPC_CLIENT_CHANNEL:
-      return "CLIENT_CHANNEL";
-    case GRPC_CLIENT_SUBCHANNEL:
-      return "CLIENT_SUBCHANNEL";
-    case GRPC_SERVER_CHANNEL:
-      return "SERVER_CHANNEL";
-    case GRPC_CLIENT_UCHANNEL:
-      return "CLIENT_UCHANNEL";
-    case GRPC_CLIENT_LAME_CHANNEL:
-      return "CLIENT_LAME_CHANNEL";
-    case GRPC_CLIENT_DIRECT_CHANNEL:
-      return "CLIENT_DIRECT_CHANNEL";
-    case GRPC_NUM_CHANNEL_STACK_TYPES:
-      break;
-  }
-  GPR_UNREACHABLE_CODE(return "UNKNOWN");
-}
-
-void *grpc_channel_init_create_stack(
-    grpc_exec_ctx *exec_ctx, grpc_channel_stack_type type, size_t prefix_bytes,
-    const grpc_channel_args *args, int initial_refs, grpc_iomgr_cb_func destroy,
-    void *destroy_arg, grpc_transport *transport) {
-  GPR_ASSERT(g_finalized);
-
-  grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create();
-  grpc_channel_stack_builder_set_name(builder, name_for_type(type));
-  grpc_channel_stack_builder_set_channel_arguments(builder, args);
-  grpc_channel_stack_builder_set_transport(builder, transport);
-
-  for (size_t i = 0; i < g_slots[type].num_slots; i++) {
-    const stage_slot *slot = &g_slots[type].slots[i];
-    if (!slot->fn(builder, slot->arg)) {
-      grpc_channel_stack_builder_destroy(builder);
-      return NULL;
-    }
-  }
-
-  return grpc_channel_stack_builder_finish(exec_ctx, builder, prefix_bytes,
-                                           initial_refs, destroy, destroy_arg);
-}
diff --git a/src/core/surface/channel_init.h b/src/core/surface/channel_init.h
deleted file mode 100644
index 06faef6..0000000
--- a/src/core/surface/channel_init.h
+++ /dev/null
@@ -1,86 +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_CORE_SURFACE_CHANNEL_INIT_H
-#define GRPC_CORE_SURFACE_CHANNEL_INIT_H
-
-#include "src/core/channel/channel_stack_builder.h"
-#include "src/core/surface/channel_stack_type.h"
-#include "src/core/transport/transport.h"
-
-/// This module provides a way for plugins (and the grpc core library itself)
-/// to register mutators for channel stacks.
-/// It also provides a universal entry path to run those mutators to build
-/// a channel stack for various subsystems.
-
-/// One stage of mutation: call functions against \a builder to influence the
-/// finally constructed channel stack
-typedef bool (*grpc_channel_init_stage)(grpc_channel_stack_builder *builder,
-                                        void *arg);
-
-/// Global initialization of the system
-void grpc_channel_init_init(void);
-
-/// Register one stage of mutators.
-/// Stages are run in priority order (lowest to highest), and then in
-/// registration order (in the case of a tie).
-/// Stages are registered against one of the pre-determined channel stack
-/// types.
-void grpc_channel_init_register_stage(grpc_channel_stack_type type,
-                                      int priority,
-                                      grpc_channel_init_stage stage_fn,
-                                      void *stage_arg);
-
-/// Finalize registration. No more calls to grpc_channel_init_register_stage are
-/// allowed.
-void grpc_channel_init_finalize(void);
-/// Shutdown the channel init system
-void grpc_channel_init_shutdown(void);
-
-/// Construct a channel stack of some sort: see channel_stack.h for details
-/// \a type is the type of channel stack to create
-/// \a prefix_bytes is the number of bytes before the channel stack to allocate
-/// \a args are configuration arguments for the channel stack
-/// \a initial_refs is the initial refcount to give the channel stack
-/// \a destroy and \a destroy_arg specify how to destroy the channel stack
-///    if destroy_arg is NULL, the returned value from this function will be
-///    substituted
-/// \a optional_transport is either NULL or a constructed transport object
-/// Returns a pointer to the base of the memory allocated (the actual channel
-/// stack object will be prefix_bytes past that pointer)
-void *grpc_channel_init_create_stack(
-    grpc_exec_ctx *exec_ctx, grpc_channel_stack_type type, size_t prefix_bytes,
-    const grpc_channel_args *args, int initial_refs, grpc_iomgr_cb_func destroy,
-    void *destroy_arg, grpc_transport *optional_transport);
-
-#endif /* GRPC_CORE_SURFACE_CHANNEL_INIT_H */
diff --git a/src/core/surface/channel_ping.c b/src/core/surface/channel_ping.c
deleted file mode 100644
index 983f1c8..0000000
--- a/src/core/surface/channel_ping.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *
- * 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/surface/channel.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/completion_queue.h"
-
-typedef struct {
-  grpc_closure closure;
-  void *tag;
-  grpc_completion_queue *cq;
-  grpc_cq_completion completion_storage;
-} ping_result;
-
-static void ping_destroy(grpc_exec_ctx *exec_ctx, void *arg,
-                         grpc_cq_completion *storage) {
-  gpr_free(arg);
-}
-
-static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  ping_result *pr = arg;
-  grpc_cq_end_op(exec_ctx, pr->cq, pr->tag, success, ping_destroy, pr,
-                 &pr->completion_storage);
-}
-
-void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq,
-                       void *tag, void *reserved) {
-  grpc_transport_op op;
-  ping_result *pr = gpr_malloc(sizeof(*pr));
-  grpc_channel_element *top_elem =
-      grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GPR_ASSERT(reserved == NULL);
-  memset(&op, 0, sizeof(op));
-  pr->tag = tag;
-  pr->cq = cq;
-  grpc_closure_init(&pr->closure, ping_done, pr);
-  op.send_ping = &pr->closure;
-  op.bind_pollset = grpc_cq_pollset(cq);
-  grpc_cq_begin_op(cq, tag);
-  top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
diff --git a/src/core/surface/channel_stack_type.c b/src/core/surface/channel_stack_type.c
deleted file mode 100644
index 6fd33d4..0000000
--- a/src/core/surface/channel_stack_type.c
+++ /dev/null
@@ -1,56 +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 <grpc/support/port_platform.h>
-#include "src/core/surface/channel_stack_type.h"
-#include <grpc/support/log.h>
-
-bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type) {
-  switch (type) {
-    case GRPC_CLIENT_CHANNEL:
-      return true;
-    case GRPC_CLIENT_UCHANNEL:
-      return true;
-    case GRPC_CLIENT_SUBCHANNEL:
-      return true;
-    case GRPC_CLIENT_LAME_CHANNEL:
-      return true;
-    case GRPC_CLIENT_DIRECT_CHANNEL:
-      return true;
-    case GRPC_SERVER_CHANNEL:
-      return false;
-    case GRPC_NUM_CHANNEL_STACK_TYPES:
-      break;
-  }
-  GPR_UNREACHABLE_CODE(return true;);
-}
diff --git a/src/core/surface/channel_stack_type.h b/src/core/surface/channel_stack_type.h
deleted file mode 100644
index 846391a..0000000
--- a/src/core/surface/channel_stack_type.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_CHANNEL_STACK_TYPE_H
-#define GRPC_CORE_SURFACE_CHANNEL_STACK_TYPE_H
-
-#include <stdbool.h>
-
-typedef enum {
-  // normal top-half client channel with load-balancing, connection management
-  GRPC_CLIENT_CHANNEL,
-  // abbreviated top-half client channel bound to one subchannel - for internal
-  // load balancing implementation
-  GRPC_CLIENT_UCHANNEL,
-  // bottom-half of a client channel: everything that happens post-load
-  // balancing (bound to a specific transport)
-  GRPC_CLIENT_SUBCHANNEL,
-  // a permanently broken client channel
-  GRPC_CLIENT_LAME_CHANNEL,
-  // a directly connected client channel (without load-balancing, directly talks
-  // to a transport)
-  GRPC_CLIENT_DIRECT_CHANNEL,
-  // server side channel
-  GRPC_SERVER_CHANNEL,
-  // must be last
-  GRPC_NUM_CHANNEL_STACK_TYPES
-} grpc_channel_stack_type;
-
-bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type);
-
-#endif /* GRPC_CORE_SURFACE_CHANNEL_STACK_TYPE_H */
diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c
deleted file mode 100644
index b22818e..0000000
--- a/src/core/surface/completion_queue.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- *
- * 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/surface/completion_queue.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
-
-#include "src/core/iomgr/pollset.h"
-#include "src/core/iomgr/timer.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/call.h"
-#include "src/core/surface/event_string.h"
-#include "src/core/surface/surface_trace.h"
-
-typedef struct {
-  grpc_pollset_worker **worker;
-  void *tag;
-} plucker;
-
-/* Completion queue structure */
-struct grpc_completion_queue {
-  /** owned by pollset */
-  gpr_mu *mu;
-  /** completed events */
-  grpc_cq_completion completed_head;
-  grpc_cq_completion *completed_tail;
-  /** Number of pending events (+1 if we're not shutdown) */
-  gpr_refcount pending_events;
-  /** Once owning_refs drops to zero, we will destroy the cq */
-  gpr_refcount owning_refs;
-  /** 0 initially, 1 once we've begun shutting down */
-  int shutdown;
-  int shutdown_called;
-  int is_server_cq;
-  int num_pluckers;
-  plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS];
-  grpc_closure pollset_shutdown_done;
-
-#ifndef NDEBUG
-  void **outstanding_tags;
-  size_t outstanding_tag_count;
-  size_t outstanding_tag_capacity;
-#endif
-
-  grpc_completion_queue *next_free;
-};
-
-#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
-
-static gpr_mu g_freelist_mu;
-static grpc_completion_queue *g_freelist;
-
-static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
-                                     bool success);
-
-void grpc_cq_global_init(void) { gpr_mu_init(&g_freelist_mu); }
-
-void grpc_cq_global_shutdown(void) {
-  gpr_mu_destroy(&g_freelist_mu);
-  while (g_freelist) {
-    grpc_completion_queue *next = g_freelist->next_free;
-    grpc_pollset_destroy(POLLSET_FROM_CQ(g_freelist));
-#ifndef NDEBUG
-    gpr_free(g_freelist->outstanding_tags);
-#endif
-    gpr_free(g_freelist);
-    g_freelist = next;
-  }
-}
-
-struct grpc_cq_alarm {
-  grpc_timer alarm;
-  grpc_cq_completion completion;
-  /** completion queue where events about this alarm will be posted */
-  grpc_completion_queue *cq;
-  /** user supplied tag */
-  void *tag;
-};
-
-grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
-  grpc_completion_queue *cc;
-  GPR_ASSERT(!reserved);
-
-  GPR_TIMER_BEGIN("grpc_completion_queue_create", 0);
-
-  GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved));
-
-  gpr_mu_lock(&g_freelist_mu);
-  if (g_freelist == NULL) {
-    gpr_mu_unlock(&g_freelist_mu);
-
-    cc = gpr_malloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
-    grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
-#ifndef NDEBUG
-    cc->outstanding_tags = NULL;
-    cc->outstanding_tag_capacity = 0;
-#endif
-  } else {
-    cc = g_freelist;
-    g_freelist = g_freelist->next_free;
-    gpr_mu_unlock(&g_freelist_mu);
-    /* pollset already initialized */
-  }
-
-  /* Initial ref is dropped by grpc_completion_queue_shutdown */
-  gpr_ref_init(&cc->pending_events, 1);
-  /* One for destroy(), one for pollset_shutdown */
-  gpr_ref_init(&cc->owning_refs, 2);
-  cc->completed_tail = &cc->completed_head;
-  cc->completed_head.next = (uintptr_t)cc->completed_tail;
-  cc->shutdown = 0;
-  cc->shutdown_called = 0;
-  cc->is_server_cq = 0;
-  cc->num_pluckers = 0;
-#ifndef NDEBUG
-  cc->outstanding_tag_count = 0;
-#endif
-  grpc_closure_init(&cc->pollset_shutdown_done, on_pollset_shutdown_done, cc);
-
-  GPR_TIMER_END("grpc_completion_queue_create", 0);
-
-  return cc;
-}
-
-#ifdef GRPC_CQ_REF_COUNT_DEBUG
-void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
-                          const char *file, int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p   ref %d -> %d %s", cc,
-          (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1, reason);
-#else
-void grpc_cq_internal_ref(grpc_completion_queue *cc) {
-#endif
-  gpr_ref(&cc->owning_refs);
-}
-
-static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *arg,
-                                     bool success) {
-  grpc_completion_queue *cc = arg;
-  GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy");
-}
-
-#ifdef GRPC_CQ_REF_COUNT_DEBUG
-void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
-                            const char *file, int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc,
-          (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason);
-#else
-void grpc_cq_internal_unref(grpc_completion_queue *cc) {
-#endif
-  if (gpr_unref(&cc->owning_refs)) {
-    GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head);
-    grpc_pollset_reset(POLLSET_FROM_CQ(cc));
-    gpr_mu_lock(&g_freelist_mu);
-    cc->next_free = g_freelist;
-    g_freelist = cc;
-    gpr_mu_unlock(&g_freelist_mu);
-  }
-}
-
-void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) {
-#ifndef NDEBUG
-  gpr_mu_lock(cc->mu);
-  GPR_ASSERT(!cc->shutdown_called);
-  if (cc->outstanding_tag_count == cc->outstanding_tag_capacity) {
-    cc->outstanding_tag_capacity = GPR_MAX(4, 2 * cc->outstanding_tag_capacity);
-    cc->outstanding_tags =
-        gpr_realloc(cc->outstanding_tags, sizeof(*cc->outstanding_tags) *
-                                              cc->outstanding_tag_capacity);
-  }
-  cc->outstanding_tags[cc->outstanding_tag_count++] = tag;
-  gpr_mu_unlock(cc->mu);
-#endif
-  gpr_ref(&cc->pending_events);
-}
-
-/* Signal the end of an operation - if this is the last waiting-to-be-queued
-   event, then enter shutdown mode */
-/* Queue a GRPC_OP_COMPLETED operation */
-void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
-                    void *tag, int success,
-                    void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
-                                 grpc_cq_completion *storage),
-                    void *done_arg, grpc_cq_completion *storage) {
-  int shutdown;
-  int i;
-  grpc_pollset_worker *pluck_worker;
-#ifndef NDEBUG
-  int found = 0;
-#endif
-
-  GPR_TIMER_BEGIN("grpc_cq_end_op", 0);
-
-  storage->tag = tag;
-  storage->done = done;
-  storage->done_arg = done_arg;
-  storage->next =
-      ((uintptr_t)&cc->completed_head) | ((uintptr_t)(success != 0));
-
-  gpr_mu_lock(cc->mu);
-#ifndef NDEBUG
-  for (i = 0; i < (int)cc->outstanding_tag_count; i++) {
-    if (cc->outstanding_tags[i] == tag) {
-      cc->outstanding_tag_count--;
-      GPR_SWAP(void *, cc->outstanding_tags[i],
-               cc->outstanding_tags[cc->outstanding_tag_count]);
-      found = 1;
-      break;
-    }
-  }
-  GPR_ASSERT(found);
-#endif
-  shutdown = gpr_unref(&cc->pending_events);
-  if (!shutdown) {
-    cc->completed_tail->next =
-        ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
-    cc->completed_tail = storage;
-    pluck_worker = NULL;
-    for (i = 0; i < cc->num_pluckers; i++) {
-      if (cc->pluckers[i].tag == tag) {
-        pluck_worker = *cc->pluckers[i].worker;
-        break;
-      }
-    }
-    grpc_pollset_kick(POLLSET_FROM_CQ(cc), pluck_worker);
-    gpr_mu_unlock(cc->mu);
-  } else {
-    cc->completed_tail->next =
-        ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
-    cc->completed_tail = storage;
-    GPR_ASSERT(!cc->shutdown);
-    GPR_ASSERT(cc->shutdown_called);
-    cc->shutdown = 1;
-    grpc_pollset_shutdown(exec_ctx, POLLSET_FROM_CQ(cc),
-                          &cc->pollset_shutdown_done);
-    gpr_mu_unlock(cc->mu);
-  }
-
-  GPR_TIMER_END("grpc_cq_end_op", 0);
-}
-
-grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
-                                      gpr_timespec deadline, void *reserved) {
-  grpc_event ret;
-  grpc_pollset_worker *worker = NULL;
-  int first_loop = 1;
-  gpr_timespec now;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GPR_TIMER_BEGIN("grpc_completion_queue_next", 0);
-
-  GRPC_API_TRACE(
-      "grpc_completion_queue_next("
-      "cc=%p, "
-      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
-      "reserved=%p)",
-      5, (cc, (long long)deadline.tv_sec, (int)deadline.tv_nsec,
-          (int)deadline.clock_type, reserved));
-  GPR_ASSERT(!reserved);
-
-  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
-
-  GRPC_CQ_INTERNAL_REF(cc, "next");
-  gpr_mu_lock(cc->mu);
-  for (;;) {
-    if (cc->completed_tail != &cc->completed_head) {
-      grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next;
-      cc->completed_head.next = c->next & ~(uintptr_t)1;
-      if (c == cc->completed_tail) {
-        cc->completed_tail = &cc->completed_head;
-      }
-      gpr_mu_unlock(cc->mu);
-      ret.type = GRPC_OP_COMPLETE;
-      ret.success = c->next & 1u;
-      ret.tag = c->tag;
-      c->done(&exec_ctx, c->done_arg, c);
-      break;
-    }
-    if (cc->shutdown) {
-      gpr_mu_unlock(cc->mu);
-      memset(&ret, 0, sizeof(ret));
-      ret.type = GRPC_QUEUE_SHUTDOWN;
-      break;
-    }
-    now = gpr_now(GPR_CLOCK_MONOTONIC);
-    if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
-      gpr_mu_unlock(cc->mu);
-      memset(&ret, 0, sizeof(ret));
-      ret.type = GRPC_QUEUE_TIMEOUT;
-      break;
-    }
-    first_loop = 0;
-    /* Check alarms - these are a global resource so we just ping
-       each time through on every pollset.
-       May update deadline to ensure timely wakeups.
-       TODO(ctiller): can this work be localized? */
-    gpr_timespec iteration_deadline = deadline;
-    if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
-      GPR_TIMER_MARK("alarm_triggered", 0);
-      gpr_mu_unlock(cc->mu);
-      grpc_exec_ctx_flush(&exec_ctx);
-      gpr_mu_lock(cc->mu);
-      continue;
-    } else {
-      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
-                        iteration_deadline);
-    }
-  }
-  GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
-  GRPC_CQ_INTERNAL_UNREF(cc, "next");
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  GPR_TIMER_END("grpc_completion_queue_next", 0);
-
-  return ret;
-}
-
-static int add_plucker(grpc_completion_queue *cc, void *tag,
-                       grpc_pollset_worker **worker) {
-  if (cc->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) {
-    return 0;
-  }
-  cc->pluckers[cc->num_pluckers].tag = tag;
-  cc->pluckers[cc->num_pluckers].worker = worker;
-  cc->num_pluckers++;
-  return 1;
-}
-
-static void del_plucker(grpc_completion_queue *cc, void *tag,
-                        grpc_pollset_worker **worker) {
-  int i;
-  for (i = 0; i < cc->num_pluckers; i++) {
-    if (cc->pluckers[i].tag == tag && cc->pluckers[i].worker == worker) {
-      cc->num_pluckers--;
-      GPR_SWAP(plucker, cc->pluckers[i], cc->pluckers[cc->num_pluckers]);
-      return;
-    }
-  }
-  GPR_UNREACHABLE_CODE(return );
-}
-
-grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
-                                       gpr_timespec deadline, void *reserved) {
-  grpc_event ret;
-  grpc_cq_completion *c;
-  grpc_cq_completion *prev;
-  grpc_pollset_worker *worker = NULL;
-  gpr_timespec now;
-  int first_loop = 1;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GPR_TIMER_BEGIN("grpc_completion_queue_pluck", 0);
-
-  GRPC_API_TRACE(
-      "grpc_completion_queue_pluck("
-      "cc=%p, tag=%p, "
-      "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
-      "reserved=%p)",
-      6, (cc, tag, (long long)deadline.tv_sec, (int)deadline.tv_nsec,
-          (int)deadline.clock_type, reserved));
-  GPR_ASSERT(!reserved);
-
-  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
-
-  GRPC_CQ_INTERNAL_REF(cc, "pluck");
-  gpr_mu_lock(cc->mu);
-  for (;;) {
-    prev = &cc->completed_head;
-    while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) !=
-           &cc->completed_head) {
-      if (c->tag == tag) {
-        prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1);
-        if (c == cc->completed_tail) {
-          cc->completed_tail = prev;
-        }
-        gpr_mu_unlock(cc->mu);
-        ret.type = GRPC_OP_COMPLETE;
-        ret.success = c->next & 1u;
-        ret.tag = c->tag;
-        c->done(&exec_ctx, c->done_arg, c);
-        goto done;
-      }
-      prev = c;
-    }
-    if (cc->shutdown) {
-      gpr_mu_unlock(cc->mu);
-      memset(&ret, 0, sizeof(ret));
-      ret.type = GRPC_QUEUE_SHUTDOWN;
-      break;
-    }
-    if (!add_plucker(cc, tag, &worker)) {
-      gpr_log(GPR_DEBUG,
-              "Too many outstanding grpc_completion_queue_pluck calls: maximum "
-              "is %d",
-              GRPC_MAX_COMPLETION_QUEUE_PLUCKERS);
-      gpr_mu_unlock(cc->mu);
-      memset(&ret, 0, sizeof(ret));
-      /* TODO(ctiller): should we use a different result here */
-      ret.type = GRPC_QUEUE_TIMEOUT;
-      break;
-    }
-    now = gpr_now(GPR_CLOCK_MONOTONIC);
-    if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
-      del_plucker(cc, tag, &worker);
-      gpr_mu_unlock(cc->mu);
-      memset(&ret, 0, sizeof(ret));
-      ret.type = GRPC_QUEUE_TIMEOUT;
-      break;
-    }
-    first_loop = 0;
-    /* Check alarms - these are a global resource so we just ping
-       each time through on every pollset.
-       May update deadline to ensure timely wakeups.
-       TODO(ctiller): can this work be localized? */
-    gpr_timespec iteration_deadline = deadline;
-    if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
-      GPR_TIMER_MARK("alarm_triggered", 0);
-      gpr_mu_unlock(cc->mu);
-      grpc_exec_ctx_flush(&exec_ctx);
-      gpr_mu_lock(cc->mu);
-    } else {
-      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
-                        iteration_deadline);
-    }
-    del_plucker(cc, tag, &worker);
-  }
-done:
-  GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
-  GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  GPR_TIMER_END("grpc_completion_queue_pluck", 0);
-
-  return ret;
-}
-
-/* Shutdown simply drops a ref that we reserved at creation time; if we drop
-   to zero here, then enter shutdown mode and wake up any waiters */
-void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GPR_TIMER_BEGIN("grpc_completion_queue_shutdown", 0);
-  GRPC_API_TRACE("grpc_completion_queue_shutdown(cc=%p)", 1, (cc));
-  gpr_mu_lock(cc->mu);
-  if (cc->shutdown_called) {
-    gpr_mu_unlock(cc->mu);
-    GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
-    return;
-  }
-  cc->shutdown_called = 1;
-  if (gpr_unref(&cc->pending_events)) {
-    GPR_ASSERT(!cc->shutdown);
-    cc->shutdown = 1;
-    grpc_pollset_shutdown(&exec_ctx, POLLSET_FROM_CQ(cc),
-                          &cc->pollset_shutdown_done);
-  }
-  gpr_mu_unlock(cc->mu);
-  grpc_exec_ctx_finish(&exec_ctx);
-  GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
-}
-
-void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
-  GRPC_API_TRACE("grpc_completion_queue_destroy(cc=%p)", 1, (cc));
-  GPR_TIMER_BEGIN("grpc_completion_queue_destroy", 0);
-  grpc_completion_queue_shutdown(cc);
-  GRPC_CQ_INTERNAL_UNREF(cc, "destroy");
-  GPR_TIMER_END("grpc_completion_queue_destroy", 0);
-}
-
-grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
-  return POLLSET_FROM_CQ(cc);
-}
-
-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/surface/completion_queue.h b/src/core/surface/completion_queue.h
deleted file mode 100644
index 07f6d0c..0000000
--- a/src/core/surface/completion_queue.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_COMPLETION_QUEUE_H
-#define GRPC_CORE_SURFACE_COMPLETION_QUEUE_H
-
-/* Internal API for completion queues */
-
-#include "src/core/iomgr/pollset.h"
-#include <grpc/grpc.h>
-
-typedef struct grpc_cq_completion {
-  /** user supplied tag */
-  void *tag;
-  /** done callback - called when this queue element is no longer
-      needed by the completion queue */
-  void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
-               struct grpc_cq_completion *c);
-  void *done_arg;
-  /** next pointer; low bit is used to indicate success or not */
-  uintptr_t next;
-} grpc_cq_completion;
-
-#ifdef GRPC_CQ_REF_COUNT_DEBUG
-void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
-                          const char *file, int line);
-void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
-                            const char *file, int line);
-#define GRPC_CQ_INTERNAL_REF(cc, reason) \
-  grpc_cq_internal_ref(cc, reason, __FILE__, __LINE__)
-#define GRPC_CQ_INTERNAL_UNREF(cc, reason) \
-  grpc_cq_internal_unref(cc, reason, __FILE__, __LINE__)
-#else
-void grpc_cq_internal_ref(grpc_completion_queue *cc);
-void grpc_cq_internal_unref(grpc_completion_queue *cc);
-#define GRPC_CQ_INTERNAL_REF(cc, reason) grpc_cq_internal_ref(cc)
-#define GRPC_CQ_INTERNAL_UNREF(cc, reason) grpc_cq_internal_unref(cc)
-#endif
-
-/* Flag that an operation is beginning: the completion channel will not finish
-   shutdown until a corrensponding grpc_cq_end_* call is made.
-   \a tag is currently used only in debug builds. */
-void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag);
-
-/* Queue a GRPC_OP_COMPLETED operation; tag must correspond to the tag passed to
-   grpc_cq_begin_op */
-void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
-                    void *tag, int success,
-                    void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
-                                 grpc_cq_completion *storage),
-                    void *done_arg, grpc_cq_completion *storage);
-
-grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);
-
-void grpc_cq_mark_server_cq(grpc_completion_queue *cc);
-int grpc_cq_is_server_cq(grpc_completion_queue *cc);
-
-void grpc_cq_global_init(void);
-void grpc_cq_global_shutdown(void);
-
-#endif /* GRPC_CORE_SURFACE_COMPLETION_QUEUE_H */
diff --git a/src/core/surface/event_string.c b/src/core/surface/event_string.c
deleted file mode 100644
index 33cd4a4..0000000
--- a/src/core/surface/event_string.c
+++ /dev/null
@@ -1,81 +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/surface/event_string.h"
-
-#include <stdio.h>
-
-#include "src/core/support/string.h"
-#include <grpc/byte_buffer.h>
-#include <grpc/support/string_util.h>
-
-static void addhdr(gpr_strvec *buf, grpc_event *ev) {
-  char *tmp;
-  gpr_asprintf(&tmp, "tag:%p", ev->tag);
-  gpr_strvec_add(buf, tmp);
-}
-
-static const char *errstr(int success) { return success ? "OK" : "ERROR"; }
-
-static void adderr(gpr_strvec *buf, int success) {
-  char *tmp;
-  gpr_asprintf(&tmp, " %s", errstr(success));
-  gpr_strvec_add(buf, tmp);
-}
-
-char *grpc_event_string(grpc_event *ev) {
-  char *out;
-  gpr_strvec buf;
-
-  if (ev == NULL) return gpr_strdup("null");
-
-  gpr_strvec_init(&buf);
-
-  switch (ev->type) {
-    case GRPC_QUEUE_TIMEOUT:
-      gpr_strvec_add(&buf, gpr_strdup("QUEUE_TIMEOUT"));
-      break;
-    case GRPC_QUEUE_SHUTDOWN:
-      gpr_strvec_add(&buf, gpr_strdup("QUEUE_SHUTDOWN"));
-      break;
-    case GRPC_OP_COMPLETE:
-      gpr_strvec_add(&buf, gpr_strdup("OP_COMPLETE: "));
-      addhdr(&buf, ev);
-      adderr(&buf, ev->success);
-      break;
-  }
-
-  out = gpr_strvec_flatten(&buf, NULL);
-  gpr_strvec_destroy(&buf);
-  return out;
-}
diff --git a/src/core/surface/event_string.h b/src/core/surface/event_string.h
deleted file mode 100644
index d0598ce..0000000
--- a/src/core/surface/event_string.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_EVENT_STRING_H
-#define GRPC_CORE_SURFACE_EVENT_STRING_H
-
-#include <grpc/grpc.h>
-
-/* Returns a string describing an event. Must be later freed with gpr_free() */
-char *grpc_event_string(grpc_event *ev);
-
-#endif /* GRPC_CORE_SURFACE_EVENT_STRING_H */
diff --git a/src/core/surface/init.c b/src/core/surface/init.c
deleted file mode 100644
index b507709..0000000
--- a/src/core/surface/init.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- *
- * 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 <grpc/support/port_platform.h>
-
-#include <limits.h>
-#include <memory.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/time.h>
-/* TODO(ctiller): find another way? - better not to include census here */
-#include "src/core/census/grpc_plugin.h"
-#include "src/core/channel/channel_stack.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/client_uchannel.h"
-#include "src/core/channel/http_client_filter.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/client_config/lb_policy_registry.h"
-#include "src/core/client_config/lb_policies/pick_first.h"
-#include "src/core/client_config/lb_policies/round_robin.h"
-#include "src/core/client_config/resolver_registry.h"
-#include "src/core/client_config/resolvers/dns_resolver.h"
-#include "src/core/client_config/resolvers/sockaddr_resolver.h"
-#include "src/core/client_config/subchannel.h"
-#include "src/core/client_config/subchannel_index.h"
-#include "src/core/debug/trace.h"
-#include "src/core/iomgr/executor.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/call.h"
-#include "src/core/surface/channel_init.h"
-#include "src/core/surface/completion_queue.h"
-#include "src/core/surface/init.h"
-#include "src/core/surface/lame_client.h"
-#include "src/core/surface/server.h"
-#include "src/core/surface/surface_trace.h"
-#include "src/core/transport/chttp2_transport.h"
-#include "src/core/transport/connectivity_state.h"
-#include "src/core/transport/transport_impl.h"
-
-#ifndef GRPC_DEFAULT_NAME_PREFIX
-#define GRPC_DEFAULT_NAME_PREFIX "dns:///"
-#endif
-
-#define MAX_PLUGINS 128
-
-static gpr_once g_basic_init = GPR_ONCE_INIT;
-static gpr_mu g_init_mu;
-static int g_initializations;
-
-static void do_basic_init(void) {
-  gpr_mu_init(&g_init_mu);
-  /* TODO(ctiller): ideally remove this strict linkage */
-  grpc_register_plugin(census_grpc_plugin_init, census_grpc_plugin_destroy);
-  g_initializations = 0;
-}
-
-static bool append_filter(grpc_channel_stack_builder *builder, void *arg) {
-  return grpc_channel_stack_builder_append_filter(builder, arg, NULL, NULL);
-}
-
-static bool prepend_filter(grpc_channel_stack_builder *builder, void *arg) {
-  return grpc_channel_stack_builder_prepend_filter(builder, arg, NULL, NULL);
-}
-
-static bool maybe_add_http_filter(grpc_channel_stack_builder *builder,
-                                  void *arg) {
-  grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
-  if (t && strstr(t->vtable->name, "http")) {
-    return grpc_channel_stack_builder_prepend_filter(builder, arg, NULL, NULL);
-  }
-  return true;
-}
-
-static void register_builtin_channel_init() {
-  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, prepend_filter,
-                                   (void *)&grpc_compress_filter);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
-                                   prepend_filter,
-                                   (void *)&grpc_compress_filter);
-  grpc_channel_init_register_stage(GRPC_CLIENT_UCHANNEL, INT_MAX,
-                                   prepend_filter,
-                                   (void *)&grpc_compress_filter);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter,
-                                   (void *)&grpc_compress_filter);
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
-                                   maybe_add_http_filter,
-                                   (void *)&grpc_http_client_filter);
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
-                                   grpc_add_connected_filter, NULL);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
-                                   maybe_add_http_filter,
-                                   (void *)&grpc_http_client_filter);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
-                                   grpc_add_connected_filter, NULL);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
-                                   maybe_add_http_filter,
-                                   (void *)&grpc_http_server_filter);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
-                                   grpc_add_connected_filter, NULL);
-  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, append_filter,
-                                   (void *)&grpc_client_channel_filter);
-  grpc_channel_init_register_stage(GRPC_CLIENT_UCHANNEL, INT_MAX, append_filter,
-                                   (void *)&grpc_client_uchannel_filter);
-  grpc_channel_init_register_stage(GRPC_CLIENT_LAME_CHANNEL, INT_MAX,
-                                   append_filter, (void *)&grpc_lame_filter);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter,
-                                   (void *)&grpc_server_top_filter);
-}
-
-typedef struct grpc_plugin {
-  void (*init)();
-  void (*destroy)();
-} grpc_plugin;
-
-static grpc_plugin g_all_of_the_plugins[MAX_PLUGINS];
-static int g_number_of_plugins = 0;
-
-void grpc_register_plugin(void (*init)(void), void (*destroy)(void)) {
-  GRPC_API_TRACE("grpc_register_plugin(init=%p, destroy=%p)", 2,
-                 ((void *)(intptr_t)init, (void *)(intptr_t)destroy));
-  GPR_ASSERT(g_number_of_plugins != MAX_PLUGINS);
-  g_all_of_the_plugins[g_number_of_plugins].init = init;
-  g_all_of_the_plugins[g_number_of_plugins].destroy = destroy;
-  g_number_of_plugins++;
-}
-
-void grpc_init(void) {
-  int i;
-  gpr_once_init(&g_basic_init, do_basic_init);
-
-  gpr_mu_lock(&g_init_mu);
-  if (++g_initializations == 1) {
-    gpr_time_init();
-    grpc_mdctx_global_init();
-    grpc_channel_init_init();
-    grpc_lb_policy_registry_init(grpc_pick_first_lb_factory_create());
-    grpc_register_lb_policy(grpc_pick_first_lb_factory_create());
-    grpc_register_lb_policy(grpc_round_robin_lb_factory_create());
-    grpc_resolver_registry_init(GRPC_DEFAULT_NAME_PREFIX);
-    grpc_register_resolver_type(grpc_dns_resolver_factory_create());
-    grpc_register_resolver_type(grpc_ipv4_resolver_factory_create());
-    grpc_register_resolver_type(grpc_ipv6_resolver_factory_create());
-#ifdef GPR_POSIX_SOCKET
-    grpc_register_resolver_type(grpc_unix_resolver_factory_create());
-#endif
-    grpc_register_tracer("api", &grpc_api_trace);
-    grpc_register_tracer("channel", &grpc_trace_channel);
-    grpc_register_tracer("http", &grpc_http_trace);
-    grpc_register_tracer("flowctl", &grpc_flowctl_trace);
-    grpc_register_tracer("connectivity_state", &grpc_connectivity_state_trace);
-    grpc_register_tracer("channel_stack_builder",
-                         &grpc_trace_channel_stack_builder);
-    grpc_security_pre_init();
-    grpc_iomgr_init();
-    grpc_executor_init();
-    grpc_tracer_init("GRPC_TRACE");
-    gpr_timers_global_init();
-    grpc_cq_global_init();
-    grpc_subchannel_index_init();
-    for (i = 0; i < g_number_of_plugins; i++) {
-      if (g_all_of_the_plugins[i].init != NULL) {
-        g_all_of_the_plugins[i].init();
-      }
-    }
-    /* register channel finalization AFTER all plugins, to ensure that it's run
-     * at the appropriate time */
-    grpc_register_security_filters();
-    register_builtin_channel_init();
-    /* no more changes to channel init pipelines */
-    grpc_channel_init_finalize();
-  }
-  gpr_mu_unlock(&g_init_mu);
-  GRPC_API_TRACE("grpc_init(void)", 0, ());
-}
-
-void grpc_shutdown(void) {
-  int i;
-  GRPC_API_TRACE("grpc_shutdown(void)", 0, ());
-  gpr_mu_lock(&g_init_mu);
-  if (--g_initializations == 0) {
-    grpc_executor_shutdown();
-    grpc_cq_global_shutdown();
-    grpc_iomgr_shutdown();
-    grpc_subchannel_index_shutdown();
-    gpr_timers_global_destroy();
-    grpc_tracer_shutdown();
-    grpc_resolver_registry_shutdown();
-    grpc_lb_policy_registry_shutdown();
-    for (i = 0; i < g_number_of_plugins; i++) {
-      if (g_all_of_the_plugins[i].destroy != NULL) {
-        g_all_of_the_plugins[i].destroy();
-      }
-    }
-    grpc_channel_init_shutdown();
-    grpc_mdctx_global_shutdown();
-  }
-  gpr_mu_unlock(&g_init_mu);
-}
-
-int grpc_is_initialized(void) {
-  int r;
-  gpr_once_init(&g_basic_init, do_basic_init);
-  gpr_mu_lock(&g_init_mu);
-  r = g_initializations > 0;
-  gpr_mu_unlock(&g_init_mu);
-  return r;
-}
diff --git a/src/core/surface/init.h b/src/core/surface/init.h
deleted file mode 100644
index 5e358c7..0000000
--- a/src/core/surface/init.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_INIT_H
-#define GRPC_CORE_SURFACE_INIT_H
-
-void grpc_register_security_filters(void);
-void grpc_security_pre_init(void);
-int grpc_is_initialized(void);
-
-#endif /* GRPC_CORE_SURFACE_INIT_H */
diff --git a/src/core/surface/init_secure.c b/src/core/surface/init_secure.c
deleted file mode 100644
index 311dda9..0000000
--- a/src/core/surface/init_secure.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *
- * 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/surface/init.h"
-
-#include <limits.h>
-#include <string.h>
-
-#include "src/core/surface/channel_init.h"
-#include "src/core/debug/trace.h"
-#include "src/core/security/auth_filters.h"
-#include "src/core/security/credentials.h"
-#include "src/core/security/secure_endpoint.h"
-#include "src/core/security/security_connector.h"
-#include "src/core/tsi/transport_security_interface.h"
-
-void grpc_security_pre_init(void) {
-  grpc_register_tracer("secure_endpoint", &grpc_trace_secure_endpoint);
-  grpc_register_tracer("transport_security", &tsi_tracing_enabled);
-}
-
-static bool maybe_prepend_client_auth_filter(
-    grpc_channel_stack_builder *builder, void *arg) {
-  const grpc_channel_args *args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  if (args) {
-    for (size_t i = 0; i < args->num_args; i++) {
-      if (0 == strcmp(GRPC_SECURITY_CONNECTOR_ARG, args->args[i].key)) {
-        return grpc_channel_stack_builder_prepend_filter(
-            builder, &grpc_client_auth_filter, NULL, NULL);
-      }
-    }
-  }
-  return true;
-}
-
-static bool maybe_prepend_server_auth_filter(
-    grpc_channel_stack_builder *builder, void *arg) {
-  const grpc_channel_args *args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  if (args) {
-    for (size_t i = 0; i < args->num_args; i++) {
-      if (0 == strcmp(GRPC_SERVER_CREDENTIALS_ARG, args->args[i].key)) {
-        return grpc_channel_stack_builder_prepend_filter(
-            builder, &grpc_server_auth_filter, NULL, NULL);
-      }
-    }
-  }
-  return true;
-}
-
-void grpc_register_security_filters(void) {
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
-                                   maybe_prepend_client_auth_filter, NULL);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
-                                   maybe_prepend_client_auth_filter, NULL);
-  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
-                                   maybe_prepend_server_auth_filter, NULL);
-}
diff --git a/src/core/surface/init_unsecure.c b/src/core/surface/init_unsecure.c
deleted file mode 100644
index 278fcc8..0000000
--- a/src/core/surface/init_unsecure.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * 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/surface/init.h"
-
-void grpc_security_pre_init(void) {}
-
-void grpc_register_security_filters(void) {}
diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c
deleted file mode 100644
index 58f8994..0000000
--- a/src/core/surface/lame_client.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- *
- * 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/surface/lame_client.h"
-
-#include <grpc/grpc.h>
-
-#include <string.h>
-
-#include "src/core/channel/channel_stack.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/call.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-typedef struct {
-  grpc_linked_mdelem status;
-  grpc_linked_mdelem details;
-} call_data;
-
-typedef struct {
-  grpc_status_code error_code;
-  const char *error_message;
-} channel_data;
-
-static void fill_metadata(grpc_call_element *elem, grpc_metadata_batch *mdb) {
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  char tmp[GPR_LTOA_MIN_BUFSIZE];
-  gpr_ltoa(chand->error_code, tmp);
-  calld->status.md = grpc_mdelem_from_strings("grpc-status", tmp);
-  calld->details.md =
-      grpc_mdelem_from_strings("grpc-message", chand->error_message);
-  calld->status.prev = calld->details.next = NULL;
-  calld->status.next = &calld->details;
-  calld->details.prev = &calld->status;
-  mdb->list.head = &calld->status;
-  mdb->list.tail = &calld->details;
-  mdb->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
-}
-
-static void lame_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
-                                           grpc_call_element *elem,
-                                           grpc_transport_stream_op *op) {
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  if (op->recv_initial_metadata != NULL) {
-    fill_metadata(elem, op->recv_initial_metadata);
-  } else if (op->recv_trailing_metadata != NULL) {
-    fill_metadata(elem, op->recv_trailing_metadata);
-  }
-  grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
-}
-
-static char *lame_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
-  return NULL;
-}
-
-static void lame_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                    grpc_channel_element *elem,
-                                    grpc_transport_op *op) {
-  if (op->on_connectivity_state_change) {
-    GPR_ASSERT(*op->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE);
-    *op->connectivity_state = GRPC_CHANNEL_FATAL_FAILURE;
-    op->on_connectivity_state_change->cb(
-        exec_ctx, op->on_connectivity_state_change->cb_arg, 1);
-  }
-  if (op->on_consumed != NULL) {
-    op->on_consumed->cb(exec_ctx, op->on_consumed->cb_arg, 1);
-  }
-}
-
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {}
-
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {}
-
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  GPR_ASSERT(args->is_first);
-  GPR_ASSERT(args->is_last);
-}
-
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {}
-
-const grpc_channel_filter grpc_lame_filter = {
-    lame_start_transport_stream_op, lame_start_transport_op, sizeof(call_data),
-    init_call_elem, grpc_call_stack_ignore_set_pollset, destroy_call_elem,
-    sizeof(channel_data), init_channel_elem, destroy_channel_elem,
-    lame_get_peer, "lame-client",
-};
-
-#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
-
-grpc_channel *grpc_lame_client_channel_create(const char *target,
-                                              grpc_status_code error_code,
-                                              const char *error_message) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_channel_element *elem;
-  channel_data *chand;
-  grpc_channel *channel = grpc_channel_create(&exec_ctx, target, NULL,
-                                              GRPC_CLIENT_LAME_CHANNEL, NULL);
-  elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
-  GRPC_API_TRACE(
-      "grpc_lame_client_channel_create(target=%s, error_code=%d, "
-      "error_message=%s)",
-      3, (target, (int)error_code, error_message));
-  GPR_ASSERT(elem->filter == &grpc_lame_filter);
-  chand = (channel_data *)elem->channel_data;
-  chand->error_code = error_code;
-  chand->error_message = error_message;
-  grpc_exec_ctx_finish(&exec_ctx);
-  return channel;
-}
diff --git a/src/core/surface/lame_client.h b/src/core/surface/lame_client.h
deleted file mode 100644
index 3f3abd2..0000000
--- a/src/core/surface/lame_client.h
+++ /dev/null
@@ -1,41 +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_CORE_SURFACE_LAME_CLIENT_H
-#define GRPC_CORE_SURFACE_LAME_CLIENT_H
-
-#include "src/core/channel/channel_stack.h"
-
-extern const grpc_channel_filter grpc_lame_filter;
-
-#endif /* GRPC_CORE_SURFACE_LAME_CLIENT_H */
diff --git a/src/core/surface/metadata_array.c b/src/core/surface/metadata_array.c
deleted file mode 100644
index 4c7bf17..0000000
--- a/src/core/surface/metadata_array.c
+++ /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.
- *
- */
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-
-#include <string.h>
-
-#include "src/core/surface/api_trace.h"
-
-void grpc_metadata_array_init(grpc_metadata_array* array) {
-  GRPC_API_TRACE("grpc_metadata_array_init(array=%p)", 1, (array));
-  memset(array, 0, sizeof(*array));
-}
-
-void grpc_metadata_array_destroy(grpc_metadata_array* array) {
-  GRPC_API_TRACE("grpc_metadata_array_destroy(array=%p)", 1, (array));
-  gpr_free(array->metadata);
-}
diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c
deleted file mode 100644
index cc75222..0000000
--- a/src/core/surface/secure_channel_create.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- *
- * 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 <grpc/grpc.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/client_config/resolver_registry.h"
-#include "src/core/iomgr/tcp_client.h"
-#include "src/core/security/auth_filters.h"
-#include "src/core/security/credentials.h"
-#include "src/core/security/security_context.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/channel.h"
-#include "src/core/transport/chttp2_transport.h"
-#include "src/core/tsi/transport_security_interface.h"
-
-typedef struct {
-  grpc_connector base;
-  gpr_refcount refs;
-
-  grpc_channel_security_connector *security_connector;
-
-  grpc_closure *notify;
-  grpc_connect_in_args args;
-  grpc_connect_out_args *result;
-  grpc_closure initial_string_sent;
-  gpr_slice_buffer initial_string_buffer;
-
-  gpr_mu mu;
-  grpc_endpoint *connecting_endpoint;
-  grpc_endpoint *newly_connecting_endpoint;
-
-  grpc_closure connected_closure;
-} connector;
-
-static void connector_ref(grpc_connector *con) {
-  connector *c = (connector *)con;
-  gpr_ref(&c->refs);
-}
-
-static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
-  connector *c = (connector *)con;
-  if (gpr_unref(&c->refs)) {
-    /* c->initial_string_buffer does not need to be destroyed */
-    gpr_free(c);
-  }
-}
-
-static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
-                                     grpc_security_status status,
-                                     grpc_endpoint *secure_endpoint,
-                                     grpc_auth_context *auth_context) {
-  connector *c = arg;
-  grpc_closure *notify;
-  grpc_channel_args *args_copy = NULL;
-  gpr_mu_lock(&c->mu);
-  if (c->connecting_endpoint == NULL) {
-    memset(c->result, 0, sizeof(*c->result));
-    gpr_mu_unlock(&c->mu);
-  } else if (status != GRPC_SECURITY_OK) {
-    gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status);
-    memset(c->result, 0, sizeof(*c->result));
-    c->connecting_endpoint = NULL;
-    gpr_mu_unlock(&c->mu);
-  } else {
-    grpc_arg auth_context_arg;
-    c->connecting_endpoint = NULL;
-    gpr_mu_unlock(&c->mu);
-    c->result->transport = grpc_create_chttp2_transport(
-        exec_ctx, c->args.channel_args, secure_endpoint, 1);
-    grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
-                                        0);
-    auth_context_arg = grpc_auth_context_to_arg(auth_context);
-    args_copy = grpc_channel_args_copy_and_add(c->args.channel_args,
-                                               &auth_context_arg, 1);
-    c->result->channel_args = args_copy;
-  }
-  notify = c->notify;
-  c->notify = NULL;
-  /* look at c->args which are connector args. */
-  notify->cb(exec_ctx, notify->cb_arg, 1);
-  if (args_copy != NULL) grpc_channel_args_destroy(args_copy);
-}
-
-static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
-                                           bool success) {
-  connector *c = arg;
-  grpc_channel_security_connector_do_handshake(exec_ctx, c->security_connector,
-                                               c->connecting_endpoint,
-                                               on_secure_handshake_done, c);
-}
-
-static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  connector *c = arg;
-  grpc_closure *notify;
-  grpc_endpoint *tcp = c->newly_connecting_endpoint;
-  if (tcp != NULL) {
-    gpr_mu_lock(&c->mu);
-    GPR_ASSERT(c->connecting_endpoint == NULL);
-    c->connecting_endpoint = tcp;
-    gpr_mu_unlock(&c->mu);
-    if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
-      grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
-                        c);
-      gpr_slice_buffer_init(&c->initial_string_buffer);
-      gpr_slice_buffer_add(&c->initial_string_buffer,
-                           c->args.initial_connect_string);
-      grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
-                          &c->initial_string_sent);
-    } else {
-      grpc_channel_security_connector_do_handshake(
-          exec_ctx, c->security_connector, tcp, on_secure_handshake_done, c);
-    }
-  } else {
-    memset(c->result, 0, sizeof(*c->result));
-    notify = c->notify;
-    c->notify = NULL;
-    notify->cb(exec_ctx, notify->cb_arg, 1);
-  }
-}
-
-static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
-  connector *c = (connector *)con;
-  grpc_endpoint *ep;
-  gpr_mu_lock(&c->mu);
-  ep = c->connecting_endpoint;
-  c->connecting_endpoint = NULL;
-  gpr_mu_unlock(&c->mu);
-  if (ep) {
-    grpc_endpoint_shutdown(exec_ctx, ep);
-  }
-}
-
-static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
-                              const grpc_connect_in_args *args,
-                              grpc_connect_out_args *result,
-                              grpc_closure *notify) {
-  connector *c = (connector *)con;
-  GPR_ASSERT(c->notify == NULL);
-  GPR_ASSERT(notify->cb);
-  c->notify = notify;
-  c->args = *args;
-  c->result = result;
-  gpr_mu_lock(&c->mu);
-  GPR_ASSERT(c->connecting_endpoint == NULL);
-  gpr_mu_unlock(&c->mu);
-  grpc_closure_init(&c->connected_closure, connected, c);
-  grpc_tcp_client_connect(
-      exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint,
-      args->interested_parties, args->addr, args->addr_len, args->deadline);
-}
-
-static const grpc_connector_vtable connector_vtable = {
-    connector_ref, connector_unref, connector_shutdown, connector_connect};
-
-typedef struct {
-  grpc_subchannel_factory base;
-  gpr_refcount refs;
-  grpc_channel_args *merge_args;
-  grpc_channel_security_connector *security_connector;
-  grpc_channel *master;
-} subchannel_factory;
-
-static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  gpr_ref(&f->refs);
-}
-
-static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_factory *scf) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  if (gpr_unref(&f->refs)) {
-    GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
-                                  "subchannel_factory");
-    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
-    grpc_channel_args_destroy(f->merge_args);
-    gpr_free(f);
-  }
-}
-
-static grpc_subchannel *subchannel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
-    grpc_subchannel_args *args) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  connector *c = gpr_malloc(sizeof(*c));
-  grpc_channel_args *final_args =
-      grpc_channel_args_merge(args->args, f->merge_args);
-  grpc_subchannel *s;
-  memset(c, 0, sizeof(*c));
-  c->base.vtable = &connector_vtable;
-  c->security_connector = f->security_connector;
-  gpr_mu_init(&c->mu);
-  gpr_ref_init(&c->refs, 1);
-  args->args = final_args;
-  s = grpc_subchannel_create(exec_ctx, &c->base, args);
-  grpc_connector_unref(exec_ctx, &c->base);
-  grpc_channel_args_destroy(final_args);
-  return s;
-}
-
-static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
-    subchannel_factory_ref, subchannel_factory_unref,
-    subchannel_factory_create_subchannel};
-
-/* Create a secure client channel:
-   Asynchronously: - resolve target
-                   - connect to it (trying alternatives as presented)
-                   - perform handshakes */
-grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
-                                         const char *target,
-                                         const grpc_channel_args *args,
-                                         void *reserved) {
-  grpc_channel *channel;
-  grpc_arg connector_arg;
-  grpc_channel_args *args_copy;
-  grpc_channel_args *new_args_from_connector;
-  grpc_channel_security_connector *security_connector;
-  grpc_resolver *resolver;
-  subchannel_factory *f;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_API_TRACE(
-      "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
-      "reserved=%p)",
-      4, (creds, target, args, reserved));
-  GPR_ASSERT(reserved == NULL);
-
-  if (grpc_find_security_connector_in_args(args) != NULL) {
-    gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
-    grpc_exec_ctx_finish(&exec_ctx);
-    return grpc_lame_client_channel_create(
-        target, GRPC_STATUS_INVALID_ARGUMENT,
-        "Security connector exists in channel args.");
-  }
-
-  if (grpc_channel_credentials_create_security_connector(
-          creds, target, args, &security_connector, &new_args_from_connector) !=
-      GRPC_SECURITY_OK) {
-    grpc_exec_ctx_finish(&exec_ctx);
-    return grpc_lame_client_channel_create(
-        target, GRPC_STATUS_INVALID_ARGUMENT,
-        "Failed to create security connector.");
-  }
-
-  connector_arg = grpc_security_connector_to_arg(&security_connector->base);
-  args_copy = grpc_channel_args_copy_and_add(
-      new_args_from_connector != NULL ? new_args_from_connector : args,
-      &connector_arg, 1);
-
-  channel = grpc_channel_create(&exec_ctx, target, args_copy,
-                                GRPC_CLIENT_CHANNEL, NULL);
-
-  f = gpr_malloc(sizeof(*f));
-  f->base.vtable = &subchannel_factory_vtable;
-  gpr_ref_init(&f->refs, 1);
-  GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory");
-  f->security_connector = security_connector;
-  f->merge_args = grpc_channel_args_copy(args_copy);
-  f->master = channel;
-  GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
-  resolver = grpc_resolver_create(target, &f->base);
-  if (resolver) {
-    grpc_client_channel_set_resolver(
-        &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
-    GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
-  }
-  grpc_subchannel_factory_unref(&exec_ctx, &f->base);
-  GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create");
-  grpc_channel_args_destroy(args_copy);
-  if (new_args_from_connector != NULL) {
-    grpc_channel_args_destroy(new_args_from_connector);
-  }
-
-  if (!resolver) {
-    GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "subchannel_factory");
-    channel = NULL;
-  }
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  return channel;
-}
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
deleted file mode 100644
index da93474..0000000
--- a/src/core/surface/server.c
+++ /dev/null
@@ -1,1311 +0,0 @@
-/*
- *
- * 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/surface/server.h"
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/support/stack_lockfree.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/call.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/completion_queue.h"
-#include "src/core/surface/init.h"
-#include "src/core/transport/metadata.h"
-#include "src/core/transport/static_metadata.h"
-
-typedef struct listener {
-  void *arg;
-  void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
-                grpc_pollset **pollsets, size_t pollset_count);
-  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
-                  grpc_closure *closure);
-  struct listener *next;
-  grpc_closure destroy_done;
-} listener;
-
-typedef struct call_data call_data;
-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 {
-  requested_call_type type;
-  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;
-  union {
-    struct {
-      grpc_call_details *details;
-    } batch;
-    struct {
-      registered_method *registered_method;
-      gpr_timespec *deadline;
-      grpc_byte_buffer **optional_payload;
-    } registered;
-  } data;
-  grpc_closure publish;
-} requested_call;
-
-typedef struct channel_registered_method {
-  registered_method *server_registered_method;
-  grpc_mdstr *method;
-  grpc_mdstr *host;
-} channel_registered_method;
-
-struct channel_data {
-  grpc_server *server;
-  grpc_connectivity_state connectivity_state;
-  grpc_channel *channel;
-  /* linked list of all channels on a server */
-  channel_data *next;
-  channel_data *prev;
-  channel_registered_method *registered_methods;
-  uint32_t registered_method_slots;
-  uint32_t registered_method_max_probes;
-  grpc_closure finish_destroy_channel_closure;
-  grpc_closure channel_connectivity_changed;
-};
-
-typedef struct shutdown_tag {
-  void *tag;
-  grpc_completion_queue *cq;
-  grpc_cq_completion completion;
-} shutdown_tag;
-
-typedef enum {
-  /* waiting for metadata */
-  NOT_STARTED,
-  /* inital metadata read, not flow controlled in yet */
-  PENDING,
-  /* flow controlled in, on completion queue */
-  ACTIVATED,
-  /* cancelled before being queued */
-  ZOMBIED
-} call_state;
-
-typedef struct request_matcher request_matcher;
-
-struct call_data {
-  grpc_call *call;
-
-  /** protects state */
-  gpr_mu mu_state;
-  /** the current state of a call - see call_state */
-  call_state state;
-
-  grpc_mdstr *path;
-  grpc_mdstr *host;
-  gpr_timespec deadline;
-
-  grpc_completion_queue *cq_new;
-
-  grpc_metadata_batch *recv_initial_metadata;
-  grpc_metadata_array initial_metadata;
-
-  grpc_closure got_initial_metadata;
-  grpc_closure server_on_recv_initial_metadata;
-  grpc_closure kill_zombie_closure;
-  grpc_closure *on_done_recv_initial_metadata;
-
-  call_data *pending_next;
-};
-
-struct request_matcher {
-  call_data *pending_head;
-  call_data *pending_tail;
-  gpr_stack_lockfree *requests;
-};
-
-struct registered_method {
-  char *method;
-  char *host;
-  request_matcher request_matcher;
-  registered_method *next;
-};
-
-typedef struct {
-  grpc_channel **channels;
-  size_t num_channels;
-} channel_broadcaster;
-
-struct grpc_server {
-  grpc_channel_args *channel_args;
-
-  grpc_completion_queue **cqs;
-  grpc_pollset **pollsets;
-  size_t cq_count;
-
-  /* The two following mutexes control access to server-state
-     mu_global controls access to non-call-related state (e.g., channel state)
-     mu_call controls access to call-related state (e.g., the call lists)
-
-     If they are ever required to be nested, you must lock mu_global
-     before mu_call. This is currently used in shutdown processing
-     (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
-  gpr_mu mu_global; /* mutex for server and channel state */
-  gpr_mu mu_call;   /* mutex for call-specific state */
-
-  registered_method *registered_methods;
-  request_matcher unregistered_request_matcher;
-  /** free list of available requested_calls indices */
-  gpr_stack_lockfree *request_freelist;
-  /** requested call backing data */
-  requested_call *requested_calls;
-  size_t max_requested_calls;
-
-  gpr_atm shutdown_flag;
-  uint8_t shutdown_published;
-  size_t num_shutdown_tags;
-  shutdown_tag *shutdown_tags;
-
-  channel_data root_channel_data;
-
-  listener *listeners;
-  int listeners_destroyed;
-  gpr_refcount internal_refcount;
-
-  /** when did we print the last shutdown progress message */
-  gpr_timespec last_shutdown_message_time;
-};
-
-#define SERVER_FROM_CALL_ELEM(elem) \
-  (((channel_data *)(elem)->channel_data)->server)
-
-static void begin_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                       call_data *calld, requested_call *rc);
-static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                      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);
-
-/*
- * channel broadcaster
- */
-
-/* assumes server locked */
-static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
-  channel_data *c;
-  size_t count = 0;
-  for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
-    count++;
-  }
-  cb->num_channels = count;
-  cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
-  count = 0;
-  for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
-    cb->channels[count++] = c->channel;
-    GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
-  }
-}
-
-struct shutdown_cleanup_args {
-  grpc_closure closure;
-  gpr_slice slice;
-};
-
-static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg,
-                             bool iomgr_status_ignored) {
-  struct shutdown_cleanup_args *a = arg;
-  gpr_slice_unref(a->slice);
-  gpr_free(a);
-}
-
-static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
-                          int send_goaway, int send_disconnect) {
-  grpc_transport_op op;
-  struct shutdown_cleanup_args *sc;
-  grpc_channel_element *elem;
-
-  memset(&op, 0, sizeof(op));
-  op.send_goaway = send_goaway;
-  sc = gpr_malloc(sizeof(*sc));
-  sc->slice = gpr_slice_from_copied_string("Server shutdown");
-  op.goaway_message = &sc->slice;
-  op.goaway_status = GRPC_STATUS_OK;
-  op.disconnect = send_disconnect;
-  grpc_closure_init(&sc->closure, shutdown_cleanup, sc);
-  op.on_consumed = &sc->closure;
-
-  elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
-  elem->filter->start_transport_op(exec_ctx, elem, &op);
-}
-
-static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
-                                         channel_broadcaster *cb,
-                                         int send_goaway,
-                                         int force_disconnect) {
-  size_t i;
-
-  for (i = 0; i < cb->num_channels; i++) {
-    send_shutdown(exec_ctx, cb->channels[i], send_goaway, force_disconnect);
-    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, cb->channels[i], "broadcast");
-  }
-  gpr_free(cb->channels);
-}
-
-/*
- * request_matcher
- */
-
-static void request_matcher_init(request_matcher *rm, size_t entries) {
-  memset(rm, 0, sizeof(*rm));
-  rm->requests = 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);
-}
-
-static void kill_zombie(grpc_exec_ctx *exec_ctx, void *elem, bool success) {
-  grpc_call_destroy(grpc_call_from_top_element(elem));
-}
-
-static void request_matcher_zombify_all_pending_calls(grpc_exec_ctx *exec_ctx,
-                                                      request_matcher *rm) {
-  while (rm->pending_head) {
-    call_data *calld = rm->pending_head;
-    rm->pending_head = calld->pending_next;
-    gpr_mu_lock(&calld->mu_state);
-    calld->state = ZOMBIED;
-    gpr_mu_unlock(&calld->mu_state);
-    grpc_closure_init(
-        &calld->kill_zombie_closure, kill_zombie,
-        grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
-    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
-  }
-}
-
-static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx,
-                                          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]);
-  }
-}
-
-/*
- * server proper
- */
-
-static void server_ref(grpc_server *server) {
-  gpr_ref(&server->internal_refcount);
-}
-
-static void server_delete(grpc_exec_ctx *exec_ctx, grpc_server *server) {
-  registered_method *rm;
-  size_t i;
-  grpc_channel_args_destroy(server->channel_args);
-  gpr_mu_destroy(&server->mu_global);
-  gpr_mu_destroy(&server->mu_call);
-  while ((rm = server->registered_methods) != NULL) {
-    server->registered_methods = rm->next;
-    request_matcher_destroy(&rm->request_matcher);
-    gpr_free(rm->method);
-    gpr_free(rm->host);
-    gpr_free(rm);
-  }
-  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);
-  gpr_free(server->shutdown_tags);
-  gpr_free(server->requested_calls);
-  gpr_free(server);
-}
-
-static void server_unref(grpc_exec_ctx *exec_ctx, grpc_server *server) {
-  if (gpr_unref(&server->internal_refcount)) {
-    server_delete(exec_ctx, server);
-  }
-}
-
-static int is_channel_orphaned(channel_data *chand) {
-  return chand->next == chand;
-}
-
-static void orphan_channel(channel_data *chand) {
-  chand->next->prev = chand->prev;
-  chand->prev->next = chand->next;
-  chand->next = chand->prev = chand;
-}
-
-static void finish_destroy_channel(grpc_exec_ctx *exec_ctx, void *cd,
-                                   bool success) {
-  channel_data *chand = cd;
-  grpc_server *server = chand->server;
-  GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "server");
-  server_unref(exec_ctx, server);
-}
-
-static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) {
-  if (is_channel_orphaned(chand)) return;
-  GPR_ASSERT(chand->server != NULL);
-  orphan_channel(chand);
-  server_ref(chand->server);
-  maybe_finish_shutdown(exec_ctx, chand->server);
-  chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
-  chand->finish_destroy_channel_closure.cb_arg = chand;
-
-  grpc_transport_op op;
-  memset(&op, 0, sizeof(op));
-  op.set_accept_stream = true;
-  op.on_consumed = &chand->finish_destroy_channel_closure;
-  grpc_channel_next_op(exec_ctx,
-                       grpc_channel_stack_element(
-                           grpc_channel_get_channel_stack(chand->channel), 0),
-                       &op);
-}
-
-static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                                 grpc_call_element *elem, request_matcher *rm) {
-  call_data *calld = elem->call_data;
-  int request_id;
-
-  if (gpr_atm_acq_load(&server->shutdown_flag)) {
-    gpr_mu_lock(&calld->mu_state);
-    calld->state = ZOMBIED;
-    gpr_mu_unlock(&calld->mu_state);
-    grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
-    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
-    return;
-  }
-
-  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;
-    } else {
-      rm->pending_tail->pending_next = calld;
-      rm->pending_tail = calld;
-    }
-    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);
-    begin_call(exec_ctx, server, calld, &server->requested_calls[request_id]);
-  }
-}
-
-static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
-  channel_data *chand = elem->channel_data;
-  call_data *calld = elem->call_data;
-  grpc_server *server = chand->server;
-  uint32_t i;
-  uint32_t hash;
-  channel_registered_method *rm;
-
-  if (chand->registered_methods && calld->path && calld->host) {
-    /* TODO(ctiller): unify these two searches */
-    /* check for an exact match with host */
-    hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
-    for (i = 0; i <= chand->registered_method_max_probes; i++) {
-      rm = &chand->registered_methods[(hash + i) %
-                                      chand->registered_method_slots];
-      if (!rm) break;
-      if (rm->host != calld->host) continue;
-      if (rm->method != calld->path) continue;
-      finish_start_new_rpc(exec_ctx, server, elem,
-                           &rm->server_registered_method->request_matcher);
-      return;
-    }
-    /* check for a wildcard method definition (no host set) */
-    hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
-    for (i = 0; i <= chand->registered_method_max_probes; i++) {
-      rm = &chand->registered_methods[(hash + i) %
-                                      chand->registered_method_slots];
-      if (!rm) break;
-      if (rm->host != NULL) continue;
-      if (rm->method != calld->path) continue;
-      finish_start_new_rpc(exec_ctx, server, elem,
-                           &rm->server_registered_method->request_matcher);
-      return;
-    }
-  }
-  finish_start_new_rpc(exec_ctx, server, elem,
-                       &server->unregistered_request_matcher);
-}
-
-static int num_listeners(grpc_server *server) {
-  listener *l;
-  int n = 0;
-  for (l = server->listeners; l; l = l->next) {
-    n++;
-  }
-  return n;
-}
-
-static void done_shutdown_event(grpc_exec_ctx *exec_ctx, void *server,
-                                grpc_cq_completion *completion) {
-  server_unref(exec_ctx, server);
-}
-
-static int num_channels(grpc_server *server) {
-  channel_data *chand;
-  int n = 0;
-  for (chand = server->root_channel_data.next;
-       chand != &server->root_channel_data; chand = chand->next) {
-    n++;
-  }
-  return n;
-}
-
-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);
-  }
-}
-
-static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
-                                  grpc_server *server) {
-  size_t i;
-  if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) {
-    return;
-  }
-
-  kill_pending_work_locked(exec_ctx, server);
-
-  if (server->root_channel_data.next != &server->root_channel_data ||
-      server->listeners_destroyed < num_listeners(server)) {
-    if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME),
-                                  server->last_shutdown_message_time),
-                     gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
-      server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
-      gpr_log(GPR_DEBUG,
-              "Waiting for %d channels and %d/%d listeners to be destroyed"
-              " before shutting down server",
-              num_channels(server),
-              num_listeners(server) - server->listeners_destroyed,
-              num_listeners(server));
-    }
-    return;
-  }
-  server->shutdown_published = 1;
-  for (i = 0; i < server->num_shutdown_tags; i++) {
-    server_ref(server);
-    grpc_cq_end_op(exec_ctx, server->shutdown_tags[i].cq,
-                   server->shutdown_tags[i].tag, 1, done_shutdown_event, server,
-                   &server->shutdown_tags[i].completion);
-  }
-}
-
-static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  if (md->key == GRPC_MDSTR_PATH) {
-    calld->path = GRPC_MDSTR_REF(md->value);
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_AUTHORITY) {
-    calld->host = GRPC_MDSTR_REF(md->value);
-    return NULL;
-  }
-  return md;
-}
-
-static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
-                                            bool success) {
-  grpc_call_element *elem = ptr;
-  call_data *calld = elem->call_data;
-  gpr_timespec op_deadline;
-
-  grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, elem);
-  op_deadline = calld->recv_initial_metadata->deadline;
-  if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
-    calld->deadline = op_deadline;
-  }
-  if (calld->host && calld->path) {
-    /* do nothing */
-  } else {
-    success = 0;
-  }
-
-  calld->on_done_recv_initial_metadata->cb(
-      exec_ctx, calld->on_done_recv_initial_metadata->cb_arg, success);
-}
-
-static void server_mutate_op(grpc_call_element *elem,
-                             grpc_transport_stream_op *op) {
-  call_data *calld = elem->call_data;
-
-  if (op->recv_initial_metadata != NULL) {
-    calld->recv_initial_metadata = op->recv_initial_metadata;
-    calld->on_done_recv_initial_metadata = op->recv_initial_metadata_ready;
-    op->recv_initial_metadata_ready = &calld->server_on_recv_initial_metadata;
-  }
-}
-
-static void server_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
-                                             grpc_call_element *elem,
-                                             grpc_transport_stream_op *op) {
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  server_mutate_op(elem, op);
-  grpc_call_next_op(exec_ctx, elem, op);
-}
-
-static void got_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
-                                 bool success) {
-  grpc_call_element *elem = ptr;
-  call_data *calld = elem->call_data;
-  if (success) {
-    start_new_rpc(exec_ctx, elem);
-  } else {
-    gpr_mu_lock(&calld->mu_state);
-    if (calld->state == NOT_STARTED) {
-      calld->state = ZOMBIED;
-      gpr_mu_unlock(&calld->mu_state);
-      grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
-      grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
-    } else if (calld->state == PENDING) {
-      calld->state = ZOMBIED;
-      gpr_mu_unlock(&calld->mu_state);
-      /* zombied call will be destroyed when it's removed from the pending
-         queue... later */
-    } else {
-      gpr_mu_unlock(&calld->mu_state);
-    }
-  }
-}
-
-static void accept_stream(grpc_exec_ctx *exec_ctx, void *cd,
-                          grpc_transport *transport,
-                          const void *transport_server_data) {
-  channel_data *chand = cd;
-  /* create a call */
-  grpc_call *call =
-      grpc_call_create(chand->channel, NULL, 0, NULL, transport_server_data,
-                       NULL, 0, gpr_inf_future(GPR_CLOCK_MONOTONIC));
-  grpc_call_element *elem =
-      grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
-  call_data *calld = elem->call_data;
-  grpc_op op;
-  memset(&op, 0, sizeof(op));
-  op.op = GRPC_OP_RECV_INITIAL_METADATA;
-  op.data.recv_initial_metadata = &calld->initial_metadata;
-  grpc_closure_init(&calld->got_initial_metadata, got_initial_metadata, elem);
-  grpc_call_start_batch_and_execute(exec_ctx, call, &op, 1,
-                                    &calld->got_initial_metadata);
-}
-
-static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd,
-                                         bool iomgr_status_ignored) {
-  channel_data *chand = cd;
-  grpc_server *server = chand->server;
-  if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
-    grpc_transport_op op;
-    memset(&op, 0, sizeof(op));
-    op.on_connectivity_state_change = &chand->channel_connectivity_changed,
-    op.connectivity_state = &chand->connectivity_state;
-    grpc_channel_next_op(exec_ctx,
-                         grpc_channel_stack_element(
-                             grpc_channel_get_channel_stack(chand->channel), 0),
-                         &op);
-  } else {
-    gpr_mu_lock(&server->mu_global);
-    destroy_channel(exec_ctx, chand);
-    gpr_mu_unlock(&server->mu_global);
-    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity");
-  }
-}
-
-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;
-  channel_data *chand = elem->channel_data;
-  memset(calld, 0, sizeof(call_data));
-  calld->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
-  calld->call = grpc_call_from_top_element(elem);
-  gpr_mu_init(&calld->mu_state);
-
-  grpc_closure_init(&calld->server_on_recv_initial_metadata,
-                    server_on_recv_initial_metadata, elem);
-
-  server_ref(chand->server);
-}
-
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {
-  channel_data *chand = elem->channel_data;
-  call_data *calld = elem->call_data;
-
-  GPR_ASSERT(calld->state != PENDING);
-
-  if (calld->host) {
-    GRPC_MDSTR_UNREF(calld->host);
-  }
-  if (calld->path) {
-    GRPC_MDSTR_UNREF(calld->path);
-  }
-  grpc_metadata_array_destroy(&calld->initial_metadata);
-
-  gpr_mu_destroy(&calld->mu_state);
-
-  server_unref(exec_ctx, chand->server);
-}
-
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  channel_data *chand = elem->channel_data;
-  GPR_ASSERT(args->is_first);
-  GPR_ASSERT(!args->is_last);
-  chand->server = NULL;
-  chand->channel = NULL;
-  chand->next = chand->prev = chand;
-  chand->registered_methods = NULL;
-  chand->connectivity_state = GRPC_CHANNEL_IDLE;
-  grpc_closure_init(&chand->channel_connectivity_changed,
-                    channel_connectivity_changed, chand);
-}
-
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  size_t i;
-  channel_data *chand = elem->channel_data;
-  if (chand->registered_methods) {
-    for (i = 0; i < chand->registered_method_slots; i++) {
-      if (chand->registered_methods[i].method) {
-        GRPC_MDSTR_UNREF(chand->registered_methods[i].method);
-      }
-      if (chand->registered_methods[i].host) {
-        GRPC_MDSTR_UNREF(chand->registered_methods[i].host);
-      }
-    }
-    gpr_free(chand->registered_methods);
-  }
-  if (chand->server) {
-    gpr_mu_lock(&chand->server->mu_global);
-    chand->next->prev = chand->prev;
-    chand->prev->next = chand->next;
-    chand->next = chand->prev = chand;
-    maybe_finish_shutdown(exec_ctx, chand->server);
-    gpr_mu_unlock(&chand->server->mu_global);
-    server_unref(exec_ctx, chand->server);
-  }
-}
-
-const grpc_channel_filter grpc_server_top_filter = {
-    server_start_transport_stream_op, grpc_channel_next_op, sizeof(call_data),
-    init_call_elem, grpc_call_stack_ignore_set_pollset, destroy_call_elem,
-    sizeof(channel_data), init_channel_elem, destroy_channel_elem,
-    grpc_call_next_get_peer, "server",
-};
-
-void grpc_server_register_completion_queue(grpc_server *server,
-                                           grpc_completion_queue *cq,
-                                           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);
-  n = server->cq_count++;
-  server->cqs = gpr_realloc(server->cqs,
-                            server->cq_count * sizeof(grpc_completion_queue *));
-  server->cqs[n] = cq;
-}
-
-grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
-  size_t i;
-
-  GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved));
-
-  grpc_server *server = gpr_malloc(sizeof(grpc_server));
-
-  GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
-
-  memset(server, 0, sizeof(grpc_server));
-
-  gpr_mu_init(&server->mu_global);
-  gpr_mu_init(&server->mu_call);
-
-  /* decremented by grpc_server_destroy */
-  gpr_ref_init(&server->internal_refcount, 1);
-  server->root_channel_data.next = server->root_channel_data.prev =
-      &server->root_channel_data;
-
-  /* TODO(ctiller): expose a channel_arg for this */
-  server->max_requested_calls = 32768;
-  server->request_freelist =
-      gpr_stack_lockfree_create(server->max_requested_calls);
-  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->requested_calls = gpr_malloc(server->max_requested_calls *
-                                       sizeof(*server->requested_calls));
-
-  server->channel_args = grpc_channel_args_copy(args);
-
-  return server;
-}
-
-static int streq(const char *a, const char *b) {
-  if (a == NULL && b == NULL) return 1;
-  if (a == NULL) return 0;
-  if (b == NULL) return 0;
-  return 0 == strcmp(a, b);
-}
-
-void *grpc_server_register_method(grpc_server *server, const char *method,
-                                  const char *host) {
-  registered_method *m;
-  GRPC_API_TRACE("grpc_server_register_method(server=%p, method=%s, host=%s)",
-                 3, (server, method, host));
-  if (!method) {
-    gpr_log(GPR_ERROR,
-            "grpc_server_register_method method string cannot be NULL");
-    return NULL;
-  }
-  for (m = server->registered_methods; m; m = m->next) {
-    if (streq(m->method, method) && streq(m->host, host)) {
-      gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
-              host ? host : "*");
-      return NULL;
-    }
-  }
-  m = gpr_malloc(sizeof(registered_method));
-  memset(m, 0, sizeof(*m));
-  request_matcher_init(&m->request_matcher, server->max_requested_calls);
-  m->method = gpr_strdup(method);
-  m->host = gpr_strdup(host);
-  m->next = server->registered_methods;
-  server->registered_methods = m;
-  return m;
-}
-
-void grpc_server_start(grpc_server *server) {
-  listener *l;
-  size_t i;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server));
-
-  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]);
-  }
-
-  for (l = server->listeners; l; l = l->next) {
-    l->start(&exec_ctx, server, l->arg, server->pollsets, server->cq_count);
-  }
-
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
-                                 grpc_transport *transport,
-                                 const grpc_channel_args *args) {
-  size_t i;
-  size_t num_registered_methods;
-  size_t alloc;
-  registered_method *rm;
-  channel_registered_method *crm;
-  grpc_channel *channel;
-  channel_data *chand;
-  grpc_mdstr *host;
-  grpc_mdstr *method;
-  uint32_t hash;
-  size_t slots;
-  uint32_t probes;
-  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(
-              grpc_channel_get_channel_stack(channel), 0)->channel_data;
-  chand->server = s;
-  server_ref(s);
-  chand->channel = channel;
-
-  num_registered_methods = 0;
-  for (rm = s->registered_methods; rm; rm = rm->next) {
-    num_registered_methods++;
-  }
-  /* build a lookup table phrased in terms of mdstr's in this channels context
-     to quickly find registered methods */
-  if (num_registered_methods > 0) {
-    slots = 2 * num_registered_methods;
-    alloc = sizeof(channel_registered_method) * slots;
-    chand->registered_methods = gpr_malloc(alloc);
-    memset(chand->registered_methods, 0, alloc);
-    for (rm = s->registered_methods; rm; rm = rm->next) {
-      host = rm->host ? grpc_mdstr_from_string(rm->host) : NULL;
-      method = grpc_mdstr_from_string(rm->method);
-      hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
-      for (probes = 0; chand->registered_methods[(hash + probes) % slots]
-                               .server_registered_method != NULL;
-           probes++)
-        ;
-      if (probes > max_probes) max_probes = probes;
-      crm = &chand->registered_methods[(hash + probes) % slots];
-      crm->server_registered_method = rm;
-      crm->host = host;
-      crm->method = method;
-    }
-    GPR_ASSERT(slots <= UINT32_MAX);
-    chand->registered_method_slots = (uint32_t)slots;
-    chand->registered_method_max_probes = max_probes;
-  }
-
-  gpr_mu_lock(&s->mu_global);
-  chand->next = &s->root_channel_data;
-  chand->prev = chand->next->prev;
-  chand->next->prev = chand->prev->next = chand;
-  gpr_mu_unlock(&s->mu_global);
-
-  GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
-  memset(&op, 0, sizeof(op));
-  op.set_accept_stream = true;
-  op.set_accept_stream_fn = accept_stream;
-  op.set_accept_stream_user_data = chand;
-  op.on_connectivity_state_change = &chand->channel_connectivity_changed;
-  op.connectivity_state = &chand->connectivity_state;
-  op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0;
-  grpc_transport_perform_op(exec_ctx, transport, &op);
-}
-
-void done_published_shutdown(grpc_exec_ctx *exec_ctx, void *done_arg,
-                             grpc_cq_completion *storage) {
-  (void)done_arg;
-  gpr_free(storage);
-}
-
-static void listener_destroy_done(grpc_exec_ctx *exec_ctx, void *s,
-                                  bool success) {
-  grpc_server *server = s;
-  gpr_mu_lock(&server->mu_global);
-  server->listeners_destroyed++;
-  maybe_finish_shutdown(exec_ctx, server);
-  gpr_mu_unlock(&server->mu_global);
-}
-
-void grpc_server_shutdown_and_notify(grpc_server *server,
-                                     grpc_completion_queue *cq, void *tag) {
-  listener *l;
-  shutdown_tag *sdt;
-  channel_broadcaster broadcaster;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_API_TRACE("grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", 3,
-                 (server, cq, tag));
-
-  /* lock, and gather up some stuff to do */
-  gpr_mu_lock(&server->mu_global);
-  grpc_cq_begin_op(cq, tag);
-  if (server->shutdown_published) {
-    grpc_cq_end_op(&exec_ctx, cq, tag, 1, done_published_shutdown, NULL,
-                   gpr_malloc(sizeof(grpc_cq_completion)));
-    gpr_mu_unlock(&server->mu_global);
-    goto done;
-  }
-  server->shutdown_tags =
-      gpr_realloc(server->shutdown_tags,
-                  sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
-  sdt = &server->shutdown_tags[server->num_shutdown_tags++];
-  sdt->tag = tag;
-  sdt->cq = cq;
-  if (gpr_atm_acq_load(&server->shutdown_flag)) {
-    gpr_mu_unlock(&server->mu_global);
-    goto done;
-  }
-
-  server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
-
-  channel_broadcaster_init(server, &broadcaster);
-
-  gpr_atm_rel_store(&server->shutdown_flag, 1);
-
-  /* collect all unregistered then registered calls */
-  gpr_mu_lock(&server->mu_call);
-  kill_pending_work_locked(&exec_ctx, server);
-  gpr_mu_unlock(&server->mu_call);
-
-  maybe_finish_shutdown(&exec_ctx, server);
-  gpr_mu_unlock(&server->mu_global);
-
-  /* Shutdown listeners */
-  for (l = server->listeners; l; l = l->next) {
-    grpc_closure_init(&l->destroy_done, listener_destroy_done, server);
-    l->destroy(&exec_ctx, server, l->arg, &l->destroy_done);
-  }
-
-  channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 1, 0);
-
-done:
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-void grpc_server_cancel_all_calls(grpc_server *server) {
-  channel_broadcaster broadcaster;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_API_TRACE("grpc_server_cancel_all_calls(server=%p)", 1, (server));
-
-  gpr_mu_lock(&server->mu_global);
-  channel_broadcaster_init(server, &broadcaster);
-  gpr_mu_unlock(&server->mu_global);
-
-  channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 0, 1);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-void grpc_server_destroy(grpc_server *server) {
-  listener *l;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_API_TRACE("grpc_server_destroy(server=%p)", 1, (server));
-
-  gpr_mu_lock(&server->mu_global);
-  GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners);
-  GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
-
-  while (server->listeners) {
-    l = server->listeners;
-    server->listeners = l->next;
-    gpr_free(l);
-  }
-
-  gpr_mu_unlock(&server->mu_global);
-
-  server_unref(&exec_ctx, server);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-void grpc_server_add_listener(
-    grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
-    void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
-                  grpc_pollset **pollsets, size_t pollset_count),
-    void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
-                    grpc_closure *on_done)) {
-  listener *l = gpr_malloc(sizeof(listener));
-  l->arg = arg;
-  l->start = start;
-  l->destroy = destroy;
-  l->next = server->listeners;
-  server->listeners = l;
-}
-
-static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
-                                          grpc_server *server,
-                                          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);
-    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);
-    return GRPC_CALL_OK;
-  }
-  switch (rc->type) {
-    case BATCH_CALL:
-      rm = &server->unregistered_request_matcher;
-      break;
-    case REGISTERED_CALL:
-      rm = &rc->data.registered.registered_method->request_matcher;
-      break;
-  }
-  server->requested_calls[request_id] = *rc;
-  gpr_free(rc);
-  if (gpr_stack_lockfree_push(rm->requests, 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);
-      if (request_id == -1) break;
-      rm->pending_head = calld->pending_next;
-      gpr_mu_unlock(&server->mu_call);
-      gpr_mu_lock(&calld->mu_state);
-      if (calld->state == ZOMBIED) {
-        gpr_mu_unlock(&calld->mu_state);
-        grpc_closure_init(
-            &calld->kill_zombie_closure, kill_zombie,
-            grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
-        grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true,
-                              NULL);
-      } else {
-        GPR_ASSERT(calld->state == PENDING);
-        calld->state = ACTIVATED;
-        gpr_mu_unlock(&calld->mu_state);
-        begin_call(exec_ctx, server, calld,
-                   &server->requested_calls[request_id]);
-      }
-      gpr_mu_lock(&server->mu_call);
-    }
-    gpr_mu_unlock(&server->mu_call);
-  }
-  return GRPC_CALL_OK;
-}
-
-grpc_call_error grpc_server_request_call(
-    grpc_server *server, grpc_call **call, grpc_call_details *details,
-    grpc_metadata_array *initial_metadata,
-    grpc_completion_queue *cq_bound_to_call,
-    grpc_completion_queue *cq_for_notification, void *tag) {
-  grpc_call_error error;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  requested_call *rc = gpr_malloc(sizeof(*rc));
-  GRPC_API_TRACE(
-      "grpc_server_request_call("
-      "server=%p, call=%p, details=%p, initial_metadata=%p, "
-      "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)) {
-    gpr_free(rc);
-    error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
-    goto done;
-  }
-  grpc_cq_begin_op(cq_for_notification, tag);
-  details->reserved = NULL;
-  rc->type = BATCH_CALL;
-  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);
-done:
-  grpc_exec_ctx_finish(&exec_ctx);
-  return error;
-}
-
-grpc_call_error grpc_server_request_registered_call(
-    grpc_server *server, void *rmp, grpc_call **call, gpr_timespec *deadline,
-    grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
-    grpc_completion_queue *cq_bound_to_call,
-    grpc_completion_queue *cq_for_notification, void *tag) {
-  grpc_call_error error;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  requested_call *rc = gpr_malloc(sizeof(*rc));
-  registered_method *rm = rmp;
-  GRPC_API_TRACE(
-      "grpc_server_request_registered_call("
-      "server=%p, rmp=%p, call=%p, deadline=%p, initial_metadata=%p, "
-      "optional_payload=%p, cq_bound_to_call=%p, cq_for_notification=%p, "
-      "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)) {
-    gpr_free(rc);
-    error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
-    goto done;
-  }
-  grpc_cq_begin_op(cq_for_notification, tag);
-  rc->type = REGISTERED_CALL;
-  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);
-done:
-  grpc_exec_ctx_finish(&exec_ctx);
-  return error;
-}
-
-static void publish_registered_or_batch(grpc_exec_ctx *exec_ctx,
-                                        void *user_data, bool success);
-
-static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
-  gpr_slice slice = value->slice;
-  size_t len = GPR_SLICE_LENGTH(slice);
-
-  if (len + 1 > *capacity) {
-    *capacity = GPR_MAX(len + 1, *capacity * 2);
-    *dest = gpr_realloc(*dest, *capacity);
-  }
-  memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
-}
-
-static void begin_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                       call_data *calld, requested_call *rc) {
-  grpc_op ops[1];
-  grpc_op *op = ops;
-
-  memset(ops, 0, sizeof(ops));
-
-  /* called once initial metadata has been read by the call, but BEFORE
-     the ioreq to fetch it out of the call has been executed.
-     This means metadata related fields can be relied on in calld, but to
-     fill in the metadata array passed by the client, we need to perform
-     an ioreq op, that should complete immediately. */
-
-  grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
-  grpc_closure_init(&rc->publish, publish_registered_or_batch, rc);
-  *rc->call = calld->call;
-  calld->cq_new = rc->cq_for_notification;
-  GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
-  switch (rc->type) {
-    case BATCH_CALL:
-      GPR_ASSERT(calld->host != NULL);
-      GPR_ASSERT(calld->path != NULL);
-      cpstr(&rc->data.batch.details->host,
-            &rc->data.batch.details->host_capacity, calld->host);
-      cpstr(&rc->data.batch.details->method,
-            &rc->data.batch.details->method_capacity, calld->path);
-      rc->data.batch.details->deadline = calld->deadline;
-      break;
-    case REGISTERED_CALL:
-      *rc->data.registered.deadline = calld->deadline;
-      if (rc->data.registered.optional_payload) {
-        op->op = GRPC_OP_RECV_MESSAGE;
-        op->data.recv_message = rc->data.registered.optional_payload;
-        op++;
-      }
-      break;
-    default:
-      GPR_UNREACHABLE_CODE(return );
-  }
-
-  GRPC_CALL_INTERNAL_REF(calld->call, "server");
-  grpc_call_start_batch_and_execute(exec_ctx, calld->call, ops,
-                                    (size_t)(op - ops), &rc->publish);
-}
-
-static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
-                               grpc_cq_completion *c) {
-  requested_call *rc = req;
-  grpc_server *server = rc->server;
-
-  if (rc >= server->requested_calls &&
-      rc < server->requested_calls + server->max_requested_calls) {
-    GPR_ASSERT(rc - server->requested_calls <= INT_MAX);
-    gpr_stack_lockfree_push(server->request_freelist,
-                            (int)(rc - server->requested_calls));
-  } else {
-    gpr_free(req);
-  }
-
-  server_unref(exec_ctx, server);
-}
-
-static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                      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);
-}
-
-static void publish_registered_or_batch(grpc_exec_ctx *exec_ctx, void *prc,
-                                        bool success) {
-  requested_call *rc = prc;
-  grpc_call *call = *rc->call;
-  grpc_call_element *elem =
-      grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  server_ref(chand->server);
-  grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, success, done_request_event,
-                 rc, &rc->completion);
-  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "server");
-}
-
-const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
-  return server->channel_args;
-}
-
-int grpc_server_has_open_connections(grpc_server *server) {
-  int r;
-  gpr_mu_lock(&server->mu_global);
-  r = server->root_channel_data.next != &server->root_channel_data;
-  gpr_mu_unlock(&server->mu_global);
-  return r;
-}
diff --git a/src/core/surface/server.h b/src/core/surface/server.h
deleted file mode 100644
index cd62ead..0000000
--- a/src/core/surface/server.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_SERVER_H
-#define GRPC_CORE_SURFACE_SERVER_H
-
-#include <grpc/grpc.h>
-#include "src/core/channel/channel_stack.h"
-#include "src/core/transport/transport.h"
-
-extern const grpc_channel_filter grpc_server_top_filter;
-
-/* Add a listener to the server: when the server starts, it will call start,
-   and when it shuts down, it will call destroy */
-void grpc_server_add_listener(
-    grpc_exec_ctx *exec_ctx, grpc_server *server, void *listener,
-    void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
-                  grpc_pollset **pollsets, size_t npollsets),
-    void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg,
-                    grpc_closure *on_done));
-
-/* Setup a transport - creates a channel stack, binds the transport to the
-   server */
-void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                                 grpc_transport *transport,
-                                 const grpc_channel_args *args);
-
-const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server);
-
-int grpc_server_has_open_connections(grpc_server *server);
-
-#endif /* GRPC_CORE_SURFACE_SERVER_H */
diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c
deleted file mode 100644
index ff2840f..0000000
--- a/src/core/surface/server_chttp2.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- *
- * 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 <grpc/grpc.h>
-
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/tcp_server.h"
-#include "src/core/surface/api_trace.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.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_tcp_server_acceptor *acceptor) {
-  /*
-   * Beware that the call to grpc_create_chttp2_transport() has to happen before
-   * grpc_tcp_server_destroy(). This is fine here, but similar code
-   * asynchronously doing a handshake instead of calling grpc_tcp_server_start()
-   * (as in server_secure_chttp2.c) needs to add synchronization to avoid this
-   * case.
-   */
-  grpc_transport *transport = grpc_create_chttp2_transport(
-      exec_ctx, grpc_server_get_channel_args(server), tcp, 0);
-  setup_transport(exec_ctx, server, transport);
-  grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
-}
-
-/* Server callback: start listening on our ports */
-static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
-                  grpc_pollset **pollsets, size_t pollset_count) {
-  grpc_tcp_server *tcp = tcpp;
-  grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, new_transport,
-                        server);
-}
-
-/* Server callback: destroy the tcp listener (so we don't generate further
-   callbacks) */
-static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
-                    grpc_closure *destroy_done) {
-  grpc_tcp_server *tcp = tcpp;
-  grpc_tcp_server_unref(exec_ctx, tcp);
-  grpc_exec_ctx_enqueue(exec_ctx, destroy_done, true, NULL);
-}
-
-int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
-  grpc_resolved_addresses *resolved = NULL;
-  grpc_tcp_server *tcp = NULL;
-  size_t i;
-  unsigned count = 0;
-  int port_num = -1;
-  int port_temp;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2,
-                 (server, addr));
-
-  resolved = grpc_blocking_resolve_address(addr, "http");
-  if (!resolved) {
-    goto error;
-  }
-
-  tcp = grpc_tcp_server_create(NULL);
-  GPR_ASSERT(tcp);
-
-  for (i = 0; i < resolved->naddrs; i++) {
-    port_temp = grpc_tcp_server_add_port(
-        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
-        resolved->addrs[i].len);
-    if (port_temp > 0) {
-      if (port_num == -1) {
-        port_num = port_temp;
-      } else {
-        GPR_ASSERT(port_num == port_temp);
-      }
-      count++;
-    }
-  }
-  if (count == 0) {
-    gpr_log(GPR_ERROR, "No address added out of total %d resolved",
-            resolved->naddrs);
-    goto error;
-  }
-  if (count != resolved->naddrs) {
-    gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved",
-            count, resolved->naddrs);
-  }
-  grpc_resolved_addresses_destroy(resolved);
-
-  /* Register with the server only upon success */
-  grpc_server_add_listener(&exec_ctx, server, tcp, start, destroy);
-  goto done;
-
-/* Error path: cleanup and return */
-error:
-  if (resolved) {
-    grpc_resolved_addresses_destroy(resolved);
-  }
-  if (tcp) {
-    grpc_tcp_server_unref(&exec_ctx, tcp);
-  }
-  port_num = 0;
-
-done:
-  grpc_exec_ctx_finish(&exec_ctx);
-  return port_num;
-}
diff --git a/src/core/surface/surface_trace.h b/src/core/surface/surface_trace.h
deleted file mode 100644
index ed820eb..0000000
--- a/src/core/surface/surface_trace.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_SURFACE_SURFACE_TRACE_H
-#define GRPC_CORE_SURFACE_SURFACE_TRACE_H
-
-#include "src/core/debug/trace.h"
-#include "src/core/surface/api_trace.h"
-#include <grpc/support/log.h>
-
-#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event)    \
-  if (grpc_api_trace) {                                 \
-    char *_ev = grpc_event_string(event);               \
-    gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
-    gpr_free(_ev);                                      \
-  }
-
-#endif /* GRPC_CORE_SURFACE_SURFACE_TRACE_H */
diff --git a/src/core/surface/validate_metadata.c b/src/core/surface/validate_metadata.c
deleted file mode 100644
index bf41268..0000000
--- a/src/core/surface/validate_metadata.c
+++ /dev/null
@@ -1,73 +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 <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/port_platform.h>
-
-static int conforms_to(const char *s, size_t len, const uint8_t *legal_bits) {
-  const char *p = s;
-  const char *e = s + len;
-  for (; p != e; p++) {
-    int idx = *p;
-    int byte = idx / 8;
-    int bit = idx % 8;
-    if ((legal_bits[byte] & (1 << bit)) == 0) return 0;
-  }
-  return 1;
-}
-
-int grpc_header_key_is_legal(const char *key, size_t length) {
-  static const uint8_t legal_header_bits[256 / 8] = {
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0x00, 0x00, 0x00,
-      0x80, 0xfe, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-  if (length == 0) {
-    return 0;
-  }
-  return conforms_to(key, length, legal_header_bits);
-}
-
-int grpc_header_nonbin_value_is_legal(const char *value, size_t length) {
-  static const uint8_t legal_header_bits[256 / 8] = {
-      0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-      0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-  return conforms_to(value, length, legal_header_bits);
-}
-
-int grpc_is_binary_header(const char *key, size_t length) {
-  if (length < 5) return 0;
-  return 0 == memcmp(key + length - 4, "-bin", 4);
-}
diff --git a/src/core/surface/version.c b/src/core/surface/version.c
deleted file mode 100644
index 7723f39..0000000
--- a/src/core/surface/version.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* This file is autogenerated from:
-   templates/src/core/surface/version.c.template */
-
-#include <grpc/grpc.h>
-
-const char *grpc_version_string(void) { return "0.14.0-dev"; }
diff --git a/src/core/transport/byte_stream.c b/src/core/transport/byte_stream.c
deleted file mode 100644
index 8e6fb2c..0000000
--- a/src/core/transport/byte_stream.c
+++ /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 "src/core/transport/byte_stream.h"
-
-#include <stdlib.h>
-
-#include <grpc/support/log.h>
-
-int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
-                          grpc_byte_stream *byte_stream, gpr_slice *slice,
-                          size_t max_size_hint, grpc_closure *on_complete) {
-  return byte_stream->next(exec_ctx, byte_stream, slice, max_size_hint,
-                           on_complete);
-}
-
-void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
-                              grpc_byte_stream *byte_stream) {
-  byte_stream->destroy(exec_ctx, byte_stream);
-}
-
-/* slice_buffer_stream */
-
-static int slice_buffer_stream_next(grpc_exec_ctx *exec_ctx,
-                                    grpc_byte_stream *byte_stream,
-                                    gpr_slice *slice, size_t max_size_hint,
-                                    grpc_closure *on_complete) {
-  grpc_slice_buffer_stream *stream = (grpc_slice_buffer_stream *)byte_stream;
-  GPR_ASSERT(stream->cursor < stream->backing_buffer->count);
-  *slice = gpr_slice_ref(stream->backing_buffer->slices[stream->cursor]);
-  stream->cursor++;
-  return 1;
-}
-
-static void slice_buffer_stream_destroy(grpc_exec_ctx *exec_ctx,
-                                        grpc_byte_stream *byte_stream) {}
-
-void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream,
-                                   gpr_slice_buffer *slice_buffer,
-                                   uint32_t flags) {
-  GPR_ASSERT(slice_buffer->length <= UINT32_MAX);
-  stream->base.length = (uint32_t)slice_buffer->length;
-  stream->base.flags = flags;
-  stream->base.next = slice_buffer_stream_next;
-  stream->base.destroy = slice_buffer_stream_destroy;
-  stream->backing_buffer = slice_buffer;
-  stream->cursor = 0;
-}
diff --git a/src/core/transport/byte_stream.h b/src/core/transport/byte_stream.h
deleted file mode 100644
index b8d0ade..0000000
--- a/src/core/transport/byte_stream.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_BYTE_STREAM_H
-#define GRPC_CORE_TRANSPORT_BYTE_STREAM_H
-
-#include "src/core/iomgr/exec_ctx.h"
-#include <grpc/support/slice_buffer.h>
-
-/** Internal bit flag for grpc_begin_message's \a flags signaling the use of
- * compression for the message */
-#define GRPC_WRITE_INTERNAL_COMPRESS (0x80000000u)
-/** Mask of all valid internal flags. */
-#define GRPC_WRITE_INTERNAL_USED_MASK (GRPC_WRITE_INTERNAL_COMPRESS)
-
-struct grpc_byte_stream;
-typedef struct grpc_byte_stream grpc_byte_stream;
-
-struct grpc_byte_stream {
-  uint32_t length;
-  uint32_t flags;
-  int (*next)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream,
-              gpr_slice *slice, size_t max_size_hint,
-              grpc_closure *on_complete);
-  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream);
-};
-
-/* returns 1 if the bytes are available immediately (in which case
- * on_complete will not be called), 0 if the bytes will be available
- * asynchronously.
- *
- * on entry, *remaining can be set as a hint as to the maximum number
- * of bytes that would be acceptable to read.
- *
- * fills *buffer, *length, *remaining with the bytes, length of bytes
- * and length of data remaining to be read before either returning 1
- * or calling on_complete.
- *
- * once a slice is returned into *slice, it is owned by the caller.
- */
-int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
-                          grpc_byte_stream *byte_stream, gpr_slice *slice,
-                          size_t max_size_hint, grpc_closure *on_complete);
-
-void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
-                              grpc_byte_stream *byte_stream);
-
-/* grpc_byte_stream that wraps a slice buffer */
-typedef struct grpc_slice_buffer_stream {
-  grpc_byte_stream base;
-  gpr_slice_buffer *backing_buffer;
-  size_t cursor;
-} grpc_slice_buffer_stream;
-
-void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream,
-                                   gpr_slice_buffer *slice_buffer,
-                                   uint32_t flags);
-
-#endif /* GRPC_CORE_TRANSPORT_BYTE_STREAM_H */
diff --git a/src/core/transport/chttp2/alpn.c b/src/core/transport/chttp2/alpn.c
deleted file mode 100644
index 69da4e6..0000000
--- a/src/core/transport/chttp2/alpn.c
+++ /dev/null
@@ -1,56 +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/transport/chttp2/alpn.h"
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-/* in order of preference */
-static const char *const supported_versions[] = {"h2"};
-
-int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size) {
-  size_t i;
-  for (i = 0; i < GPR_ARRAY_SIZE(supported_versions); i++) {
-    if (!strncmp(version, supported_versions[i], size)) return 1;
-  }
-  return 0;
-}
-
-size_t grpc_chttp2_num_alpn_versions(void) {
-  return GPR_ARRAY_SIZE(supported_versions);
-}
-
-const char *grpc_chttp2_get_alpn_version_index(size_t i) {
-  GPR_ASSERT(i < GPR_ARRAY_SIZE(supported_versions));
-  return supported_versions[i];
-}
diff --git a/src/core/transport/chttp2/alpn.h b/src/core/transport/chttp2/alpn.h
deleted file mode 100644
index 68010e3..0000000
--- a/src/core/transport/chttp2/alpn.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_ALPN_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_ALPN_H
-
-#include <string.h>
-
-/* Retuns 1 if the version is supported, 0 otherwise. */
-int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size);
-
-/* Returns the number of protocol versions to advertise */
-size_t grpc_chttp2_num_alpn_versions(void);
-
-/* Returns the protocol version at index i (0 <= i <
- * grpc_chttp2_num_alpn_versions()) */
-const char *grpc_chttp2_get_alpn_version_index(size_t i);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_ALPN_H */
diff --git a/src/core/transport/chttp2/bin_encoder.c b/src/core/transport/chttp2/bin_encoder.c
deleted file mode 100644
index f26bc7e..0000000
--- a/src/core/transport/chttp2/bin_encoder.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- *
- * 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/transport/chttp2/bin_encoder.h"
-
-#include <string.h>
-
-#include "src/core/transport/chttp2/huffsyms.h"
-#include <grpc/support/log.h>
-
-static const char alphabet[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-typedef struct {
-  uint16_t bits;
-  uint8_t length;
-} b64_huff_sym;
-
-static const b64_huff_sym huff_alphabet[64] = {{0x21, 6},
-                                               {0x5d, 7},
-                                               {0x5e, 7},
-                                               {0x5f, 7},
-                                               {0x60, 7},
-                                               {0x61, 7},
-                                               {0x62, 7},
-                                               {0x63, 7},
-                                               {0x64, 7},
-                                               {0x65, 7},
-                                               {0x66, 7},
-                                               {0x67, 7},
-                                               {0x68, 7},
-                                               {0x69, 7},
-                                               {0x6a, 7},
-                                               {0x6b, 7},
-                                               {0x6c, 7},
-                                               {0x6d, 7},
-                                               {0x6e, 7},
-                                               {0x6f, 7},
-                                               {0x70, 7},
-                                               {0x71, 7},
-                                               {0x72, 7},
-                                               {0xfc, 8},
-                                               {0x73, 7},
-                                               {0xfd, 8},
-                                               {0x3, 5},
-                                               {0x23, 6},
-                                               {0x4, 5},
-                                               {0x24, 6},
-                                               {0x5, 5},
-                                               {0x25, 6},
-                                               {0x26, 6},
-                                               {0x27, 6},
-                                               {0x6, 5},
-                                               {0x74, 7},
-                                               {0x75, 7},
-                                               {0x28, 6},
-                                               {0x29, 6},
-                                               {0x2a, 6},
-                                               {0x7, 5},
-                                               {0x2b, 6},
-                                               {0x76, 7},
-                                               {0x2c, 6},
-                                               {0x8, 5},
-                                               {0x9, 5},
-                                               {0x2d, 6},
-                                               {0x77, 7},
-                                               {0x78, 7},
-                                               {0x79, 7},
-                                               {0x7a, 7},
-                                               {0x7b, 7},
-                                               {0x0, 5},
-                                               {0x1, 5},
-                                               {0x2, 5},
-                                               {0x19, 6},
-                                               {0x1a, 6},
-                                               {0x1b, 6},
-                                               {0x1c, 6},
-                                               {0x1d, 6},
-                                               {0x1e, 6},
-                                               {0x1f, 6},
-                                               {0x7fb, 11},
-                                               {0x18, 6}};
-
-static const uint8_t tail_xtra[3] = {0, 2, 3};
-
-gpr_slice grpc_chttp2_base64_encode(gpr_slice input) {
-  size_t input_length = GPR_SLICE_LENGTH(input);
-  size_t input_triplets = input_length / 3;
-  size_t tail_case = input_length % 3;
-  size_t output_length = input_triplets * 4 + tail_xtra[tail_case];
-  gpr_slice output = gpr_slice_malloc(output_length);
-  uint8_t *in = GPR_SLICE_START_PTR(input);
-  char *out = (char *)GPR_SLICE_START_PTR(output);
-  size_t i;
-
-  /* encode full triplets */
-  for (i = 0; i < input_triplets; i++) {
-    out[0] = alphabet[in[0] >> 2];
-    out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
-    out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)];
-    out[3] = alphabet[in[2] & 0x3f];
-    out += 4;
-    in += 3;
-  }
-
-  /* encode the remaining bytes */
-  switch (tail_case) {
-    case 0:
-      break;
-    case 1:
-      out[0] = alphabet[in[0] >> 2];
-      out[1] = alphabet[(in[0] & 0x3) << 4];
-      out += 2;
-      in += 1;
-      break;
-    case 2:
-      out[0] = alphabet[in[0] >> 2];
-      out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
-      out[2] = alphabet[(in[1] & 0xf) << 2];
-      out += 3;
-      in += 2;
-      break;
-  }
-
-  GPR_ASSERT(out == (char *)GPR_SLICE_END_PTR(output));
-  GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
-  return output;
-}
-
-gpr_slice grpc_chttp2_huffman_compress(gpr_slice input) {
-  size_t nbits;
-  uint8_t *in;
-  uint8_t *out;
-  gpr_slice output;
-  uint32_t temp = 0;
-  uint32_t temp_length = 0;
-
-  nbits = 0;
-  for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
-    nbits += grpc_chttp2_huffsyms[*in].length;
-  }
-
-  output = gpr_slice_malloc(nbits / 8 + (nbits % 8 != 0));
-  out = GPR_SLICE_START_PTR(output);
-  for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
-    int sym = *in;
-    temp <<= grpc_chttp2_huffsyms[sym].length;
-    temp |= grpc_chttp2_huffsyms[sym].bits;
-    temp_length += grpc_chttp2_huffsyms[sym].length;
-
-    while (temp_length > 8) {
-      temp_length -= 8;
-      *out++ = (uint8_t)(temp >> temp_length);
-    }
-  }
-
-  if (temp_length) {
-    /* NB: the following integer arithmetic operation needs to be in its
-     * expanded form due to the "integral promotion" performed (see section
-     * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
-     * is then required to avoid the compiler warning */
-    *out++ = (uint8_t)((uint8_t)(temp << (8u - temp_length)) |
-                       (uint8_t)(0xffu >> temp_length));
-  }
-
-  GPR_ASSERT(out == GPR_SLICE_END_PTR(output));
-
-  return output;
-}
-
-typedef struct {
-  uint32_t temp;
-  uint32_t temp_length;
-  uint8_t *out;
-} huff_out;
-
-static void enc_flush_some(huff_out *out) {
-  while (out->temp_length > 8) {
-    out->temp_length -= 8;
-    *out->out++ = (uint8_t)(out->temp >> out->temp_length);
-  }
-}
-
-static void enc_add2(huff_out *out, uint8_t a, uint8_t b) {
-  b64_huff_sym sa = huff_alphabet[a];
-  b64_huff_sym sb = huff_alphabet[b];
-  out->temp = (out->temp << (sa.length + sb.length)) |
-              ((uint32_t)sa.bits << sb.length) | sb.bits;
-  out->temp_length += (uint32_t)sa.length + (uint32_t)sb.length;
-  enc_flush_some(out);
-}
-
-static void enc_add1(huff_out *out, uint8_t a) {
-  b64_huff_sym sa = huff_alphabet[a];
-  out->temp = (out->temp << sa.length) | sa.bits;
-  out->temp_length += sa.length;
-  enc_flush_some(out);
-}
-
-gpr_slice grpc_chttp2_base64_encode_and_huffman_compress(gpr_slice input) {
-  size_t input_length = GPR_SLICE_LENGTH(input);
-  size_t input_triplets = input_length / 3;
-  size_t tail_case = input_length % 3;
-  size_t output_syms = input_triplets * 4 + tail_xtra[tail_case];
-  size_t max_output_bits = 11 * output_syms;
-  size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0);
-  gpr_slice output = gpr_slice_malloc(max_output_length);
-  uint8_t *in = GPR_SLICE_START_PTR(input);
-  uint8_t *start_out = GPR_SLICE_START_PTR(output);
-  huff_out out;
-  size_t i;
-
-  out.temp = 0;
-  out.temp_length = 0;
-  out.out = start_out;
-
-  /* encode full triplets */
-  for (i = 0; i < input_triplets; i++) {
-    enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4) | (in[1] >> 4));
-    enc_add2(&out, (uint8_t)((in[1] & 0xf) << 2) | (in[2] >> 6),
-             (uint8_t)(in[2] & 0x3f));
-    in += 3;
-  }
-
-  /* encode the remaining bytes */
-  switch (tail_case) {
-    case 0:
-      break;
-    case 1:
-      enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4));
-      in += 1;
-      break;
-    case 2:
-      enc_add2(&out, in[0] >> 2,
-               (uint8_t)((in[0] & 0x3) << 4) | (uint8_t)(in[1] >> 4));
-      enc_add1(&out, (uint8_t)((in[1] & 0xf) << 2));
-      in += 2;
-      break;
-  }
-
-  if (out.temp_length) {
-    /* NB: the following integer arithmetic operation needs to be in its
-     * expanded form due to the "integral promotion" performed (see section
-     * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
-     * is then required to avoid the compiler warning */
-    *out.out++ = (uint8_t)((uint8_t)(out.temp << (8u - out.temp_length)) |
-                           (uint8_t)(0xffu >> out.temp_length));
-  }
-
-  GPR_ASSERT(out.out <= GPR_SLICE_END_PTR(output));
-  GPR_SLICE_SET_LENGTH(output, out.out - start_out);
-
-  GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
-  return output;
-}
diff --git a/src/core/transport/chttp2/bin_encoder.h b/src/core/transport/chttp2/bin_encoder.h
deleted file mode 100644
index edb6f2d..0000000
--- a/src/core/transport/chttp2/bin_encoder.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_BIN_ENCODER_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_BIN_ENCODER_H
-
-#include <grpc/support/slice.h>
-
-/* base64 encode a slice. Returns a new slice, does not take ownership of the
-   input */
-gpr_slice grpc_chttp2_base64_encode(gpr_slice input);
-
-/* Compress a slice with the static huffman encoder detailed in the hpack
-   standard. Returns a new slice, does not take ownership of the input */
-gpr_slice grpc_chttp2_huffman_compress(gpr_slice input);
-
-/* equivalent to:
-   gpr_slice x = grpc_chttp2_base64_encode(input);
-   gpr_slice y = grpc_chttp2_huffman_compress(x);
-   gpr_slice_unref(x);
-   return y; */
-gpr_slice grpc_chttp2_base64_encode_and_huffman_compress(gpr_slice input);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_BIN_ENCODER_H */
diff --git a/src/core/transport/chttp2/frame.h b/src/core/transport/chttp2/frame.h
deleted file mode 100644
index 560a667..0000000
--- a/src/core/transport/chttp2/frame.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_FRAME_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_FRAME_H
-
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice.h>
-
-/* Common definitions for frame handling in the chttp2 transport */
-
-typedef enum {
-  GRPC_CHTTP2_PARSE_OK,
-  GRPC_CHTTP2_STREAM_ERROR,
-  GRPC_CHTTP2_CONNECTION_ERROR
-} grpc_chttp2_parse_error;
-
-/* defined in internal.h */
-typedef struct grpc_chttp2_stream_parsing grpc_chttp2_stream_parsing;
-typedef struct grpc_chttp2_transport_parsing grpc_chttp2_transport_parsing;
-
-#define GRPC_CHTTP2_FRAME_DATA 0
-#define GRPC_CHTTP2_FRAME_HEADER 1
-#define GRPC_CHTTP2_FRAME_CONTINUATION 9
-#define GRPC_CHTTP2_FRAME_RST_STREAM 3
-#define GRPC_CHTTP2_FRAME_SETTINGS 4
-#define GRPC_CHTTP2_FRAME_PING 6
-#define GRPC_CHTTP2_FRAME_GOAWAY 7
-#define GRPC_CHTTP2_FRAME_WINDOW_UPDATE 8
-
-#define GRPC_CHTTP2_MAX_PAYLOAD_LENGTH ((1 << 14) - 1)
-
-#define GRPC_CHTTP2_DATA_FLAG_END_STREAM 1
-#define GRPC_CHTTP2_FLAG_ACK 1
-#define GRPC_CHTTP2_DATA_FLAG_END_HEADERS 4
-#define GRPC_CHTTP2_DATA_FLAG_PADDED 8
-#define GRPC_CHTTP2_FLAG_HAS_PRIORITY 0x20
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_FRAME_H */
diff --git a/src/core/transport/chttp2/frame_data.c b/src/core/transport/chttp2/frame_data.c
deleted file mode 100644
index f9a1af8..0000000
--- a/src/core/transport/chttp2/frame_data.c
+++ /dev/null
@@ -1,248 +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/transport/chttp2/frame_data.h"
-
-#include <string.h>
-
-#include "src/core/transport/chttp2/internal.h"
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-#include "src/core/transport/transport.h"
-
-grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
-    grpc_chttp2_data_parser *parser) {
-  parser->state = GRPC_CHTTP2_DATA_FH_0;
-  parser->parsing_frame = NULL;
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
-                                     grpc_chttp2_data_parser *parser) {
-  grpc_byte_stream *bs;
-  if (parser->parsing_frame) {
-    grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame,
-                                              0, 1);
-  }
-  while (
-      (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
-    grpc_byte_stream_destroy(exec_ctx, bs);
-  }
-}
-
-grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
-    grpc_chttp2_data_parser *parser, uint8_t flags) {
-  if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
-    gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
-    return GRPC_CHTTP2_STREAM_ERROR;
-  }
-
-  if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
-    parser->is_last_frame = 1;
-  } else {
-    parser->is_last_frame = 0;
-  }
-
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-void grpc_chttp2_incoming_frame_queue_merge(
-    grpc_chttp2_incoming_frame_queue *head_dst,
-    grpc_chttp2_incoming_frame_queue *tail_src) {
-  if (tail_src->head == NULL) {
-    return;
-  }
-
-  if (head_dst->head == NULL) {
-    *head_dst = *tail_src;
-    memset(tail_src, 0, sizeof(*tail_src));
-    return;
-  }
-
-  head_dst->tail->next_message = tail_src->head;
-  head_dst->tail = tail_src->tail;
-  memset(tail_src, 0, sizeof(*tail_src));
-}
-
-grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
-    grpc_chttp2_incoming_frame_queue *q) {
-  grpc_byte_stream *out;
-  if (q->head == NULL) {
-    return NULL;
-  }
-  out = &q->head->base;
-  if (q->head == q->tail) {
-    memset(q, 0, sizeof(*q));
-  } else {
-    q->head = q->head->next_message;
-  }
-  return out;
-}
-
-void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf,
-                             uint32_t write_bytes, int is_eof,
-                             gpr_slice_buffer *outbuf) {
-  gpr_slice hdr;
-  uint8_t *p;
-
-  hdr = gpr_slice_malloc(9);
-  p = GPR_SLICE_START_PTR(hdr);
-  GPR_ASSERT(write_bytes < (1 << 24));
-  *p++ = (uint8_t)(write_bytes >> 16);
-  *p++ = (uint8_t)(write_bytes >> 8);
-  *p++ = (uint8_t)(write_bytes);
-  *p++ = GRPC_CHTTP2_FRAME_DATA;
-  *p++ = is_eof ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0;
-  *p++ = (uint8_t)(id >> 24);
-  *p++ = (uint8_t)(id >> 16);
-  *p++ = (uint8_t)(id >> 8);
-  *p++ = (uint8_t)(id);
-  gpr_slice_buffer_add(outbuf, hdr);
-
-  gpr_slice_buffer_move_first(inbuf, write_bytes, outbuf);
-}
-
-grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
-  uint8_t *const end = GPR_SLICE_END_PTR(slice);
-  uint8_t *cur = beg;
-  grpc_chttp2_data_parser *p = parser;
-  uint32_t message_flags;
-  grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
-
-  if (is_last && p->is_last_frame) {
-    stream_parsing->received_close = 1;
-  }
-
-  if (cur == end) {
-    return GRPC_CHTTP2_PARSE_OK;
-  }
-
-  switch (p->state) {
-  fh_0:
-    case GRPC_CHTTP2_DATA_FH_0:
-      p->frame_type = *cur;
-      switch (p->frame_type) {
-        case 0:
-          p->is_frame_compressed = 0; /* GPR_FALSE */
-          break;
-        case 1:
-          p->is_frame_compressed = 1; /* GPR_TRUE */
-          break;
-        default:
-          gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
-          return GRPC_CHTTP2_STREAM_ERROR;
-      }
-      if (++cur == end) {
-        p->state = GRPC_CHTTP2_DATA_FH_1;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-    /* fallthrough */
-    case GRPC_CHTTP2_DATA_FH_1:
-      p->frame_size = ((uint32_t)*cur) << 24;
-      if (++cur == end) {
-        p->state = GRPC_CHTTP2_DATA_FH_2;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-    /* fallthrough */
-    case GRPC_CHTTP2_DATA_FH_2:
-      p->frame_size |= ((uint32_t)*cur) << 16;
-      if (++cur == end) {
-        p->state = GRPC_CHTTP2_DATA_FH_3;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-    /* fallthrough */
-    case GRPC_CHTTP2_DATA_FH_3:
-      p->frame_size |= ((uint32_t)*cur) << 8;
-      if (++cur == end) {
-        p->state = GRPC_CHTTP2_DATA_FH_4;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-    /* fallthrough */
-    case GRPC_CHTTP2_DATA_FH_4:
-      p->frame_size |= ((uint32_t)*cur);
-      p->state = GRPC_CHTTP2_DATA_FRAME;
-      ++cur;
-      message_flags = 0;
-      if (p->is_frame_compressed) {
-        message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
-      }
-      p->parsing_frame = incoming_byte_stream =
-          grpc_chttp2_incoming_byte_stream_create(
-              exec_ctx, transport_parsing, stream_parsing, p->frame_size,
-              message_flags, &p->incoming_frames);
-    /* fallthrough */
-    case GRPC_CHTTP2_DATA_FRAME:
-      if (cur == end) {
-        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
-                                                 stream_parsing);
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
-                                               stream_parsing);
-      if ((uint32_t)(end - cur) == p->frame_size) {
-        grpc_chttp2_incoming_byte_stream_push(
-            exec_ctx, p->parsing_frame,
-            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
-        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
-                                                  1);
-        p->parsing_frame = NULL;
-        p->state = GRPC_CHTTP2_DATA_FH_0;
-        return GRPC_CHTTP2_PARSE_OK;
-      } else if ((uint32_t)(end - cur) > p->frame_size) {
-        grpc_chttp2_incoming_byte_stream_push(
-            exec_ctx, p->parsing_frame,
-            gpr_slice_sub(slice, (size_t)(cur - beg),
-                          (size_t)(cur + p->frame_size - beg)));
-        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
-                                                  1);
-        p->parsing_frame = NULL;
-        cur += p->frame_size;
-        goto fh_0; /* loop */
-      } else {
-        grpc_chttp2_incoming_byte_stream_push(
-            exec_ctx, p->parsing_frame,
-            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
-        GPR_ASSERT((size_t)(end - cur) <= p->frame_size);
-        p->frame_size -= (uint32_t)(end - cur);
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-  }
-
-  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
-}
diff --git a/src/core/transport/chttp2/frame_data.h b/src/core/transport/chttp2/frame_data.h
deleted file mode 100644
index 92929d5..0000000
--- a/src/core/transport/chttp2/frame_data.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_FRAME_DATA_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_FRAME_DATA_H
-
-/* Parser for GRPC streams embedded in DATA frames */
-
-#include "src/core/iomgr/exec_ctx.h"
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-#include "src/core/transport/byte_stream.h"
-#include "src/core/transport/chttp2/frame.h"
-
-typedef enum {
-  GRPC_CHTTP2_DATA_FH_0,
-  GRPC_CHTTP2_DATA_FH_1,
-  GRPC_CHTTP2_DATA_FH_2,
-  GRPC_CHTTP2_DATA_FH_3,
-  GRPC_CHTTP2_DATA_FH_4,
-  GRPC_CHTTP2_DATA_FRAME
-} grpc_chttp2_stream_state;
-
-typedef struct grpc_chttp2_incoming_byte_stream
-    grpc_chttp2_incoming_byte_stream;
-
-typedef struct grpc_chttp2_incoming_frame_queue {
-  grpc_chttp2_incoming_byte_stream *head;
-  grpc_chttp2_incoming_byte_stream *tail;
-} grpc_chttp2_incoming_frame_queue;
-
-typedef struct {
-  grpc_chttp2_stream_state state;
-  uint8_t is_last_frame;
-  uint8_t frame_type;
-  uint32_t frame_size;
-
-  int is_frame_compressed;
-  grpc_chttp2_incoming_frame_queue incoming_frames;
-  grpc_chttp2_incoming_byte_stream *parsing_frame;
-} grpc_chttp2_data_parser;
-
-void grpc_chttp2_incoming_frame_queue_merge(
-    grpc_chttp2_incoming_frame_queue *head_dst,
-    grpc_chttp2_incoming_frame_queue *tail_src);
-grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
-    grpc_chttp2_incoming_frame_queue *q);
-
-/* initialize per-stream state for data frame parsing */
-grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
-    grpc_chttp2_data_parser *parser);
-
-void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
-                                     grpc_chttp2_data_parser *parser);
-
-/* start processing a new data frame */
-grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
-    grpc_chttp2_data_parser *parser, uint8_t flags);
-
-/* handle a slice of a data frame - is_last indicates the last slice of a
-   frame */
-grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf,
-                             uint32_t write_bytes, int is_eof,
-                             gpr_slice_buffer *outbuf);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_FRAME_DATA_H */
diff --git a/src/core/transport/chttp2/frame_goaway.c b/src/core/transport/chttp2/frame_goaway.c
deleted file mode 100644
index 2fa525e..0000000
--- a/src/core/transport/chttp2/frame_goaway.c
+++ /dev/null
@@ -1,193 +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/transport/chttp2/frame_goaway.h"
-#include "src/core/transport/chttp2/internal.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) {
-  p->debug_data = NULL;
-}
-
-void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p) {
-  gpr_free(p->debug_data);
-}
-
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
-    grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) {
-  if (length < 8) {
-    gpr_log(GPR_ERROR, "goaway frame too short (%d bytes)", length);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  }
-
-  gpr_free(p->debug_data);
-  p->debug_length = length - 8;
-  p->debug_data = gpr_malloc(p->debug_length);
-  p->debug_pos = 0;
-  p->state = GRPC_CHTTP2_GOAWAY_LSI0;
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
-  uint8_t *const end = GPR_SLICE_END_PTR(slice);
-  uint8_t *cur = beg;
-  grpc_chttp2_goaway_parser *p = parser;
-
-  switch (p->state) {
-    case GRPC_CHTTP2_GOAWAY_LSI0:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_LSI0;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->last_stream_id = ((uint32_t)*cur) << 24;
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_LSI1:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_LSI1;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->last_stream_id |= ((uint32_t)*cur) << 16;
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_LSI2:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_LSI2;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->last_stream_id |= ((uint32_t)*cur) << 8;
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_LSI3:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_LSI3;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->last_stream_id |= ((uint32_t)*cur);
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_ERR0:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_ERR0;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->error_code = ((uint32_t)*cur) << 24;
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_ERR1:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_ERR1;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->error_code |= ((uint32_t)*cur) << 16;
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_ERR2:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_ERR2;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->error_code |= ((uint32_t)*cur) << 8;
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_ERR3:
-      if (cur == end) {
-        p->state = GRPC_CHTTP2_GOAWAY_ERR3;
-        return GRPC_CHTTP2_PARSE_OK;
-      }
-      p->error_code |= ((uint32_t)*cur);
-      ++cur;
-    /* fallthrough */
-    case GRPC_CHTTP2_GOAWAY_DEBUG:
-      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;
-      if (is_last) {
-        transport_parsing->goaway_received = 1;
-        transport_parsing->goaway_last_stream_index = p->last_stream_id;
-        gpr_slice_unref(transport_parsing->goaway_text);
-        transport_parsing->goaway_error = (grpc_status_code)p->error_code;
-        transport_parsing->goaway_text =
-            gpr_slice_new(p->debug_data, p->debug_length, gpr_free);
-        p->debug_data = NULL;
-      }
-      return GRPC_CHTTP2_PARSE_OK;
-  }
-  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
-}
-
-void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,
-                               gpr_slice debug_data,
-                               gpr_slice_buffer *slice_buffer) {
-  gpr_slice header = gpr_slice_malloc(9 + 4 + 4);
-  uint8_t *p = GPR_SLICE_START_PTR(header);
-  uint32_t frame_length;
-  GPR_ASSERT(GPR_SLICE_LENGTH(debug_data) < UINT32_MAX - 4 - 4);
-  frame_length = 4 + 4 + (uint32_t)GPR_SLICE_LENGTH(debug_data);
-
-  /* frame header: length */
-  *p++ = (uint8_t)(frame_length >> 16);
-  *p++ = (uint8_t)(frame_length >> 8);
-  *p++ = (uint8_t)(frame_length);
-  /* frame header: type */
-  *p++ = GRPC_CHTTP2_FRAME_GOAWAY;
-  /* frame header: flags */
-  *p++ = 0;
-  /* frame header: stream id */
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  /* payload: last stream id */
-  *p++ = (uint8_t)(last_stream_id >> 24);
-  *p++ = (uint8_t)(last_stream_id >> 16);
-  *p++ = (uint8_t)(last_stream_id >> 8);
-  *p++ = (uint8_t)(last_stream_id);
-  /* payload: error code */
-  *p++ = (uint8_t)(error_code >> 24);
-  *p++ = (uint8_t)(error_code >> 16);
-  *p++ = (uint8_t)(error_code >> 8);
-  *p++ = (uint8_t)(error_code);
-  GPR_ASSERT(p == GPR_SLICE_END_PTR(header));
-  gpr_slice_buffer_add(slice_buffer, header);
-  gpr_slice_buffer_add(slice_buffer, debug_data);
-}
diff --git a/src/core/transport/chttp2/frame_goaway.h b/src/core/transport/chttp2/frame_goaway.h
deleted file mode 100644
index 616287e..0000000
--- a/src/core/transport/chttp2/frame_goaway.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_FRAME_GOAWAY_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_FRAME_GOAWAY_H
-
-#include "src/core/iomgr/exec_ctx.h"
-#include "src/core/transport/chttp2/frame.h"
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-
-typedef enum {
-  GRPC_CHTTP2_GOAWAY_LSI0,
-  GRPC_CHTTP2_GOAWAY_LSI1,
-  GRPC_CHTTP2_GOAWAY_LSI2,
-  GRPC_CHTTP2_GOAWAY_LSI3,
-  GRPC_CHTTP2_GOAWAY_ERR0,
-  GRPC_CHTTP2_GOAWAY_ERR1,
-  GRPC_CHTTP2_GOAWAY_ERR2,
-  GRPC_CHTTP2_GOAWAY_ERR3,
-  GRPC_CHTTP2_GOAWAY_DEBUG
-} grpc_chttp2_goaway_parse_state;
-
-typedef struct {
-  grpc_chttp2_goaway_parse_state state;
-  uint32_t last_stream_id;
-  uint32_t error_code;
-  char *debug_data;
-  uint32_t debug_length;
-  uint32_t debug_pos;
-} grpc_chttp2_goaway_parser;
-
-void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p);
-void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p);
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
-    grpc_chttp2_goaway_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,
-                               gpr_slice debug_data,
-                               gpr_slice_buffer *slice_buffer);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_FRAME_GOAWAY_H */
diff --git a/src/core/transport/chttp2/frame_ping.c b/src/core/transport/chttp2/frame_ping.c
deleted file mode 100644
index c6ab522..0000000
--- a/src/core/transport/chttp2/frame_ping.c
+++ /dev/null
@@ -1,97 +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/transport/chttp2/frame_ping.h"
-#include "src/core/transport/chttp2/internal.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
-  gpr_slice slice = gpr_slice_malloc(9 + 8);
-  uint8_t *p = GPR_SLICE_START_PTR(slice);
-
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 8;
-  *p++ = GRPC_CHTTP2_FRAME_PING;
-  *p++ = ack ? 1 : 0;
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  memcpy(p, opaque_8bytes, 8);
-
-  return slice;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
-    grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags) {
-  if (flags & 0xfe || length != 8) {
-    gpr_log(GPR_ERROR, "invalid ping: length=%d, flags=%02x", length, flags);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  }
-  parser->byte = 0;
-  parser->is_ack = flags;
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
-  uint8_t *const end = GPR_SLICE_END_PTR(slice);
-  uint8_t *cur = beg;
-  grpc_chttp2_ping_parser *p = parser;
-
-  while (p->byte != 8 && cur != end) {
-    p->opaque_8bytes[p->byte] = *cur;
-    cur++;
-    p->byte++;
-  }
-
-  if (p->byte == 8) {
-    GPR_ASSERT(is_last);
-    if (p->is_ack) {
-      grpc_chttp2_ack_ping(exec_ctx, transport_parsing, p->opaque_8bytes);
-    } else {
-      gpr_slice_buffer_add(&transport_parsing->qbuf,
-                           grpc_chttp2_ping_create(1, p->opaque_8bytes));
-    }
-  }
-
-  return GRPC_CHTTP2_PARSE_OK;
-}
diff --git a/src/core/transport/chttp2/frame_ping.h b/src/core/transport/chttp2/frame_ping.h
deleted file mode 100644
index fc4dd7a..0000000
--- a/src/core/transport/chttp2/frame_ping.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_FRAME_PING_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_FRAME_PING_H
-
-#include "src/core/iomgr/exec_ctx.h"
-#include <grpc/support/slice.h>
-#include "src/core/transport/chttp2/frame.h"
-
-typedef struct {
-  uint8_t byte;
-  uint8_t is_ack;
-  uint8_t opaque_8bytes[8];
-} grpc_chttp2_ping_parser;
-
-gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes);
-
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
-    grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_FRAME_PING_H */
diff --git a/src/core/transport/chttp2/frame_rst_stream.c b/src/core/transport/chttp2/frame_rst_stream.c
deleted file mode 100644
index 754529e..0000000
--- a/src/core/transport/chttp2/frame_rst_stream.c
+++ /dev/null
@@ -1,99 +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/transport/chttp2/frame_rst_stream.h"
-#include "src/core/transport/chttp2/internal.h"
-
-#include <grpc/support/log.h>
-
-#include "src/core/transport/chttp2/frame.h"
-
-gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code) {
-  gpr_slice slice = gpr_slice_malloc(13);
-  uint8_t *p = GPR_SLICE_START_PTR(slice);
-
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 4;
-  *p++ = GRPC_CHTTP2_FRAME_RST_STREAM;
-  *p++ = 0;
-  *p++ = (uint8_t)(id >> 24);
-  *p++ = (uint8_t)(id >> 16);
-  *p++ = (uint8_t)(id >> 8);
-  *p++ = (uint8_t)(id);
-  *p++ = (uint8_t)(code >> 24);
-  *p++ = (uint8_t)(code >> 16);
-  *p++ = (uint8_t)(code >> 8);
-  *p++ = (uint8_t)(code);
-
-  return slice;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
-    grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags) {
-  if (length != 4) {
-    gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length,
-            flags);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  }
-  parser->byte = 0;
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
-  uint8_t *const end = GPR_SLICE_END_PTR(slice);
-  uint8_t *cur = beg;
-  grpc_chttp2_rst_stream_parser *p = parser;
-
-  while (p->byte != 4 && cur != end) {
-    p->reason_bytes[p->byte] = *cur;
-    cur++;
-    p->byte++;
-  }
-
-  if (p->byte == 4) {
-    GPR_ASSERT(is_last);
-    stream_parsing->received_close = 1;
-    stream_parsing->saw_rst_stream = 1;
-    stream_parsing->rst_stream_reason = (((uint32_t)p->reason_bytes[0]) << 24) |
-                                        (((uint32_t)p->reason_bytes[1]) << 16) |
-                                        (((uint32_t)p->reason_bytes[2]) << 8) |
-                                        (((uint32_t)p->reason_bytes[3]));
-  }
-
-  return GRPC_CHTTP2_PARSE_OK;
-}
diff --git a/src/core/transport/chttp2/frame_rst_stream.h b/src/core/transport/chttp2/frame_rst_stream.h
deleted file mode 100644
index d563a22..0000000
--- a/src/core/transport/chttp2/frame_rst_stream.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H
-
-#include <grpc/support/slice.h>
-#include "src/core/transport/chttp2/frame.h"
-#include "src/core/iomgr/exec_ctx.h"
-
-typedef struct {
-  uint8_t byte;
-  uint8_t reason_bytes[4];
-} grpc_chttp2_rst_stream_parser;
-
-gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code);
-
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
-    grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H */
diff --git a/src/core/transport/chttp2/frame_settings.c b/src/core/transport/chttp2/frame_settings.c
deleted file mode 100644
index cc49dd4..0000000
--- a/src/core/transport/chttp2/frame_settings.c
+++ /dev/null
@@ -1,259 +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/transport/chttp2/frame_settings.h"
-#include "src/core/transport/chttp2/internal.h"
-
-#include <string.h>
-
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/debug/trace.h"
-#include "src/core/transport/chttp2/frame.h"
-#include "src/core/transport/chttp2/http2_errors.h"
-#include "src/core/transport/chttp2_transport.h"
-
-#define MAX_MAX_HEADER_LIST_SIZE (1024 * 1024 * 1024)
-
-/* HTTP/2 mandated initial connection settings */
-const grpc_chttp2_setting_parameters
-    grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {
-        {NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
-         GRPC_CHTTP2_PROTOCOL_ERROR},
-        {"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff,
-         GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
-        {"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
-         GRPC_CHTTP2_PROTOCOL_ERROR},
-        {"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu,
-         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
-        {"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu,
-         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
-         GRPC_CHTTP2_FLOW_CONTROL_ERROR},
-        {"MAX_FRAME_SIZE", 16384, 16384, 16777215,
-         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
-        {"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0,
-         MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE,
-         GRPC_CHTTP2_PROTOCOL_ERROR},
-};
-
-static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) {
-  *out++ = (uint8_t)(length >> 16);
-  *out++ = (uint8_t)(length >> 8);
-  *out++ = (uint8_t)(length);
-  *out++ = GRPC_CHTTP2_FRAME_SETTINGS;
-  *out++ = flags;
-  *out++ = 0;
-  *out++ = 0;
-  *out++ = 0;
-  *out++ = 0;
-  return out;
-}
-
-gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
-                                      uint32_t force_mask, size_t count) {
-  size_t i;
-  uint32_t n = 0;
-  gpr_slice output;
-  uint8_t *p;
-
-  for (i = 0; i < count; i++) {
-    n += (new[i] != old[i] || (force_mask & (1u << i)) != 0);
-  }
-
-  output = gpr_slice_malloc(9 + 6 * n);
-  p = fill_header(GPR_SLICE_START_PTR(output), 6 * n, 0);
-
-  for (i = 0; i < count; i++) {
-    if (new[i] != old[i] || (force_mask & (1u << i)) != 0) {
-      GPR_ASSERT(i);
-      *p++ = (uint8_t)(i >> 8);
-      *p++ = (uint8_t)(i);
-      *p++ = (uint8_t)(new[i] >> 24);
-      *p++ = (uint8_t)(new[i] >> 16);
-      *p++ = (uint8_t)(new[i] >> 8);
-      *p++ = (uint8_t)(new[i]);
-      old[i] = new[i];
-    }
-  }
-
-  GPR_ASSERT(p == GPR_SLICE_END_PTR(output));
-
-  return output;
-}
-
-gpr_slice grpc_chttp2_settings_ack_create(void) {
-  gpr_slice output = gpr_slice_malloc(9);
-  fill_header(GPR_SLICE_START_PTR(output), 0, GRPC_CHTTP2_FLAG_ACK);
-  return output;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
-    grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
-    uint32_t *settings) {
-  parser->target_settings = settings;
-  memcpy(parser->incoming_settings, settings,
-         GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
-  parser->is_ack = 0;
-  parser->state = GRPC_CHTTP2_SPS_ID0;
-  if (flags == GRPC_CHTTP2_FLAG_ACK) {
-    parser->is_ack = 1;
-    if (length != 0) {
-      gpr_log(GPR_ERROR, "non-empty settings ack frame received");
-      return GRPC_CHTTP2_CONNECTION_ERROR;
-    }
-    return GRPC_CHTTP2_PARSE_OK;
-  } else if (flags != 0) {
-    gpr_log(GPR_ERROR, "invalid flags on settings frame");
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  } else if (length % 6 != 0) {
-    gpr_log(GPR_ERROR, "settings frames must be a multiple of six bytes");
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  } else {
-    return GRPC_CHTTP2_PARSE_OK;
-  }
-}
-
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *p,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  grpc_chttp2_settings_parser *parser = p;
-  const uint8_t *cur = GPR_SLICE_START_PTR(slice);
-  const uint8_t *end = GPR_SLICE_END_PTR(slice);
-
-  if (parser->is_ack) {
-    return GRPC_CHTTP2_PARSE_OK;
-  }
-
-  for (;;) {
-    switch (parser->state) {
-      case GRPC_CHTTP2_SPS_ID0:
-        if (cur == end) {
-          parser->state = GRPC_CHTTP2_SPS_ID0;
-          if (is_last) {
-            transport_parsing->settings_updated = 1;
-            memcpy(parser->target_settings, parser->incoming_settings,
-                   GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
-            gpr_slice_buffer_add(&transport_parsing->qbuf,
-                                 grpc_chttp2_settings_ack_create());
-          }
-          return GRPC_CHTTP2_PARSE_OK;
-        }
-        parser->id = (uint16_t)(((uint16_t)*cur) << 8);
-        cur++;
-      /* fallthrough */
-      case GRPC_CHTTP2_SPS_ID1:
-        if (cur == end) {
-          parser->state = GRPC_CHTTP2_SPS_ID1;
-          return GRPC_CHTTP2_PARSE_OK;
-        }
-        parser->id = (uint16_t)(parser->id | (*cur));
-        cur++;
-      /* fallthrough */
-      case GRPC_CHTTP2_SPS_VAL0:
-        if (cur == end) {
-          parser->state = GRPC_CHTTP2_SPS_VAL0;
-          return GRPC_CHTTP2_PARSE_OK;
-        }
-        parser->value = ((uint32_t)*cur) << 24;
-        cur++;
-      /* fallthrough */
-      case GRPC_CHTTP2_SPS_VAL1:
-        if (cur == end) {
-          parser->state = GRPC_CHTTP2_SPS_VAL1;
-          return GRPC_CHTTP2_PARSE_OK;
-        }
-        parser->value |= ((uint32_t)*cur) << 16;
-        cur++;
-      /* fallthrough */
-      case GRPC_CHTTP2_SPS_VAL2:
-        if (cur == end) {
-          parser->state = GRPC_CHTTP2_SPS_VAL2;
-          return GRPC_CHTTP2_PARSE_OK;
-        }
-        parser->value |= ((uint32_t)*cur) << 8;
-        cur++;
-      /* fallthrough */
-      case GRPC_CHTTP2_SPS_VAL3:
-        if (cur == end) {
-          parser->state = GRPC_CHTTP2_SPS_VAL3;
-          return GRPC_CHTTP2_PARSE_OK;
-        } else {
-          parser->state = GRPC_CHTTP2_SPS_ID0;
-        }
-        parser->value |= *cur;
-        cur++;
-
-        if (parser->id > 0 && parser->id < GRPC_CHTTP2_NUM_SETTINGS) {
-          const grpc_chttp2_setting_parameters *sp =
-              &grpc_chttp2_settings_parameters[parser->id];
-          if (parser->value < sp->min_value || parser->value > sp->max_value) {
-            switch (sp->invalid_value_behavior) {
-              case GRPC_CHTTP2_CLAMP_INVALID_VALUE:
-                parser->value =
-                    GPR_CLAMP(parser->value, sp->min_value, sp->max_value);
-                break;
-              case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE:
-                grpc_chttp2_goaway_append(
-                    transport_parsing->last_incoming_stream_id, sp->error_value,
-                    gpr_slice_from_static_string("HTTP2 settings error"),
-                    &transport_parsing->qbuf);
-                gpr_log(GPR_ERROR, "invalid value %u passed for %s",
-                        parser->value, sp->name);
-                return GRPC_CHTTP2_CONNECTION_ERROR;
-            }
-          }
-          if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
-              parser->incoming_settings[parser->id] != parser->value) {
-            transport_parsing->initial_window_update =
-                (int64_t)parser->value - parser->incoming_settings[parser->id];
-            if (grpc_http_trace) {
-              gpr_log(GPR_DEBUG, "adding %d for initial_window change",
-                      (int)transport_parsing->initial_window_update);
-            }
-          }
-          parser->incoming_settings[parser->id] = parser->value;
-          if (grpc_http_trace) {
-            gpr_log(GPR_DEBUG, "CHTTP2:%s: got setting %d = %d",
-                    transport_parsing->is_client ? "CLI" : "SVR", parser->id,
-                    parser->value);
-          }
-        } else {
-          gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
-                  parser->id, parser->value);
-        }
-        break;
-    }
-  }
-}
diff --git a/src/core/transport/chttp2/frame_settings.h b/src/core/transport/chttp2/frame_settings.h
deleted file mode 100644
index e3c10d3..0000000
--- a/src/core/transport/chttp2/frame_settings.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_FRAME_SETTINGS_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_FRAME_SETTINGS_H
-
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice.h>
-#include "src/core/transport/chttp2/frame.h"
-#include "src/core/iomgr/exec_ctx.h"
-
-typedef enum {
-  GRPC_CHTTP2_SPS_ID0,
-  GRPC_CHTTP2_SPS_ID1,
-  GRPC_CHTTP2_SPS_VAL0,
-  GRPC_CHTTP2_SPS_VAL1,
-  GRPC_CHTTP2_SPS_VAL2,
-  GRPC_CHTTP2_SPS_VAL3
-} grpc_chttp2_settings_parse_state;
-
-/* The things HTTP/2 defines as connection level settings */
-typedef enum {
-  GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 1,
-  GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 2,
-  GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 3,
-  GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 4,
-  GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 5,
-  GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 6,
-  GRPC_CHTTP2_NUM_SETTINGS
-} grpc_chttp2_setting_id;
-
-typedef struct {
-  grpc_chttp2_settings_parse_state state;
-  uint32_t *target_settings;
-  uint8_t is_ack;
-  uint16_t id;
-  uint32_t value;
-  uint32_t incoming_settings[GRPC_CHTTP2_NUM_SETTINGS];
-} grpc_chttp2_settings_parser;
-
-typedef enum {
-  GRPC_CHTTP2_CLAMP_INVALID_VALUE,
-  GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
-} grpc_chttp2_invalid_value_behavior;
-
-typedef struct {
-  const char *name;
-  uint32_t default_value;
-  uint32_t min_value;
-  uint32_t max_value;
-  grpc_chttp2_invalid_value_behavior invalid_value_behavior;
-  uint32_t error_value;
-} grpc_chttp2_setting_parameters;
-
-/* HTTP/2 mandated connection setting parameters */
-extern const grpc_chttp2_setting_parameters
-    grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
-
-/* Create a settings frame by diffing old & new, and updating old to be new */
-gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
-                                      uint32_t force_mask, size_t count);
-/* Create an ack settings frame */
-gpr_slice grpc_chttp2_settings_ack_create(void);
-
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
-    grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
-    uint32_t *settings);
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_FRAME_SETTINGS_H */
diff --git a/src/core/transport/chttp2/frame_window_update.c b/src/core/transport/chttp2/frame_window_update.c
deleted file mode 100644
index 62d9bac..0000000
--- a/src/core/transport/chttp2/frame_window_update.c
+++ /dev/null
@@ -1,113 +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/transport/chttp2/frame_window_update.h"
-#include "src/core/transport/chttp2/internal.h"
-
-#include <grpc/support/log.h>
-
-gpr_slice grpc_chttp2_window_update_create(uint32_t id,
-                                           uint32_t window_update) {
-  gpr_slice slice = gpr_slice_malloc(13);
-  uint8_t *p = GPR_SLICE_START_PTR(slice);
-
-  GPR_ASSERT(window_update);
-
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 4;
-  *p++ = GRPC_CHTTP2_FRAME_WINDOW_UPDATE;
-  *p++ = 0;
-  *p++ = (uint8_t)(id >> 24);
-  *p++ = (uint8_t)(id >> 16);
-  *p++ = (uint8_t)(id >> 8);
-  *p++ = (uint8_t)(id);
-  *p++ = (uint8_t)(window_update >> 24);
-  *p++ = (uint8_t)(window_update >> 16);
-  *p++ = (uint8_t)(window_update >> 8);
-  *p++ = (uint8_t)(window_update);
-
-  return slice;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
-    grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags) {
-  if (flags || length != 4) {
-    gpr_log(GPR_ERROR, "invalid window update: length=%d, flags=%02x", length,
-            flags);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  }
-  parser->byte = 0;
-  parser->amount = 0;
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
-  uint8_t *const end = GPR_SLICE_END_PTR(slice);
-  uint8_t *cur = beg;
-  grpc_chttp2_window_update_parser *p = parser;
-
-  while (p->byte != 4 && cur != end) {
-    p->amount |= ((uint32_t)*cur) << (8 * (3 - p->byte));
-    cur++;
-    p->byte++;
-  }
-
-  if (p->byte == 4) {
-    uint32_t received_update = p->amount;
-    if (received_update == 0 || (received_update & 0x80000000u)) {
-      gpr_log(GPR_ERROR, "invalid window update bytes: %d", p->amount);
-      return GRPC_CHTTP2_CONNECTION_ERROR;
-    }
-    GPR_ASSERT(is_last);
-
-    if (transport_parsing->incoming_stream_id != 0) {
-      if (stream_parsing != NULL) {
-        GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", transport_parsing,
-                                       stream_parsing, outgoing_window,
-                                       received_update);
-        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
-                                                 stream_parsing);
-      }
-    } else {
-      GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parse", transport_parsing,
-                                        outgoing_window, received_update);
-    }
-  }
-
-  return GRPC_CHTTP2_PARSE_OK;
-}
diff --git a/src/core/transport/chttp2/frame_window_update.h b/src/core/transport/chttp2/frame_window_update.h
deleted file mode 100644
index 0b3712b..0000000
--- a/src/core/transport/chttp2/frame_window_update.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H
-
-#include "src/core/iomgr/exec_ctx.h"
-#include <grpc/support/slice.h>
-#include "src/core/transport/chttp2/frame.h"
-
-typedef struct {
-  uint8_t byte;
-  uint8_t is_connection_update;
-  uint32_t amount;
-} grpc_chttp2_window_update_parser;
-
-gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta);
-
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
-    grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H */
diff --git a/src/core/transport/chttp2/hpack_encoder.c b/src/core/transport/chttp2/hpack_encoder.c
deleted file mode 100644
index f30f574..0000000
--- a/src/core/transport/chttp2/hpack_encoder.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- *
- * 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/transport/chttp2/hpack_encoder.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* This is here for grpc_is_binary_header
- * TODO(murgatroid99): Remove this
- */
-#include <grpc/grpc.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/transport/chttp2/bin_encoder.h"
-#include "src/core/transport/chttp2/hpack_table.h"
-#include "src/core/transport/chttp2/timeout_encoding.h"
-#include "src/core/transport/chttp2/varint.h"
-#include "src/core/transport/static_metadata.h"
-
-#define HASH_FRAGMENT_1(x) ((x)&255)
-#define HASH_FRAGMENT_2(x) ((x >> 8) & 255)
-#define HASH_FRAGMENT_3(x) ((x >> 16) & 255)
-#define HASH_FRAGMENT_4(x) ((x >> 24) & 255)
-
-/* if the probability of this item being seen again is < 1/x then don't add
-   it to the table */
-#define ONE_ON_ADD_PROBABILITY 128
-/* don't consider adding anything bigger than this to the hpack table */
-#define MAX_DECODER_SPACE_USAGE 512
-
-typedef struct {
-  int is_first_frame;
-  /* number of bytes in 'output' when we started the frame - used to calculate
-     frame length */
-  size_t output_length_at_start_of_frame;
-  /* index (in output) of the header for the current frame */
-  size_t header_idx;
-  /* have we seen a regular (non-colon-prefixed) header yet? */
-  uint8_t seen_regular_header;
-  /* output stream id */
-  uint32_t stream_id;
-  gpr_slice_buffer *output;
-} framer_state;
-
-/* fills p (which is expected to be 9 bytes long) with a data frame header */
-static void fill_header(uint8_t *p, uint8_t type, uint32_t id, size_t len,
-                        uint8_t flags) {
-  GPR_ASSERT(len < 16777316);
-  *p++ = (uint8_t)(len >> 16);
-  *p++ = (uint8_t)(len >> 8);
-  *p++ = (uint8_t)(len);
-  *p++ = type;
-  *p++ = flags;
-  *p++ = (uint8_t)(id >> 24);
-  *p++ = (uint8_t)(id >> 16);
-  *p++ = (uint8_t)(id >> 8);
-  *p++ = (uint8_t)(id);
-}
-
-/* finish a frame - fill in the previously reserved header */
-static void finish_frame(framer_state *st, int is_header_boundary,
-                         int is_last_in_stream) {
-  uint8_t type = 0xff;
-  type = st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER
-                            : GRPC_CHTTP2_FRAME_CONTINUATION;
-  fill_header(
-      GPR_SLICE_START_PTR(st->output->slices[st->header_idx]), type,
-      st->stream_id, st->output->length - st->output_length_at_start_of_frame,
-      (uint8_t)((is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) |
-                (is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0)));
-  st->is_first_frame = 0;
-}
-
-/* begin a new frame: reserve off header space, remember how many bytes we'd
-   output before beginning */
-static void begin_frame(framer_state *st) {
-  st->header_idx =
-      gpr_slice_buffer_add_indexed(st->output, gpr_slice_malloc(9));
-  st->output_length_at_start_of_frame = st->output->length;
-}
-
-/* make sure that the current frame is of the type desired, and has sufficient
-   space to add at least about_to_add bytes -- finishes the current frame if
-   needed */
-static void ensure_space(framer_state *st, size_t need_bytes) {
-  if (st->output->length - st->output_length_at_start_of_frame + need_bytes <=
-      GRPC_CHTTP2_MAX_PAYLOAD_LENGTH) {
-    return;
-  }
-  finish_frame(st, 0, 0);
-  begin_frame(st);
-}
-
-/* increment a filter count, halve all counts if one element reaches max */
-static void inc_filter(uint8_t idx, uint32_t *sum, uint8_t *elems) {
-  elems[idx]++;
-  if (elems[idx] < 255) {
-    (*sum)++;
-  } else {
-    int i;
-    *sum = 0;
-    for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_FILTERS; i++) {
-      elems[i] /= 2;
-      (*sum) += elems[i];
-    }
-  }
-}
-
-static void add_header_data(framer_state *st, gpr_slice slice) {
-  size_t len = GPR_SLICE_LENGTH(slice);
-  size_t remaining;
-  if (len == 0) return;
-  remaining = GRPC_CHTTP2_MAX_PAYLOAD_LENGTH +
-              st->output_length_at_start_of_frame - st->output->length;
-  if (len <= remaining) {
-    gpr_slice_buffer_add(st->output, slice);
-  } else {
-    gpr_slice_buffer_add(st->output, gpr_slice_split_head(&slice, remaining));
-    finish_frame(st, 0, 0);
-    begin_frame(st);
-    add_header_data(st, slice);
-  }
-}
-
-static uint8_t *add_tiny_header_data(framer_state *st, size_t len) {
-  ensure_space(st, len);
-  return gpr_slice_buffer_tiny_add(st->output, len);
-}
-
-static void evict_entry(grpc_chttp2_hpack_compressor *c) {
-  c->tail_remote_index++;
-  GPR_ASSERT(c->tail_remote_index > 0);
-  GPR_ASSERT(c->table_size >=
-             c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
-  GPR_ASSERT(c->table_elems > 0);
-  c->table_size =
-      (uint16_t)(c->table_size -
-                 c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
-  c->table_elems--;
-}
-
-/* add an element to the decoder table */
-static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) {
-  uint32_t key_hash = elem->key->hash;
-  uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
-  uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
-  size_t elem_size = 32 + GPR_SLICE_LENGTH(elem->key->slice) +
-                     GPR_SLICE_LENGTH(elem->value->slice);
-
-  GPR_ASSERT(elem_size < 65536);
-
-  if (elem_size > c->max_table_size) {
-    while (c->table_size > 0) {
-      evict_entry(c);
-    }
-    return;
-  }
-
-  /* Reserve space for this element in the remote table: if this overflows
-     the current table, drop elements until it fits, matching the decompressor
-     algorithm */
-  while (c->table_size + elem_size > c->max_table_size) {
-    evict_entry(c);
-  }
-  GPR_ASSERT(c->table_elems < c->max_table_size);
-  c->table_elem_size[new_index % c->cap_table_elems] = (uint16_t)elem_size;
-  c->table_size = (uint16_t)(c->table_size + elem_size);
-  c->table_elems++;
-
-  /* Store this element into {entries,indices}_elem */
-  if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem) {
-    /* already there: update with new index */
-    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
-  } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem) {
-    /* already there (cuckoo): update with new index */
-    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
-  } else if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == NULL) {
-    /* not there, but a free element: add */
-    c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
-    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
-  } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == NULL) {
-    /* not there (cuckoo), but a free element: add */
-    c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
-    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
-  } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] <
-             c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) {
-    /* not there: replace oldest */
-    GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_2(elem_hash)]);
-    c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
-    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
-  } else {
-    /* not there: replace oldest */
-    GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_3(elem_hash)]);
-    c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
-    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
-  }
-
-  /* do exactly the same for the key (so we can find by that again too) */
-
-  if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key) {
-    c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
-  } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) {
-    c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
-  } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) {
-    c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
-    c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
-  } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) {
-    c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
-    c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
-  } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
-             c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
-    GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
-    c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
-    c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
-  } else {
-    GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
-    c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
-    c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
-  }
-}
-
-static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
-                         framer_state *st) {
-  uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1);
-  GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len),
-                           len);
-}
-
-static gpr_slice get_wire_value(grpc_mdelem *elem, uint8_t *huffman_prefix) {
-  if (grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(elem->key->slice),
-                            GPR_SLICE_LENGTH(elem->key->slice))) {
-    *huffman_prefix = 0x80;
-    return grpc_mdstr_as_base64_encoded_and_huffman_compressed(elem->value);
-  }
-  /* TODO(ctiller): opportunistically compress non-binary headers */
-  *huffman_prefix = 0x00;
-  return elem->value->slice;
-}
-
-static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
-                               uint32_t key_index, grpc_mdelem *elem,
-                               framer_state *st) {
-  uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
-  uint8_t huffman_prefix;
-  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
-  size_t len_val = GPR_SLICE_LENGTH(value_slice);
-  uint32_t len_val_len;
-  GPR_ASSERT(len_val <= UINT32_MAX);
-  len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
-  GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40,
-                           add_tiny_header_data(st, len_pfx), len_pfx);
-  GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
-                           add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, gpr_slice_ref(value_slice));
-}
-
-static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
-                              uint32_t key_index, grpc_mdelem *elem,
-                              framer_state *st) {
-  uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
-  uint8_t huffman_prefix;
-  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
-  size_t len_val = GPR_SLICE_LENGTH(value_slice);
-  uint32_t len_val_len;
-  GPR_ASSERT(len_val <= UINT32_MAX);
-  len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
-  GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00,
-                           add_tiny_header_data(st, len_pfx), len_pfx);
-  GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
-                           add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, gpr_slice_ref(value_slice));
-}
-
-static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
-                                 grpc_mdelem *elem, framer_state *st) {
-  uint32_t len_key = (uint32_t)GPR_SLICE_LENGTH(elem->key->slice);
-  uint8_t huffman_prefix;
-  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
-  uint32_t len_val = (uint32_t)GPR_SLICE_LENGTH(value_slice);
-  uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
-  uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
-  GPR_ASSERT(len_key <= UINT32_MAX);
-  GPR_ASSERT(GPR_SLICE_LENGTH(value_slice) <= UINT32_MAX);
-  *add_tiny_header_data(st, 1) = 0x40;
-  GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
-                           add_tiny_header_data(st, len_key_len), len_key_len);
-  add_header_data(st, gpr_slice_ref(elem->key->slice));
-  GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
-                           add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, gpr_slice_ref(value_slice));
-}
-
-static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
-                                grpc_mdelem *elem, framer_state *st) {
-  uint32_t len_key = (uint32_t)GPR_SLICE_LENGTH(elem->key->slice);
-  uint8_t huffman_prefix;
-  gpr_slice value_slice = get_wire_value(elem, &huffman_prefix);
-  uint32_t len_val = (uint32_t)GPR_SLICE_LENGTH(value_slice);
-  uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
-  uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
-  GPR_ASSERT(len_key <= UINT32_MAX);
-  GPR_ASSERT(GPR_SLICE_LENGTH(value_slice) <= UINT32_MAX);
-  *add_tiny_header_data(st, 1) = 0x00;
-  GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
-                           add_tiny_header_data(st, len_key_len), len_key_len);
-  add_header_data(st, gpr_slice_ref(elem->key->slice));
-  GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
-                           add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, gpr_slice_ref(value_slice));
-}
-
-static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
-                                             framer_state *st) {
-  uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(c->max_table_size, 3);
-  GRPC_CHTTP2_WRITE_VARINT(c->max_table_size, 3, 0x20,
-                           add_tiny_header_data(st, len), len);
-  c->advertise_table_size_change = 0;
-}
-
-static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) {
-  return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index +
-         c->table_elems - elem_index;
-}
-
-/* encode an mdelem */
-static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem,
-                      framer_state *st) {
-  uint32_t key_hash = elem->key->hash;
-  uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
-  size_t decoder_space_usage;
-  uint32_t indices_key;
-  int should_add_elem;
-
-  GPR_ASSERT(GPR_SLICE_LENGTH(elem->key->slice) > 0);
-  if (GPR_SLICE_START_PTR(elem->key->slice)[0] != ':') { /* regular header */
-    st->seen_regular_header = 1;
-  } else {
-    GPR_ASSERT(
-        st->seen_regular_header == 0 &&
-        "Reserved header (colon-prefixed) happening after regular ones.");
-  }
-
-  inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems);
-
-  /* is this elem currently in the decoders table? */
-
-  if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem &&
-      c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
-    /* HIT: complete element (first cuckoo hash) */
-    emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
-                 st);
-    return;
-  }
-
-  if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem &&
-      c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
-    /* HIT: complete element (second cuckoo hash) */
-    emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
-                 st);
-    return;
-  }
-
-  /* should this elem be in the table? */
-  decoder_space_usage = 32 + GPR_SLICE_LENGTH(elem->key->slice) +
-                        GPR_SLICE_LENGTH(elem->value->slice);
-  should_add_elem = decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
-                    c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
-                        c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
-
-  /* no hits for the elem... maybe there's a key? */
-
-  indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
-  if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key &&
-      indices_key > c->tail_remote_index) {
-    /* HIT: key (first cuckoo hash) */
-    if (should_add_elem) {
-      emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st);
-      add_elem(c, elem);
-      return;
-    } else {
-      emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
-      return;
-    }
-    GPR_UNREACHABLE_CODE(return );
-  }
-
-  indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
-  if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key &&
-      indices_key > c->tail_remote_index) {
-    /* HIT: key (first cuckoo hash) */
-    if (should_add_elem) {
-      emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st);
-      add_elem(c, elem);
-      return;
-    } else {
-      emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
-      return;
-    }
-    GPR_UNREACHABLE_CODE(return );
-  }
-
-  /* no elem, key in the table... fall back to literal emission */
-
-  if (should_add_elem) {
-    emit_lithdr_incidx_v(c, elem, st);
-    add_elem(c, elem);
-    return;
-  } else {
-    emit_lithdr_noidx_v(c, elem, st);
-    return;
-  }
-  GPR_UNREACHABLE_CODE(return );
-}
-
-#define STRLEN_LIT(x) (sizeof(x) - 1)
-#define TIMEOUT_KEY "grpc-timeout"
-
-static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
-                         framer_state *st) {
-  char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
-  grpc_mdelem *mdelem;
-  grpc_chttp2_encode_timeout(
-      gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
-  mdelem = grpc_mdelem_from_metadata_strings(
-      GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str));
-  hpack_enc(c, mdelem, st);
-  GRPC_MDELEM_UNREF(mdelem);
-}
-
-static uint32_t elems_for_bytes(uint32_t bytes) { return (bytes + 31) / 32; }
-
-void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) {
-  memset(c, 0, sizeof(*c));
-  c->max_table_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
-  c->cap_table_elems = elems_for_bytes(c->max_table_size);
-  c->max_table_elems = c->cap_table_elems;
-  c->max_usable_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
-  c->table_elem_size =
-      gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
-  memset(c->table_elem_size, 0,
-         sizeof(*c->table_elem_size) * c->cap_table_elems);
-}
-
-void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
-  int i;
-  for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
-    if (c->entries_keys[i]) GRPC_MDSTR_UNREF(c->entries_keys[i]);
-    if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]);
-  }
-  gpr_free(c->table_elem_size);
-}
-
-void grpc_chttp2_hpack_compressor_set_max_usable_size(
-    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) {
-  c->max_usable_size = max_table_size;
-  grpc_chttp2_hpack_compressor_set_max_table_size(
-      c, GPR_MIN(c->max_table_size, max_table_size));
-}
-
-static void rebuild_elems(grpc_chttp2_hpack_compressor *c, uint32_t new_cap) {
-  uint16_t *table_elem_size = gpr_malloc(sizeof(*table_elem_size) * new_cap);
-  uint32_t i;
-
-  memset(table_elem_size, 0, sizeof(*table_elem_size) * new_cap);
-  GPR_ASSERT(c->table_elems <= new_cap);
-
-  for (i = 0; i < c->table_elems; i++) {
-    uint32_t ofs = c->tail_remote_index + i + 1;
-    table_elem_size[ofs % new_cap] =
-        c->table_elem_size[ofs % c->cap_table_elems];
-  }
-
-  c->cap_table_elems = new_cap;
-  gpr_free(c->table_elem_size);
-  c->table_elem_size = table_elem_size;
-}
-
-void grpc_chttp2_hpack_compressor_set_max_table_size(
-    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) {
-  max_table_size = GPR_MIN(max_table_size, c->max_usable_size);
-  if (max_table_size == c->max_table_size) {
-    return;
-  }
-  while (c->table_size > 0 && c->table_size > max_table_size) {
-    evict_entry(c);
-  }
-  c->max_table_size = max_table_size;
-  c->max_table_elems = elems_for_bytes(max_table_size);
-  if (c->max_table_elems > c->cap_table_elems) {
-    rebuild_elems(c, GPR_MAX(c->max_table_elems, 2 * c->cap_table_elems));
-  } else if (c->max_table_elems < c->cap_table_elems / 3) {
-    uint32_t new_cap = GPR_MAX(c->max_table_elems, 16);
-    if (new_cap != c->cap_table_elems) {
-      rebuild_elems(c, new_cap);
-    }
-  }
-  c->advertise_table_size_change = 1;
-  gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size);
-}
-
-void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
-                               uint32_t stream_id,
-                               grpc_metadata_batch *metadata, int is_eof,
-                               gpr_slice_buffer *outbuf) {
-  framer_state st;
-  grpc_linked_mdelem *l;
-  gpr_timespec deadline;
-
-  GPR_ASSERT(stream_id != 0);
-
-  st.seen_regular_header = 0;
-  st.stream_id = stream_id;
-  st.output = outbuf;
-  st.is_first_frame = 1;
-
-  /* Encode a metadata batch; store the returned values, representing
-     a metadata element that needs to be unreffed back into the metadata
-     slot. THIS MAY NOT BE THE SAME ELEMENT (if a decoder table slot got
-     updated). After this loop, we'll do a batch unref of elements. */
-  begin_frame(&st);
-  if (c->advertise_table_size_change != 0) {
-    emit_advertise_table_size_change(c, &st);
-  }
-  grpc_metadata_batch_assert_ok(metadata);
-  for (l = metadata->list.head; l; l = l->next) {
-    hpack_enc(c, l->md, &st);
-  }
-  deadline = metadata->deadline;
-  if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) {
-    deadline_enc(c, deadline, &st);
-  }
-
-  finish_frame(&st, 1, is_eof);
-}
diff --git a/src/core/transport/chttp2/hpack_encoder.h b/src/core/transport/chttp2/hpack_encoder.h
deleted file mode 100644
index 90aaf86..0000000
--- a/src/core/transport/chttp2/hpack_encoder.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_HPACK_ENCODER_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_HPACK_ENCODER_H
-
-#include "src/core/transport/chttp2/frame.h"
-#include "src/core/transport/metadata.h"
-#include "src/core/transport/metadata_batch.h"
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-
-#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256
-#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256
-/* initial table size, per spec */
-#define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096
-/* maximum table size we'll actually use */
-#define GRPC_CHTTP2_HPACKC_MAX_TABLE_SIZE (1024 * 1024)
-
-typedef struct {
-  uint32_t filter_elems_sum;
-  uint32_t max_table_size;
-  uint32_t max_table_elems;
-  uint32_t cap_table_elems;
-  /** if non-zero, advertise to the decoder that we'll start using a table
-      of this size */
-  uint8_t advertise_table_size_change;
-  /** maximum number of bytes we'll use for the decode table (to guard against
-      peers ooming us by setting decode table size high) */
-  uint32_t max_usable_size;
-  /* one before the lowest usable table index */
-  uint32_t tail_remote_index;
-  uint32_t table_size;
-  uint32_t table_elems;
-
-  /* filter tables for elems: this tables provides an approximate
-     popularity count for particular hashes, and are used to determine whether
-     a new literal should be added to the compression table or not.
-     They track a single integer that counts how often a particular value has
-     been seen. When that count reaches max (255), all values are halved. */
-  uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_FILTERS];
-
-  /* entry tables for keys & elems: these tables track values that have been
-     seen and *may* be in the decompressor table */
-  grpc_mdstr *entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
-  grpc_mdelem *entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
-  uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
-  uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
-
-  uint16_t *table_elem_size;
-} grpc_chttp2_hpack_compressor;
-
-void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c);
-void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c);
-void grpc_chttp2_hpack_compressor_set_max_table_size(
-    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size);
-void grpc_chttp2_hpack_compressor_set_max_usable_size(
-    grpc_chttp2_hpack_compressor *c, uint32_t max_table_size);
-
-void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, uint32_t id,
-                               grpc_metadata_batch *metadata, int is_eof,
-                               gpr_slice_buffer *outbuf);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_HPACK_ENCODER_H */
diff --git a/src/core/transport/chttp2/hpack_parser.c b/src/core/transport/chttp2/hpack_parser.c
deleted file mode 100644
index a63c7db..0000000
--- a/src/core/transport/chttp2/hpack_parser.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/*
- *
- * 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/transport/chttp2/hpack_parser.h"
-#include "src/core/transport/chttp2/internal.h"
-
-#include <stddef.h>
-#include <string.h>
-#include <assert.h>
-
-/* This is here for grpc_is_binary_header
- * TODO(murgatroid99): Remove this
- */
-#include <grpc/grpc.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-#include "src/core/transport/chttp2/bin_encoder.h"
-
-typedef enum {
-  NOT_BINARY,
-  B64_BYTE0,
-  B64_BYTE1,
-  B64_BYTE2,
-  B64_BYTE3
-} binary_state;
-
-/* How parsing works:
-
-   The parser object keeps track of a function pointer which represents the
-   current parse state.
-
-   Each time new bytes are presented, we call into the current state, which
-   recursively parses until all bytes in the given chunk are exhausted.
-
-   The parse state that terminates then saves its function pointer to be the
-   current state so that it can resume when more bytes are available.
-
-   It's expected that most optimizing compilers will turn this code into
-   a set of indirect jumps, and so not waste stack space. */
-
-/* forward declarations for parsing states */
-static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end);
-static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end);
-static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end);
-
-static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end);
-static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end);
-static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end);
-
-static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                          const uint8_t *end);
-
-static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end);
-static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end);
-
-/* we translate the first byte of a hpack field into one of these decoding
-   cases, then use a lookup table to jump directly to the appropriate parser.
-
-   _X => the integer index is all ones, meaning we need to do varint decoding
-   _V => the integer index is all zeros, meaning we need to decode an additional
-         string value */
-typedef enum {
-  INDEXED_FIELD,
-  INDEXED_FIELD_X,
-  LITHDR_INCIDX,
-  LITHDR_INCIDX_X,
-  LITHDR_INCIDX_V,
-  LITHDR_NOTIDX,
-  LITHDR_NOTIDX_X,
-  LITHDR_NOTIDX_V,
-  LITHDR_NVRIDX,
-  LITHDR_NVRIDX_X,
-  LITHDR_NVRIDX_V,
-  MAX_TBL_SIZE,
-  MAX_TBL_SIZE_X,
-  ILLEGAL
-} first_byte_type;
-
-/* jump table of parse state functions -- order must match first_byte_type
-   above */
-static const grpc_chttp2_hpack_parser_state first_byte_action[] = {
-    parse_indexed_field,   parse_indexed_field_x, parse_lithdr_incidx,
-    parse_lithdr_incidx_x, parse_lithdr_incidx_v, parse_lithdr_notidx,
-    parse_lithdr_notidx_x, parse_lithdr_notidx_v, parse_lithdr_nvridx,
-    parse_lithdr_nvridx_x, parse_lithdr_nvridx_v, parse_max_tbl_size,
-    parse_max_tbl_size_x,  parse_illegal_op};
-
-/* indexes the first byte to a parse state function - generated by
-   gen_hpack_tables.c */
-static const uint8_t first_byte_lut[256] = {
-    LITHDR_NOTIDX_V, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX,
-    LITHDR_NOTIDX,   LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX,
-    LITHDR_NOTIDX,   LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX,
-    LITHDR_NOTIDX,   LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX_X,
-    LITHDR_NVRIDX_V, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
-    LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
-    LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
-    LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX_X,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
-    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE_X,
-    LITHDR_INCIDX_V, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX,
-    LITHDR_INCIDX,   LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX_X,
-    ILLEGAL,         INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
-    INDEXED_FIELD,   INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD_X,
-};
-
-/* state table for huffman decoding: given a state, gives an index/16 into
-   next_sub_tbl. Taking that index and adding the value of the nibble being
-   considered returns the next state.
-
-   generated by gen_hpack_tables.c */
-static const uint8_t next_tbl[256] = {
-    0,  1,  2,  3,  4,  1,  2, 5,  6,  1, 7,  8,  1,  3,  3,  9,  10, 11, 1,  1,
-    1,  12, 1,  2,  13, 1,  1, 1,  1,  1, 1,  1,  1,  1,  1,  1,  1,  1,  1,  2,
-    14, 1,  15, 16, 1,  17, 1, 15, 2,  7, 3,  18, 19, 1,  1,  1,  1,  20, 1,  1,
-    1,  1,  1,  1,  1,  1,  1, 1,  15, 2, 2,  7,  21, 1,  22, 1,  1,  1,  1,  1,
-    1,  1,  1,  15, 2,  2,  2, 2,  2,  2, 23, 24, 25, 1,  1,  1,  1,  2,  2,  2,
-    26, 3,  3,  27, 10, 28, 1, 1,  1,  1, 1,  1,  2,  3,  29, 10, 30, 1,  1,  1,
-    1,  1,  1,  1,  1,  1,  1, 1,  1,  1, 1,  31, 1,  1,  1,  1,  1,  1,  1,  2,
-    2,  2,  2,  2,  2,  2,  2, 32, 1,  1, 15, 33, 1,  34, 35, 9,  36, 1,  1,  1,
-    1,  1,  1,  1,  37, 1,  1, 1,  1,  1, 1,  2,  2,  2,  2,  2,  2,  2,  26, 9,
-    38, 1,  1,  1,  1,  1,  1, 1,  15, 2, 2,  2,  2,  26, 3,  3,  39, 1,  1,  1,
-    1,  1,  1,  1,  1,  1,  1, 1,  2,  2, 2,  2,  2,  2,  7,  3,  3,  3,  40, 2,
-    41, 1,  1,  1,  42, 43, 1, 1,  44, 1, 1,  1,  1,  15, 2,  2,  2,  2,  2,  2,
-    3,  3,  3,  45, 46, 1,  1, 2,  2,  2, 35, 3,  3,  18, 47, 2,
-};
-
-/* next state, based upon current state and the current nibble: see above.
-   generated by gen_hpack_tables.c */
-static const int16_t next_sub_tbl[48 * 16] = {
-    1,   204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
-    218, 2,   6,   10,  13,  14,  15,  16,  17,  2,   6,   10,  13,  14,  15,
-    16,  17,  3,   7,   11,  24,  3,   7,   11,  24,  3,   7,   11,  24,  3,
-    7,   11,  24,  4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,
-    4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,
-    199, 200, 201, 202, 203, 4,   8,   4,   8,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   9,   133, 134, 135, 136, 137, 138, 139, 140,
-    141, 142, 143, 144, 145, 146, 147, 3,   7,   11,  24,  3,   7,   11,  24,
-    4,   8,   4,   8,   4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   12,  132, 4,   8,   4,   8,   4,   8,
-    4,   8,   4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,   18,  19,  20,  21,  4,   8,   4,
-    8,   4,   8,   4,   8,   4,   8,   0,   0,   0,   22,  23,  91,  25,  26,
-    27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  3,
-    7,   11,  24,  3,   7,   11,  24,  0,   0,   0,   0,   0,   41,  42,  43,
-    2,   6,   10,  13,  14,  15,  16,  17,  3,   7,   11,  24,  3,   7,   11,
-    24,  4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   0,   0,
-    44,  45,  2,   6,   10,  13,  14,  15,  16,  17,  46,  47,  48,  49,  50,
-    51,  52,  57,  4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   53,  54,  55,  56,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,
-    68,  69,  70,  71,  72,  74,  0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   73,  75,  76,  77,  78,  79,  80,  81,  82,
-    83,  84,  85,  86,  87,  88,  89,  90,  3,   7,   11,  24,  3,   7,   11,
-    24,  3,   7,   11,  24,  0,   0,   0,   0,   3,   7,   11,  24,  3,   7,
-    11,  24,  4,   8,   4,   8,   0,   0,   0,   92,  0,   0,   0,   93,  94,
-    95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 3,   7,   11,  24,
-    4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,
-    8,   4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 4,
-    8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   0,   0,
-    0,   117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
-    131, 2,   6,   10,  13,  14,  15,  16,  17,  4,   8,   4,   8,   4,   8,
-    4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   148,
-    149, 150, 151, 3,   7,   11,  24,  4,   8,   4,   8,   0,   0,   0,   0,
-    0,   0,   152, 153, 3,   7,   11,  24,  3,   7,   11,  24,  3,   7,   11,
-    24,  154, 155, 156, 164, 3,   7,   11,  24,  3,   7,   11,  24,  3,   7,
-    11,  24,  4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    157, 158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172,
-    173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
-    188, 189, 190, 191, 192, 193, 194, 195, 196, 4,   8,   4,   8,   4,   8,
-    4,   8,   4,   8,   4,   8,   4,   8,   197, 198, 4,   8,   4,   8,   4,
-    8,   4,   8,   0,   0,   0,   0,   0,   0,   219, 220, 3,   7,   11,  24,
-    4,   8,   4,   8,   4,   8,   0,   0,   221, 222, 223, 224, 3,   7,   11,
-    24,  3,   7,   11,  24,  4,   8,   4,   8,   4,   8,   225, 228, 4,   8,
-    4,   8,   4,   8,   0,   0,   0,   0,   0,   0,   0,   0,   226, 227, 229,
-    230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
-    4,   8,   4,   8,   4,   8,   4,   8,   4,   8,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   245, 246, 247, 248, 249, 250, 251, 252,
-    253, 254, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   255,
-};
-
-/* emission table: indexed like next_tbl, ultimately gives the byte to be
-   emitted, or -1 for no byte, or 256 for end of stream
-
-   generated by gen_hpack_tables.c */
-static const uint16_t emit_tbl[256] = {
-    0,   1,   2,   3,   4,   5,   6,   7,   0,   8,   9,   10,  11,  12,  13,
-    14,  15,  16,  17,  18,  19,  20,  21,  22,  0,   23,  24,  25,  26,  27,
-    28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
-    43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  0,   55,  56,
-    57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  0,
-    71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
-    86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100,
-    101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
-    116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
-    131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
-    146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 0,
-    160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
-    0,   175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
-    189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
-    204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
-    219, 220, 221, 0,   222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
-    233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
-    248,
-};
-
-/* generated by gen_hpack_tables.c */
-static const int16_t emit_sub_tbl[249 * 16] = {
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  48,  48,  48,  48,  48,  48,  48,  48,  49,  49,  49,  49,  49,  49,
-    49,  49,  48,  48,  48,  48,  49,  49,  49,  49,  50,  50,  50,  50,  97,
-    97,  97,  97,  48,  48,  49,  49,  50,  50,  97,  97,  99,  99,  101, 101,
-    105, 105, 111, 111, 48,  49,  50,  97,  99,  101, 105, 111, 115, 116, -1,
-    -1,  -1,  -1,  -1,  -1,  32,  32,  32,  32,  32,  32,  32,  32,  37,  37,
-    37,  37,  37,  37,  37,  37,  99,  99,  99,  99,  101, 101, 101, 101, 105,
-    105, 105, 105, 111, 111, 111, 111, 115, 115, 116, 116, 32,  37,  45,  46,
-    47,  51,  52,  53,  54,  55,  56,  57,  61,  61,  61,  61,  61,  61,  61,
-    61,  65,  65,  65,  65,  65,  65,  65,  65,  115, 115, 115, 115, 116, 116,
-    116, 116, 32,  32,  37,  37,  45,  45,  46,  46,  61,  65,  95,  98,  100,
-    102, 103, 104, 108, 109, 110, 112, 114, 117, -1,  -1,  58,  58,  58,  58,
-    58,  58,  58,  58,  66,  66,  66,  66,  66,  66,  66,  66,  47,  47,  51,
-    51,  52,  52,  53,  53,  54,  54,  55,  55,  56,  56,  57,  57,  61,  61,
-    65,  65,  95,  95,  98,  98,  100, 100, 102, 102, 103, 103, 104, 104, 108,
-    108, 109, 109, 110, 110, 112, 112, 114, 114, 117, 117, 58,  66,  67,  68,
-    69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-    84,  85,  86,  87,  89,  106, 107, 113, 118, 119, 120, 121, 122, -1,  -1,
-    -1,  -1,  38,  38,  38,  38,  38,  38,  38,  38,  42,  42,  42,  42,  42,
-    42,  42,  42,  44,  44,  44,  44,  44,  44,  44,  44,  59,  59,  59,  59,
-    59,  59,  59,  59,  88,  88,  88,  88,  88,  88,  88,  88,  90,  90,  90,
-    90,  90,  90,  90,  90,  33,  33,  34,  34,  40,  40,  41,  41,  63,  63,
-    39,  43,  124, -1,  -1,  -1,  35,  35,  35,  35,  35,  35,  35,  35,  62,
-    62,  62,  62,  62,  62,  62,  62,  0,   0,   0,   0,   36,  36,  36,  36,
-    64,  64,  64,  64,  91,  91,  91,  91,  69,  69,  69,  69,  69,  69,  69,
-    69,  70,  70,  70,  70,  70,  70,  70,  70,  71,  71,  71,  71,  71,  71,
-    71,  71,  72,  72,  72,  72,  72,  72,  72,  72,  73,  73,  73,  73,  73,
-    73,  73,  73,  74,  74,  74,  74,  74,  74,  74,  74,  75,  75,  75,  75,
-    75,  75,  75,  75,  76,  76,  76,  76,  76,  76,  76,  76,  77,  77,  77,
-    77,  77,  77,  77,  77,  78,  78,  78,  78,  78,  78,  78,  78,  79,  79,
-    79,  79,  79,  79,  79,  79,  80,  80,  80,  80,  80,  80,  80,  80,  81,
-    81,  81,  81,  81,  81,  81,  81,  82,  82,  82,  82,  82,  82,  82,  82,
-    83,  83,  83,  83,  83,  83,  83,  83,  84,  84,  84,  84,  84,  84,  84,
-    84,  85,  85,  85,  85,  85,  85,  85,  85,  86,  86,  86,  86,  86,  86,
-    86,  86,  87,  87,  87,  87,  87,  87,  87,  87,  89,  89,  89,  89,  89,
-    89,  89,  89,  106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107,
-    107, 107, 107, 107, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118,
-    118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 120, 120,
-    120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 122,
-    122, 122, 122, 122, 122, 122, 122, 38,  38,  38,  38,  42,  42,  42,  42,
-    44,  44,  44,  44,  59,  59,  59,  59,  88,  88,  88,  88,  90,  90,  90,
-    90,  33,  34,  40,  41,  63,  -1,  -1,  -1,  39,  39,  39,  39,  39,  39,
-    39,  39,  43,  43,  43,  43,  43,  43,  43,  43,  124, 124, 124, 124, 124,
-    124, 124, 124, 35,  35,  35,  35,  62,  62,  62,  62,  0,   0,   36,  36,
-    64,  64,  91,  91,  93,  93,  126, 126, 94,  125, -1,  -1,  60,  60,  60,
-    60,  60,  60,  60,  60,  96,  96,  96,  96,  96,  96,  96,  96,  123, 123,
-    123, 123, 123, 123, 123, 123, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  92,
-    92,  92,  92,  92,  92,  92,  92,  195, 195, 195, 195, 195, 195, 195, 195,
-    208, 208, 208, 208, 208, 208, 208, 208, 128, 128, 128, 128, 130, 130, 130,
-    130, 131, 131, 131, 131, 162, 162, 162, 162, 184, 184, 184, 184, 194, 194,
-    194, 194, 224, 224, 224, 224, 226, 226, 226, 226, 153, 153, 161, 161, 167,
-    167, 172, 172, 176, 176, 177, 177, 179, 179, 209, 209, 216, 216, 217, 217,
-    227, 227, 229, 229, 230, 230, 129, 132, 133, 134, 136, 146, 154, 156, 160,
-    163, 164, 169, 170, 173, 178, 181, 185, 186, 187, 189, 190, 196, 198, 228,
-    232, 233, -1,  -1,  -1,  -1,  1,   1,   1,   1,   1,   1,   1,   1,   135,
-    135, 135, 135, 135, 135, 135, 135, 137, 137, 137, 137, 137, 137, 137, 137,
-    138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, 139, 139, 139,
-    139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141,
-    141, 141, 143, 143, 143, 143, 143, 143, 143, 143, 147, 147, 147, 147, 147,
-    147, 147, 147, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150,
-    150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, 152,
-    152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 157, 157,
-    157, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 165,
-    165, 165, 165, 165, 165, 165, 165, 166, 166, 166, 166, 166, 166, 166, 166,
-    168, 168, 168, 168, 168, 168, 168, 168, 174, 174, 174, 174, 174, 174, 174,
-    174, 175, 175, 175, 175, 175, 175, 175, 175, 180, 180, 180, 180, 180, 180,
-    180, 180, 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, 183, 183, 183,
-    183, 183, 183, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191,
-    191, 191, 191, 191, 197, 197, 197, 197, 197, 197, 197, 197, 231, 231, 231,
-    231, 231, 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 9,   9,
-    9,   9,   142, 142, 142, 142, 144, 144, 144, 144, 145, 145, 145, 145, 148,
-    148, 148, 148, 159, 159, 159, 159, 171, 171, 171, 171, 206, 206, 206, 206,
-    215, 215, 215, 215, 225, 225, 225, 225, 236, 236, 236, 236, 237, 237, 237,
-    237, 199, 199, 207, 207, 234, 234, 235, 235, 192, 193, 200, 201, 202, 205,
-    210, 213, 218, 219, 238, 240, 242, 243, 255, -1,  203, 203, 203, 203, 203,
-    203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 211, 211, 211, 211,
-    211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 214, 214, 214,
-    214, 214, 214, 214, 214, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222,
-    222, 222, 222, 222, 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 241,
-    241, 241, 241, 241, 241, 241, 241, 244, 244, 244, 244, 244, 244, 244, 244,
-    245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246,
-    246, 247, 247, 247, 247, 247, 247, 247, 247, 248, 248, 248, 248, 248, 248,
-    248, 248, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251,
-    251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253,
-    253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 2,   2,   2,
-    2,   3,   3,   3,   3,   4,   4,   4,   4,   5,   5,   5,   5,   6,   6,
-    6,   6,   7,   7,   7,   7,   8,   8,   8,   8,   11,  11,  11,  11,  12,
-    12,  12,  12,  14,  14,  14,  14,  15,  15,  15,  15,  16,  16,  16,  16,
-    17,  17,  17,  17,  18,  18,  18,  18,  19,  19,  19,  19,  20,  20,  20,
-    20,  21,  21,  21,  21,  23,  23,  23,  23,  24,  24,  24,  24,  25,  25,
-    25,  25,  26,  26,  26,  26,  27,  27,  27,  27,  28,  28,  28,  28,  29,
-    29,  29,  29,  30,  30,  30,  30,  31,  31,  31,  31,  127, 127, 127, 127,
-    220, 220, 220, 220, 249, 249, 249, 249, 10,  13,  22,  256, 93,  93,  93,
-    93,  126, 126, 126, 126, 94,  94,  125, 125, 60,  96,  123, -1,  92,  195,
-    208, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  128,
-    128, 128, 128, 128, 128, 128, 128, 130, 130, 130, 130, 130, 130, 130, 130,
-    131, 131, 131, 131, 131, 131, 131, 131, 162, 162, 162, 162, 162, 162, 162,
-    162, 184, 184, 184, 184, 184, 184, 184, 184, 194, 194, 194, 194, 194, 194,
-    194, 194, 224, 224, 224, 224, 224, 224, 224, 224, 226, 226, 226, 226, 226,
-    226, 226, 226, 153, 153, 153, 153, 161, 161, 161, 161, 167, 167, 167, 167,
-    172, 172, 172, 172, 176, 176, 176, 176, 177, 177, 177, 177, 179, 179, 179,
-    179, 209, 209, 209, 209, 216, 216, 216, 216, 217, 217, 217, 217, 227, 227,
-    227, 227, 229, 229, 229, 229, 230, 230, 230, 230, 129, 129, 132, 132, 133,
-    133, 134, 134, 136, 136, 146, 146, 154, 154, 156, 156, 160, 160, 163, 163,
-    164, 164, 169, 169, 170, 170, 173, 173, 178, 178, 181, 181, 185, 185, 186,
-    186, 187, 187, 189, 189, 190, 190, 196, 196, 198, 198, 228, 228, 232, 232,
-    233, 233, 1,   135, 137, 138, 139, 140, 141, 143, 147, 149, 150, 151, 152,
-    155, 157, 158, 165, 166, 168, 174, 175, 180, 182, 183, 188, 191, 197, 231,
-    239, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  9,   9,   9,
-    9,   9,   9,   9,   9,   142, 142, 142, 142, 142, 142, 142, 142, 144, 144,
-    144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 148,
-    148, 148, 148, 148, 148, 148, 148, 159, 159, 159, 159, 159, 159, 159, 159,
-    171, 171, 171, 171, 171, 171, 171, 171, 206, 206, 206, 206, 206, 206, 206,
-    206, 215, 215, 215, 215, 215, 215, 215, 215, 225, 225, 225, 225, 225, 225,
-    225, 225, 236, 236, 236, 236, 236, 236, 236, 236, 237, 237, 237, 237, 237,
-    237, 237, 237, 199, 199, 199, 199, 207, 207, 207, 207, 234, 234, 234, 234,
-    235, 235, 235, 235, 192, 192, 193, 193, 200, 200, 201, 201, 202, 202, 205,
-    205, 210, 210, 213, 213, 218, 218, 219, 219, 238, 238, 240, 240, 242, 242,
-    243, 243, 255, 255, 203, 204, 211, 212, 214, 221, 222, 223, 241, 244, 245,
-    246, 247, 248, 250, 251, 252, 253, 254, -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  2,   2,   2,   2,   2,   2,   2,
-    2,   3,   3,   3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   4,
-    4,   4,   5,   5,   5,   5,   5,   5,   5,   5,   6,   6,   6,   6,   6,
-    6,   6,   6,   7,   7,   7,   7,   7,   7,   7,   7,   8,   8,   8,   8,
-    8,   8,   8,   8,   11,  11,  11,  11,  11,  11,  11,  11,  12,  12,  12,
-    12,  12,  12,  12,  12,  14,  14,  14,  14,  14,  14,  14,  14,  15,  15,
-    15,  15,  15,  15,  15,  15,  16,  16,  16,  16,  16,  16,  16,  16,  17,
-    17,  17,  17,  17,  17,  17,  17,  18,  18,  18,  18,  18,  18,  18,  18,
-    19,  19,  19,  19,  19,  19,  19,  19,  20,  20,  20,  20,  20,  20,  20,
-    20,  21,  21,  21,  21,  21,  21,  21,  21,  23,  23,  23,  23,  23,  23,
-    23,  23,  24,  24,  24,  24,  24,  24,  24,  24,  25,  25,  25,  25,  25,
-    25,  25,  25,  26,  26,  26,  26,  26,  26,  26,  26,  27,  27,  27,  27,
-    27,  27,  27,  27,  28,  28,  28,  28,  28,  28,  28,  28,  29,  29,  29,
-    29,  29,  29,  29,  29,  30,  30,  30,  30,  30,  30,  30,  30,  31,  31,
-    31,  31,  31,  31,  31,  31,  127, 127, 127, 127, 127, 127, 127, 127, 220,
-    220, 220, 220, 220, 220, 220, 220, 249, 249, 249, 249, 249, 249, 249, 249,
-    10,  10,  13,  13,  22,  22,  256, 256, 67,  67,  67,  67,  67,  67,  67,
-    67,  68,  68,  68,  68,  68,  68,  68,  68,  95,  95,  95,  95,  95,  95,
-    95,  95,  98,  98,  98,  98,  98,  98,  98,  98,  100, 100, 100, 100, 100,
-    100, 100, 100, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103,
-    103, 103, 103, 103, 104, 104, 104, 104, 104, 104, 104, 104, 108, 108, 108,
-    108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 110, 110,
-    110, 110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 112, 112, 114,
-    114, 114, 114, 114, 114, 114, 114, 117, 117, 117, 117, 117, 117, 117, 117,
-    58,  58,  58,  58,  66,  66,  66,  66,  67,  67,  67,  67,  68,  68,  68,
-    68,  69,  69,  69,  69,  70,  70,  70,  70,  71,  71,  71,  71,  72,  72,
-    72,  72,  73,  73,  73,  73,  74,  74,  74,  74,  75,  75,  75,  75,  76,
-    76,  76,  76,  77,  77,  77,  77,  78,  78,  78,  78,  79,  79,  79,  79,
-    80,  80,  80,  80,  81,  81,  81,  81,  82,  82,  82,  82,  83,  83,  83,
-    83,  84,  84,  84,  84,  85,  85,  85,  85,  86,  86,  86,  86,  87,  87,
-    87,  87,  89,  89,  89,  89,  106, 106, 106, 106, 107, 107, 107, 107, 113,
-    113, 113, 113, 118, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 120,
-    121, 121, 121, 121, 122, 122, 122, 122, 38,  38,  42,  42,  44,  44,  59,
-    59,  88,  88,  90,  90,  -1,  -1,  -1,  -1,  33,  33,  33,  33,  33,  33,
-    33,  33,  34,  34,  34,  34,  34,  34,  34,  34,  40,  40,  40,  40,  40,
-    40,  40,  40,  41,  41,  41,  41,  41,  41,  41,  41,  63,  63,  63,  63,
-    63,  63,  63,  63,  39,  39,  39,  39,  43,  43,  43,  43,  124, 124, 124,
-    124, 35,  35,  62,  62,  0,   36,  64,  91,  93,  126, -1,  -1,  94,  94,
-    94,  94,  94,  94,  94,  94,  125, 125, 125, 125, 125, 125, 125, 125, 60,
-    60,  60,  60,  96,  96,  96,  96,  123, 123, 123, 123, -1,  -1,  -1,  -1,
-    92,  92,  92,  92,  195, 195, 195, 195, 208, 208, 208, 208, 128, 128, 130,
-    130, 131, 131, 162, 162, 184, 184, 194, 194, 224, 224, 226, 226, 153, 161,
-    167, 172, 176, 177, 179, 209, 216, 217, 227, 229, 230, -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  129, 129, 129, 129, 129, 129, 129, 129, 132, 132, 132, 132,
-    132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, 134,
-    134, 134, 134, 134, 134, 136, 136, 136, 136, 136, 136, 136, 136, 146, 146,
-    146, 146, 146, 146, 146, 146, 154, 154, 154, 154, 154, 154, 154, 154, 156,
-    156, 156, 156, 156, 156, 156, 156, 160, 160, 160, 160, 160, 160, 160, 160,
-    163, 163, 163, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 164, 164,
-    164, 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170,
-    170, 170, 173, 173, 173, 173, 173, 173, 173, 173, 178, 178, 178, 178, 178,
-    178, 178, 178, 181, 181, 181, 181, 181, 181, 181, 181, 185, 185, 185, 185,
-    185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187,
-    187, 187, 187, 187, 187, 189, 189, 189, 189, 189, 189, 189, 189, 190, 190,
-    190, 190, 190, 190, 190, 190, 196, 196, 196, 196, 196, 196, 196, 196, 198,
-    198, 198, 198, 198, 198, 198, 198, 228, 228, 228, 228, 228, 228, 228, 228,
-    232, 232, 232, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233,
-    233, 1,   1,   1,   1,   135, 135, 135, 135, 137, 137, 137, 137, 138, 138,
-    138, 138, 139, 139, 139, 139, 140, 140, 140, 140, 141, 141, 141, 141, 143,
-    143, 143, 143, 147, 147, 147, 147, 149, 149, 149, 149, 150, 150, 150, 150,
-    151, 151, 151, 151, 152, 152, 152, 152, 155, 155, 155, 155, 157, 157, 157,
-    157, 158, 158, 158, 158, 165, 165, 165, 165, 166, 166, 166, 166, 168, 168,
-    168, 168, 174, 174, 174, 174, 175, 175, 175, 175, 180, 180, 180, 180, 182,
-    182, 182, 182, 183, 183, 183, 183, 188, 188, 188, 188, 191, 191, 191, 191,
-    197, 197, 197, 197, 231, 231, 231, 231, 239, 239, 239, 239, 9,   9,   142,
-    142, 144, 144, 145, 145, 148, 148, 159, 159, 171, 171, 206, 206, 215, 215,
-    225, 225, 236, 236, 237, 237, 199, 207, 234, 235, 192, 192, 192, 192, 192,
-    192, 192, 192, 193, 193, 193, 193, 193, 193, 193, 193, 200, 200, 200, 200,
-    200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 201, 202, 202, 202,
-    202, 202, 202, 202, 202, 205, 205, 205, 205, 205, 205, 205, 205, 210, 210,
-    210, 210, 210, 210, 210, 210, 213, 213, 213, 213, 213, 213, 213, 213, 218,
-    218, 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 219, 219, 219, 219,
-    238, 238, 238, 238, 238, 238, 238, 238, 240, 240, 240, 240, 240, 240, 240,
-    240, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243, 243, 243,
-    243, 243, 255, 255, 255, 255, 255, 255, 255, 255, 203, 203, 203, 203, 204,
-    204, 204, 204, 211, 211, 211, 211, 212, 212, 212, 212, 214, 214, 214, 214,
-    221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 241, 241, 241,
-    241, 244, 244, 244, 244, 245, 245, 245, 245, 246, 246, 246, 246, 247, 247,
-    247, 247, 248, 248, 248, 248, 250, 250, 250, 250, 251, 251, 251, 251, 252,
-    252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254, 2,   2,   3,   3,
-    4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   11,  11,  12,  12,  14,
-    14,  15,  15,  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,
-    23,  23,  24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,
-    30,  31,  31,  127, 127, 220, 220, 249, 249, -1,  -1,  10,  10,  10,  10,
-    10,  10,  10,  10,  13,  13,  13,  13,  13,  13,  13,  13,  22,  22,  22,
-    22,  22,  22,  22,  22,  256, 256, 256, 256, 256, 256, 256, 256, 45,  45,
-    45,  45,  45,  45,  45,  45,  46,  46,  46,  46,  46,  46,  46,  46,  47,
-    47,  47,  47,  47,  47,  47,  47,  51,  51,  51,  51,  51,  51,  51,  51,
-    52,  52,  52,  52,  52,  52,  52,  52,  53,  53,  53,  53,  53,  53,  53,
-    53,  54,  54,  54,  54,  54,  54,  54,  54,  55,  55,  55,  55,  55,  55,
-    55,  55,  56,  56,  56,  56,  56,  56,  56,  56,  57,  57,  57,  57,  57,
-    57,  57,  57,  50,  50,  50,  50,  50,  50,  50,  50,  97,  97,  97,  97,
-    97,  97,  97,  97,  99,  99,  99,  99,  99,  99,  99,  99,  101, 101, 101,
-    101, 101, 101, 101, 101, 105, 105, 105, 105, 105, 105, 105, 105, 111, 111,
-    111, 111, 111, 111, 111, 111, 115, 115, 115, 115, 115, 115, 115, 115, 116,
-    116, 116, 116, 116, 116, 116, 116, 32,  32,  32,  32,  37,  37,  37,  37,
-    45,  45,  45,  45,  46,  46,  46,  46,  47,  47,  47,  47,  51,  51,  51,
-    51,  52,  52,  52,  52,  53,  53,  53,  53,  54,  54,  54,  54,  55,  55,
-    55,  55,  56,  56,  56,  56,  57,  57,  57,  57,  61,  61,  61,  61,  65,
-    65,  65,  65,  95,  95,  95,  95,  98,  98,  98,  98,  100, 100, 100, 100,
-    102, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 104, 108, 108, 108,
-    108, 109, 109, 109, 109, 110, 110, 110, 110, 112, 112, 112, 112, 114, 114,
-    114, 114, 117, 117, 117, 117, 58,  58,  66,  66,  67,  67,  68,  68,  69,
-    69,  70,  70,  71,  71,  72,  72,  73,  73,  74,  74,  75,  75,  76,  76,
-    77,  77,  78,  78,  79,  79,  80,  80,  81,  81,  82,  82,  83,  83,  84,
-    84,  85,  85,  86,  86,  87,  87,  89,  89,  106, 106, 107, 107, 113, 113,
-    118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 38,  42,  44,  59,  88,
-    90,  -1,  -1,  33,  33,  33,  33,  34,  34,  34,  34,  40,  40,  40,  40,
-    41,  41,  41,  41,  63,  63,  63,  63,  39,  39,  43,  43,  124, 124, 35,
-    62,  -1,  -1,  -1,  -1,  0,   0,   0,   0,   0,   0,   0,   0,   36,  36,
-    36,  36,  36,  36,  36,  36,  64,  64,  64,  64,  64,  64,  64,  64,  91,
-    91,  91,  91,  91,  91,  91,  91,  93,  93,  93,  93,  93,  93,  93,  93,
-    126, 126, 126, 126, 126, 126, 126, 126, 94,  94,  94,  94,  125, 125, 125,
-    125, 60,  60,  96,  96,  123, 123, -1,  -1,  92,  92,  195, 195, 208, 208,
-    128, 130, 131, 162, 184, 194, 224, 226, -1,  -1,  153, 153, 153, 153, 153,
-    153, 153, 153, 161, 161, 161, 161, 161, 161, 161, 161, 167, 167, 167, 167,
-    167, 167, 167, 167, 172, 172, 172, 172, 172, 172, 172, 172, 176, 176, 176,
-    176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 177, 177, 179, 179,
-    179, 179, 179, 179, 179, 179, 209, 209, 209, 209, 209, 209, 209, 209, 216,
-    216, 216, 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 217,
-    227, 227, 227, 227, 227, 227, 227, 227, 229, 229, 229, 229, 229, 229, 229,
-    229, 230, 230, 230, 230, 230, 230, 230, 230, 129, 129, 129, 129, 132, 132,
-    132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 136, 136, 136, 136, 146,
-    146, 146, 146, 154, 154, 154, 154, 156, 156, 156, 156, 160, 160, 160, 160,
-    163, 163, 163, 163, 164, 164, 164, 164, 169, 169, 169, 169, 170, 170, 170,
-    170, 173, 173, 173, 173, 178, 178, 178, 178, 181, 181, 181, 181, 185, 185,
-    185, 185, 186, 186, 186, 186, 187, 187, 187, 187, 189, 189, 189, 189, 190,
-    190, 190, 190, 196, 196, 196, 196, 198, 198, 198, 198, 228, 228, 228, 228,
-    232, 232, 232, 232, 233, 233, 233, 233, 1,   1,   135, 135, 137, 137, 138,
-    138, 139, 139, 140, 140, 141, 141, 143, 143, 147, 147, 149, 149, 150, 150,
-    151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 165, 165, 166, 166, 168,
-    168, 174, 174, 175, 175, 180, 180, 182, 182, 183, 183, 188, 188, 191, 191,
-    197, 197, 231, 231, 239, 239, 9,   142, 144, 145, 148, 159, 171, 206, 215,
-    225, 236, 237, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  199, 199,
-    199, 199, 199, 199, 199, 199, 207, 207, 207, 207, 207, 207, 207, 207, 234,
-    234, 234, 234, 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235,
-    192, 192, 192, 192, 193, 193, 193, 193, 200, 200, 200, 200, 201, 201, 201,
-    201, 202, 202, 202, 202, 205, 205, 205, 205, 210, 210, 210, 210, 213, 213,
-    213, 213, 218, 218, 218, 218, 219, 219, 219, 219, 238, 238, 238, 238, 240,
-    240, 240, 240, 242, 242, 242, 242, 243, 243, 243, 243, 255, 255, 255, 255,
-    203, 203, 204, 204, 211, 211, 212, 212, 214, 214, 221, 221, 222, 222, 223,
-    223, 241, 241, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 250, 250,
-    251, 251, 252, 252, 253, 253, 254, 254, 2,   3,   4,   5,   6,   7,   8,
-    11,  12,  14,  15,  16,  17,  18,  19,  20,  21,  23,  24,  25,  26,  27,
-    28,  29,  30,  31,  127, 220, 249, -1,  10,  10,  10,  10,  13,  13,  13,
-    13,  22,  22,  22,  22,  256, 256, 256, 256,
-};
-
-static const uint8_t inverse_base64[256] = {
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62,  255,
-    255, 255, 63,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  255, 255,
-    255, 64,  255, 255, 255, 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
-    10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
-    25,  255, 255, 255, 255, 255, 255, 26,  27,  28,  29,  30,  31,  32,  33,
-    34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-    49,  50,  51,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255,
-};
-
-/* emission helpers */
-static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
-                  int add_to_table) {
-  if (add_to_table) {
-    if (!grpc_chttp2_hptbl_add(&p->table, md)) {
-      return 0;
-    }
-  }
-  p->on_header(p->on_header_user_data, md);
-  return 1;
-}
-
-static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
-                               grpc_chttp2_hpack_parser_string *str) {
-  grpc_mdstr *s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length);
-  str->length = 0;
-  return s;
-}
-
-/* jump to the next state */
-static int parse_next(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                      const uint8_t *end) {
-  p->state = *p->next_state++;
-  return p->state(p, cur, end);
-}
-
-/* begin parsing a header: all functionality is encoded into lookup tables
-   above */
-static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_begin;
-    return 1;
-  }
-
-  return first_byte_action[first_byte_lut[*cur]](p, cur, end);
-}
-
-/* stream dependency and prioritization data: we just skip it */
-static int parse_stream_weight(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_stream_weight;
-    return 1;
-  }
-
-  return p->after_prioritization(p, cur + 1, end);
-}
-
-static int parse_stream_dep3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_stream_dep3;
-    return 1;
-  }
-
-  return parse_stream_weight(p, cur + 1, end);
-}
-
-static int parse_stream_dep2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_stream_dep2;
-    return 1;
-  }
-
-  return parse_stream_dep3(p, cur + 1, end);
-}
-
-static int parse_stream_dep1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_stream_dep1;
-    return 1;
-  }
-
-  return parse_stream_dep2(p, cur + 1, end);
-}
-
-static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_stream_dep0;
-    return 1;
-  }
-
-  return parse_stream_dep1(p, cur + 1, end);
-}
-
-/* emit an indexed field; for now just logs it to console; jumps to
-   begin the next field on completion */
-static int finish_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  if (md == NULL) {
-    gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
-    return 0;
-  }
-  GRPC_MDELEM_REF(md);
-  return on_hdr(p, md, 0) && parse_begin(p, cur, end);
-}
-
-/* parse an indexed field with index < 127 */
-static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
-  p->dynamic_table_update_allowed = 0;
-  p->index = (*cur) & 0x7f;
-  return finish_indexed_field(p, cur + 1, end);
-}
-
-/* parse an indexed field with index >= 127 */
-static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      finish_indexed_field};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  p->index = 0x7f;
-  p->parsing.value = &p->index;
-  return parse_value0(p, cur + 1, end);
-}
-
-/* finish a literal header with incremental indexing: just log, and jump to '
-   begin */
-static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  GPR_ASSERT(md != NULL); /* handled in string parsing */
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
-                                                     take_string(p, &p->value)),
-                1) &&
-         parse_begin(p, cur, end);
-}
-
-/* finish a literal header with incremental indexing with no index */
-static int finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
-                                  const uint8_t *cur, const uint8_t *end) {
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
-                                                     take_string(p, &p->value)),
-                1) &&
-         parse_begin(p, cur, end);
-}
-
-/* parse a literal header with incremental indexing; index < 63 */
-static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_value_string_with_indexed_key, finish_lithdr_incidx};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  p->index = (*cur) & 0x3f;
-  return parse_string_prefix(p, cur + 1, end);
-}
-
-/* parse a literal header with incremental indexing; index >= 63 */
-static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_string_prefix, parse_value_string_with_indexed_key,
-      finish_lithdr_incidx};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  p->index = 0x3f;
-  p->parsing.value = &p->index;
-  return parse_value0(p, cur + 1, end);
-}
-
-/* parse a literal header with incremental indexing; index = 0 */
-static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_key_string, parse_string_prefix,
-      parse_value_string_with_literal_key, finish_lithdr_incidx_v};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  return parse_string_prefix(p, cur + 1, end);
-}
-
-/* finish a literal header without incremental indexing */
-static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  GPR_ASSERT(md != NULL); /* handled in string parsing */
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
-}
-
-/* finish a literal header without incremental indexing with index = 0 */
-static int finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
-                                  const uint8_t *cur, const uint8_t *end) {
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
-}
-
-/* parse a literal header without incremental indexing; index < 15 */
-static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_value_string_with_indexed_key, finish_lithdr_notidx};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  p->index = (*cur) & 0xf;
-  return parse_string_prefix(p, cur + 1, end);
-}
-
-/* parse a literal header without incremental indexing; index >= 15 */
-static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_string_prefix, parse_value_string_with_indexed_key,
-      finish_lithdr_notidx};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  p->index = 0xf;
-  p->parsing.value = &p->index;
-  return parse_value0(p, cur + 1, end);
-}
-
-/* parse a literal header without incremental indexing; index == 0 */
-static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_key_string, parse_string_prefix,
-      parse_value_string_with_literal_key, finish_lithdr_notidx_v};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  return parse_string_prefix(p, cur + 1, end);
-}
-
-/* finish a literal header that is never indexed */
-static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  GPR_ASSERT(md != NULL); /* handled in string parsing */
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
-}
-
-/* finish a literal header that is never indexed with an extra value */
-static int finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
-                                  const uint8_t *cur, const uint8_t *end) {
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
-}
-
-/* parse a literal header that is never indexed; index < 15 */
-static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_value_string_with_indexed_key, finish_lithdr_nvridx};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  p->index = (*cur) & 0xf;
-  return parse_string_prefix(p, cur + 1, end);
-}
-
-/* parse a literal header that is never indexed; index >= 15 */
-static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_string_prefix, parse_value_string_with_indexed_key,
-      finish_lithdr_nvridx};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  p->index = 0xf;
-  p->parsing.value = &p->index;
-  return parse_value0(p, cur + 1, end);
-}
-
-/* parse a literal header that is never indexed; index == 0 */
-static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      parse_key_string, parse_string_prefix,
-      parse_value_string_with_literal_key, finish_lithdr_nvridx_v};
-  p->dynamic_table_update_allowed = 0;
-  p->next_state = and_then;
-  return parse_string_prefix(p, cur + 1, end);
-}
-
-/* finish parsing a max table size change */
-static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
-  gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index);
-  return grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index) &&
-         parse_begin(p, cur, end);
-}
-
-/* parse a max table size change, max size < 15 */
-static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end) {
-  if (p->dynamic_table_update_allowed == 0) {
-    return 0;
-  }
-  p->dynamic_table_update_allowed--;
-  p->index = (*cur) & 0x1f;
-  return finish_max_tbl_size(p, cur + 1, end);
-}
-
-/* parse a max table size change, max size >= 15 */
-static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
-  static const grpc_chttp2_hpack_parser_state and_then[] = {
-      finish_max_tbl_size};
-  if (p->dynamic_table_update_allowed == 0) {
-    return 0;
-  }
-  p->dynamic_table_update_allowed--;
-  p->next_state = and_then;
-  p->index = 0x1f;
-  p->parsing.value = &p->index;
-  return parse_value0(p, cur + 1, end);
-}
-
-/* a parse error: jam the parse state into parse_error, and return error */
-static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end) {
-  p->state = parse_error;
-  return 0;
-}
-
-static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end) {
-  GPR_ASSERT(cur != end);
-  gpr_log(GPR_DEBUG, "Illegal hpack op code %d", *cur);
-  return parse_error(p, cur, end);
-}
-
-/* parse the 1st byte of a varint into p->parsing.value
-   no overflow is possible */
-static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_value0;
-    return 1;
-  }
-
-  *p->parsing.value += (*cur) & 0x7f;
-
-  if ((*cur) & 0x80) {
-    return parse_value1(p, cur + 1, end);
-  } else {
-    return parse_next(p, cur + 1, end);
-  }
-}
-
-/* parse the 2nd byte of a varint into p->parsing.value
-   no overflow is possible */
-static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_value1;
-    return 1;
-  }
-
-  *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 7;
-
-  if ((*cur) & 0x80) {
-    return parse_value2(p, cur + 1, end);
-  } else {
-    return parse_next(p, cur + 1, end);
-  }
-}
-
-/* parse the 3rd byte of a varint into p->parsing.value
-   no overflow is possible */
-static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_value2;
-    return 1;
-  }
-
-  *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 14;
-
-  if ((*cur) & 0x80) {
-    return parse_value3(p, cur + 1, end);
-  } else {
-    return parse_next(p, cur + 1, end);
-  }
-}
-
-/* parse the 4th byte of a varint into p->parsing.value
-   no overflow is possible */
-static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_value3;
-    return 1;
-  }
-
-  *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 21;
-
-  if ((*cur) & 0x80) {
-    return parse_value4(p, cur + 1, end);
-  } else {
-    return parse_next(p, cur + 1, end);
-  }
-}
-
-/* parse the 5th byte of a varint into p->parsing.value
-   depending on the byte, we may overflow, and care must be taken */
-static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
-  uint8_t c;
-  uint32_t cur_value;
-  uint32_t add_value;
-
-  if (cur == end) {
-    p->state = parse_value4;
-    return 1;
-  }
-
-  c = (*cur) & 0x7f;
-  if (c > 0xf) {
-    goto error;
-  }
-
-  cur_value = *p->parsing.value;
-  add_value = ((uint32_t)c) << 28;
-  if (add_value > 0xffffffffu - cur_value) {
-    goto error;
-  }
-
-  *p->parsing.value = cur_value + add_value;
-
-  if ((*cur) & 0x80) {
-    return parse_value5up(p, cur + 1, end);
-  } else {
-    return parse_next(p, cur + 1, end);
-  }
-
-error:
-  gpr_log(GPR_ERROR,
-          "integer overflow in hpack integer decoding: have 0x%08x, "
-          "got byte 0x%02x on byte 5",
-          *p->parsing.value, *cur);
-  return parse_error(p, cur, end);
-}
-
-/* parse any trailing bytes in a varint: it's possible to append an arbitrary
-   number of 0x80's and not affect the value - a zero will terminate - and
-   anything else will overflow */
-static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                          const uint8_t *end) {
-  while (cur != end && *cur == 0x80) {
-    ++cur;
-  }
-
-  if (cur == end) {
-    p->state = parse_value5up;
-    return 1;
-  }
-
-  if (*cur == 0) {
-    return parse_next(p, cur + 1, end);
-  }
-
-  gpr_log(GPR_ERROR,
-          "integer overflow in hpack integer decoding: have 0x%08x, "
-          "got byte 0x%02x sometime after byte 5",
-          *p->parsing.value, *cur);
-  return parse_error(p, cur, end);
-}
-
-/* parse a string prefix */
-static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
-  if (cur == end) {
-    p->state = parse_string_prefix;
-    return 1;
-  }
-
-  p->strlen = (*cur) & 0x7f;
-  p->huff = (*cur) >> 7;
-  if (p->strlen == 0x7f) {
-    p->parsing.value = &p->strlen;
-    return parse_value0(p, cur + 1, end);
-  } else {
-    return parse_next(p, cur + 1, end);
-  }
-}
-
-/* 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 + str->length > str->capacity) {
-    GPR_ASSERT(str->length + length <= UINT32_MAX);
-    str->capacity = (uint32_t)(str->length + length);
-    str->str = gpr_realloc(str->str, str->capacity);
-  }
-  memcpy(str->str + str->length, data, length);
-  GPR_ASSERT(length <= UINT32_MAX - str->length);
-  str->length += (uint32_t)length;
-}
-
-static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                         const uint8_t *end) {
-  grpc_chttp2_hpack_parser_string *str = p->parsing.str;
-  uint32_t bits;
-  uint8_t decoded[3];
-  switch ((binary_state)p->binary) {
-    case NOT_BINARY:
-      append_bytes(str, cur, (size_t)(end - cur));
-      return 1;
-    b64_byte0:
-    case B64_BYTE0:
-      if (cur == end) {
-        p->binary = B64_BYTE0;
-        return 1;
-      }
-      bits = inverse_base64[*cur];
-      ++cur;
-      if (bits == 255)
-        return 0;
-      else if (bits == 64)
-        goto b64_byte0;
-      p->base64_buffer = bits << 18;
-    /* fallthrough */
-    b64_byte1:
-    case B64_BYTE1:
-      if (cur == end) {
-        p->binary = B64_BYTE1;
-        return 1;
-      }
-      bits = inverse_base64[*cur];
-      ++cur;
-      if (bits == 255)
-        return 0;
-      else if (bits == 64)
-        goto b64_byte1;
-      p->base64_buffer |= bits << 12;
-    /* fallthrough */
-    b64_byte2:
-    case B64_BYTE2:
-      if (cur == end) {
-        p->binary = B64_BYTE2;
-        return 1;
-      }
-      bits = inverse_base64[*cur];
-      ++cur;
-      if (bits == 255)
-        return 0;
-      else if (bits == 64)
-        goto b64_byte2;
-      p->base64_buffer |= bits << 6;
-    /* fallthrough */
-    b64_byte3:
-    case B64_BYTE3:
-      if (cur == end) {
-        p->binary = B64_BYTE3;
-        return 1;
-      }
-      bits = inverse_base64[*cur];
-      ++cur;
-      if (bits == 255)
-        return 0;
-      else if (bits == 64)
-        goto b64_byte3;
-      p->base64_buffer |= bits;
-      bits = p->base64_buffer;
-      decoded[0] = (uint8_t)(bits >> 16);
-      decoded[1] = (uint8_t)(bits >> 8);
-      decoded[2] = (uint8_t)(bits);
-      append_bytes(str, decoded, 3);
-      goto b64_byte0;
-  }
-  GPR_UNREACHABLE_CODE(return 1);
-}
-
-/* append a null terminator to a string */
-static int finish_str(grpc_chttp2_hpack_parser *p) {
-  uint8_t terminator = 0;
-  uint8_t decoded[2];
-  uint32_t bits;
-  grpc_chttp2_hpack_parser_string *str = p->parsing.str;
-  switch ((binary_state)p->binary) {
-    case NOT_BINARY:
-      break;
-    case B64_BYTE0:
-      break;
-    case B64_BYTE1:
-      gpr_log(GPR_ERROR, "illegal base64 encoding");
-      return 0; /* illegal encoding */
-    case B64_BYTE2:
-      bits = p->base64_buffer;
-      if (bits & 0xffff) {
-        gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%04x",
-                bits & 0xffff);
-        return 0;
-      }
-      decoded[0] = (uint8_t)(bits >> 16);
-      append_bytes(str, decoded, 1);
-      break;
-    case B64_BYTE3:
-      bits = p->base64_buffer;
-      if (bits & 0xff) {
-        gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%02x",
-                bits & 0xff);
-        return 0;
-      }
-      decoded[0] = (uint8_t)(bits >> 16);
-      decoded[1] = (uint8_t)(bits >> 8);
-      append_bytes(str, decoded, 2);
-      break;
-  }
-  append_bytes(str, &terminator, 1);
-  p->parsing.str->length--; /* don't actually count the null terminator */
-  return 1;
-}
-
-/* decode a nibble from a huffman encoded stream */
-static int huff_nibble(grpc_chttp2_hpack_parser *p, uint8_t nibble) {
-  int16_t emit = emit_sub_tbl[16 * emit_tbl[p->huff_state] + nibble];
-  int16_t next = next_sub_tbl[16 * next_tbl[p->huff_state] + nibble];
-  if (emit != -1) {
-    if (emit >= 0 && emit < 256) {
-      uint8_t c = (uint8_t)emit;
-      if (!append_string(p, &c, (&c) + 1)) return 0;
-    } else {
-      assert(emit == 256);
-    }
-  }
-  p->huff_state = next;
-  return 1;
-}
-
-/* decode full bytes from a huffman encoded stream */
-static int add_huff_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                          const uint8_t *end) {
-  for (; cur != end; ++cur) {
-    if (!huff_nibble(p, *cur >> 4) || !huff_nibble(p, *cur & 0xf)) return 0;
-  }
-  return 1;
-}
-
-/* decode some string bytes based on the current decoding mode
-   (huffman or not) */
-static int add_str_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                         const uint8_t *end) {
-  if (p->huff) {
-    return add_huff_bytes(p, cur, end);
-  } else {
-    return append_string(p, cur, end);
-  }
-}
-
-/* parse a string - tries to do large chunks at a time */
-static int parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
-  size_t remaining = p->strlen - p->strgot;
-  size_t given = (size_t)(end - cur);
-  if (remaining <= given) {
-    return add_str_bytes(p, cur, cur + remaining) && finish_str(p) &&
-           parse_next(p, cur + remaining, end);
-  } else {
-    if (!add_str_bytes(p, cur, cur + given)) return 0;
-    GPR_ASSERT(given <= UINT32_MAX - p->strgot);
-    p->strgot += (uint32_t)given;
-    p->state = parse_string;
-    return 1;
-  }
-}
-
-/* begin parsing a string - performs setup, calls parse_string */
-static int begin_parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end, uint8_t binary,
-                              grpc_chttp2_hpack_parser_string *str) {
-  p->strgot = 0;
-  str->length = 0;
-  p->parsing.str = str;
-  p->huff_state = 0;
-  p->binary = binary;
-  return parse_string(p, cur, end);
-}
-
-/* parse the key string */
-static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end) {
-  return begin_parse_string(p, cur, end, NOT_BINARY, &p->key);
-}
-
-/* check if a key represents a binary header or not */
-typedef enum { BINARY_HEADER, PLAINTEXT_HEADER, ERROR_HEADER } is_binary_header;
-
-static is_binary_header is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
-  return grpc_is_binary_header(p->key.str, p->key.length) ? BINARY_HEADER
-                                                          : PLAINTEXT_HEADER;
-}
-
-static is_binary_header is_binary_indexed_header(grpc_chttp2_hpack_parser *p) {
-  grpc_mdelem *elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  if (!elem) {
-    gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
-    return ERROR_HEADER;
-  }
-  return grpc_is_binary_header(
-             (const char *)GPR_SLICE_START_PTR(elem->key->slice),
-             GPR_SLICE_LENGTH(elem->key->slice))
-             ? BINARY_HEADER
-             : PLAINTEXT_HEADER;
-}
-
-/* parse the value string */
-static int parse_value_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end, is_binary_header type) {
-  switch (type) {
-    case BINARY_HEADER:
-      return begin_parse_string(p, cur, end, B64_BYTE0, &p->value);
-    case PLAINTEXT_HEADER:
-      return begin_parse_string(p, cur, end, NOT_BINARY, &p->value);
-    case ERROR_HEADER:
-      return 0;
-  }
-  /* Add code to prevent return without value error */
-  GPR_UNREACHABLE_CODE(return 0);
-}
-
-static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end) {
-  return parse_value_string(p, cur, end, is_binary_indexed_header(p));
-}
-
-static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end) {
-  return parse_value_string(p, cur, end, is_binary_literal_header(p));
-}
-
-/* PUBLIC INTERFACE */
-
-static void on_header_not_set(void *user_data, grpc_mdelem *md) {
-  GPR_UNREACHABLE_CODE(return );
-}
-
-void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p) {
-  p->on_header = on_header_not_set;
-  p->on_header_user_data = NULL;
-  p->state = parse_begin;
-  p->key.str = NULL;
-  p->key.capacity = 0;
-  p->key.length = 0;
-  p->value.str = NULL;
-  p->value.capacity = 0;
-  p->value.length = 0;
-  p->dynamic_table_update_allowed = 2;
-  grpc_chttp2_hptbl_init(&p->table);
-}
-
-void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p) {
-  p->after_prioritization = p->state;
-  p->state = parse_stream_dep0;
-}
-
-void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p) {
-  grpc_chttp2_hptbl_destroy(&p->table);
-  gpr_free(p->key.str);
-  gpr_free(p->value.str);
-}
-
-int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
-                                   const uint8_t *beg, const uint8_t *end) {
-  /* TODO(ctiller): limit the distance of end from beg, and perform multiple
-     steps in the event of a large chunk of data to limit
-     stack space usage when no tail call optimization is
-     available */
-  return p->state(p, beg, end);
-}
-
-grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *hpack_parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  grpc_chttp2_hpack_parser *parser = hpack_parser;
-  GPR_TIMER_BEGIN("grpc_chttp2_hpack_parser_parse", 0);
-  if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice),
-                                      GPR_SLICE_END_PTR(slice))) {
-    GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  }
-  if (is_last) {
-    if (parser->is_boundary && parser->state != parse_begin) {
-      gpr_log(GPR_ERROR,
-              "end of header frame not aligned with a hpack record boundary");
-      GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
-      return GRPC_CHTTP2_CONNECTION_ERROR;
-    }
-    /* need to check for null stream: this can occur if we receive an invalid
-       stream id on a header */
-    if (stream_parsing != NULL) {
-      if (parser->is_boundary) {
-        stream_parsing
-            ->got_metadata_on_parse[stream_parsing->header_frames_received] = 1;
-        stream_parsing->header_frames_received++;
-        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
-                                                 stream_parsing);
-      }
-      if (parser->is_eof) {
-        stream_parsing->received_close = 1;
-      }
-    }
-    parser->on_header = on_header_not_set;
-    parser->on_header_user_data = NULL;
-    parser->is_boundary = 0xde;
-    parser->is_eof = 0xde;
-    parser->dynamic_table_update_allowed = 2;
-  }
-  GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
-  return GRPC_CHTTP2_PARSE_OK;
-}
diff --git a/src/core/transport/chttp2/hpack_parser.h b/src/core/transport/chttp2/hpack_parser.h
deleted file mode 100644
index 6a6d136..0000000
--- a/src/core/transport/chttp2/hpack_parser.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_HPACK_PARSER_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_HPACK_PARSER_H
-
-#include <stddef.h>
-
-#include <grpc/support/port_platform.h>
-#include "src/core/iomgr/exec_ctx.h"
-#include "src/core/transport/chttp2/frame.h"
-#include "src/core/transport/chttp2/hpack_table.h"
-#include "src/core/transport/metadata.h"
-
-typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser;
-
-typedef int (*grpc_chttp2_hpack_parser_state)(grpc_chttp2_hpack_parser *p,
-                                              const uint8_t *beg,
-                                              const uint8_t *end);
-
-typedef struct {
-  char *str;
-  uint32_t length;
-  uint32_t capacity;
-} grpc_chttp2_hpack_parser_string;
-
-struct grpc_chttp2_hpack_parser {
-  /* user specified callback for each header output */
-  void (*on_header)(void *user_data, grpc_mdelem *md);
-  void *on_header_user_data;
-
-  /* current parse state - or a function that implements it */
-  grpc_chttp2_hpack_parser_state state;
-  /* future states dependent on the opening op code */
-  const grpc_chttp2_hpack_parser_state *next_state;
-  /* what to do after skipping prioritization data */
-  grpc_chttp2_hpack_parser_state after_prioritization;
-  /* the value we're currently parsing */
-  union {
-    uint32_t *value;
-    grpc_chttp2_hpack_parser_string *str;
-  } parsing;
-  /* string parameters for each chunk */
-  grpc_chttp2_hpack_parser_string key;
-  grpc_chttp2_hpack_parser_string value;
-  /* parsed index */
-  uint32_t index;
-  /* length of source bytes for the currently parsing string */
-  uint32_t strlen;
-  /* number of source bytes read for the currently parsing string */
-  uint32_t strgot;
-  /* huffman decoding state */
-  int16_t huff_state;
-  /* is the string being decoded binary? */
-  uint8_t binary;
-  /* is the current string huffman encoded? */
-  uint8_t huff;
-  /* is a dynamic table update allowed? */
-  uint8_t dynamic_table_update_allowed;
-  /* set by higher layers, used by grpc_chttp2_header_parser_parse to signal
-     it should append a metadata boundary at the end of frame */
-  uint8_t is_boundary;
-  uint8_t is_eof;
-  uint32_t base64_buffer;
-
-  /* hpack table */
-  grpc_chttp2_hptbl table;
-};
-
-void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p);
-void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p);
-
-void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p);
-
-/* returns 1 on success, 0 on error */
-int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
-                                   const uint8_t *beg, const uint8_t *end);
-
-/* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
-   the transport */
-grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
-    grpc_exec_ctx *exec_ctx, void *hpack_parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_HPACK_PARSER_H */
diff --git a/src/core/transport/chttp2/hpack_table.c b/src/core/transport/chttp2/hpack_table.c
deleted file mode 100644
index f1ce3b8..0000000
--- a/src/core/transport/chttp2/hpack_table.c
+++ /dev/null
@@ -1,361 +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/transport/chttp2/hpack_table.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/support/murmur_hash.h"
-
-static struct {
-  const char *key;
-  const char *value;
-} static_table[] = {
-    /* 0: */
-    {NULL, NULL},
-    /* 1: */
-    {":authority", ""},
-    /* 2: */
-    {":method", "GET"},
-    /* 3: */
-    {":method", "POST"},
-    /* 4: */
-    {":path", "/"},
-    /* 5: */
-    {":path", "/index.html"},
-    /* 6: */
-    {":scheme", "http"},
-    /* 7: */
-    {":scheme", "https"},
-    /* 8: */
-    {":status", "200"},
-    /* 9: */
-    {":status", "204"},
-    /* 10: */
-    {":status", "206"},
-    /* 11: */
-    {":status", "304"},
-    /* 12: */
-    {":status", "400"},
-    /* 13: */
-    {":status", "404"},
-    /* 14: */
-    {":status", "500"},
-    /* 15: */
-    {"accept-charset", ""},
-    /* 16: */
-    {"accept-encoding", "gzip, deflate"},
-    /* 17: */
-    {"accept-language", ""},
-    /* 18: */
-    {"accept-ranges", ""},
-    /* 19: */
-    {"accept", ""},
-    /* 20: */
-    {"access-control-allow-origin", ""},
-    /* 21: */
-    {"age", ""},
-    /* 22: */
-    {"allow", ""},
-    /* 23: */
-    {"authorization", ""},
-    /* 24: */
-    {"cache-control", ""},
-    /* 25: */
-    {"content-disposition", ""},
-    /* 26: */
-    {"content-encoding", ""},
-    /* 27: */
-    {"content-language", ""},
-    /* 28: */
-    {"content-length", ""},
-    /* 29: */
-    {"content-location", ""},
-    /* 30: */
-    {"content-range", ""},
-    /* 31: */
-    {"content-type", ""},
-    /* 32: */
-    {"cookie", ""},
-    /* 33: */
-    {"date", ""},
-    /* 34: */
-    {"etag", ""},
-    /* 35: */
-    {"expect", ""},
-    /* 36: */
-    {"expires", ""},
-    /* 37: */
-    {"from", ""},
-    /* 38: */
-    {"host", ""},
-    /* 39: */
-    {"if-match", ""},
-    /* 40: */
-    {"if-modified-since", ""},
-    /* 41: */
-    {"if-none-match", ""},
-    /* 42: */
-    {"if-range", ""},
-    /* 43: */
-    {"if-unmodified-since", ""},
-    /* 44: */
-    {"last-modified", ""},
-    /* 45: */
-    {"link", ""},
-    /* 46: */
-    {"location", ""},
-    /* 47: */
-    {"max-forwards", ""},
-    /* 48: */
-    {"proxy-authenticate", ""},
-    /* 49: */
-    {"proxy-authorization", ""},
-    /* 50: */
-    {"range", ""},
-    /* 51: */
-    {"referer", ""},
-    /* 52: */
-    {"refresh", ""},
-    /* 53: */
-    {"retry-after", ""},
-    /* 54: */
-    {"server", ""},
-    /* 55: */
-    {"set-cookie", ""},
-    /* 56: */
-    {"strict-transport-security", ""},
-    /* 57: */
-    {"transfer-encoding", ""},
-    /* 58: */
-    {"user-agent", ""},
-    /* 59: */
-    {"vary", ""},
-    /* 60: */
-    {"via", ""},
-    /* 61: */
-    {"www-authenticate", ""},
-};
-
-static uint32_t entries_for_bytes(uint32_t bytes) {
-  return (bytes + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) /
-         GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
-}
-
-void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl) {
-  size_t i;
-
-  memset(tbl, 0, sizeof(*tbl));
-  tbl->current_table_bytes = tbl->max_bytes =
-      GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE;
-  tbl->max_entries = tbl->cap_entries =
-      entries_for_bytes(tbl->current_table_bytes);
-  tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
-  memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
-  for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
-    tbl->static_ents[i - 1] =
-        grpc_mdelem_from_strings(static_table[i].key, static_table[i].value);
-  }
-}
-
-void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) {
-  size_t i;
-  for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
-    GRPC_MDELEM_UNREF(tbl->static_ents[i]);
-  }
-  for (i = 0; i < tbl->num_ents; i++) {
-    GRPC_MDELEM_UNREF(tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]);
-  }
-  gpr_free(tbl->ents);
-}
-
-grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
-                                      uint32_t tbl_index) {
-  /* Static table comes first, just return an entry from it */
-  if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) {
-    return tbl->static_ents[tbl_index - 1];
-  }
-  /* Otherwise, find the value in the list of valid entries */
-  tbl_index -= (GRPC_CHTTP2_LAST_STATIC_ENTRY + 1);
-  if (tbl_index < tbl->num_ents) {
-    uint32_t offset =
-        (tbl->num_ents - 1u - tbl_index + tbl->first_ent) % tbl->cap_entries;
-    return tbl->ents[offset];
-  }
-  /* Invalid entry: return error */
-  return NULL;
-}
-
-/* Evict one element from the table */
-static void evict1(grpc_chttp2_hptbl *tbl) {
-  grpc_mdelem *first_ent = tbl->ents[tbl->first_ent];
-  size_t elem_bytes = GPR_SLICE_LENGTH(first_ent->key->slice) +
-                      GPR_SLICE_LENGTH(first_ent->value->slice) +
-                      GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
-  GPR_ASSERT(elem_bytes <= tbl->mem_used);
-  tbl->mem_used -= (uint32_t)elem_bytes;
-  tbl->first_ent = ((tbl->first_ent + 1) % tbl->cap_entries);
-  tbl->num_ents--;
-  GRPC_MDELEM_UNREF(first_ent);
-}
-
-static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) {
-  grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap);
-  uint32_t i;
-
-  for (i = 0; i < tbl->num_ents; i++) {
-    ents[i] = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
-  }
-  gpr_free(tbl->ents);
-  tbl->ents = ents;
-  tbl->cap_entries = new_cap;
-  tbl->first_ent = 0;
-}
-
-void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
-                                     uint32_t max_bytes) {
-  if (tbl->max_bytes == max_bytes) {
-    return;
-  }
-  gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes);
-  while (tbl->mem_used > max_bytes) {
-    evict1(tbl);
-  }
-  tbl->max_bytes = max_bytes;
-}
-
-int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
-                                             uint32_t bytes) {
-  if (tbl->current_table_bytes == bytes) {
-    return 1;
-  }
-  if (bytes > tbl->max_bytes) {
-    gpr_log(GPR_ERROR,
-            "Attempt to make hpack table %d bytes when max is %d bytes", bytes,
-            tbl->max_bytes);
-    return 0;
-  }
-  gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
-  while (tbl->mem_used > bytes) {
-    evict1(tbl);
-  }
-  tbl->current_table_bytes = bytes;
-  tbl->max_entries = entries_for_bytes(bytes);
-  if (tbl->max_entries > tbl->cap_entries) {
-    rebuild_ents(tbl, GPR_MAX(tbl->max_entries, 2 * tbl->cap_entries));
-  } else if (tbl->max_entries < tbl->cap_entries / 3) {
-    uint32_t new_cap = GPR_MAX(tbl->max_entries, 16u);
-    if (new_cap != tbl->cap_entries) {
-      rebuild_ents(tbl, new_cap);
-    }
-  }
-  return 1;
-}
-
-int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
-  /* determine how many bytes of buffer this entry represents */
-  size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) +
-                      GPR_SLICE_LENGTH(md->value->slice) +
-                      GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
-
-  if (tbl->current_table_bytes > tbl->max_bytes) {
-    gpr_log(GPR_ERROR,
-            "HPACK max table size reduced to %d but not reflected by hpack "
-            "stream (still at %d)",
-            tbl->max_bytes, tbl->current_table_bytes);
-    return 0;
-  }
-
-  /* we can't add elements bigger than the max table size */
-  if (elem_bytes > tbl->current_table_bytes) {
-    /* HPACK draft 10 section 4.4 states:
-     * If the size of the new entry is less than or equal to the maximum
-     * size, that entry is added to the table.  It is not an error to
-     * attempt to add an entry that is larger than the maximum size; an
-     * attempt to add an entry larger than the entire table causes
-     * the table
-     * to be emptied of all existing entries, and results in an
-     * empty table.
-     */
-    while (tbl->num_ents) {
-      evict1(tbl);
-    }
-    return 1;
-  }
-
-  /* evict entries to ensure no overflow */
-  while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) {
-    evict1(tbl);
-  }
-
-  /* copy the finalized entry in */
-  tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] =
-      GRPC_MDELEM_REF(md);
-
-  /* update accounting values */
-  tbl->num_ents++;
-  tbl->mem_used += (uint32_t)elem_bytes;
-  return 1;
-}
-
-grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
-    const grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
-  grpc_chttp2_hptbl_find_result r = {0, 0};
-  uint32_t i;
-
-  /* See if the string is in the static table */
-  for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
-    grpc_mdelem *ent = tbl->static_ents[i];
-    if (md->key != ent->key) continue;
-    r.index = i + 1u;
-    r.has_value = md->value == ent->value;
-    if (r.has_value) return r;
-  }
-
-  /* Scan the dynamic table */
-  for (i = 0; i < tbl->num_ents; i++) {
-    uint32_t idx =
-        (uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
-    grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
-    if (md->key != ent->key) continue;
-    r.index = idx;
-    r.has_value = md->value == ent->value;
-    if (r.has_value) return r;
-  }
-
-  return r;
-}
diff --git a/src/core/transport/chttp2/hpack_table.h b/src/core/transport/chttp2/hpack_table.h
deleted file mode 100644
index 6e1b5e6..0000000
--- a/src/core/transport/chttp2/hpack_table.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_HPACK_TABLE_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_HPACK_TABLE_H
-
-#include "src/core/transport/metadata.h"
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice.h>
-
-/* HPACK header table */
-
-/* last index in the static table */
-#define GRPC_CHTTP2_LAST_STATIC_ENTRY 61
-
-/* Initial table size as per the spec */
-#define GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE 4096
-/* Maximum table size that we'll use */
-#define GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE
-/* Per entry overhead bytes as per the spec */
-#define GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD 32
-#if 0
-/* Maximum number of entries we could possibly fit in the table, given defined
-   overheads */
-#define GRPC_CHTTP2_MAX_TABLE_COUNT                                            \
-  ((GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / \
-   GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD)
-#endif
-
-/* hpack decoder table */
-typedef struct {
-  /* the first used entry in ents */
-  uint32_t first_ent;
-  /* how many entries are in the table */
-  uint32_t num_ents;
-  /* the amount of memory used by the table, according to the hpack algorithm */
-  uint32_t mem_used;
-  /* the max memory allowed to be used by the table, according to the hpack
-     algorithm */
-  uint32_t max_bytes;
-  /* the currently agreed size of the table, according to the hpack algorithm */
-  uint32_t current_table_bytes;
-  /* Maximum number of entries we could possibly fit in the table, given defined
-     overheads */
-  uint32_t max_entries;
-  /* Number of entries allocated in ents */
-  uint32_t cap_entries;
-  /* a circular buffer of headers - this is stored in the opposite order to
-     what hpack specifies, in order to simplify table management a little...
-     meaning lookups need to SUBTRACT from the end position */
-  grpc_mdelem **ents;
-  grpc_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY];
-} grpc_chttp2_hptbl;
-
-/* initialize a hpack table */
-void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl);
-void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl);
-void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
-                                     uint32_t max_bytes);
-int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
-                                             uint32_t bytes);
-
-/* lookup a table entry based on its hpack index */
-grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
-                                      uint32_t index);
-/* add a table entry to the index */
-int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
-                          grpc_mdelem *md) GRPC_MUST_USE_RESULT;
-/* Find a key/value pair in the table... returns the index in the table of the
-   most similar entry, or 0 if the value was not found */
-typedef struct {
-  uint32_t index;
-  int has_value;
-} grpc_chttp2_hptbl_find_result;
-grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
-    const grpc_chttp2_hptbl *tbl, grpc_mdelem *md);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_HPACK_TABLE_H */
diff --git a/src/core/transport/chttp2/http2_errors.h b/src/core/transport/chttp2/http2_errors.h
deleted file mode 100644
index 4290df3..0000000
--- a/src/core/transport/chttp2/http2_errors.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_HTTP2_ERRORS_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_HTTP2_ERRORS_H
-
-/* error codes for RST_STREAM from http2 draft 14 section 7 */
-typedef enum {
-  GRPC_CHTTP2_NO_ERROR = 0x0,
-  GRPC_CHTTP2_PROTOCOL_ERROR = 0x1,
-  GRPC_CHTTP2_INTERNAL_ERROR = 0x2,
-  GRPC_CHTTP2_FLOW_CONTROL_ERROR = 0x3,
-  GRPC_CHTTP2_SETTINGS_TIMEOUT = 0x4,
-  GRPC_CHTTP2_STREAM_CLOSED = 0x5,
-  GRPC_CHTTP2_FRAME_SIZE_ERROR = 0x6,
-  GRPC_CHTTP2_REFUSED_STREAM = 0x7,
-  GRPC_CHTTP2_CANCEL = 0x8,
-  GRPC_CHTTP2_COMPRESSION_ERROR = 0x9,
-  GRPC_CHTTP2_CONNECT_ERROR = 0xa,
-  GRPC_CHTTP2_ENHANCE_YOUR_CALM = 0xb,
-  GRPC_CHTTP2_INADEQUATE_SECURITY = 0xc,
-  /* force use of a default clause */
-  GRPC_CHTTP2__ERROR_DO_NOT_USE = -1
-} grpc_chttp2_error_code;
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_HTTP2_ERRORS_H */
diff --git a/src/core/transport/chttp2/huffsyms.c b/src/core/transport/chttp2/huffsyms.c
deleted file mode 100644
index 7b138e9..0000000
--- a/src/core/transport/chttp2/huffsyms.c
+++ /dev/null
@@ -1,297 +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/transport/chttp2/huffsyms.h"
-
-/* Constants pulled from the HPACK spec, and converted to C using the vim
-   command:
-   :%s/.*   \([0-9a-f]\+\)  \[ *\([0-9]\+\)\]/{0x\1, \2},/g */
-const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS] = {
-    {0x1ff8, 13},
-    {0x7fffd8, 23},
-    {0xfffffe2, 28},
-    {0xfffffe3, 28},
-    {0xfffffe4, 28},
-    {0xfffffe5, 28},
-    {0xfffffe6, 28},
-    {0xfffffe7, 28},
-    {0xfffffe8, 28},
-    {0xffffea, 24},
-    {0x3ffffffc, 30},
-    {0xfffffe9, 28},
-    {0xfffffea, 28},
-    {0x3ffffffd, 30},
-    {0xfffffeb, 28},
-    {0xfffffec, 28},
-    {0xfffffed, 28},
-    {0xfffffee, 28},
-    {0xfffffef, 28},
-    {0xffffff0, 28},
-    {0xffffff1, 28},
-    {0xffffff2, 28},
-    {0x3ffffffe, 30},
-    {0xffffff3, 28},
-    {0xffffff4, 28},
-    {0xffffff5, 28},
-    {0xffffff6, 28},
-    {0xffffff7, 28},
-    {0xffffff8, 28},
-    {0xffffff9, 28},
-    {0xffffffa, 28},
-    {0xffffffb, 28},
-    {0x14, 6},
-    {0x3f8, 10},
-    {0x3f9, 10},
-    {0xffa, 12},
-    {0x1ff9, 13},
-    {0x15, 6},
-    {0xf8, 8},
-    {0x7fa, 11},
-    {0x3fa, 10},
-    {0x3fb, 10},
-    {0xf9, 8},
-    {0x7fb, 11},
-    {0xfa, 8},
-    {0x16, 6},
-    {0x17, 6},
-    {0x18, 6},
-    {0x0, 5},
-    {0x1, 5},
-    {0x2, 5},
-    {0x19, 6},
-    {0x1a, 6},
-    {0x1b, 6},
-    {0x1c, 6},
-    {0x1d, 6},
-    {0x1e, 6},
-    {0x1f, 6},
-    {0x5c, 7},
-    {0xfb, 8},
-    {0x7ffc, 15},
-    {0x20, 6},
-    {0xffb, 12},
-    {0x3fc, 10},
-    {0x1ffa, 13},
-    {0x21, 6},
-    {0x5d, 7},
-    {0x5e, 7},
-    {0x5f, 7},
-    {0x60, 7},
-    {0x61, 7},
-    {0x62, 7},
-    {0x63, 7},
-    {0x64, 7},
-    {0x65, 7},
-    {0x66, 7},
-    {0x67, 7},
-    {0x68, 7},
-    {0x69, 7},
-    {0x6a, 7},
-    {0x6b, 7},
-    {0x6c, 7},
-    {0x6d, 7},
-    {0x6e, 7},
-    {0x6f, 7},
-    {0x70, 7},
-    {0x71, 7},
-    {0x72, 7},
-    {0xfc, 8},
-    {0x73, 7},
-    {0xfd, 8},
-    {0x1ffb, 13},
-    {0x7fff0, 19},
-    {0x1ffc, 13},
-    {0x3ffc, 14},
-    {0x22, 6},
-    {0x7ffd, 15},
-    {0x3, 5},
-    {0x23, 6},
-    {0x4, 5},
-    {0x24, 6},
-    {0x5, 5},
-    {0x25, 6},
-    {0x26, 6},
-    {0x27, 6},
-    {0x6, 5},
-    {0x74, 7},
-    {0x75, 7},
-    {0x28, 6},
-    {0x29, 6},
-    {0x2a, 6},
-    {0x7, 5},
-    {0x2b, 6},
-    {0x76, 7},
-    {0x2c, 6},
-    {0x8, 5},
-    {0x9, 5},
-    {0x2d, 6},
-    {0x77, 7},
-    {0x78, 7},
-    {0x79, 7},
-    {0x7a, 7},
-    {0x7b, 7},
-    {0x7ffe, 15},
-    {0x7fc, 11},
-    {0x3ffd, 14},
-    {0x1ffd, 13},
-    {0xffffffc, 28},
-    {0xfffe6, 20},
-    {0x3fffd2, 22},
-    {0xfffe7, 20},
-    {0xfffe8, 20},
-    {0x3fffd3, 22},
-    {0x3fffd4, 22},
-    {0x3fffd5, 22},
-    {0x7fffd9, 23},
-    {0x3fffd6, 22},
-    {0x7fffda, 23},
-    {0x7fffdb, 23},
-    {0x7fffdc, 23},
-    {0x7fffdd, 23},
-    {0x7fffde, 23},
-    {0xffffeb, 24},
-    {0x7fffdf, 23},
-    {0xffffec, 24},
-    {0xffffed, 24},
-    {0x3fffd7, 22},
-    {0x7fffe0, 23},
-    {0xffffee, 24},
-    {0x7fffe1, 23},
-    {0x7fffe2, 23},
-    {0x7fffe3, 23},
-    {0x7fffe4, 23},
-    {0x1fffdc, 21},
-    {0x3fffd8, 22},
-    {0x7fffe5, 23},
-    {0x3fffd9, 22},
-    {0x7fffe6, 23},
-    {0x7fffe7, 23},
-    {0xffffef, 24},
-    {0x3fffda, 22},
-    {0x1fffdd, 21},
-    {0xfffe9, 20},
-    {0x3fffdb, 22},
-    {0x3fffdc, 22},
-    {0x7fffe8, 23},
-    {0x7fffe9, 23},
-    {0x1fffde, 21},
-    {0x7fffea, 23},
-    {0x3fffdd, 22},
-    {0x3fffde, 22},
-    {0xfffff0, 24},
-    {0x1fffdf, 21},
-    {0x3fffdf, 22},
-    {0x7fffeb, 23},
-    {0x7fffec, 23},
-    {0x1fffe0, 21},
-    {0x1fffe1, 21},
-    {0x3fffe0, 22},
-    {0x1fffe2, 21},
-    {0x7fffed, 23},
-    {0x3fffe1, 22},
-    {0x7fffee, 23},
-    {0x7fffef, 23},
-    {0xfffea, 20},
-    {0x3fffe2, 22},
-    {0x3fffe3, 22},
-    {0x3fffe4, 22},
-    {0x7ffff0, 23},
-    {0x3fffe5, 22},
-    {0x3fffe6, 22},
-    {0x7ffff1, 23},
-    {0x3ffffe0, 26},
-    {0x3ffffe1, 26},
-    {0xfffeb, 20},
-    {0x7fff1, 19},
-    {0x3fffe7, 22},
-    {0x7ffff2, 23},
-    {0x3fffe8, 22},
-    {0x1ffffec, 25},
-    {0x3ffffe2, 26},
-    {0x3ffffe3, 26},
-    {0x3ffffe4, 26},
-    {0x7ffffde, 27},
-    {0x7ffffdf, 27},
-    {0x3ffffe5, 26},
-    {0xfffff1, 24},
-    {0x1ffffed, 25},
-    {0x7fff2, 19},
-    {0x1fffe3, 21},
-    {0x3ffffe6, 26},
-    {0x7ffffe0, 27},
-    {0x7ffffe1, 27},
-    {0x3ffffe7, 26},
-    {0x7ffffe2, 27},
-    {0xfffff2, 24},
-    {0x1fffe4, 21},
-    {0x1fffe5, 21},
-    {0x3ffffe8, 26},
-    {0x3ffffe9, 26},
-    {0xffffffd, 28},
-    {0x7ffffe3, 27},
-    {0x7ffffe4, 27},
-    {0x7ffffe5, 27},
-    {0xfffec, 20},
-    {0xfffff3, 24},
-    {0xfffed, 20},
-    {0x1fffe6, 21},
-    {0x3fffe9, 22},
-    {0x1fffe7, 21},
-    {0x1fffe8, 21},
-    {0x7ffff3, 23},
-    {0x3fffea, 22},
-    {0x3fffeb, 22},
-    {0x1ffffee, 25},
-    {0x1ffffef, 25},
-    {0xfffff4, 24},
-    {0xfffff5, 24},
-    {0x3ffffea, 26},
-    {0x7ffff4, 23},
-    {0x3ffffeb, 26},
-    {0x7ffffe6, 27},
-    {0x3ffffec, 26},
-    {0x3ffffed, 26},
-    {0x7ffffe7, 27},
-    {0x7ffffe8, 27},
-    {0x7ffffe9, 27},
-    {0x7ffffea, 27},
-    {0x7ffffeb, 27},
-    {0xffffffe, 28},
-    {0x7ffffec, 27},
-    {0x7ffffed, 27},
-    {0x7ffffee, 27},
-    {0x7ffffef, 27},
-    {0x7fffff0, 27},
-    {0x3ffffee, 26},
-    {0x3fffffff, 30},
-};
diff --git a/src/core/transport/chttp2/huffsyms.h b/src/core/transport/chttp2/huffsyms.h
deleted file mode 100644
index 9c4f09d..0000000
--- a/src/core/transport/chttp2/huffsyms.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_HUFFSYMS_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_HUFFSYMS_H
-
-/* HPACK static huffman table */
-
-#define GRPC_CHTTP2_NUM_HUFFSYMS 257
-
-typedef struct {
-  unsigned bits;
-  unsigned length;
-} grpc_chttp2_huffsym;
-
-extern const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS];
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_HUFFSYMS_H */
diff --git a/src/core/transport/chttp2/incoming_metadata.c b/src/core/transport/chttp2/incoming_metadata.c
deleted file mode 100644
index 315bc2f..0000000
--- a/src/core/transport/chttp2/incoming_metadata.c
+++ /dev/null
@@ -1,96 +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/transport/chttp2/incoming_metadata.h"
-
-#include <string.h>
-
-#include "src/core/transport/chttp2/internal.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-void grpc_chttp2_incoming_metadata_buffer_init(
-    grpc_chttp2_incoming_metadata_buffer *buffer) {
-  buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
-}
-
-void grpc_chttp2_incoming_metadata_buffer_destroy(
-    grpc_chttp2_incoming_metadata_buffer *buffer) {
-  size_t i;
-  if (!buffer->published) {
-    for (i = 0; i < buffer->count; i++) {
-      GRPC_MDELEM_UNREF(buffer->elems[i].md);
-    }
-  }
-  gpr_free(buffer->elems);
-}
-
-void grpc_chttp2_incoming_metadata_buffer_add(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) {
-  GPR_ASSERT(!buffer->published);
-  if (buffer->capacity == buffer->count) {
-    buffer->capacity = GPR_MAX(8, 2 * buffer->capacity);
-    buffer->elems =
-        gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity);
-  }
-  buffer->elems[buffer->count++].md = elem;
-}
-
-void grpc_chttp2_incoming_metadata_buffer_set_deadline(
-    grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) {
-  GPR_ASSERT(!buffer->published);
-  buffer->deadline = deadline;
-}
-
-void grpc_chttp2_incoming_metadata_buffer_publish(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) {
-  GPR_ASSERT(!buffer->published);
-  buffer->published = 1;
-  if (buffer->count > 0) {
-    size_t i;
-    for (i = 1; i < buffer->count; i++) {
-      buffer->elems[i].prev = &buffer->elems[i - 1];
-    }
-    for (i = 0; i < buffer->count - 1; i++) {
-      buffer->elems[i].next = &buffer->elems[i + 1];
-    }
-    buffer->elems[0].prev = NULL;
-    buffer->elems[buffer->count - 1].next = NULL;
-    batch->list.head = &buffer->elems[0];
-    batch->list.tail = &buffer->elems[buffer->count - 1];
-  } else {
-    batch->list.head = batch->list.tail = NULL;
-  }
-  batch->deadline = buffer->deadline;
-}
diff --git a/src/core/transport/chttp2/incoming_metadata.h b/src/core/transport/chttp2/incoming_metadata.h
deleted file mode 100644
index 52454f3..0000000
--- a/src/core/transport/chttp2/incoming_metadata.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_INCOMING_METADATA_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_INCOMING_METADATA_H
-
-#include "src/core/transport/transport.h"
-
-typedef struct {
-  grpc_linked_mdelem *elems;
-  size_t count;
-  size_t capacity;
-  gpr_timespec deadline;
-  int published;
-} grpc_chttp2_incoming_metadata_buffer;
-
-/** assumes everything initially zeroed */
-void grpc_chttp2_incoming_metadata_buffer_init(
-    grpc_chttp2_incoming_metadata_buffer *buffer);
-void grpc_chttp2_incoming_metadata_buffer_destroy(
-    grpc_chttp2_incoming_metadata_buffer *buffer);
-void grpc_chttp2_incoming_metadata_buffer_publish(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch);
-
-void grpc_chttp2_incoming_metadata_buffer_add(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem);
-void grpc_chttp2_incoming_metadata_buffer_set_deadline(
-    grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_INCOMING_METADATA_H */
diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h
deleted file mode 100644
index 0690cb3..0000000
--- a/src/core/transport/chttp2/internal.h
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_INTERNAL_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_INTERNAL_H
-
-#include <assert.h>
-#include <stdbool.h>
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/transport/chttp2/frame.h"
-#include "src/core/transport/chttp2/frame_data.h"
-#include "src/core/transport/chttp2/frame_goaway.h"
-#include "src/core/transport/chttp2/frame_ping.h"
-#include "src/core/transport/chttp2/frame_rst_stream.h"
-#include "src/core/transport/chttp2/frame_settings.h"
-#include "src/core/transport/chttp2/frame_window_update.h"
-#include "src/core/transport/chttp2/hpack_encoder.h"
-#include "src/core/transport/chttp2/hpack_parser.h"
-#include "src/core/transport/chttp2/incoming_metadata.h"
-#include "src/core/transport/chttp2/stream_map.h"
-#include "src/core/transport/connectivity_state.h"
-#include "src/core/transport/transport_impl.h"
-
-typedef struct grpc_chttp2_transport grpc_chttp2_transport;
-typedef struct grpc_chttp2_stream grpc_chttp2_stream;
-
-/* streams are kept in various linked lists depending on what things need to
-   happen to them... this enum labels each list */
-typedef enum {
-  GRPC_CHTTP2_LIST_ALL_STREAMS,
-  GRPC_CHTTP2_LIST_CHECK_READ_OPS,
-  GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE,
-  GRPC_CHTTP2_LIST_WRITABLE,
-  GRPC_CHTTP2_LIST_WRITING,
-  GRPC_CHTTP2_LIST_WRITTEN,
-  GRPC_CHTTP2_LIST_PARSING_SEEN,
-  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
-  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING,
-  GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT,
-  /* streams waiting for the outgoing window in the writing path, they will be
-   * merged to the stalled list or writable list under transport lock. */
-  GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT,
-  /** streams that are waiting to start because there are too many concurrent
-      streams on the connection */
-  GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
-  STREAM_LIST_COUNT /* must be last */
-} grpc_chttp2_stream_list_id;
-
-/* deframer state for the overall http2 stream of bytes */
-typedef enum {
-  /* prefix: one entry per http2 connection prefix byte */
-  GRPC_DTS_CLIENT_PREFIX_0 = 0,
-  GRPC_DTS_CLIENT_PREFIX_1,
-  GRPC_DTS_CLIENT_PREFIX_2,
-  GRPC_DTS_CLIENT_PREFIX_3,
-  GRPC_DTS_CLIENT_PREFIX_4,
-  GRPC_DTS_CLIENT_PREFIX_5,
-  GRPC_DTS_CLIENT_PREFIX_6,
-  GRPC_DTS_CLIENT_PREFIX_7,
-  GRPC_DTS_CLIENT_PREFIX_8,
-  GRPC_DTS_CLIENT_PREFIX_9,
-  GRPC_DTS_CLIENT_PREFIX_10,
-  GRPC_DTS_CLIENT_PREFIX_11,
-  GRPC_DTS_CLIENT_PREFIX_12,
-  GRPC_DTS_CLIENT_PREFIX_13,
-  GRPC_DTS_CLIENT_PREFIX_14,
-  GRPC_DTS_CLIENT_PREFIX_15,
-  GRPC_DTS_CLIENT_PREFIX_16,
-  GRPC_DTS_CLIENT_PREFIX_17,
-  GRPC_DTS_CLIENT_PREFIX_18,
-  GRPC_DTS_CLIENT_PREFIX_19,
-  GRPC_DTS_CLIENT_PREFIX_20,
-  GRPC_DTS_CLIENT_PREFIX_21,
-  GRPC_DTS_CLIENT_PREFIX_22,
-  GRPC_DTS_CLIENT_PREFIX_23,
-  /* frame header byte 0... */
-  /* must follow from the prefix states */
-  GRPC_DTS_FH_0,
-  GRPC_DTS_FH_1,
-  GRPC_DTS_FH_2,
-  GRPC_DTS_FH_3,
-  GRPC_DTS_FH_4,
-  GRPC_DTS_FH_5,
-  GRPC_DTS_FH_6,
-  GRPC_DTS_FH_7,
-  /* ... frame header byte 8 */
-  GRPC_DTS_FH_8,
-  /* inside a http2 frame */
-  GRPC_DTS_FRAME
-} grpc_chttp2_deframe_transport_state;
-
-typedef struct {
-  grpc_chttp2_stream *head;
-  grpc_chttp2_stream *tail;
-} grpc_chttp2_stream_list;
-
-typedef struct {
-  grpc_chttp2_stream *next;
-  grpc_chttp2_stream *prev;
-} grpc_chttp2_stream_link;
-
-/* We keep several sets of connection wide parameters */
-typedef enum {
-  /* The settings our peer has asked for (and we have acked) */
-  GRPC_PEER_SETTINGS = 0,
-  /* The settings we'd like to have */
-  GRPC_LOCAL_SETTINGS,
-  /* The settings we've published to our peer */
-  GRPC_SENT_SETTINGS,
-  /* The settings the peer has acked */
-  GRPC_ACKED_SETTINGS,
-  GRPC_NUM_SETTING_SETS
-} grpc_chttp2_setting_set;
-
-/* Outstanding ping request data */
-typedef struct grpc_chttp2_outstanding_ping {
-  uint8_t id[8];
-  grpc_closure *on_recv;
-  struct grpc_chttp2_outstanding_ping *next;
-  struct grpc_chttp2_outstanding_ping *prev;
-} grpc_chttp2_outstanding_ping;
-
-/* forward declared in frame_data.h */
-struct grpc_chttp2_incoming_byte_stream {
-  grpc_byte_stream base;
-  gpr_refcount refs;
-  struct grpc_chttp2_incoming_byte_stream *next_message;
-  int failed;
-
-  grpc_chttp2_transport *transport;
-  grpc_chttp2_stream *stream;
-  int is_tail;
-  gpr_slice_buffer slices;
-  grpc_closure *on_next;
-  gpr_slice *next;
-};
-
-typedef struct {
-  /** data to write next write */
-  gpr_slice_buffer qbuf;
-
-  /** window available for us to send to peer */
-  int64_t outgoing_window;
-  /** window available to announce to peer */
-  int64_t announce_incoming_window;
-  /** how much window would we like to have for incoming_window */
-  uint32_t connection_window_target;
-
-  /** have we seen a goaway */
-  uint8_t seen_goaway;
-  /** have we sent a goaway */
-  uint8_t sent_goaway;
-
-  /** is this transport a client? */
-  uint8_t is_client;
-  /** are the local settings dirty and need to be sent? */
-  uint8_t dirtied_local_settings;
-  /** have local settings been sent? */
-  uint8_t sent_local_settings;
-  /** bitmask of setting indexes to send out */
-  uint32_t force_send_settings;
-  /** settings values */
-  uint32_t settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
-
-  /** what is the next stream id to be allocated by this peer?
-      copied to next_stream_id in parsing when parsing commences */
-  uint32_t next_stream_id;
-
-  /** how far to lookahead in a stream? */
-  uint32_t stream_lookahead;
-
-  /** last received stream id */
-  uint32_t last_incoming_stream_id;
-
-  /** pings awaiting responses */
-  grpc_chttp2_outstanding_ping pings;
-  /** next payload for an outgoing ping */
-  uint64_t ping_counter;
-
-  /** concurrent stream count: updated when not parsing,
-      so this is a strict over-estimation on the client */
-  uint32_t concurrent_stream_count;
-} grpc_chttp2_transport_global;
-
-typedef struct {
-  /** data to write now */
-  gpr_slice_buffer outbuf;
-  /** hpack encoding */
-  grpc_chttp2_hpack_compressor hpack_compressor;
-  int64_t outgoing_window;
-  /** is this a client? */
-  uint8_t is_client;
-  /** callback for when writing is done */
-  grpc_closure done_cb;
-} grpc_chttp2_transport_writing;
-
-struct grpc_chttp2_transport_parsing {
-  /** is this transport a client? (boolean) */
-  uint8_t is_client;
-
-  /** were settings updated? */
-  uint8_t settings_updated;
-  /** was a settings ack received? */
-  uint8_t settings_ack_received;
-  /** was a goaway frame received? */
-  uint8_t goaway_received;
-
-  /** the last sent max_table_size setting */
-  uint32_t last_sent_max_table_size;
-
-  /** initial window change */
-  int64_t initial_window_update;
-
-  /** data to write later - after parsing */
-  gpr_slice_buffer qbuf;
-  /** parser for headers */
-  grpc_chttp2_hpack_parser hpack_parser;
-  /** simple one shot parsers */
-  union {
-    grpc_chttp2_window_update_parser window_update;
-    grpc_chttp2_settings_parser settings;
-    grpc_chttp2_ping_parser ping;
-    grpc_chttp2_rst_stream_parser rst_stream;
-  } simple;
-  /** parser for goaway frames */
-  grpc_chttp2_goaway_parser goaway_parser;
-
-  /** window available for peer to send to us */
-  int64_t incoming_window;
-
-  /** next stream id available at the time of beginning parsing */
-  uint32_t next_stream_id;
-  uint32_t last_incoming_stream_id;
-
-  /* deframing */
-  grpc_chttp2_deframe_transport_state deframe_state;
-  uint8_t incoming_frame_type;
-  uint8_t incoming_frame_flags;
-  uint8_t header_eof;
-  uint32_t expect_continuation_stream_id;
-  uint32_t incoming_frame_size;
-  uint32_t incoming_stream_id;
-
-  /* active parser */
-  void *parser_data;
-  grpc_chttp2_stream_parsing *incoming_stream;
-  grpc_chttp2_parse_error (*parser)(
-      grpc_exec_ctx *exec_ctx, void *parser_user_data,
-      grpc_chttp2_transport_parsing *transport_parsing,
-      grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
-
-  /* received settings */
-  uint32_t settings[GRPC_CHTTP2_NUM_SETTINGS];
-
-  /* goaway data */
-  grpc_status_code goaway_error;
-  uint32_t goaway_last_stream_index;
-  gpr_slice goaway_text;
-
-  int64_t outgoing_window;
-};
-
-struct grpc_chttp2_transport {
-  grpc_transport base; /* must be first */
-  grpc_endpoint *ep;
-  gpr_refcount refs;
-  char *peer_string;
-
-  /** when this drops to zero it's safe to shutdown the endpoint */
-  gpr_refcount shutdown_ep_refs;
-
-  gpr_mu mu;
-
-  /** is the transport destroying itself? */
-  uint8_t destroying;
-  /** has the upper layer closed the transport? */
-  uint8_t closed;
-
-  /** is a thread currently writing */
-  uint8_t writing_active;
-  /** is a thread currently parsing */
-  uint8_t parsing_active;
-
-  /** is there a read request to the endpoint outstanding? */
-  uint8_t endpoint_reading;
-
-  /** various lists of streams */
-  grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
-
-  /** global state for reading/writing */
-  grpc_chttp2_transport_global global;
-  /** state only accessible by the chain of execution that
-      set writing_active=1 */
-  grpc_chttp2_transport_writing writing;
-  /** state only accessible by the chain of execution that
-      set parsing_active=1 */
-  grpc_chttp2_transport_parsing parsing;
-
-  /** maps stream id to grpc_chttp2_stream objects;
-      owned by the parsing thread when parsing */
-  grpc_chttp2_stream_map parsing_stream_map;
-
-  /** streams created by the client (possibly during parsing);
-      merged with parsing_stream_map during unlock when no
-      parsing is occurring */
-  grpc_chttp2_stream_map new_stream_map;
-
-  /** closure to execute writing */
-  grpc_closure writing_action;
-  /** closure to finish reading from the endpoint */
-  grpc_closure recv_data;
-
-  /** incoming read bytes */
-  gpr_slice_buffer read_buffer;
-
-  /** address to place a newly accepted stream - set and unset by
-      grpc_chttp2_parsing_accept_stream; used by init_stream to
-      publish the accepted server stream */
-  grpc_chttp2_stream **accepting_stream;
-
-  struct {
-    /* accept stream callback */
-    void (*accept_stream)(grpc_exec_ctx *exec_ctx, void *user_data,
-                          grpc_transport *transport, const void *server_data);
-    void *accept_stream_user_data;
-
-    /** connectivity tracking */
-    grpc_connectivity_state_tracker state_tracker;
-  } channel_callback;
-
-  /** Transport op to be applied post-parsing */
-  grpc_transport_op *post_parsing_op;
-};
-
-typedef struct {
-  /** HTTP2 stream id for this stream, or zero if one has not been assigned */
-  uint32_t id;
-
-  /** window available for us to send to peer */
-  int64_t outgoing_window;
-  /** The number of bytes the upper layers have offered to receive.
-      As the upper layer offers more bytes, this value increases.
-      As bytes are read, this value decreases. */
-  uint32_t max_recv_bytes;
-  /** The number of bytes the upper layer has offered to read but we have
-      not yet announced to HTTP2 flow control.
-      As the upper layers offer to read more bytes, this value increases.
-      As we advertise incoming flow control window, this value decreases. */
-  uint32_t unannounced_incoming_window_for_parse;
-  uint32_t unannounced_incoming_window_for_writing;
-  /** things the upper layers would like to send */
-  grpc_metadata_batch *send_initial_metadata;
-  grpc_closure *send_initial_metadata_finished;
-  grpc_byte_stream *send_message;
-  grpc_closure *send_message_finished;
-  grpc_metadata_batch *send_trailing_metadata;
-  grpc_closure *send_trailing_metadata_finished;
-
-  grpc_metadata_batch *recv_initial_metadata;
-  grpc_closure *recv_initial_metadata_ready;
-  grpc_byte_stream **recv_message;
-  grpc_closure *recv_message_ready;
-  grpc_metadata_batch *recv_trailing_metadata;
-  grpc_closure *recv_trailing_metadata_finished;
-
-  /** when the application requests writes be closed, the write_closed is
-      'queued'; when the close is flow controlled into the send path, we are
-      'sending' it; when the write has been performed it is 'sent' */
-  uint8_t write_closed;
-  /** is this stream reading half-closed (boolean) */
-  uint8_t read_closed;
-  /** is this stream in the stream map? (boolean) */
-  uint8_t in_stream_map;
-  /** has this stream seen an error? if 1, then pending incoming frames
-      can be thrown away */
-  uint8_t seen_error;
-
-  uint8_t published_initial_metadata;
-  uint8_t published_trailing_metadata;
-  uint8_t faked_trailing_metadata;
-
-  grpc_chttp2_incoming_metadata_buffer received_initial_metadata;
-  grpc_chttp2_incoming_metadata_buffer received_trailing_metadata;
-
-  grpc_chttp2_incoming_frame_queue incoming_frames;
-} grpc_chttp2_stream_global;
-
-typedef struct {
-  /** HTTP2 stream id for this stream, or zero if one has not been assigned */
-  uint32_t id;
-  uint8_t fetching;
-  bool sent_initial_metadata;
-  uint8_t sent_message;
-  uint8_t sent_trailing_metadata;
-  uint8_t read_closed;
-  /** send this initial metadata */
-  grpc_metadata_batch *send_initial_metadata;
-  grpc_byte_stream *send_message;
-  grpc_metadata_batch *send_trailing_metadata;
-  int64_t outgoing_window;
-  /** how much window should we announce? */
-  uint32_t announce_window;
-  gpr_slice_buffer flow_controlled_buffer;
-  gpr_slice fetching_slice;
-  size_t stream_fetched;
-  grpc_closure finished_fetch;
-} grpc_chttp2_stream_writing;
-
-struct grpc_chttp2_stream_parsing {
-  /** HTTP2 stream id for this stream, or zero if one has not been assigned */
-  uint32_t id;
-  /** has this stream received a close */
-  uint8_t received_close;
-  /** saw a rst_stream */
-  uint8_t saw_rst_stream;
-  /** how many header frames have we received? */
-  uint8_t header_frames_received;
-  /** which metadata did we get (on this parse) */
-  uint8_t got_metadata_on_parse[2];
-  /** should we raise the seen_error flag in transport_global */
-  uint8_t seen_error;
-  /** window available for peer to send to us */
-  int64_t incoming_window;
-  /** parsing state for data frames */
-  grpc_chttp2_data_parser data_parser;
-  /** reason give to rst_stream */
-  uint32_t rst_stream_reason;
-  /** amount of window given */
-  int64_t outgoing_window;
-  /** number of bytes received - reset at end of parse thread execution */
-  int64_t received_bytes;
-
-  /** incoming metadata */
-  grpc_chttp2_incoming_metadata_buffer metadata_buffer[2];
-};
-
-struct grpc_chttp2_stream {
-  grpc_stream_refcount *refcount;
-  grpc_chttp2_stream_global global;
-  grpc_chttp2_stream_writing writing;
-  grpc_chttp2_stream_parsing parsing;
-
-  grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
-  uint8_t included[STREAM_LIST_COUNT];
-};
-
-/** Transport writing call flow:
-    chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
-   are required;
-    if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
-   writes.
-    Once writes have been completed (meaning another write could potentially be
-   started),
-    grpc_chttp2_terminate_writing is called. This will call
-   grpc_chttp2_cleanup_writing, at which
-    point the write phase is complete. */
-
-/** Someone is unlocking the transport mutex: check to see if writes
-    are required, and schedule them if so */
-int grpc_chttp2_unlocking_check_writes(grpc_exec_ctx *exec_ctx,
-                                       grpc_chttp2_transport_global *global,
-                                       grpc_chttp2_transport_writing *writing,
-                                       int is_parsing);
-void grpc_chttp2_perform_writes(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
-    grpc_endpoint *endpoint);
-void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
-                                   void *transport_writing, bool success);
-void grpc_chttp2_cleanup_writing(grpc_exec_ctx *exec_ctx,
-                                 grpc_chttp2_transport_global *global,
-                                 grpc_chttp2_transport_writing *writing);
-
-void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
-                                 grpc_chttp2_transport_parsing *parsing);
-/** Process one slice of incoming data; return 1 if the connection is still
-    viable after reading, or 0 if the connection should be torn down */
-int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice);
-void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx,
-                               grpc_chttp2_transport_global *global,
-                               grpc_chttp2_transport_parsing *parsing);
-
-bool grpc_chttp2_list_add_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-/** Get a writable stream
-    returns non-zero if there was a stream available */
-int grpc_chttp2_list_pop_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_writing **stream_writing);
-bool grpc_chttp2_list_remove_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) GRPC_MUST_USE_RESULT;
-
-void grpc_chttp2_list_add_writing_stream(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing);
-int grpc_chttp2_list_have_writing_streams(
-    grpc_chttp2_transport_writing *transport_writing);
-int grpc_chttp2_list_pop_writing_stream(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing **stream_writing);
-
-void grpc_chttp2_list_add_written_stream(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing);
-int grpc_chttp2_list_pop_written_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_writing **stream_writing);
-
-void grpc_chttp2_list_add_parsing_seen_stream(
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing);
-int grpc_chttp2_list_pop_parsing_seen_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_parsing **stream_parsing);
-
-void grpc_chttp2_list_add_waiting_for_concurrency(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-int grpc_chttp2_list_pop_waiting_for_concurrency(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global);
-
-void grpc_chttp2_list_add_check_read_ops(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-int grpc_chttp2_list_pop_check_read_ops(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global);
-
-void grpc_chttp2_list_add_writing_stalled_by_transport(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing);
-void grpc_chttp2_list_flush_writing_stalled_by_transport(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
-    bool is_window_available);
-
-void grpc_chttp2_list_add_stalled_by_transport(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing);
-int grpc_chttp2_list_pop_stalled_by_transport(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global);
-void grpc_chttp2_list_remove_stalled_by_transport(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-
-void grpc_chttp2_list_add_unannounced_incoming_window_available(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-void grpc_chttp2_list_remove_unannounced_incoming_window_available(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-int grpc_chttp2_list_pop_unannounced_incoming_window_available(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_parsing **stream_parsing);
-
-void grpc_chttp2_list_add_closed_waiting_for_parsing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-int grpc_chttp2_list_pop_closed_waiting_for_parsing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global);
-
-void grpc_chttp2_list_add_closed_waiting_for_writing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
-int grpc_chttp2_list_pop_closed_waiting_for_writing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global);
-
-grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
-    grpc_chttp2_transport_parsing *transport_parsing, uint32_t id);
-grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    uint32_t id);
-
-void grpc_chttp2_add_incoming_goaway(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    uint32_t goaway_error, gpr_slice goaway_text);
-
-void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
-                                 grpc_chttp2_stream *s);
-/* returns 1 if this is the last stream, 0 otherwise */
-int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
-                                  grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
-int grpc_chttp2_has_streams(grpc_chttp2_transport *t);
-void grpc_chttp2_for_all_streams(
-    grpc_chttp2_transport_global *transport_global, void *user_data,
-    void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
-               grpc_chttp2_stream_global *stream_global));
-
-void grpc_chttp2_parsing_become_skip_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-
-void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
-                                       grpc_closure **pclosure, int success);
-
-#define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
-#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
-  (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
-
-extern int grpc_http_trace;
-extern int grpc_flowctl_trace;
-
-#define GRPC_CHTTP2_IF_TRACING(stmt) \
-  if (!(grpc_http_trace))            \
-    ;                                \
-  else                               \
-  stmt
-
-typedef enum {
-  GRPC_CHTTP2_FLOWCTL_MOVE,
-  GRPC_CHTTP2_FLOWCTL_CREDIT,
-  GRPC_CHTTP2_FLOWCTL_DEBIT
-} grpc_chttp2_flowctl_op;
-
-#define GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, id1, id2, dst_context, \
-                                     dst_var, src_context, src_var)           \
-  do {                                                                        \
-    assert(id1 == id2);                                                       \
-    if (grpc_flowctl_trace) {                                                 \
-      grpc_chttp2_flowctl_trace(                                              \
-          __FILE__, __LINE__, phase, GRPC_CHTTP2_FLOWCTL_MOVE, #dst_context,  \
-          #dst_var, #src_context, #src_var, transport->is_client, id1,        \
-          dst_context->dst_var, src_context->src_var);                        \
-    }                                                                         \
-    dst_context->dst_var += src_context->src_var;                             \
-    src_context->src_var = 0;                                                 \
-  } while (0)
-
-#define GRPC_CHTTP2_FLOW_MOVE_STREAM(phase, transport, dst_context, dst_var, \
-                                     src_context, src_var)                   \
-  GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, dst_context->id,            \
-                               src_context->id, dst_context, dst_var,        \
-                               src_context, src_var)
-#define GRPC_CHTTP2_FLOW_MOVE_TRANSPORT(phase, dst_context, dst_var,           \
-                                        src_context, src_var)                  \
-  GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, dst_context, 0, 0, dst_context, dst_var, \
-                               src_context, src_var)
-
-#define GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, id, dst_context,      \
-                                       dst_var, amount)                        \
-  do {                                                                         \
-    if (grpc_flowctl_trace) {                                                  \
-      grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase,                     \
-                                GRPC_CHTTP2_FLOWCTL_CREDIT, #dst_context,      \
-                                #dst_var, NULL, #amount, transport->is_client, \
-                                id, dst_context->dst_var, amount);             \
-    }                                                                          \
-    dst_context->dst_var += amount;                                            \
-  } while (0)
-
-#define GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, dst_var, \
-                                       amount)                                 \
-  GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, dst_context->id,            \
-                                 dst_context, dst_var, amount)
-#define GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT(phase, dst_context, dst_var, amount) \
-  GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var,  \
-                                 amount)
-
-#define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context,       \
-                                      dst_var, amount)                         \
-  do {                                                                         \
-    if (grpc_flowctl_trace) {                                                  \
-      grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase,                     \
-                                GRPC_CHTTP2_FLOWCTL_DEBIT, #dst_context,       \
-                                #dst_var, NULL, #amount, transport->is_client, \
-                                id, dst_context->dst_var, amount);             \
-    }                                                                          \
-    dst_context->dst_var -= amount;                                            \
-  } while (0)
-
-#define GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, dst_var, \
-                                      amount)                                 \
-  GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, dst_context->id,            \
-                                dst_context, dst_var, amount)
-#define GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT(phase, dst_context, dst_var, amount) \
-  GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, dst_context, 0, dst_context, dst_var,  \
-                                amount)
-
-void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
-                               grpc_chttp2_flowctl_op op, const char *context1,
-                               const char *var1, const char *context2,
-                               const char *var2, int is_client,
-                               uint32_t stream_id, int64_t val1, int64_t val2);
-
-void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_global *transport_global,
-                             grpc_chttp2_stream_global *stream,
-                             grpc_status_code status, gpr_slice *details);
-void grpc_chttp2_mark_stream_closed(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, int close_reads,
-    int close_writes);
-void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx,
-                               grpc_chttp2_transport_global *transport_global);
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-#define GRPC_CHTTP2_STREAM_REF(stream_global, reason) \
-  grpc_chttp2_stream_ref(stream_global, reason)
-#define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, reason) \
-  grpc_chttp2_stream_unref(exec_ctx, stream_global, reason)
-void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global,
-                            const char *reason);
-void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_stream_global *stream_global,
-                              const char *reason);
-#else
-#define GRPC_CHTTP2_STREAM_REF(stream_global, reason) \
-  grpc_chttp2_stream_ref(stream_global)
-#define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, reason) \
-  grpc_chttp2_stream_unref(exec_ctx, stream_global)
-void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global);
-void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_stream_global *stream_global);
-#endif
-
-grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, uint32_t frame_size,
-    uint32_t flags, grpc_chttp2_incoming_frame_queue *add_to_queue);
-void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
-                                           grpc_chttp2_incoming_byte_stream *bs,
-                                           gpr_slice slice);
-void grpc_chttp2_incoming_byte_stream_finished(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
-    int from_parsing_thread);
-
-void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
-                          grpc_chttp2_transport_parsing *parsing,
-                          const uint8_t *opaque_8bytes);
-
-/** add a ref to the stream and add it to the writable list;
-    ref will be dropped in writing.c */
-void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
-                                 grpc_chttp2_stream_global *stream_global);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_INTERNAL_H */
diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c
deleted file mode 100644
index 0516f39..0000000
--- a/src/core/transport/chttp2/parsing.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- *
- * 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/transport/chttp2/internal.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/profiling/timers.h"
-#include "src/core/transport/chttp2/http2_errors.h"
-#include "src/core/transport/chttp2/status_conversion.h"
-#include "src/core/transport/chttp2/timeout_encoding.h"
-#include "src/core/transport/static_metadata.h"
-
-static int init_frame_parser(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing);
-static int init_header_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    int is_continuation);
-static int init_data_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_rst_stream_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_settings_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_window_update_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_ping_parser(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_parsing *transport_parsing);
-static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_transport_parsing *transport_parsing);
-static int init_skip_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    int is_header);
-
-static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice, int is_last);
-
-void grpc_chttp2_prepare_to_read(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_parsing *transport_parsing) {
-  grpc_chttp2_stream_global *stream_global;
-  grpc_chttp2_stream_parsing *stream_parsing;
-
-  GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
-
-  transport_parsing->next_stream_id = transport_global->next_stream_id;
-  transport_parsing->last_sent_max_table_size =
-      transport_global->settings[GRPC_SENT_SETTINGS]
-                                [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
-
-  /* update the parsing view of incoming window */
-  while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
-      transport_global, transport_parsing, &stream_global, &stream_parsing)) {
-    GRPC_CHTTP2_FLOW_MOVE_STREAM("parse", transport_parsing, stream_parsing,
-                                 incoming_window, stream_global,
-                                 unannounced_incoming_window_for_parse);
-  }
-
-  GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0);
-}
-
-void grpc_chttp2_publish_reads(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_parsing *transport_parsing) {
-  grpc_chttp2_stream_global *stream_global;
-  grpc_chttp2_stream_parsing *stream_parsing;
-  int was_zero;
-  int is_zero;
-
-  /* transport_parsing->last_incoming_stream_id is used as
-     last-grpc_chttp2_stream-id when
-     sending GOAWAY frame.
-     https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
-     says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
-     ID.  So,
-     since we don't have server pushed streams, client should send
-     GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
-  if (!transport_parsing->is_client) {
-    transport_global->last_incoming_stream_id =
-        transport_parsing->incoming_stream_id;
-  }
-
-  /* update global settings */
-  if (transport_parsing->settings_updated) {
-    memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
-           transport_parsing->settings, sizeof(transport_parsing->settings));
-    transport_parsing->settings_updated = 0;
-  }
-
-  /* update settings based on ack if received */
-  if (transport_parsing->settings_ack_received) {
-    memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
-           transport_global->settings[GRPC_SENT_SETTINGS],
-           GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
-    transport_parsing->settings_ack_received = 0;
-    transport_global->sent_local_settings = 0;
-  }
-
-  /* move goaway to the global state if we received one (it will be
-     published later */
-  if (transport_parsing->goaway_received) {
-    grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
-                                    (uint32_t)transport_parsing->goaway_error,
-                                    transport_parsing->goaway_text);
-    transport_parsing->goaway_text = gpr_empty_slice();
-    transport_parsing->goaway_received = 0;
-  }
-
-  /* propagate flow control tokens to global state */
-  was_zero = transport_global->outgoing_window <= 0;
-  GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window,
-                                  transport_parsing, outgoing_window);
-  is_zero = transport_global->outgoing_window <= 0;
-  if (was_zero && !is_zero) {
-    while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
-                                                     &stream_global)) {
-      grpc_chttp2_become_writable(transport_global, stream_global);
-    }
-  }
-
-  if (transport_parsing->incoming_window <
-      transport_global->connection_window_target * 3 / 4) {
-    int64_t announce_bytes = transport_global->connection_window_target -
-                             transport_parsing->incoming_window;
-    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global,
-                                      announce_incoming_window, announce_bytes);
-    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
-                                      incoming_window, announce_bytes);
-  }
-
-  /* for each stream that saw an update, fixup global state */
-  while (grpc_chttp2_list_pop_parsing_seen_stream(
-      transport_global, transport_parsing, &stream_global, &stream_parsing)) {
-    if (stream_parsing->seen_error) {
-      stream_global->seen_error = 1;
-      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-    }
-
-    /* update outgoing flow control window */
-    was_zero = stream_global->outgoing_window <= 0;
-    GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global,
-                                 outgoing_window, stream_parsing,
-                                 outgoing_window);
-    is_zero = stream_global->outgoing_window <= 0;
-    if (was_zero && !is_zero) {
-      grpc_chttp2_become_writable(transport_global, stream_global);
-    }
-
-    stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(
-        stream_global->max_recv_bytes, stream_parsing->received_bytes);
-    stream_parsing->received_bytes = 0;
-
-    /* publish incoming stream ops */
-    if (stream_global->incoming_frames.tail != NULL) {
-      stream_global->incoming_frames.tail->is_tail = 0;
-    }
-    if (stream_parsing->data_parser.incoming_frames.head != NULL) {
-      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-    }
-    grpc_chttp2_incoming_frame_queue_merge(
-        &stream_global->incoming_frames,
-        &stream_parsing->data_parser.incoming_frames);
-    if (stream_global->incoming_frames.tail != NULL) {
-      stream_global->incoming_frames.tail->is_tail = 1;
-    }
-
-    if (!stream_global->published_initial_metadata &&
-        stream_parsing->got_metadata_on_parse[0]) {
-      stream_parsing->got_metadata_on_parse[0] = 0;
-      stream_global->published_initial_metadata = 1;
-      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
-               stream_parsing->metadata_buffer[0],
-               stream_global->received_initial_metadata);
-      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-    }
-    if (!stream_global->published_trailing_metadata &&
-        stream_parsing->got_metadata_on_parse[1]) {
-      stream_parsing->got_metadata_on_parse[1] = 0;
-      stream_global->published_trailing_metadata = 1;
-      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
-               stream_parsing->metadata_buffer[1],
-               stream_global->received_trailing_metadata);
-      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-    }
-
-    if (stream_parsing->saw_rst_stream) {
-      if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
-        grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
-            (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
-        char *status_details;
-        gpr_slice slice_details;
-        gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
-                     stream_parsing->rst_stream_reason);
-        slice_details = gpr_slice_from_copied_string(status_details);
-        gpr_free(status_details);
-        grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
-                                status_code, &slice_details);
-      }
-      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
-                                     1, 1);
-    }
-
-    if (stream_parsing->received_close) {
-      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
-                                     1, 0);
-    }
-  }
-}
-
-int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice) {
-  uint8_t *beg = GPR_SLICE_START_PTR(slice);
-  uint8_t *end = GPR_SLICE_END_PTR(slice);
-  uint8_t *cur = beg;
-
-  if (cur == end) return 1;
-
-  switch (transport_parsing->deframe_state) {
-    case GRPC_DTS_CLIENT_PREFIX_0:
-    case GRPC_DTS_CLIENT_PREFIX_1:
-    case GRPC_DTS_CLIENT_PREFIX_2:
-    case GRPC_DTS_CLIENT_PREFIX_3:
-    case GRPC_DTS_CLIENT_PREFIX_4:
-    case GRPC_DTS_CLIENT_PREFIX_5:
-    case GRPC_DTS_CLIENT_PREFIX_6:
-    case GRPC_DTS_CLIENT_PREFIX_7:
-    case GRPC_DTS_CLIENT_PREFIX_8:
-    case GRPC_DTS_CLIENT_PREFIX_9:
-    case GRPC_DTS_CLIENT_PREFIX_10:
-    case GRPC_DTS_CLIENT_PREFIX_11:
-    case GRPC_DTS_CLIENT_PREFIX_12:
-    case GRPC_DTS_CLIENT_PREFIX_13:
-    case GRPC_DTS_CLIENT_PREFIX_14:
-    case GRPC_DTS_CLIENT_PREFIX_15:
-    case GRPC_DTS_CLIENT_PREFIX_16:
-    case GRPC_DTS_CLIENT_PREFIX_17:
-    case GRPC_DTS_CLIENT_PREFIX_18:
-    case GRPC_DTS_CLIENT_PREFIX_19:
-    case GRPC_DTS_CLIENT_PREFIX_20:
-    case GRPC_DTS_CLIENT_PREFIX_21:
-    case GRPC_DTS_CLIENT_PREFIX_22:
-    case GRPC_DTS_CLIENT_PREFIX_23:
-      while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
-        if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
-                                                          ->deframe_state]) {
-          gpr_log(GPR_INFO,
-                  "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
-                  "at byte %d",
-                  GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
-                                                        ->deframe_state],
-                  (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
-                      [transport_parsing->deframe_state],
-                  *cur, (int)*cur, transport_parsing->deframe_state);
-          return 0;
-        }
-        ++cur;
-        ++transport_parsing->deframe_state;
-      }
-      if (cur == end) {
-        return 1;
-      }
-    /* fallthrough */
-    dts_fh_0:
-    case GRPC_DTS_FH_0:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_1;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_1:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_2;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_2:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_frame_size |= *cur;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_3;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_3:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_frame_type = *cur;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_4;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_4:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_frame_flags = *cur;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_5;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_5:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_6;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_6:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_7;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_7:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8;
-      if (++cur == end) {
-        transport_parsing->deframe_state = GRPC_DTS_FH_8;
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FH_8:
-      GPR_ASSERT(cur < end);
-      transport_parsing->incoming_stream_id |= ((uint32_t)*cur);
-      transport_parsing->deframe_state = GRPC_DTS_FRAME;
-      if (!init_frame_parser(exec_ctx, transport_parsing)) {
-        return 0;
-      }
-      if (transport_parsing->incoming_stream_id) {
-        transport_parsing->last_incoming_stream_id =
-            transport_parsing->incoming_stream_id;
-      }
-      if (transport_parsing->incoming_frame_size == 0) {
-        if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
-                               1)) {
-          return 0;
-        }
-        transport_parsing->incoming_stream = NULL;
-        if (++cur == end) {
-          transport_parsing->deframe_state = GRPC_DTS_FH_0;
-          return 1;
-        }
-        goto dts_fh_0; /* loop */
-      }
-      if (++cur == end) {
-        return 1;
-      }
-    /* fallthrough */
-    case GRPC_DTS_FRAME:
-      GPR_ASSERT(cur < end);
-      if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) {
-        if (!parse_frame_slice(exec_ctx, transport_parsing,
-                               gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
-                                                    (size_t)(end - beg)),
-                               1)) {
-          return 0;
-        }
-        transport_parsing->deframe_state = GRPC_DTS_FH_0;
-        transport_parsing->incoming_stream = NULL;
-        return 1;
-      } else if ((uint32_t)(end - cur) >
-                 transport_parsing->incoming_frame_size) {
-        size_t cur_offset = (size_t)(cur - beg);
-        if (!parse_frame_slice(
-                exec_ctx, transport_parsing,
-                gpr_slice_sub_no_ref(
-                    slice, cur_offset,
-                    cur_offset + transport_parsing->incoming_frame_size),
-                1)) {
-          return 0;
-        }
-        cur += transport_parsing->incoming_frame_size;
-        transport_parsing->incoming_stream = NULL;
-        goto dts_fh_0; /* loop */
-      } else {
-        if (!parse_frame_slice(exec_ctx, transport_parsing,
-                               gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
-                                                    (size_t)(end - beg)),
-                               0)) {
-          return 0;
-        }
-        transport_parsing->incoming_frame_size -= (uint32_t)(end - cur);
-        return 1;
-      }
-      GPR_UNREACHABLE_CODE(return 0);
-  }
-
-  GPR_UNREACHABLE_CODE(return 0);
-}
-
-static int init_frame_parser(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing) {
-  if (transport_parsing->expect_continuation_stream_id != 0) {
-    if (transport_parsing->incoming_frame_type !=
-        GRPC_CHTTP2_FRAME_CONTINUATION) {
-      gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
-              transport_parsing->incoming_frame_type);
-      return 0;
-    }
-    if (transport_parsing->expect_continuation_stream_id !=
-        transport_parsing->incoming_stream_id) {
-      gpr_log(GPR_ERROR,
-              "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
-              "grpc_chttp2_stream %08x",
-              transport_parsing->expect_continuation_stream_id,
-              transport_parsing->incoming_stream_id);
-      return 0;
-    }
-    return init_header_frame_parser(exec_ctx, transport_parsing, 1);
-  }
-  switch (transport_parsing->incoming_frame_type) {
-    case GRPC_CHTTP2_FRAME_DATA:
-      return init_data_frame_parser(exec_ctx, transport_parsing);
-    case GRPC_CHTTP2_FRAME_HEADER:
-      return init_header_frame_parser(exec_ctx, transport_parsing, 0);
-    case GRPC_CHTTP2_FRAME_CONTINUATION:
-      gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
-      return 0;
-    case GRPC_CHTTP2_FRAME_RST_STREAM:
-      return init_rst_stream_parser(exec_ctx, transport_parsing);
-    case GRPC_CHTTP2_FRAME_SETTINGS:
-      return init_settings_frame_parser(exec_ctx, transport_parsing);
-    case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
-      return init_window_update_frame_parser(exec_ctx, transport_parsing);
-    case GRPC_CHTTP2_FRAME_PING:
-      return init_ping_parser(exec_ctx, transport_parsing);
-    case GRPC_CHTTP2_FRAME_GOAWAY:
-      return init_goaway_parser(exec_ctx, transport_parsing);
-    default:
-      gpr_log(GPR_ERROR, "Unknown frame type %02x",
-              transport_parsing->incoming_frame_type);
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
-  }
-}
-
-static grpc_chttp2_parse_error skip_parser(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
-
-static int init_skip_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    int is_header) {
-  if (is_header) {
-    uint8_t is_eoh = transport_parsing->expect_continuation_stream_id != 0;
-    transport_parsing->parser = grpc_chttp2_header_parser_parse;
-    transport_parsing->parser_data = &transport_parsing->hpack_parser;
-    transport_parsing->hpack_parser.on_header = skip_header;
-    transport_parsing->hpack_parser.on_header_user_data = NULL;
-    transport_parsing->hpack_parser.is_boundary = is_eoh;
-    transport_parsing->hpack_parser.is_eof =
-        (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
-  } else {
-    transport_parsing->parser = skip_parser;
-  }
-  return 1;
-}
-
-void grpc_chttp2_parsing_become_skip_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  init_skip_frame_parser(
-      exec_ctx, transport_parsing,
-      transport_parsing->parser == grpc_chttp2_header_parser_parse);
-}
-
-static grpc_chttp2_parse_error update_incoming_window(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing) {
-  uint32_t incoming_frame_size = transport_parsing->incoming_frame_size;
-  if (incoming_frame_size > transport_parsing->incoming_window) {
-    gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
-            transport_parsing->incoming_frame_size,
-            transport_parsing->incoming_window);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  }
-
-  if (incoming_frame_size > stream_parsing->incoming_window) {
-    gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
-            transport_parsing->incoming_frame_size,
-            stream_parsing->incoming_window);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
-  }
-
-  GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
-                                   incoming_frame_size);
-  GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", transport_parsing, stream_parsing,
-                                incoming_window, incoming_frame_size);
-  stream_parsing->received_bytes += incoming_frame_size;
-
-  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
-
-  return GRPC_CHTTP2_PARSE_OK;
-}
-
-static int init_data_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  grpc_chttp2_stream_parsing *stream_parsing =
-      grpc_chttp2_parsing_lookup_stream(transport_parsing,
-                                        transport_parsing->incoming_stream_id);
-  grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
-  if (!stream_parsing || stream_parsing->received_close)
-    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
-  if (err == GRPC_CHTTP2_PARSE_OK) {
-    err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
-  }
-  if (err == GRPC_CHTTP2_PARSE_OK) {
-    err = grpc_chttp2_data_parser_begin_frame(
-        &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
-  }
-  switch (err) {
-    case GRPC_CHTTP2_PARSE_OK:
-      transport_parsing->incoming_stream = stream_parsing;
-      transport_parsing->parser = grpc_chttp2_data_parser_parse;
-      transport_parsing->parser_data = &stream_parsing->data_parser;
-      return 1;
-    case GRPC_CHTTP2_STREAM_ERROR:
-      stream_parsing->received_close = 1;
-      stream_parsing->saw_rst_stream = 1;
-      stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
-      gpr_slice_buffer_add(
-          &transport_parsing->qbuf,
-          grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
-                                        GRPC_CHTTP2_PROTOCOL_ERROR));
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
-    case GRPC_CHTTP2_CONNECTION_ERROR:
-      return 0;
-  }
-  GPR_UNREACHABLE_CODE(return 0);
-}
-
-static void free_timeout(void *p) { gpr_free(p); }
-
-static void on_initial_header(void *tp, grpc_mdelem *md) {
-  grpc_chttp2_transport_parsing *transport_parsing = tp;
-  grpc_chttp2_stream_parsing *stream_parsing =
-      transport_parsing->incoming_stream;
-
-  GPR_TIMER_BEGIN("on_initial_header", 0);
-
-  GPR_ASSERT(stream_parsing);
-
-  GRPC_CHTTP2_IF_TRACING(gpr_log(
-      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
-      transport_parsing->is_client ? "CLI" : "SVR",
-      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
-
-  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
-    /* TODO(ctiller): check for a status like " 0" */
-    stream_parsing->seen_error = 1;
-  }
-
-  if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
-    gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
-    if (!cached_timeout) {
-      /* not already parsed: parse it now, and store the result away */
-      cached_timeout = gpr_malloc(sizeof(gpr_timespec));
-      if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
-                                      cached_timeout)) {
-        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
-                grpc_mdstr_as_c_string(md->value));
-        *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
-      }
-      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
-    }
-    grpc_chttp2_incoming_metadata_buffer_set_deadline(
-        &stream_parsing->metadata_buffer[0],
-        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
-    GRPC_MDELEM_UNREF(md);
-  } else {
-    grpc_chttp2_incoming_metadata_buffer_add(
-        &stream_parsing->metadata_buffer[0], md);
-  }
-
-  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
-
-  GPR_TIMER_END("on_initial_header", 0);
-}
-
-static void on_trailing_header(void *tp, grpc_mdelem *md) {
-  grpc_chttp2_transport_parsing *transport_parsing = tp;
-  grpc_chttp2_stream_parsing *stream_parsing =
-      transport_parsing->incoming_stream;
-
-  GPR_TIMER_BEGIN("on_trailing_header", 0);
-
-  GPR_ASSERT(stream_parsing);
-
-  GRPC_CHTTP2_IF_TRACING(gpr_log(
-      GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", stream_parsing->id,
-      transport_parsing->is_client ? "CLI" : "SVR",
-      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
-
-  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
-    /* TODO(ctiller): check for a status like " 0" */
-    stream_parsing->seen_error = 1;
-  }
-
-  grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1],
-                                           md);
-
-  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
-
-  GPR_TIMER_END("on_trailing_header", 0);
-}
-
-static int init_header_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    int is_continuation) {
-  uint8_t is_eoh = (transport_parsing->incoming_frame_flags &
-                    GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
-  int via_accept = 0;
-  grpc_chttp2_stream_parsing *stream_parsing;
-
-  /* TODO(ctiller): when to increment header_frames_received? */
-
-  if (is_eoh) {
-    transport_parsing->expect_continuation_stream_id = 0;
-  } else {
-    transport_parsing->expect_continuation_stream_id =
-        transport_parsing->incoming_stream_id;
-  }
-
-  if (!is_continuation) {
-    transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
-                                     GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
-  }
-
-  /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
-  stream_parsing = grpc_chttp2_parsing_lookup_stream(
-      transport_parsing, transport_parsing->incoming_stream_id);
-  if (stream_parsing == NULL) {
-    if (is_continuation) {
-      gpr_log(GPR_ERROR,
-              "grpc_chttp2_stream disbanded before CONTINUATION received");
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
-    }
-    if (transport_parsing->is_client) {
-      if ((transport_parsing->incoming_stream_id & 1) &&
-          transport_parsing->incoming_stream_id <
-              transport_parsing->next_stream_id) {
-        /* this is an old (probably cancelled) grpc_chttp2_stream */
-      } else {
-        gpr_log(GPR_ERROR,
-                "ignoring new grpc_chttp2_stream creation on client");
-      }
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
-    } else if (transport_parsing->last_incoming_stream_id >
-               transport_parsing->incoming_stream_id) {
-      gpr_log(GPR_ERROR,
-              "ignoring out of order new grpc_chttp2_stream request on server; "
-              "last grpc_chttp2_stream "
-              "id=%d, new grpc_chttp2_stream id=%d",
-              transport_parsing->last_incoming_stream_id,
-              transport_parsing->incoming_stream_id);
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
-    } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
-      gpr_log(GPR_ERROR,
-              "ignoring grpc_chttp2_stream with non-client generated index %d",
-              transport_parsing->incoming_stream_id);
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
-    }
-    stream_parsing = transport_parsing->incoming_stream =
-        grpc_chttp2_parsing_accept_stream(
-            exec_ctx, transport_parsing, transport_parsing->incoming_stream_id);
-    if (stream_parsing == NULL) {
-      gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
-    }
-    via_accept = 1;
-  } else {
-    transport_parsing->incoming_stream = stream_parsing;
-  }
-  GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
-  if (stream_parsing->received_close) {
-    gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
-    transport_parsing->incoming_stream = NULL;
-    return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
-  }
-  transport_parsing->parser = grpc_chttp2_header_parser_parse;
-  transport_parsing->parser_data = &transport_parsing->hpack_parser;
-  switch (stream_parsing->header_frames_received) {
-    case 0:
-      transport_parsing->hpack_parser.on_header = on_initial_header;
-      break;
-    case 1:
-      transport_parsing->hpack_parser.on_header = on_trailing_header;
-      break;
-    case 2:
-      gpr_log(GPR_ERROR, "too many header frames received");
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
-  }
-  transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
-  transport_parsing->hpack_parser.is_boundary = is_eoh;
-  transport_parsing->hpack_parser.is_eof =
-      (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
-  if (!is_continuation && (transport_parsing->incoming_frame_flags &
-                           GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
-    grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
-  }
-  return 1;
-}
-
-static int init_window_update_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
-                                       &transport_parsing->simple.window_update,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
-  if (transport_parsing->incoming_stream_id) {
-    transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
-        transport_parsing, transport_parsing->incoming_stream_id);
-  }
-  transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
-  transport_parsing->parser_data = &transport_parsing->simple.window_update;
-  return ok;
-}
-
-static int init_ping_parser(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
-                                       &transport_parsing->simple.ping,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
-  transport_parsing->parser = grpc_chttp2_ping_parser_parse;
-  transport_parsing->parser_data = &transport_parsing->simple.ping;
-  return ok;
-}
-
-static int init_rst_stream_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
-                                       &transport_parsing->simple.rst_stream,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
-  transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
-      transport_parsing, transport_parsing->incoming_stream_id);
-  if (!transport_parsing->incoming_stream) {
-    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
-  }
-  transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
-  transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
-  return ok;
-}
-
-static int init_goaway_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
-                                       &transport_parsing->goaway_parser,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
-  transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
-  transport_parsing->parser_data = &transport_parsing->goaway_parser;
-  return ok;
-}
-
-static int init_settings_frame_parser(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok;
-
-  if (transport_parsing->incoming_stream_id != 0) {
-    gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
-            transport_parsing->incoming_stream_id);
-    return 0;
-  }
-
-  ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
-                                   &transport_parsing->simple.settings,
-                                   transport_parsing->incoming_frame_size,
-                                   transport_parsing->incoming_frame_flags,
-                                   transport_parsing->settings);
-  if (!ok) {
-    return 0;
-  }
-  if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
-    transport_parsing->settings_ack_received = 1;
-    grpc_chttp2_hptbl_set_max_bytes(
-        &transport_parsing->hpack_parser.table,
-        transport_parsing->last_sent_max_table_size);
-  }
-  transport_parsing->parser = grpc_chttp2_settings_parser_parse;
-  transport_parsing->parser_data = &transport_parsing->simple.settings;
-  return ok;
-}
-
-/*
-static int is_window_update_legal(int64_t window_update, int64_t window) {
-  return window + window_update < MAX_WINDOW;
-}
-*/
-
-static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice, int is_last) {
-  grpc_chttp2_stream_parsing *stream_parsing =
-      transport_parsing->incoming_stream;
-  switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
-                                    transport_parsing, stream_parsing, slice,
-                                    is_last)) {
-    case GRPC_CHTTP2_PARSE_OK:
-      if (stream_parsing) {
-        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
-                                                 stream_parsing);
-      }
-      return 1;
-    case GRPC_CHTTP2_STREAM_ERROR:
-      grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
-      if (stream_parsing) {
-        stream_parsing->saw_rst_stream = 1;
-        stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
-        gpr_slice_buffer_add(
-            &transport_parsing->qbuf,
-            grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
-                                          GRPC_CHTTP2_PROTOCOL_ERROR));
-      }
-      return 1;
-    case GRPC_CHTTP2_CONNECTION_ERROR:
-      return 0;
-  }
-  GPR_UNREACHABLE_CODE(return 0);
-}
diff --git a/src/core/transport/chttp2/status_conversion.c b/src/core/transport/chttp2/status_conversion.c
deleted file mode 100644
index bf214b0..0000000
--- a/src/core/transport/chttp2/status_conversion.c
+++ /dev/null
@@ -1,109 +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/transport/chttp2/status_conversion.h"
-
-int grpc_chttp2_grpc_status_to_http2_error(grpc_status_code status) {
-  switch (status) {
-    case GRPC_STATUS_OK:
-      return GRPC_CHTTP2_NO_ERROR;
-    case GRPC_STATUS_CANCELLED:
-      return GRPC_CHTTP2_CANCEL;
-    case GRPC_STATUS_RESOURCE_EXHAUSTED:
-      return GRPC_CHTTP2_ENHANCE_YOUR_CALM;
-    case GRPC_STATUS_PERMISSION_DENIED:
-      return GRPC_CHTTP2_INADEQUATE_SECURITY;
-    case GRPC_STATUS_UNAVAILABLE:
-      return GRPC_CHTTP2_REFUSED_STREAM;
-    default:
-      return GRPC_CHTTP2_INTERNAL_ERROR;
-  }
-}
-
-grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
-    grpc_chttp2_error_code error) {
-  switch (error) {
-    case GRPC_CHTTP2_NO_ERROR:
-      /* should never be received */
-      return GRPC_STATUS_INTERNAL;
-    case GRPC_CHTTP2_CANCEL:
-      return GRPC_STATUS_CANCELLED;
-    case GRPC_CHTTP2_ENHANCE_YOUR_CALM:
-      return GRPC_STATUS_RESOURCE_EXHAUSTED;
-    case GRPC_CHTTP2_INADEQUATE_SECURITY:
-      return GRPC_STATUS_PERMISSION_DENIED;
-    case GRPC_CHTTP2_REFUSED_STREAM:
-      return GRPC_STATUS_UNAVAILABLE;
-    default:
-      return GRPC_STATUS_INTERNAL;
-  }
-}
-
-grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status) {
-  switch (status) {
-    /* these HTTP2 status codes are called out explicitly in status.proto */
-    case 200:
-      return GRPC_STATUS_OK;
-    case 400:
-      return GRPC_STATUS_INVALID_ARGUMENT;
-    case 401:
-      return GRPC_STATUS_UNAUTHENTICATED;
-    case 403:
-      return GRPC_STATUS_PERMISSION_DENIED;
-    case 404:
-      return GRPC_STATUS_NOT_FOUND;
-    case 409:
-      return GRPC_STATUS_ABORTED;
-    case 412:
-      return GRPC_STATUS_FAILED_PRECONDITION;
-    case 429:
-      return GRPC_STATUS_RESOURCE_EXHAUSTED;
-    case 499:
-      return GRPC_STATUS_CANCELLED;
-    case 500:
-      return GRPC_STATUS_UNKNOWN;
-    case 501:
-      return GRPC_STATUS_UNIMPLEMENTED;
-    case 503:
-      return GRPC_STATUS_UNAVAILABLE;
-    case 504:
-      return GRPC_STATUS_DEADLINE_EXCEEDED;
-    /* everything else is unknown */
-    default:
-      return GRPC_STATUS_UNKNOWN;
-  }
-}
-
-int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status) {
-  return 200;
-}
diff --git a/src/core/transport/chttp2/status_conversion.h b/src/core/transport/chttp2/status_conversion.h
deleted file mode 100644
index c6e066b..0000000
--- a/src/core/transport/chttp2/status_conversion.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_STATUS_CONVERSION_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_STATUS_CONVERSION_H
-
-#include <grpc/grpc.h>
-#include "src/core/transport/chttp2/http2_errors.h"
-
-/* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */
-grpc_chttp2_error_code grpc_chttp2_grpc_status_to_http2_error(
-    grpc_status_code status);
-grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
-    grpc_chttp2_error_code error);
-
-/* Conversion of HTTP status codes (:status) to grpc status codes */
-grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status);
-int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_STATUS_CONVERSION_H */
diff --git a/src/core/transport/chttp2/stream_lists.c b/src/core/transport/chttp2/stream_lists.c
deleted file mode 100644
index 60fe735..0000000
--- a/src/core/transport/chttp2/stream_lists.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- *
- * 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/transport/chttp2/internal.h"
-
-#include <grpc/support/log.h>
-
-#define TRANSPORT_FROM_GLOBAL(tg)                                         \
-  ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
-                                                   global)))
-
-#define STREAM_FROM_GLOBAL(sg) \
-  ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
-
-#define TRANSPORT_FROM_WRITING(tw)                                        \
-  ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
-                                                   writing)))
-
-#define STREAM_FROM_WRITING(sw) \
-  ((grpc_chttp2_stream *)((char *)(sw)-offsetof(grpc_chttp2_stream, writing)))
-
-#define TRANSPORT_FROM_PARSING(tp)                                        \
-  ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
-                                                   parsing)))
-
-#define STREAM_FROM_PARSING(sp) \
-  ((grpc_chttp2_stream *)((char *)(sp)-offsetof(grpc_chttp2_stream, parsing)))
-
-/* core list management */
-
-static int stream_list_empty(grpc_chttp2_transport *t,
-                             grpc_chttp2_stream_list_id id) {
-  return t->lists[id].head == NULL;
-}
-
-static int stream_list_pop(grpc_chttp2_transport *t,
-                           grpc_chttp2_stream **stream,
-                           grpc_chttp2_stream_list_id id) {
-  grpc_chttp2_stream *s = t->lists[id].head;
-  if (s) {
-    grpc_chttp2_stream *new_head = s->links[id].next;
-    GPR_ASSERT(s->included[id]);
-    if (new_head) {
-      t->lists[id].head = new_head;
-      new_head->links[id].prev = NULL;
-    } else {
-      t->lists[id].head = NULL;
-      t->lists[id].tail = NULL;
-    }
-    s->included[id] = 0;
-  }
-  *stream = s;
-  return s != 0;
-}
-
-static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
-                               grpc_chttp2_stream_list_id id) {
-  GPR_ASSERT(s->included[id]);
-  s->included[id] = 0;
-  if (s->links[id].prev) {
-    s->links[id].prev->links[id].next = s->links[id].next;
-  } else {
-    GPR_ASSERT(t->lists[id].head == s);
-    t->lists[id].head = s->links[id].next;
-  }
-  if (s->links[id].next) {
-    s->links[id].next->links[id].prev = s->links[id].prev;
-  } else {
-    t->lists[id].tail = s->links[id].prev;
-  }
-}
-
-static bool stream_list_maybe_remove(grpc_chttp2_transport *t,
-                                     grpc_chttp2_stream *s,
-                                     grpc_chttp2_stream_list_id id) {
-  if (s->included[id]) {
-    stream_list_remove(t, s, id);
-    return true;
-  } else {
-    return false;
-  }
-}
-
-static void stream_list_add_tail(grpc_chttp2_transport *t,
-                                 grpc_chttp2_stream *s,
-                                 grpc_chttp2_stream_list_id id) {
-  grpc_chttp2_stream *old_tail;
-  GPR_ASSERT(!s->included[id]);
-  old_tail = t->lists[id].tail;
-  s->links[id].next = NULL;
-  s->links[id].prev = old_tail;
-  if (old_tail) {
-    old_tail->links[id].next = s;
-  } else {
-    t->lists[id].head = s;
-  }
-  t->lists[id].tail = s;
-  s->included[id] = 1;
-}
-
-static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
-                            grpc_chttp2_stream_list_id id) {
-  if (s->included[id]) {
-    return false;
-  }
-  stream_list_add_tail(t, s, id);
-  return true;
-}
-
-/* wrappers for specializations */
-
-bool grpc_chttp2_list_add_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  GPR_ASSERT(stream_global->id != 0);
-  return stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
-                         STREAM_FROM_GLOBAL(stream_global),
-                         GRPC_CHTTP2_LIST_WRITABLE);
-}
-
-int grpc_chttp2_list_pop_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_writing **stream_writing) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
-                          GRPC_CHTTP2_LIST_WRITABLE);
-  if (r != 0) {
-    *stream_global = &stream->global;
-    *stream_writing = &stream->writing;
-  }
-  return r;
-}
-
-bool grpc_chttp2_list_remove_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  return stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
-                                  STREAM_FROM_GLOBAL(stream_global),
-                                  GRPC_CHTTP2_LIST_WRITABLE);
-}
-
-void grpc_chttp2_list_add_writing_stream(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing) {
-  GPR_ASSERT(stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
-                             STREAM_FROM_WRITING(stream_writing),
-                             GRPC_CHTTP2_LIST_WRITING));
-}
-
-int grpc_chttp2_list_have_writing_streams(
-    grpc_chttp2_transport_writing *transport_writing) {
-  return !stream_list_empty(TRANSPORT_FROM_WRITING(transport_writing),
-                            GRPC_CHTTP2_LIST_WRITING);
-}
-
-int grpc_chttp2_list_pop_writing_stream(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing **stream_writing) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
-                          GRPC_CHTTP2_LIST_WRITING);
-  if (r != 0) {
-    *stream_writing = &stream->writing;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_add_written_stream(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing) {
-  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
-                  STREAM_FROM_WRITING(stream_writing),
-                  GRPC_CHTTP2_LIST_WRITTEN);
-}
-
-int grpc_chttp2_list_pop_written_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_writing **stream_writing) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
-                          GRPC_CHTTP2_LIST_WRITTEN);
-  if (r != 0) {
-    *stream_global = &stream->global;
-    *stream_writing = &stream->writing;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_add_unannounced_incoming_window_available(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  GPR_ASSERT(stream_global->id != 0);
-  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
-                  STREAM_FROM_GLOBAL(stream_global),
-                  GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
-}
-
-void grpc_chttp2_list_remove_unannounced_incoming_window_available(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  stream_list_maybe_remove(
-      TRANSPORT_FROM_GLOBAL(transport_global),
-      STREAM_FROM_GLOBAL(stream_global),
-      GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
-}
-
-int grpc_chttp2_list_pop_unannounced_incoming_window_available(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_parsing **stream_parsing) {
-  grpc_chttp2_stream *stream;
-  int r =
-      stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
-                      GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
-  if (r != 0) {
-    *stream_global = &stream->global;
-    *stream_parsing = &stream->parsing;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_add_parsing_seen_stream(
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing) {
-  stream_list_add(TRANSPORT_FROM_PARSING(transport_parsing),
-                  STREAM_FROM_PARSING(stream_parsing),
-                  GRPC_CHTTP2_LIST_PARSING_SEEN);
-}
-
-int grpc_chttp2_list_pop_parsing_seen_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_global **stream_global,
-    grpc_chttp2_stream_parsing **stream_parsing) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_PARSING(transport_parsing), &stream,
-                          GRPC_CHTTP2_LIST_PARSING_SEEN);
-  if (r != 0) {
-    *stream_global = &stream->global;
-    *stream_parsing = &stream->parsing;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_add_waiting_for_concurrency(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
-                  STREAM_FROM_GLOBAL(stream_global),
-                  GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
-}
-
-int grpc_chttp2_list_pop_waiting_for_concurrency(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
-                          GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
-  if (r != 0) {
-    *stream_global = &stream->global;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_add_check_read_ops(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
-                  STREAM_FROM_GLOBAL(stream_global),
-                  GRPC_CHTTP2_LIST_CHECK_READ_OPS);
-}
-
-int grpc_chttp2_list_pop_check_read_ops(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
-                          GRPC_CHTTP2_LIST_CHECK_READ_OPS);
-  if (r != 0) {
-    *stream_global = &stream->global;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_add_writing_stalled_by_transport(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing) {
-  grpc_chttp2_stream *stream = STREAM_FROM_WRITING(stream_writing);
-  if (!stream->included[GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT]) {
-    GRPC_CHTTP2_STREAM_REF(&stream->global, "chttp2_writing_stalled");
-  }
-  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), stream,
-                  GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT);
-}
-
-void grpc_chttp2_list_flush_writing_stalled_by_transport(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
-    bool is_window_available) {
-  grpc_chttp2_stream *stream;
-  grpc_chttp2_transport *transport = TRANSPORT_FROM_WRITING(transport_writing);
-  while (stream_list_pop(transport, &stream,
-                         GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) {
-    if (is_window_available) {
-      grpc_chttp2_become_writable(&transport->global, &stream->global);
-    } else {
-      grpc_chttp2_list_add_stalled_by_transport(transport_writing,
-                                                &stream->writing);
-    }
-    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &stream->global,
-                             "chttp2_writing_stalled");
-  }
-}
-
-void grpc_chttp2_list_add_stalled_by_transport(
-    grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing) {
-  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
-                  STREAM_FROM_WRITING(stream_writing),
-                  GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
-}
-
-int grpc_chttp2_list_pop_stalled_by_transport(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
-                          GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
-  if (r != 0) {
-    *stream_global = &stream->global;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_remove_stalled_by_transport(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
-                           STREAM_FROM_GLOBAL(stream_global),
-                           GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
-}
-
-void grpc_chttp2_list_add_closed_waiting_for_parsing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
-                  STREAM_FROM_GLOBAL(stream_global),
-                  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
-}
-
-int grpc_chttp2_list_pop_closed_waiting_for_parsing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
-                          GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
-  if (r != 0) {
-    *stream_global = &stream->global;
-  }
-  return r;
-}
-
-void grpc_chttp2_list_add_closed_waiting_for_writing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
-                  STREAM_FROM_GLOBAL(stream_global),
-                  GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING);
-}
-
-int grpc_chttp2_list_pop_closed_waiting_for_writing(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global **stream_global) {
-  grpc_chttp2_stream *stream;
-  int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
-                          GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING);
-  if (r != 0) {
-    *stream_global = &stream->global;
-  }
-  return r;
-}
-
-void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
-                                 grpc_chttp2_stream *s) {
-  stream_list_add_tail(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
-}
-
-int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
-                                  grpc_chttp2_stream *s) {
-  stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
-  return stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
-}
-
-int grpc_chttp2_has_streams(grpc_chttp2_transport *t) {
-  return !stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
-}
-
-void grpc_chttp2_for_all_streams(
-    grpc_chttp2_transport_global *transport_global, void *user_data,
-    void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
-               grpc_chttp2_stream_global *stream_global)) {
-  grpc_chttp2_stream *s;
-  grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global);
-  for (s = t->lists[GRPC_CHTTP2_LIST_ALL_STREAMS].head; s != NULL;
-       s = s->links[GRPC_CHTTP2_LIST_ALL_STREAMS].next) {
-    cb(transport_global, user_data, &s->global);
-  }
-}
diff --git a/src/core/transport/chttp2/stream_map.c b/src/core/transport/chttp2/stream_map.c
deleted file mode 100644
index 555a16f..0000000
--- a/src/core/transport/chttp2/stream_map.c
+++ /dev/null
@@ -1,197 +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/transport/chttp2/stream_map.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map,
-                                 size_t initial_capacity) {
-  GPR_ASSERT(initial_capacity > 1);
-  map->keys = gpr_malloc(sizeof(uint32_t) * initial_capacity);
-  map->values = gpr_malloc(sizeof(void *) * initial_capacity);
-  map->count = 0;
-  map->free = 0;
-  map->capacity = initial_capacity;
-}
-
-void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map) {
-  gpr_free(map->keys);
-  gpr_free(map->values);
-}
-
-static size_t compact(uint32_t *keys, void **values, size_t count) {
-  size_t i, out;
-
-  for (i = 0, out = 0; i < count; i++) {
-    if (values[i]) {
-      keys[out] = keys[i];
-      values[out] = values[i];
-      out++;
-    }
-  }
-
-  return out;
-}
-
-void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key,
-                                void *value) {
-  size_t count = map->count;
-  size_t capacity = map->capacity;
-  uint32_t *keys = map->keys;
-  void **values = map->values;
-
-  GPR_ASSERT(count == 0 || keys[count - 1] < key);
-  GPR_ASSERT(value);
-
-  if (count == capacity) {
-    if (map->free > capacity / 4) {
-      count = compact(keys, values, count);
-      map->free = 0;
-    } else {
-      /* resize when less than 25% of the table is free, because compaction
-         won't help much */
-      map->capacity = capacity = 3 * capacity / 2;
-      map->keys = keys = gpr_realloc(keys, capacity * sizeof(uint32_t));
-      map->values = values = gpr_realloc(values, capacity * sizeof(void *));
-    }
-  }
-
-  keys[count] = key;
-  values[count] = value;
-  map->count = count + 1;
-}
-
-void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src,
-                                      grpc_chttp2_stream_map *dst) {
-  /* if src is empty we dont need to do anything */
-  if (src->count == src->free) {
-    return;
-  }
-  /* if dst is empty we simply need to swap */
-  if (dst->count == dst->free) {
-    GPR_SWAP(grpc_chttp2_stream_map, *src, *dst);
-    return;
-  }
-  /* the first element of src must be greater than the last of dst...
-   * however the maps may need compacting for this property to hold */
-  if (src->keys[0] <= dst->keys[dst->count - 1]) {
-    src->count = compact(src->keys, src->values, src->count);
-    src->free = 0;
-    dst->count = compact(dst->keys, dst->values, dst->count);
-    dst->free = 0;
-  }
-  GPR_ASSERT(src->keys[0] > dst->keys[dst->count - 1]);
-  /* if dst doesn't have capacity, resize */
-  if (dst->count + src->count > dst->capacity) {
-    dst->capacity = GPR_MAX(dst->capacity * 3 / 2, dst->count + src->count);
-    dst->keys = gpr_realloc(dst->keys, dst->capacity * sizeof(uint32_t));
-    dst->values = gpr_realloc(dst->values, dst->capacity * sizeof(void *));
-  }
-  memcpy(dst->keys + dst->count, src->keys, src->count * sizeof(uint32_t));
-  memcpy(dst->values + dst->count, src->values, src->count * sizeof(void *));
-  dst->count += src->count;
-  dst->free += src->free;
-  src->count = 0;
-  src->free = 0;
-}
-
-static void **find(grpc_chttp2_stream_map *map, uint32_t key) {
-  size_t min_idx = 0;
-  size_t max_idx = map->count;
-  size_t mid_idx;
-  uint32_t *keys = map->keys;
-  void **values = map->values;
-  uint32_t mid_key;
-
-  if (max_idx == 0) return NULL;
-
-  while (min_idx < max_idx) {
-    /* find the midpoint, avoiding overflow */
-    mid_idx = min_idx + ((max_idx - min_idx) / 2);
-    mid_key = keys[mid_idx];
-
-    if (mid_key < key) {
-      min_idx = mid_idx + 1;
-    } else if (mid_key > key) {
-      max_idx = mid_idx;
-    } else /* mid_key == key */
-    {
-      return &values[mid_idx];
-    }
-  }
-
-  return NULL;
-}
-
-void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key) {
-  void **pvalue = find(map, key);
-  void *out = NULL;
-  if (pvalue != NULL) {
-    out = *pvalue;
-    *pvalue = NULL;
-    map->free += (out != NULL);
-    /* recognize complete emptyness and ensure we can skip
-     * defragmentation later */
-    if (map->free == map->count) {
-      map->free = map->count = 0;
-    }
-  }
-  return out;
-}
-
-void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key) {
-  void **pvalue = find(map, key);
-  return pvalue != NULL ? *pvalue : NULL;
-}
-
-size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map) {
-  return map->count - map->free;
-}
-
-void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map,
-                                     void (*f)(void *user_data, uint32_t key,
-                                               void *value),
-                                     void *user_data) {
-  size_t i;
-
-  for (i = 0; i < map->count; i++) {
-    if (map->values[i]) {
-      f(user_data, map->keys[i], map->values[i]);
-    }
-  }
-}
diff --git a/src/core/transport/chttp2/stream_map.h b/src/core/transport/chttp2/stream_map.h
deleted file mode 100644
index 957a58a..0000000
--- a/src/core/transport/chttp2/stream_map.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_STREAM_MAP_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_STREAM_MAP_H
-
-#include <grpc/support/port_platform.h>
-
-#include <stddef.h>
-
-/* Data structure to map a uint32_t to a data object (represented by a void*)
-
-   Represented as a sorted array of keys, and a corresponding array of values.
-   Lookups are performed with binary search.
-   Adds are restricted to strictly higher keys than previously seen (this is
-   guaranteed by http2). */
-typedef struct {
-  uint32_t *keys;
-  void **values;
-  size_t count;
-  size_t free;
-  size_t capacity;
-} grpc_chttp2_stream_map;
-
-void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map,
-                                 size_t initial_capacity);
-void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map);
-
-/* Add a new key: given http2 semantics, new keys must always be greater than
-   existing keys - this is asserted */
-void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key,
-                                void *value);
-
-/* Delete an existing key - returns the previous value of the key if it existed,
-   or NULL otherwise */
-void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key);
-
-/* Move all elements of src into dst */
-void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src,
-                                      grpc_chttp2_stream_map *dst);
-
-/* Return an existing key, or NULL if it does not exist */
-void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key);
-
-/* How many (populated) entries are in the stream map? */
-size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map);
-
-/* Callback on each stream */
-void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map,
-                                     void (*f)(void *user_data, uint32_t key,
-                                               void *value),
-                                     void *user_data);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_STREAM_MAP_H */
diff --git a/src/core/transport/chttp2/timeout_encoding.c b/src/core/transport/chttp2/timeout_encoding.c
deleted file mode 100644
index a6f7081..0000000
--- a/src/core/transport/chttp2/timeout_encoding.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *
- * 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/transport/chttp2/timeout_encoding.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/support/port_platform.h>
-#include "src/core/support/string.h"
-
-static int64_t round_up(int64_t x, int64_t divisor) {
-  return (x / divisor + (x % divisor != 0)) * divisor;
-}
-
-/* round an integer up to the next value with three significant figures */
-static int64_t round_up_to_three_sig_figs(int64_t x) {
-  if (x < 1000) return x;
-  if (x < 10000) return round_up(x, 10);
-  if (x < 100000) return round_up(x, 100);
-  if (x < 1000000) return round_up(x, 1000);
-  if (x < 10000000) return round_up(x, 10000);
-  if (x < 100000000) return round_up(x, 100000);
-  if (x < 1000000000) return round_up(x, 1000000);
-  return round_up(x, 10000000);
-}
-
-/* encode our minimum viable timeout value */
-static void enc_tiny(char *buffer) { memcpy(buffer, "1n", 3); }
-
-static void enc_ext(char *buffer, int64_t value, char ext) {
-  int n = int64_ttoa(value, buffer);
-  buffer[n] = ext;
-  buffer[n + 1] = 0;
-}
-
-static void enc_seconds(char *buffer, int64_t sec) {
-  if (sec % 3600 == 0) {
-    enc_ext(buffer, sec / 3600, 'H');
-  } else if (sec % 60 == 0) {
-    enc_ext(buffer, sec / 60, 'M');
-  } else {
-    enc_ext(buffer, sec, 'S');
-  }
-}
-
-static void enc_nanos(char *buffer, int64_t x) {
-  x = round_up_to_three_sig_figs(x);
-  if (x < 100000) {
-    if (x % 1000 == 0) {
-      enc_ext(buffer, x / 1000, 'u');
-    } else {
-      enc_ext(buffer, x, 'n');
-    }
-  } else if (x < 100000000) {
-    if (x % 1000000 == 0) {
-      enc_ext(buffer, x / 1000000, 'm');
-    } else {
-      enc_ext(buffer, x / 1000, 'u');
-    }
-  } else if (x < 1000000000) {
-    enc_ext(buffer, x / 1000000, 'm');
-  } else {
-    /* note that this is only ever called with times of less than one second,
-       so if we reach here the time must have been rounded up to a whole second
-       (and no more) */
-    memcpy(buffer, "1S", 3);
-  }
-}
-
-static void enc_micros(char *buffer, int64_t x) {
-  x = round_up_to_three_sig_figs(x);
-  if (x < 100000) {
-    if (x % 1000 == 0) {
-      enc_ext(buffer, x / 1000, 'm');
-    } else {
-      enc_ext(buffer, x, 'u');
-    }
-  } else if (x < 100000000) {
-    if (x % 1000000 == 0) {
-      enc_ext(buffer, x / 1000000, 'S');
-    } else {
-      enc_ext(buffer, x / 1000, 'm');
-    }
-  } else {
-    enc_ext(buffer, x / 1000000, 'S');
-  }
-}
-
-void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer) {
-  if (timeout.tv_sec < 0) {
-    enc_tiny(buffer);
-  } else if (timeout.tv_sec == 0) {
-    enc_nanos(buffer, timeout.tv_nsec);
-  } else if (timeout.tv_sec < 1000 && timeout.tv_nsec != 0) {
-    enc_micros(buffer,
-               (int64_t)(timeout.tv_sec * 1000000) +
-                   (timeout.tv_nsec / 1000 + (timeout.tv_nsec % 1000 != 0)));
-  } else {
-    enc_seconds(buffer, timeout.tv_sec + (timeout.tv_nsec != 0));
-  }
-}
-
-static int is_all_whitespace(const char *p) {
-  while (*p == ' ') p++;
-  return *p == 0;
-}
-
-int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout) {
-  int32_t x = 0;
-  const uint8_t *p = (const uint8_t *)buffer;
-  int have_digit = 0;
-  /* skip whitespace */
-  for (; *p == ' '; p++)
-    ;
-  /* decode numeric part */
-  for (; *p >= '0' && *p <= '9'; p++) {
-    int32_t digit = (int32_t)(*p - (uint8_t)'0');
-    have_digit = 1;
-    /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */
-    if (x >= (100 * 1000 * 1000)) {
-      if (x != (100 * 1000 * 1000) || digit != 0) {
-        *timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
-        return 1;
-      }
-    }
-    x = x * 10 + digit;
-  }
-  if (!have_digit) return 0;
-  /* skip whitespace */
-  for (; *p == ' '; p++)
-    ;
-  /* decode unit specifier */
-  switch (*p) {
-    case 'n':
-      *timeout = gpr_time_from_nanos(x, GPR_TIMESPAN);
-      break;
-    case 'u':
-      *timeout = gpr_time_from_micros(x, GPR_TIMESPAN);
-      break;
-    case 'm':
-      *timeout = gpr_time_from_millis(x, GPR_TIMESPAN);
-      break;
-    case 'S':
-      *timeout = gpr_time_from_seconds(x, GPR_TIMESPAN);
-      break;
-    case 'M':
-      *timeout = gpr_time_from_minutes(x, GPR_TIMESPAN);
-      break;
-    case 'H':
-      *timeout = gpr_time_from_hours(x, GPR_TIMESPAN);
-      break;
-    default:
-      return 0;
-  }
-  p++;
-  return is_all_whitespace((const char *)p);
-}
diff --git a/src/core/transport/chttp2/timeout_encoding.h b/src/core/transport/chttp2/timeout_encoding.h
deleted file mode 100644
index 81bae8e..0000000
--- a/src/core/transport/chttp2/timeout_encoding.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H
-
-#include "src/core/support/string.h"
-#include <grpc/support/time.h>
-
-#define GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1)
-
-/* Encode/decode timeouts to the GRPC over HTTP2 format;
-   encoding may round up arbitrarily */
-void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer);
-int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H */
diff --git a/src/core/transport/chttp2/varint.c b/src/core/transport/chttp2/varint.c
deleted file mode 100644
index 1cc235e..0000000
--- a/src/core/transport/chttp2/varint.c
+++ /dev/null
@@ -1,65 +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/transport/chttp2/varint.h"
-
-uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value) {
-  if (tail_value < (1 << 7)) {
-    return 2;
-  } else if (tail_value < (1 << 14)) {
-    return 3;
-  } else if (tail_value < (1 << 21)) {
-    return 4;
-  } else if (tail_value < (1 << 28)) {
-    return 5;
-  } else {
-    return 6;
-  }
-}
-
-void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target,
-                                         uint32_t tail_length) {
-  switch (tail_length) {
-    case 5:
-      target[4] = (uint8_t)((tail_value >> 28) | 0x80);
-    case 4:
-      target[3] = (uint8_t)((tail_value >> 21) | 0x80);
-    case 3:
-      target[2] = (uint8_t)((tail_value >> 14) | 0x80);
-    case 2:
-      target[1] = (uint8_t)((tail_value >> 7) | 0x80);
-    case 1:
-      target[0] = (uint8_t)((tail_value) | 0x80);
-  }
-  target[tail_length - 1] &= 0x7f;
-}
diff --git a/src/core/transport/chttp2/varint.h b/src/core/transport/chttp2/varint.h
deleted file mode 100644
index 7ab9d22..0000000
--- a/src/core/transport/chttp2/varint.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_VARINT_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_VARINT_H
-
-#include <grpc/support/port_platform.h>
-
-/* Helpers for hpack varint encoding */
-
-/* length of a value that needs varint tail encoding (it's bigger than can be
-   bitpacked into the opcode byte) - returned value includes the length of the
-   opcode byte */
-uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value);
-
-void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target,
-                                         uint32_t tail_length);
-
-/* maximum value that can be bitpacked with the opcode if the opcode has a
-   prefix
-   of length prefix_bits */
-#define GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits) \
-  ((uint32_t)((1 << (8 - (prefix_bits))) - 1))
-
-/* length required to bitpack a value */
-#define GRPC_CHTTP2_VARINT_LENGTH(n, prefix_bits) \
-  ((n) < GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits)   \
-       ? 1u                                       \
-       : grpc_chttp2_hpack_varint_length(         \
-             (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits)))
-
-#define GRPC_CHTTP2_WRITE_VARINT(n, prefix_bits, prefix_or, target, length)   \
-  do {                                                                        \
-    uint8_t* tgt = target;                                                    \
-    if ((length) == 1u) {                                                     \
-      (tgt)[0] = (uint8_t)((prefix_or) | (n));                                \
-    } else {                                                                  \
-      (tgt)[0] =                                                              \
-          (prefix_or) | (uint8_t)GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits);      \
-      grpc_chttp2_hpack_write_varint_tail(                                    \
-          (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits), (tgt) + 1, (length)-1); \
-    }                                                                         \
-  } while (0)
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_VARINT_H */
diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c
deleted file mode 100644
index 107725c..0000000
--- a/src/core/transport/chttp2/writing.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- *
- * 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/transport/chttp2/internal.h"
-
-#include <limits.h>
-
-#include <grpc/support/log.h>
-
-#include "src/core/profiling/timers.h"
-#include "src/core/transport/chttp2/http2_errors.h"
-
-static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_writing *transport_writing);
-
-int grpc_chttp2_unlocking_check_writes(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_writing *transport_writing, int is_parsing) {
-  grpc_chttp2_stream_global *stream_global;
-  grpc_chttp2_stream_writing *stream_writing;
-
-  GPR_TIMER_BEGIN("grpc_chttp2_unlocking_check_writes", 0);
-
-  /* simple writes are queued to qbuf, and flushed here */
-  gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf);
-  GPR_ASSERT(transport_global->qbuf.count == 0);
-
-  grpc_chttp2_hpack_compressor_set_max_table_size(
-      &transport_writing->hpack_compressor,
-      transport_global->settings[GRPC_PEER_SETTINGS]
-                                [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
-
-  if (transport_global->dirtied_local_settings &&
-      !transport_global->sent_local_settings && !is_parsing) {
-    gpr_slice_buffer_add(
-        &transport_writing->outbuf,
-        grpc_chttp2_settings_create(
-            transport_global->settings[GRPC_SENT_SETTINGS],
-            transport_global->settings[GRPC_LOCAL_SETTINGS],
-            transport_global->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS));
-    transport_global->force_send_settings = 0;
-    transport_global->dirtied_local_settings = 0;
-    transport_global->sent_local_settings = 1;
-  }
-
-  GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window,
-                                  transport_global, outgoing_window);
-  bool is_window_available = transport_writing->outgoing_window > 0;
-  grpc_chttp2_list_flush_writing_stalled_by_transport(
-      exec_ctx, transport_writing, is_window_available);
-
-  /* for each grpc_chttp2_stream that's become writable, frame it's data
-     (according to available window sizes) and add to the output buffer */
-  while (grpc_chttp2_list_pop_writable_stream(
-      transport_global, transport_writing, &stream_global, &stream_writing)) {
-    bool sent_initial_metadata = stream_writing->sent_initial_metadata;
-    bool become_writable = false;
-
-    stream_writing->id = stream_global->id;
-    stream_writing->read_closed = stream_global->read_closed;
-
-    GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_writing, stream_writing,
-                                 outgoing_window, stream_global,
-                                 outgoing_window);
-
-    if (!sent_initial_metadata && stream_global->send_initial_metadata) {
-      stream_writing->send_initial_metadata =
-          stream_global->send_initial_metadata;
-      stream_global->send_initial_metadata = NULL;
-      become_writable = true;
-      sent_initial_metadata = true;
-    }
-    if (sent_initial_metadata) {
-      if (stream_global->send_message != NULL) {
-        gpr_slice hdr = gpr_slice_malloc(5);
-        uint8_t *p = GPR_SLICE_START_PTR(hdr);
-        uint32_t len = stream_global->send_message->length;
-        GPR_ASSERT(stream_writing->send_message == NULL);
-        p[0] = (stream_global->send_message->flags &
-                GRPC_WRITE_INTERNAL_COMPRESS) != 0;
-        p[1] = (uint8_t)(len >> 24);
-        p[2] = (uint8_t)(len >> 16);
-        p[3] = (uint8_t)(len >> 8);
-        p[4] = (uint8_t)(len);
-        gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer, hdr);
-        if (stream_global->send_message->length > 0) {
-          stream_writing->send_message = stream_global->send_message;
-        } else {
-          stream_writing->send_message = NULL;
-        }
-        stream_writing->stream_fetched = 0;
-        stream_global->send_message = NULL;
-      }
-      if ((stream_writing->send_message != NULL ||
-           stream_writing->flow_controlled_buffer.length > 0) &&
-          stream_writing->outgoing_window > 0) {
-        if (transport_writing->outgoing_window > 0) {
-          become_writable = true;
-        } else {
-          grpc_chttp2_list_add_stalled_by_transport(transport_writing,
-                                                    stream_writing);
-        }
-      }
-      if (stream_global->send_trailing_metadata) {
-        stream_writing->send_trailing_metadata =
-            stream_global->send_trailing_metadata;
-        stream_global->send_trailing_metadata = NULL;
-        become_writable = true;
-      }
-    }
-
-    if (!stream_global->read_closed &&
-        stream_global->unannounced_incoming_window_for_writing > 1024) {
-      GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing,
-                                   announce_window, stream_global,
-                                   unannounced_incoming_window_for_writing);
-      become_writable = true;
-    }
-
-    if (become_writable) {
-      grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
-    } else {
-      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
-    }
-  }
-
-  /* if the grpc_chttp2_transport is ready to send a window update, do so here
-     also; 3/4 is a magic number that will likely get tuned soon */
-  if (transport_global->announce_incoming_window > 0) {
-    uint32_t announced = (uint32_t)GPR_MIN(
-        transport_global->announce_incoming_window, UINT32_MAX);
-    GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_global,
-                                     announce_incoming_window, announced);
-    gpr_slice_buffer_add(&transport_writing->outbuf,
-                         grpc_chttp2_window_update_create(0, announced));
-  }
-
-  GPR_TIMER_END("grpc_chttp2_unlocking_check_writes", 0);
-
-  return transport_writing->outbuf.count > 0 ||
-         grpc_chttp2_list_have_writing_streams(transport_writing);
-}
-
-void grpc_chttp2_perform_writes(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
-    grpc_endpoint *endpoint) {
-  GPR_ASSERT(transport_writing->outbuf.count > 0 ||
-             grpc_chttp2_list_have_writing_streams(transport_writing));
-
-  finalize_outbuf(exec_ctx, transport_writing);
-
-  GPR_ASSERT(endpoint);
-
-  if (transport_writing->outbuf.count > 0) {
-    grpc_endpoint_write(exec_ctx, endpoint, &transport_writing->outbuf,
-                        &transport_writing->done_cb);
-  } else {
-    grpc_exec_ctx_enqueue(exec_ctx, &transport_writing->done_cb, true, NULL);
-  }
-}
-
-static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_writing *transport_writing) {
-  grpc_chttp2_stream_writing *stream_writing;
-
-  GPR_TIMER_BEGIN("finalize_outbuf", 0);
-
-  while (
-      grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) {
-    uint32_t max_outgoing =
-        (uint32_t)GPR_MIN(GRPC_CHTTP2_MAX_PAYLOAD_LENGTH,
-                          GPR_MIN(stream_writing->outgoing_window,
-                                  transport_writing->outgoing_window));
-    /* send initial metadata if it's available */
-    if (stream_writing->send_initial_metadata != NULL) {
-      grpc_chttp2_encode_header(
-          &transport_writing->hpack_compressor, stream_writing->id,
-          stream_writing->send_initial_metadata, 0, &transport_writing->outbuf);
-      stream_writing->send_initial_metadata = NULL;
-      stream_writing->sent_initial_metadata = 1;
-    }
-    /* send any window updates */
-    if (stream_writing->announce_window > 0 &&
-        stream_writing->send_initial_metadata == NULL) {
-      uint32_t announce = stream_writing->announce_window;
-      gpr_slice_buffer_add(
-          &transport_writing->outbuf,
-          grpc_chttp2_window_update_create(stream_writing->id,
-                                           stream_writing->announce_window));
-      GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, stream_writing,
-                                    announce_window, announce);
-      stream_writing->announce_window = 0;
-    }
-    /* fetch any body bytes */
-    while (!stream_writing->fetching && stream_writing->send_message &&
-           stream_writing->flow_controlled_buffer.length < max_outgoing &&
-           stream_writing->stream_fetched <
-               stream_writing->send_message->length) {
-      if (grpc_byte_stream_next(exec_ctx, stream_writing->send_message,
-                                &stream_writing->fetching_slice, max_outgoing,
-                                &stream_writing->finished_fetch)) {
-        stream_writing->stream_fetched +=
-            GPR_SLICE_LENGTH(stream_writing->fetching_slice);
-        if (stream_writing->stream_fetched ==
-            stream_writing->send_message->length) {
-          stream_writing->send_message = NULL;
-        }
-        gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer,
-                             stream_writing->fetching_slice);
-      } else {
-        stream_writing->fetching = 1;
-      }
-    }
-    /* send any body bytes */
-    if (stream_writing->flow_controlled_buffer.length > 0) {
-      if (max_outgoing > 0) {
-        uint32_t send_bytes = (uint32_t)GPR_MIN(
-            max_outgoing, stream_writing->flow_controlled_buffer.length);
-        int is_last_data_frame =
-            stream_writing->send_message == NULL &&
-            send_bytes == stream_writing->flow_controlled_buffer.length;
-        int is_last_frame = is_last_data_frame &&
-                            stream_writing->send_trailing_metadata != NULL &&
-                            grpc_metadata_batch_is_empty(
-                                stream_writing->send_trailing_metadata);
-        grpc_chttp2_encode_data(
-            stream_writing->id, &stream_writing->flow_controlled_buffer,
-            send_bytes, is_last_frame, &transport_writing->outbuf);
-        GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing,
-                                      stream_writing, outgoing_window,
-                                      send_bytes);
-        GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_writing,
-                                         outgoing_window, send_bytes);
-        if (is_last_frame) {
-          stream_writing->send_trailing_metadata = NULL;
-          stream_writing->sent_trailing_metadata = 1;
-        }
-        if (is_last_data_frame) {
-          GPR_ASSERT(stream_writing->send_message == NULL);
-          stream_writing->sent_message = 1;
-        }
-      } else if (transport_writing->outgoing_window == 0) {
-        grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
-                                                          stream_writing);
-        grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
-      }
-    }
-    /* send trailing metadata if it's available and we're ready for it */
-    if (stream_writing->send_message == NULL &&
-        stream_writing->flow_controlled_buffer.length == 0 &&
-        stream_writing->send_trailing_metadata != NULL) {
-      if (grpc_metadata_batch_is_empty(
-              stream_writing->send_trailing_metadata)) {
-        grpc_chttp2_encode_data(stream_writing->id,
-                                &stream_writing->flow_controlled_buffer, 0, 1,
-                                &transport_writing->outbuf);
-      } else {
-        grpc_chttp2_encode_header(&transport_writing->hpack_compressor,
-                                  stream_writing->id,
-                                  stream_writing->send_trailing_metadata, 1,
-                                  &transport_writing->outbuf);
-      }
-      if (!transport_writing->is_client && !stream_writing->read_closed) {
-        gpr_slice_buffer_add(&transport_writing->outbuf,
-                             grpc_chttp2_rst_stream_create(
-                                 stream_writing->id, GRPC_CHTTP2_NO_ERROR));
-      }
-      stream_writing->send_trailing_metadata = NULL;
-      stream_writing->sent_trailing_metadata = 1;
-    }
-    /* if there's more to write, then loop, otherwise prepare to finish the
-     * write */
-    if ((stream_writing->flow_controlled_buffer.length > 0 ||
-         (stream_writing->send_message && !stream_writing->fetching)) &&
-        stream_writing->outgoing_window > 0) {
-      if (transport_writing->outgoing_window > 0) {
-        grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
-      } else {
-        grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
-                                                          stream_writing);
-        grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
-      }
-    } else {
-      grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
-    }
-  }
-
-  GPR_TIMER_END("finalize_outbuf", 0);
-}
-
-void grpc_chttp2_cleanup_writing(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_writing *transport_writing) {
-  grpc_chttp2_stream_writing *stream_writing;
-  grpc_chttp2_stream_global *stream_global;
-
-  while (grpc_chttp2_list_pop_written_stream(
-      transport_global, transport_writing, &stream_global, &stream_writing)) {
-    if (stream_writing->sent_initial_metadata) {
-      grpc_chttp2_complete_closure_step(
-          exec_ctx, &stream_global->send_initial_metadata_finished, 1);
-    }
-    if (stream_writing->sent_message) {
-      GPR_ASSERT(stream_writing->send_message == NULL);
-      grpc_chttp2_complete_closure_step(
-          exec_ctx, &stream_global->send_message_finished, 1);
-      stream_writing->sent_message = 0;
-    }
-    if (stream_writing->sent_trailing_metadata) {
-      grpc_chttp2_complete_closure_step(
-          exec_ctx, &stream_global->send_trailing_metadata_finished, 1);
-    }
-    if (stream_writing->sent_trailing_metadata) {
-      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
-                                     !transport_global->is_client, 1);
-    }
-    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
-  }
-  gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf);
-}
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
deleted file mode 100644
index b16768d..0000000
--- a/src/core/transport/chttp2_transport.c
+++ /dev/null
@@ -1,1779 +0,0 @@
-/*
- *
- * 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/transport/chttp2_transport.h"
-
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/profiling/timers.h"
-#include "src/core/support/string.h"
-#include "src/core/transport/chttp2/http2_errors.h"
-#include "src/core/transport/chttp2/internal.h"
-#include "src/core/transport/chttp2/status_conversion.h"
-#include "src/core/transport/chttp2/timeout_encoding.h"
-#include "src/core/transport/static_metadata.h"
-#include "src/core/transport/transport_impl.h"
-
-#define DEFAULT_WINDOW 65535
-#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
-#define MAX_WINDOW 0x7fffffffu
-
-#define MAX_CLIENT_STREAM_ID 0x7fffffffu
-
-int grpc_http_trace = 0;
-int grpc_flowctl_trace = 0;
-
-#define TRANSPORT_FROM_WRITING(tw)                                        \
-  ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
-                                                   writing)))
-
-#define TRANSPORT_FROM_PARSING(tw)                                        \
-  ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
-                                                   parsing)))
-
-#define TRANSPORT_FROM_GLOBAL(tg)                                         \
-  ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
-                                                   global)))
-
-#define STREAM_FROM_GLOBAL(sg) \
-  ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
-
-#define STREAM_FROM_PARSING(sg) \
-  ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, parsing)))
-
-static const grpc_transport_vtable vtable;
-
-static void lock(grpc_chttp2_transport *t);
-static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
-
-/* forward declarations of various callbacks that we'll build closures around */
-static void writing_action(grpc_exec_ctx *exec_ctx, void *t,
-                           bool iomgr_success_ignored);
-
-/** Set a transport level setting, and push it to our peer */
-static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
-                         uint32_t value);
-
-/** Endpoint callback to process incoming data */
-static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success);
-
-/** Start disconnection chain */
-static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
-
-/** Perform a transport_op */
-static void perform_stream_op_locked(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op);
-
-/** Cancel a stream: coming from the transport API */
-static void cancel_from_api(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_global *transport_global,
-                            grpc_chttp2_stream_global *stream_global,
-                            grpc_status_code status);
-
-static void close_from_api(grpc_exec_ctx *exec_ctx,
-                           grpc_chttp2_transport_global *transport_global,
-                           grpc_chttp2_stream_global *stream_global,
-                           grpc_status_code status,
-                           gpr_slice *optional_message);
-
-/** Add endpoint from this transport to pollset */
-static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
-                                  grpc_chttp2_transport *t,
-                                  grpc_pollset *pollset);
-static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
-                                      grpc_chttp2_transport *t,
-                                      grpc_pollset_set *pollset_set);
-
-/** Start new streams that have been created if we can */
-static void maybe_start_some_streams(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global);
-
-static void connectivity_state_set(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_connectivity_state state, const char *reason);
-
-static void check_read_ops(grpc_exec_ctx *exec_ctx,
-                           grpc_chttp2_transport_global *transport_global);
-
-static void incoming_byte_stream_update_flow_control(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
-    size_t have_already);
-
-static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
-                                grpc_chttp2_stream_global *stream_global);
-
-/*******************************************************************************
- * CONSTRUCTION/DESTRUCTION/REFCOUNTING
- */
-
-static void destruct_transport(grpc_exec_ctx *exec_ctx,
-                               grpc_chttp2_transport *t) {
-  size_t i;
-
-  gpr_mu_lock(&t->mu);
-
-  GPR_ASSERT(t->ep == NULL);
-
-  gpr_slice_buffer_destroy(&t->global.qbuf);
-
-  gpr_slice_buffer_destroy(&t->writing.outbuf);
-  grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor);
-
-  gpr_slice_buffer_destroy(&t->parsing.qbuf);
-  gpr_slice_buffer_destroy(&t->read_buffer);
-  grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser);
-  grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser);
-
-  for (i = 0; i < STREAM_LIST_COUNT; i++) {
-    GPR_ASSERT(t->lists[i].head == NULL);
-    GPR_ASSERT(t->lists[i].tail == NULL);
-  }
-
-  GPR_ASSERT(grpc_chttp2_stream_map_size(&t->parsing_stream_map) == 0);
-  GPR_ASSERT(grpc_chttp2_stream_map_size(&t->new_stream_map) == 0);
-
-  grpc_chttp2_stream_map_destroy(&t->parsing_stream_map);
-  grpc_chttp2_stream_map_destroy(&t->new_stream_map);
-  grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
-
-  gpr_mu_unlock(&t->mu);
-  gpr_mu_destroy(&t->mu);
-
-  /* callback remaining pings: they're not allowed to call into the transpot,
-     and maybe they hold resources that need to be freed */
-  while (t->global.pings.next != &t->global.pings) {
-    grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
-    grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, false, NULL);
-    ping->next->prev = ping->prev;
-    ping->prev->next = ping->next;
-    gpr_free(ping);
-  }
-
-  gpr_free(t->peer_string);
-  gpr_free(t);
-}
-
-#ifdef REFCOUNTING_DEBUG
-#define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__)
-#define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t, r, __FILE__, __LINE__)
-static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                            const char *reason, const char *file, int line) {
-  gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count,
-          t->refs.count - 1, reason, file, line);
-  if (!gpr_unref(&t->refs)) return;
-  destruct_transport(exec_ctx, t);
-}
-
-static void ref_transport(grpc_chttp2_transport *t, const char *reason,
-                          const char *file, int line) {
-  gpr_log(GPR_DEBUG, "chttp2:  ref:%p %d->%d %s [%s:%d]", t, t->refs.count,
-          t->refs.count + 1, reason, file, line);
-  gpr_ref(&t->refs);
-}
-#else
-#define REF_TRANSPORT(t, r) ref_transport(t)
-#define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t)
-static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
-  if (!gpr_unref(&t->refs)) return;
-  destruct_transport(exec_ctx, t);
-}
-
-static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
-#endif
-
-static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                           const grpc_channel_args *channel_args,
-                           grpc_endpoint *ep, uint8_t is_client) {
-  size_t i;
-  int j;
-
-  GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
-             GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
-
-  memset(t, 0, sizeof(*t));
-
-  t->base.vtable = &vtable;
-  t->ep = ep;
-  /* one ref is for destroy, the other for when ep becomes NULL */
-  gpr_ref_init(&t->refs, 2);
-  /* ref is dropped at transport close() */
-  gpr_ref_init(&t->shutdown_ep_refs, 1);
-  gpr_mu_init(&t->mu);
-  t->peer_string = grpc_endpoint_get_peer(ep);
-  t->endpoint_reading = 1;
-  t->global.next_stream_id = is_client ? 1 : 2;
-  t->global.is_client = is_client;
-  t->writing.outgoing_window = DEFAULT_WINDOW;
-  t->parsing.incoming_window = DEFAULT_WINDOW;
-  t->global.stream_lookahead = DEFAULT_WINDOW;
-  t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
-  t->global.ping_counter = 1;
-  t->global.pings.next = t->global.pings.prev = &t->global.pings;
-  t->parsing.is_client = is_client;
-  t->parsing.deframe_state =
-      is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
-  t->writing.is_client = is_client;
-  grpc_connectivity_state_init(
-      &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
-      is_client ? "client_transport" : "server_transport");
-
-  gpr_slice_buffer_init(&t->global.qbuf);
-
-  gpr_slice_buffer_init(&t->writing.outbuf);
-  grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor);
-  grpc_closure_init(&t->writing_action, writing_action, t);
-
-  gpr_slice_buffer_init(&t->parsing.qbuf);
-  grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser);
-  grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser);
-
-  grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing,
-                    &t->writing);
-  grpc_closure_init(&t->recv_data, recv_data, t);
-  gpr_slice_buffer_init(&t->read_buffer);
-
-  if (is_client) {
-    gpr_slice_buffer_add(
-        &t->global.qbuf,
-        gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
-  }
-  /* 8 is a random stab in the dark as to a good initial size: it's small enough
-     that it shouldn't waste memory for infrequently used connections, yet
-     large enough that the exponential growth should happen nicely when it's
-     needed.
-     TODO(ctiller): tune this */
-  grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8);
-  grpc_chttp2_stream_map_init(&t->new_stream_map, 8);
-
-  /* copy in initial settings to all setting sets */
-  for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) {
-    t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value;
-    for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) {
-      t->global.settings[j][i] =
-          grpc_chttp2_settings_parameters[i].default_value;
-    }
-  }
-  t->global.dirtied_local_settings = 1;
-  /* Hack: it's common for implementations to assume 65536 bytes initial send
-     window -- this should by rights be 0 */
-  t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
-  t->global.sent_local_settings = 0;
-
-  /* configure http2 the way we like it */
-  if (is_client) {
-    push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
-    push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
-  }
-  push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW);
-
-  if (channel_args) {
-    for (i = 0; i < channel_args->num_args; i++) {
-      if (0 ==
-          strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) {
-        if (is_client) {
-          gpr_log(GPR_ERROR, "%s: is ignored on the client",
-                  GRPC_ARG_MAX_CONCURRENT_STREAMS);
-        } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
-          gpr_log(GPR_ERROR, "%s: must be an integer",
-                  GRPC_ARG_MAX_CONCURRENT_STREAMS);
-        } else {
-          push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
-                       (uint32_t)channel_args->args[i].value.integer);
-        }
-      } else if (0 == strcmp(channel_args->args[i].key,
-                             GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
-        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
-          gpr_log(GPR_ERROR, "%s: must be an integer",
-                  GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER);
-        } else if ((t->global.next_stream_id & 1) !=
-                   (channel_args->args[i].value.integer & 1)) {
-          gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
-                  GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER,
-                  t->global.next_stream_id & 1,
-                  is_client ? "client" : "server");
-        } else {
-          t->global.next_stream_id =
-              (uint32_t)channel_args->args[i].value.integer;
-        }
-      } else if (0 == strcmp(channel_args->args[i].key,
-                             GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
-        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
-          gpr_log(GPR_ERROR, "%s: must be an integer",
-                  GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
-        } else if (channel_args->args[i].value.integer <= 5) {
-          gpr_log(GPR_ERROR, "%s: must be at least 5",
-                  GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
-        } else {
-          t->global.stream_lookahead =
-              (uint32_t)channel_args->args[i].value.integer;
-        }
-      } else if (0 == strcmp(channel_args->args[i].key,
-                             GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) {
-        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
-          gpr_log(GPR_ERROR, "%s: must be an integer",
-                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
-        } else if (channel_args->args[i].value.integer < 0) {
-          gpr_log(GPR_ERROR, "%s: must be non-negative",
-                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
-        } else {
-          push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
-                       (uint32_t)channel_args->args[i].value.integer);
-        }
-      } else if (0 == strcmp(channel_args->args[i].key,
-                             GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
-        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
-          gpr_log(GPR_ERROR, "%s: must be an integer",
-                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
-        } else if (channel_args->args[i].value.integer < 0) {
-          gpr_log(GPR_ERROR, "%s: must be non-negative",
-                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
-        } else {
-          grpc_chttp2_hpack_compressor_set_max_usable_size(
-              &t->writing.hpack_compressor,
-              (uint32_t)channel_args->args[i].value.integer);
-        }
-      }
-    }
-  }
-}
-
-static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
-
-  lock(t);
-  t->destroying = 1;
-  drop_connection(exec_ctx, t);
-  unlock(exec_ctx, t);
-
-  UNREF_TRANSPORT(exec_ctx, t, "destroy");
-}
-
-/** block grpc_endpoint_shutdown being called until a paired
-    allow_endpoint_shutdown is made */
-static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) {
-  GPR_ASSERT(t->ep);
-  gpr_ref(&t->shutdown_ep_refs);
-}
-
-static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx,
-                                           grpc_chttp2_transport *t) {
-  if (gpr_unref(&t->shutdown_ep_refs)) {
-    if (t->ep) {
-      grpc_endpoint_shutdown(exec_ctx, t->ep);
-    }
-  }
-}
-
-static void allow_endpoint_shutdown_unlocked(grpc_exec_ctx *exec_ctx,
-                                             grpc_chttp2_transport *t) {
-  if (gpr_unref(&t->shutdown_ep_refs)) {
-    gpr_mu_lock(&t->mu);
-    if (t->ep) {
-      grpc_endpoint_shutdown(exec_ctx, t->ep);
-    }
-    gpr_mu_unlock(&t->mu);
-  }
-}
-
-static void destroy_endpoint(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport *t) {
-  grpc_endpoint_destroy(exec_ctx, t->ep);
-  t->ep = NULL;
-  /* safe because we'll still have the ref for write */
-  UNREF_TRANSPORT(exec_ctx, t, "disconnect");
-}
-
-static void close_transport_locked(grpc_exec_ctx *exec_ctx,
-                                   grpc_chttp2_transport *t) {
-  if (!t->closed) {
-    t->closed = 1;
-    connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_FATAL_FAILURE,
-                           "close_transport");
-    if (t->ep) {
-      allow_endpoint_shutdown_locked(exec_ctx, t);
-    }
-
-    /* flush writable stream list to avoid dangling references */
-    grpc_chttp2_stream_global *stream_global;
-    grpc_chttp2_stream_writing *stream_writing;
-    while (grpc_chttp2_list_pop_writable_stream(
-        &t->global, &t->writing, &stream_global, &stream_writing)) {
-      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
-    }
-  }
-}
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global,
-                            const char *reason) {
-  grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount, reason);
-}
-void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_stream_global *stream_global,
-                              const char *reason) {
-  grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount,
-                    reason);
-}
-#else
-void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global) {
-  grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount);
-}
-void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_stream_global *stream_global) {
-  grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount);
-}
-#endif
-
-static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
-                       grpc_stream *gs, grpc_stream_refcount *refcount,
-                       const void *server_data) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
-  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
-
-  memset(s, 0, sizeof(*s));
-
-  s->refcount = refcount;
-  GRPC_CHTTP2_STREAM_REF(&s->global, "chttp2");
-
-  grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[0]);
-  grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[1]);
-  grpc_chttp2_incoming_metadata_buffer_init(
-      &s->global.received_initial_metadata);
-  grpc_chttp2_incoming_metadata_buffer_init(
-      &s->global.received_trailing_metadata);
-  grpc_chttp2_data_parser_init(&s->parsing.data_parser);
-  gpr_slice_buffer_init(&s->writing.flow_controlled_buffer);
-
-  REF_TRANSPORT(t, "stream");
-
-  lock(t);
-  grpc_chttp2_register_stream(t, s);
-  if (server_data) {
-    GPR_ASSERT(t->parsing_active);
-    s->global.id = (uint32_t)(uintptr_t)server_data;
-    s->parsing.id = s->global.id;
-    s->global.outgoing_window =
-        t->global.settings[GRPC_PEER_SETTINGS]
-                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    s->parsing.incoming_window = s->global.max_recv_bytes =
-        t->global.settings[GRPC_SENT_SETTINGS]
-                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    *t->accepting_stream = s;
-    grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s);
-    s->global.in_stream_map = 1;
-  }
-  unlock(exec_ctx, t);
-
-  return 0;
-}
-
-static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
-                           grpc_stream *gs) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
-  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
-  int i;
-  grpc_byte_stream *bs;
-
-  GPR_TIMER_BEGIN("destroy_stream", 0);
-
-  gpr_mu_lock(&t->mu);
-
-  GPR_ASSERT((s->global.write_closed && s->global.read_closed) ||
-             s->global.id == 0);
-  GPR_ASSERT(!s->global.in_stream_map);
-  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
-    close_transport_locked(exec_ctx, t);
-  }
-  if (!t->parsing_active && s->global.id) {
-    GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
-                                           s->global.id) == NULL);
-  }
-
-  grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global,
-                                                                &s->global);
-  grpc_chttp2_list_remove_stalled_by_transport(&t->global, &s->global);
-
-  gpr_mu_unlock(&t->mu);
-
-  for (i = 0; i < STREAM_LIST_COUNT; i++) {
-    if (s->included[i]) {
-      gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
-              t->global.is_client ? "client" : "server", s->global.id, i);
-      abort();
-    }
-  }
-
-  while (
-      (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) {
-    grpc_byte_stream_destroy(exec_ctx, bs);
-  }
-
-  GPR_ASSERT(s->global.send_initial_metadata_finished == NULL);
-  GPR_ASSERT(s->global.send_message_finished == NULL);
-  GPR_ASSERT(s->global.send_trailing_metadata_finished == NULL);
-  GPR_ASSERT(s->global.recv_initial_metadata_ready == NULL);
-  GPR_ASSERT(s->global.recv_message_ready == NULL);
-  GPR_ASSERT(s->global.recv_trailing_metadata_finished == NULL);
-  grpc_chttp2_data_parser_destroy(exec_ctx, &s->parsing.data_parser);
-  grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[0]);
-  grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[1]);
-  grpc_chttp2_incoming_metadata_buffer_destroy(
-      &s->global.received_initial_metadata);
-  grpc_chttp2_incoming_metadata_buffer_destroy(
-      &s->global.received_trailing_metadata);
-  gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer);
-
-  UNREF_TRANSPORT(exec_ctx, t, "stream");
-
-  GPR_TIMER_END("destroy_stream", 0);
-}
-
-grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
-    grpc_chttp2_transport_parsing *transport_parsing, uint32_t id) {
-  grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
-  grpc_chttp2_stream *s =
-      grpc_chttp2_stream_map_find(&t->parsing_stream_map, id);
-  return s ? &s->parsing : NULL;
-}
-
-grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    uint32_t id) {
-  grpc_chttp2_stream *accepting;
-  grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
-  GPR_ASSERT(t->accepting_stream == NULL);
-  t->accepting_stream = &accepting;
-  t->channel_callback.accept_stream(exec_ctx,
-                                    t->channel_callback.accept_stream_user_data,
-                                    &t->base, (void *)(uintptr_t)id);
-  t->accepting_stream = NULL;
-  return &accepting->parsing;
-}
-
-/*******************************************************************************
- * LOCK MANAGEMENT
- */
-
-/* We take a grpc_chttp2_transport-global lock in response to calls coming in
-   from above,
-   and in response to data being received from below. New data to be written
-   is always queued, as are callbacks to process data. During unlock() we
-   check our todo lists and initiate callbacks and flush writes. */
-
-static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
-
-static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
-  GPR_TIMER_BEGIN("unlock", 0);
-  if (!t->writing_active && !t->closed &&
-      grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing,
-                                         t->parsing_active)) {
-    t->writing_active = 1;
-    REF_TRANSPORT(t, "writing");
-    grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, true, NULL);
-    prevent_endpoint_shutdown(t);
-  }
-  check_read_ops(exec_ctx, &t->global);
-
-  gpr_mu_unlock(&t->mu);
-  GPR_TIMER_END("unlock", 0);
-}
-
-/*******************************************************************************
- * OUTPUT PROCESSING
- */
-
-void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
-                                 grpc_chttp2_stream_global *stream_global) {
-  if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed &&
-      grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) {
-    GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
-  }
-}
-
-static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
-                         uint32_t value) {
-  const grpc_chttp2_setting_parameters *sp =
-      &grpc_chttp2_settings_parameters[id];
-  uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
-  if (use_value != value) {
-    gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
-            value, use_value);
-  }
-  if (use_value != t->global.settings[GRPC_LOCAL_SETTINGS][id]) {
-    t->global.settings[GRPC_LOCAL_SETTINGS][id] = use_value;
-    t->global.dirtied_local_settings = 1;
-  }
-}
-
-void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
-                                   void *transport_writing_ptr, bool success) {
-  grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr;
-  grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
-  grpc_chttp2_stream_global *stream_global;
-
-  GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0);
-
-  lock(t);
-
-  allow_endpoint_shutdown_locked(exec_ctx, t);
-
-  if (!success) {
-    drop_connection(exec_ctx, t);
-  }
-
-  grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
-
-  while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
-                                                         &stream_global)) {
-    fail_pending_writes(exec_ctx, stream_global);
-    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
-  }
-
-  /* leave the writing flag up on shutdown to prevent further writes in unlock()
-     from starting */
-  t->writing_active = 0;
-  if (t->ep && !t->endpoint_reading) {
-    destroy_endpoint(exec_ctx, t);
-  }
-
-  unlock(exec_ctx, t);
-
-  UNREF_TRANSPORT(exec_ctx, t, "writing");
-
-  GPR_TIMER_END("grpc_chttp2_terminate_writing", 0);
-}
-
-static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
-                           bool iomgr_success_ignored) {
-  grpc_chttp2_transport *t = gt;
-  GPR_TIMER_BEGIN("writing_action", 0);
-  grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
-  GPR_TIMER_END("writing_action", 0);
-}
-
-void grpc_chttp2_add_incoming_goaway(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    uint32_t goaway_error, gpr_slice goaway_text) {
-  char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
-  gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg);
-  gpr_free(msg);
-  gpr_slice_unref(goaway_text);
-  transport_global->seen_goaway = 1;
-  connectivity_state_set(exec_ctx, transport_global, GRPC_CHANNEL_FATAL_FAILURE,
-                         "got_goaway");
-}
-
-static void maybe_start_some_streams(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) {
-  grpc_chttp2_stream_global *stream_global;
-  uint32_t stream_incoming_window;
-  /* start streams where we have free grpc_chttp2_stream ids and free
-   * concurrency */
-  while (transport_global->next_stream_id <= MAX_CLIENT_STREAM_ID &&
-         transport_global->concurrent_stream_count <
-             transport_global
-                 ->settings[GRPC_PEER_SETTINGS]
-                           [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] &&
-         grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
-                                                      &stream_global)) {
-    /* safe since we can't (legally) be parsing this stream yet */
-    grpc_chttp2_stream_parsing *stream_parsing =
-        &STREAM_FROM_GLOBAL(stream_global)->parsing;
-    GRPC_CHTTP2_IF_TRACING(gpr_log(
-        GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
-        transport_global->is_client ? "CLI" : "SVR", stream_global,
-        transport_global->next_stream_id));
-
-    GPR_ASSERT(stream_global->id == 0);
-    stream_global->id = stream_parsing->id = transport_global->next_stream_id;
-    transport_global->next_stream_id += 2;
-
-    if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
-      connectivity_state_set(exec_ctx, transport_global,
-                             GRPC_CHANNEL_TRANSIENT_FAILURE,
-                             "no_more_stream_ids");
-    }
-
-    stream_global->outgoing_window =
-        transport_global->settings[GRPC_PEER_SETTINGS]
-                                  [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    stream_parsing->incoming_window = stream_incoming_window =
-        transport_global->settings[GRPC_SENT_SETTINGS]
-                                  [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    stream_global->max_recv_bytes =
-        GPR_MAX(stream_incoming_window, stream_global->max_recv_bytes);
-    grpc_chttp2_stream_map_add(
-        &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map,
-        stream_global->id, STREAM_FROM_GLOBAL(stream_global));
-    stream_global->in_stream_map = 1;
-    transport_global->concurrent_stream_count++;
-    grpc_chttp2_become_writable(transport_global, stream_global);
-  }
-  /* cancel out streams that will never be started */
-  while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
-         grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
-                                                      &stream_global)) {
-    cancel_from_api(exec_ctx, transport_global, stream_global,
-                    GRPC_STATUS_UNAVAILABLE);
-  }
-}
-
-static grpc_closure *add_closure_barrier(grpc_closure *closure) {
-  closure->final_data += 2;
-  return closure;
-}
-
-void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
-                                       grpc_closure **pclosure, int success) {
-  grpc_closure *closure = *pclosure;
-  if (closure == NULL) {
-    return;
-  }
-  closure->final_data -= 2;
-  if (!success) {
-    closure->final_data |= 1;
-  }
-  if (closure->final_data < 2) {
-    grpc_exec_ctx_enqueue(exec_ctx, closure, closure->final_data == 0, NULL);
-  }
-  *pclosure = NULL;
-}
-
-static int contains_non_ok_status(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_metadata_batch *batch) {
-  grpc_linked_mdelem *l;
-  for (l = batch->list.head; l; l = l->next) {
-    if (l->md->key == GRPC_MDSTR_GRPC_STATUS &&
-        l->md != GRPC_MDELEM_GRPC_STATUS_0) {
-      return 1;
-    }
-  }
-  return 0;
-}
-
-static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool success) {}
-
-static void perform_stream_op_locked(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) {
-  grpc_closure *on_complete;
-
-  GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
-
-  on_complete = op->on_complete;
-  if (on_complete == NULL) {
-    on_complete = grpc_closure_create(do_nothing, NULL);
-  }
-  /* use final_data as a barrier until enqueue time; the inital counter is
-     dropped at the end of this function */
-  on_complete->final_data = 2;
-
-  if (op->cancel_with_status != GRPC_STATUS_OK) {
-    cancel_from_api(exec_ctx, transport_global, stream_global,
-                    op->cancel_with_status);
-  }
-
-  if (op->close_with_status != GRPC_STATUS_OK) {
-    close_from_api(exec_ctx, transport_global, stream_global,
-                   op->close_with_status, op->optional_close_message);
-  }
-
-  if (op->send_initial_metadata != NULL) {
-    GPR_ASSERT(stream_global->send_initial_metadata_finished == NULL);
-    stream_global->send_initial_metadata_finished =
-        add_closure_barrier(on_complete);
-    stream_global->send_initial_metadata = op->send_initial_metadata;
-    if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
-      stream_global->seen_error = 1;
-      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-    }
-    if (!stream_global->write_closed) {
-      if (transport_global->is_client) {
-        GPR_ASSERT(stream_global->id == 0);
-        grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
-                                                     stream_global);
-        maybe_start_some_streams(exec_ctx, transport_global);
-      } else {
-        GPR_ASSERT(stream_global->id != 0);
-        grpc_chttp2_become_writable(transport_global, stream_global);
-      }
-    } else {
-      grpc_chttp2_complete_closure_step(
-          exec_ctx, &stream_global->send_initial_metadata_finished, 0);
-    }
-  }
-
-  if (op->send_message != NULL) {
-    GPR_ASSERT(stream_global->send_message_finished == NULL);
-    GPR_ASSERT(stream_global->send_message == NULL);
-    stream_global->send_message_finished = add_closure_barrier(on_complete);
-    if (stream_global->write_closed) {
-      grpc_chttp2_complete_closure_step(
-          exec_ctx, &stream_global->send_message_finished, 0);
-    } else {
-      stream_global->send_message = op->send_message;
-      if (stream_global->id != 0) {
-        grpc_chttp2_become_writable(transport_global, stream_global);
-      }
-    }
-  }
-
-  if (op->send_trailing_metadata != NULL) {
-    GPR_ASSERT(stream_global->send_trailing_metadata_finished == NULL);
-    stream_global->send_trailing_metadata_finished =
-        add_closure_barrier(on_complete);
-    stream_global->send_trailing_metadata = op->send_trailing_metadata;
-    if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) {
-      stream_global->seen_error = 1;
-      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-    }
-    if (stream_global->write_closed) {
-      grpc_chttp2_complete_closure_step(
-          exec_ctx, &stream_global->send_trailing_metadata_finished,
-          grpc_metadata_batch_is_empty(op->send_trailing_metadata));
-    } else if (stream_global->id != 0) {
-      /* TODO(ctiller): check if there's flow control for any outstanding
-         bytes before going writable */
-      grpc_chttp2_become_writable(transport_global, stream_global);
-    }
-  }
-
-  if (op->recv_initial_metadata != NULL) {
-    GPR_ASSERT(stream_global->recv_initial_metadata_ready == NULL);
-    stream_global->recv_initial_metadata_ready =
-        op->recv_initial_metadata_ready;
-    stream_global->recv_initial_metadata = op->recv_initial_metadata;
-    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-  }
-
-  if (op->recv_message != NULL) {
-    GPR_ASSERT(stream_global->recv_message_ready == NULL);
-    stream_global->recv_message_ready = op->recv_message_ready;
-    stream_global->recv_message = op->recv_message;
-    if (stream_global->id != 0 &&
-        (stream_global->incoming_frames.head == NULL ||
-         stream_global->incoming_frames.head->is_tail)) {
-      incoming_byte_stream_update_flow_control(
-          transport_global, stream_global, transport_global->stream_lookahead,
-          0);
-    }
-    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-  }
-
-  if (op->recv_trailing_metadata != NULL) {
-    GPR_ASSERT(stream_global->recv_trailing_metadata_finished == NULL);
-    stream_global->recv_trailing_metadata_finished =
-        add_closure_barrier(on_complete);
-    stream_global->recv_trailing_metadata = op->recv_trailing_metadata;
-    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-  }
-
-  grpc_chttp2_complete_closure_step(exec_ctx, &on_complete, 1);
-
-  GPR_TIMER_END("perform_stream_op_locked", 0);
-}
-
-static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
-                              grpc_stream *gs, grpc_transport_stream_op *op) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
-  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
-
-  lock(t);
-  perform_stream_op_locked(exec_ctx, &t->global, &s->global, op);
-  unlock(exec_ctx, t);
-}
-
-static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) {
-  grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
-  p->next = &t->global.pings;
-  p->prev = p->next->prev;
-  p->prev->next = p->next->prev = p;
-  p->id[0] = (uint8_t)((t->global.ping_counter >> 56) & 0xff);
-  p->id[1] = (uint8_t)((t->global.ping_counter >> 48) & 0xff);
-  p->id[2] = (uint8_t)((t->global.ping_counter >> 40) & 0xff);
-  p->id[3] = (uint8_t)((t->global.ping_counter >> 32) & 0xff);
-  p->id[4] = (uint8_t)((t->global.ping_counter >> 24) & 0xff);
-  p->id[5] = (uint8_t)((t->global.ping_counter >> 16) & 0xff);
-  p->id[6] = (uint8_t)((t->global.ping_counter >> 8) & 0xff);
-  p->id[7] = (uint8_t)(t->global.ping_counter & 0xff);
-  p->on_recv = on_recv;
-  gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id));
-}
-
-void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
-                          grpc_chttp2_transport_parsing *transport_parsing,
-                          const uint8_t *opaque_8bytes) {
-  grpc_chttp2_outstanding_ping *ping;
-  grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing);
-  grpc_chttp2_transport_global *transport_global = &t->global;
-  lock(t);
-  for (ping = transport_global->pings.next; ping != &transport_global->pings;
-       ping = ping->next) {
-    if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
-      grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, true, NULL);
-      ping->next->prev = ping->prev;
-      ping->prev->next = ping->next;
-      gpr_free(ping);
-      break;
-    }
-  }
-  unlock(exec_ctx, t);
-}
-
-static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
-                                        grpc_chttp2_transport *t,
-                                        grpc_transport_op *op) {
-  bool close_transport = false;
-
-  grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
-
-  if (op->on_connectivity_state_change != NULL) {
-    grpc_connectivity_state_notify_on_state_change(
-        exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state,
-        op->on_connectivity_state_change);
-  }
-
-  if (op->send_goaway) {
-    t->global.sent_goaway = 1;
-    grpc_chttp2_goaway_append(
-        t->global.last_incoming_stream_id,
-        (uint32_t)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
-        gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
-    close_transport = !grpc_chttp2_has_streams(t);
-  }
-
-  if (op->set_accept_stream) {
-    t->channel_callback.accept_stream = op->set_accept_stream_fn;
-    t->channel_callback.accept_stream_user_data =
-        op->set_accept_stream_user_data;
-  }
-
-  if (op->bind_pollset) {
-    add_to_pollset_locked(exec_ctx, t, op->bind_pollset);
-  }
-
-  if (op->bind_pollset_set) {
-    add_to_pollset_set_locked(exec_ctx, t, op->bind_pollset_set);
-  }
-
-  if (op->send_ping) {
-    send_ping_locked(t, op->send_ping);
-  }
-
-  if (op->disconnect) {
-    close_transport_locked(exec_ctx, t);
-  }
-
-  if (close_transport) {
-    close_transport_locked(exec_ctx, t);
-  }
-}
-
-static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
-                                 grpc_transport_op *op) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
-
-  lock(t);
-
-  /* If there's a set_accept_stream ensure that we're not parsing
-     to avoid changing things out from underneath */
-  if (t->parsing_active && op->set_accept_stream) {
-    GPR_ASSERT(t->post_parsing_op == NULL);
-    t->post_parsing_op = gpr_malloc(sizeof(*op));
-    memcpy(t->post_parsing_op, op, sizeof(*op));
-  } else {
-    perform_transport_op_locked(exec_ctx, t, op);
-  }
-
-  unlock(exec_ctx, t);
-}
-
-/*******************************************************************************
- * INPUT PROCESSING
- */
-
-static void check_read_ops(grpc_exec_ctx *exec_ctx,
-                           grpc_chttp2_transport_global *transport_global) {
-  grpc_chttp2_stream_global *stream_global;
-  grpc_byte_stream *bs;
-  while (
-      grpc_chttp2_list_pop_check_read_ops(transport_global, &stream_global)) {
-    if (stream_global->recv_initial_metadata_ready != NULL &&
-        stream_global->published_initial_metadata) {
-      grpc_chttp2_incoming_metadata_buffer_publish(
-          &stream_global->received_initial_metadata,
-          stream_global->recv_initial_metadata);
-      grpc_exec_ctx_enqueue(
-          exec_ctx, stream_global->recv_initial_metadata_ready, true, NULL);
-      stream_global->recv_initial_metadata_ready = NULL;
-    }
-    if (stream_global->recv_message_ready != NULL) {
-      while (stream_global->seen_error &&
-             (bs = grpc_chttp2_incoming_frame_queue_pop(
-                  &stream_global->incoming_frames)) != NULL) {
-        grpc_byte_stream_destroy(exec_ctx, bs);
-      }
-      if (stream_global->incoming_frames.head != NULL) {
-        *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
-            &stream_global->incoming_frames);
-        GPR_ASSERT(*stream_global->recv_message != NULL);
-        grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
-                              NULL);
-        stream_global->recv_message_ready = NULL;
-      } else if (stream_global->published_trailing_metadata) {
-        *stream_global->recv_message = NULL;
-        grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
-                              NULL);
-        stream_global->recv_message_ready = NULL;
-      }
-    }
-    if (stream_global->recv_trailing_metadata_finished != NULL &&
-        stream_global->read_closed && stream_global->write_closed) {
-      while (stream_global->seen_error &&
-             (bs = grpc_chttp2_incoming_frame_queue_pop(
-                  &stream_global->incoming_frames)) != NULL) {
-        grpc_byte_stream_destroy(exec_ctx, bs);
-      }
-      if (stream_global->incoming_frames.head == NULL) {
-        grpc_chttp2_incoming_metadata_buffer_publish(
-            &stream_global->received_trailing_metadata,
-            stream_global->recv_trailing_metadata);
-        grpc_chttp2_complete_closure_step(
-            exec_ctx, &stream_global->recv_trailing_metadata_finished, 1);
-      }
-    }
-  }
-}
-
-static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                          uint32_t id) {
-  size_t new_stream_count;
-  grpc_chttp2_stream *s =
-      grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
-  if (!s) {
-    s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
-  }
-  GPR_ASSERT(s);
-  s->global.in_stream_map = 0;
-  if (t->parsing.incoming_stream == &s->parsing) {
-    t->parsing.incoming_stream = NULL;
-    grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing);
-  }
-  if (s->parsing.data_parser.parsing_frame != NULL) {
-    grpc_chttp2_incoming_byte_stream_finished(
-        exec_ctx, s->parsing.data_parser.parsing_frame, 0, 0);
-    s->parsing.data_parser.parsing_frame = NULL;
-  }
-
-  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
-    close_transport_locked(exec_ctx, t);
-  }
-  if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
-    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
-  }
-
-  new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
-                     grpc_chttp2_stream_map_size(&t->new_stream_map);
-  GPR_ASSERT(new_stream_count <= UINT32_MAX);
-  if (new_stream_count != t->global.concurrent_stream_count) {
-    t->global.concurrent_stream_count = (uint32_t)new_stream_count;
-    maybe_start_some_streams(exec_ctx, &t->global);
-  }
-}
-
-static void cancel_from_api(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_global *transport_global,
-                            grpc_chttp2_stream_global *stream_global,
-                            grpc_status_code status) {
-  if (stream_global->id != 0) {
-    gpr_slice_buffer_add(
-        &transport_global->qbuf,
-        grpc_chttp2_rst_stream_create(
-            stream_global->id,
-            (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status)));
-  }
-  grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
-                          NULL);
-  grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
-                                 1);
-}
-
-void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_global *transport_global,
-                             grpc_chttp2_stream_global *stream_global,
-                             grpc_status_code status, gpr_slice *slice) {
-  if (status != GRPC_STATUS_OK) {
-    stream_global->seen_error = 1;
-    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-  }
-  /* stream_global->recv_trailing_metadata_finished gives us a
-     last chance replacement: we've received trailing metadata,
-     but something more important has become available to signal
-     to the upper layers - drop what we've got, and then publish
-     what we want - which is safe because we haven't told anyone
-     about the metadata yet */
-  if (!stream_global->published_trailing_metadata ||
-      stream_global->recv_trailing_metadata_finished != NULL) {
-    char status_string[GPR_LTOA_MIN_BUFSIZE];
-    gpr_ltoa(status, status_string);
-    grpc_chttp2_incoming_metadata_buffer_add(
-        &stream_global->received_trailing_metadata,
-        grpc_mdelem_from_metadata_strings(
-            GRPC_MDSTR_GRPC_STATUS, grpc_mdstr_from_string(status_string)));
-    if (slice) {
-      grpc_chttp2_incoming_metadata_buffer_add(
-          &stream_global->received_trailing_metadata,
-          grpc_mdelem_from_metadata_strings(
-              GRPC_MDSTR_GRPC_MESSAGE,
-              grpc_mdstr_from_slice(gpr_slice_ref(*slice))));
-    }
-    stream_global->published_trailing_metadata = 1;
-    grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-  }
-  if (slice) {
-    gpr_slice_unref(*slice);
-  }
-}
-
-static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
-                                grpc_chttp2_stream_global *stream_global) {
-  grpc_chttp2_complete_closure_step(
-      exec_ctx, &stream_global->send_initial_metadata_finished, 0);
-  grpc_chttp2_complete_closure_step(
-      exec_ctx, &stream_global->send_trailing_metadata_finished, 0);
-  grpc_chttp2_complete_closure_step(exec_ctx,
-                                    &stream_global->send_message_finished, 0);
-}
-
-void grpc_chttp2_mark_stream_closed(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, int close_reads,
-    int close_writes) {
-  if (stream_global->read_closed && stream_global->write_closed) {
-    /* already closed */
-    return;
-  }
-  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
-  if (close_reads && !stream_global->read_closed) {
-    stream_global->read_closed = 1;
-    stream_global->published_initial_metadata = 1;
-    stream_global->published_trailing_metadata = 1;
-  }
-  if (close_writes && !stream_global->write_closed) {
-    stream_global->write_closed = 1;
-    if (TRANSPORT_FROM_GLOBAL(transport_global)->writing_active) {
-      GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes");
-      grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
-                                                      stream_global);
-    } else {
-      fail_pending_writes(exec_ctx, stream_global);
-    }
-  }
-  if (stream_global->read_closed && stream_global->write_closed) {
-    if (stream_global->id != 0 &&
-        TRANSPORT_FROM_GLOBAL(transport_global)->parsing_active) {
-      grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
-                                                      stream_global);
-    } else {
-      if (stream_global->id != 0) {
-        remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
-                      stream_global->id);
-      }
-      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
-    }
-  }
-}
-
-static void close_from_api(grpc_exec_ctx *exec_ctx,
-                           grpc_chttp2_transport_global *transport_global,
-                           grpc_chttp2_stream_global *stream_global,
-                           grpc_status_code status,
-                           gpr_slice *optional_message) {
-  gpr_slice hdr;
-  gpr_slice status_hdr;
-  gpr_slice message_pfx;
-  uint8_t *p;
-  uint32_t len = 0;
-
-  GPR_ASSERT(status >= 0 && (int)status < 100);
-
-  GPR_ASSERT(stream_global->id != 0);
-
-  /* Hand roll a header block.
-     This is unnecessarily ugly - at some point we should find a more elegant
-     solution.
-     It's complicated by the fact that our send machinery would be dead by the
-     time we got around to sending this, so instead we ignore HPACK compression
-     and just write the uncompressed bytes onto the wire. */
-  status_hdr = gpr_slice_malloc(15 + (status >= 10));
-  p = GPR_SLICE_START_PTR(status_hdr);
-  *p++ = 0x40; /* literal header */
-  *p++ = 11;   /* len(grpc-status) */
-  *p++ = 'g';
-  *p++ = 'r';
-  *p++ = 'p';
-  *p++ = 'c';
-  *p++ = '-';
-  *p++ = 's';
-  *p++ = 't';
-  *p++ = 'a';
-  *p++ = 't';
-  *p++ = 'u';
-  *p++ = 's';
-  if (status < 10) {
-    *p++ = 1;
-    *p++ = (uint8_t)('0' + status);
-  } else {
-    *p++ = 2;
-    *p++ = (uint8_t)('0' + (status / 10));
-    *p++ = (uint8_t)('0' + (status % 10));
-  }
-  GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
-  len += (uint32_t)GPR_SLICE_LENGTH(status_hdr);
-
-  if (optional_message) {
-    GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127);
-    message_pfx = gpr_slice_malloc(15);
-    p = GPR_SLICE_START_PTR(message_pfx);
-    *p++ = 0x40;
-    *p++ = 12; /* len(grpc-message) */
-    *p++ = 'g';
-    *p++ = 'r';
-    *p++ = 'p';
-    *p++ = 'c';
-    *p++ = '-';
-    *p++ = 'm';
-    *p++ = 'e';
-    *p++ = 's';
-    *p++ = 's';
-    *p++ = 'a';
-    *p++ = 'g';
-    *p++ = 'e';
-    *p++ = (uint8_t)GPR_SLICE_LENGTH(*optional_message);
-    GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
-    len += (uint32_t)GPR_SLICE_LENGTH(message_pfx);
-    len += (uint32_t)GPR_SLICE_LENGTH(*optional_message);
-  }
-
-  hdr = gpr_slice_malloc(9);
-  p = GPR_SLICE_START_PTR(hdr);
-  *p++ = (uint8_t)(len >> 16);
-  *p++ = (uint8_t)(len >> 8);
-  *p++ = (uint8_t)(len);
-  *p++ = GRPC_CHTTP2_FRAME_HEADER;
-  *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
-  *p++ = (uint8_t)(stream_global->id >> 24);
-  *p++ = (uint8_t)(stream_global->id >> 16);
-  *p++ = (uint8_t)(stream_global->id >> 8);
-  *p++ = (uint8_t)(stream_global->id);
-  GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr));
-
-  gpr_slice_buffer_add(&transport_global->qbuf, hdr);
-  gpr_slice_buffer_add(&transport_global->qbuf, status_hdr);
-  if (optional_message) {
-    gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
-    gpr_slice_buffer_add(&transport_global->qbuf,
-                         gpr_slice_ref(*optional_message));
-  }
-
-  gpr_slice_buffer_add(
-      &transport_global->qbuf,
-      grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR));
-
-  if (optional_message) {
-    gpr_slice_ref(*optional_message);
-  }
-  grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
-                          optional_message);
-  grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
-                                 1);
-}
-
-static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
-                             void *user_data,
-                             grpc_chttp2_stream_global *stream_global) {
-  cancel_from_api(user_data, transport_global, stream_global,
-                  GRPC_STATUS_UNAVAILABLE);
-}
-
-static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_transport *t) {
-  grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb);
-}
-
-static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
-  close_transport_locked(exec_ctx, t);
-  end_all_the_calls(exec_ctx, t);
-}
-
-/** update window from a settings change */
-static void update_global_window(void *args, uint32_t id, void *stream) {
-  grpc_chttp2_transport *t = args;
-  grpc_chttp2_stream *s = stream;
-  grpc_chttp2_transport_global *transport_global = &t->global;
-  grpc_chttp2_stream_global *stream_global = &s->global;
-  int was_zero;
-  int is_zero;
-  int64_t initial_window_update = t->parsing.initial_window_update;
-
-  was_zero = stream_global->outgoing_window <= 0;
-  GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", transport_global, stream_global,
-                                 outgoing_window, initial_window_update);
-  is_zero = stream_global->outgoing_window <= 0;
-
-  if (was_zero && !is_zero) {
-    grpc_chttp2_become_writable(transport_global, stream_global);
-  }
-}
-
-static void read_error_locked(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_transport *t) {
-  t->endpoint_reading = 0;
-  if (!t->writing_active && t->ep) {
-    destroy_endpoint(exec_ctx, t);
-  }
-}
-
-/* tcp read callback */
-static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
-  size_t i;
-  int keep_reading = 0;
-  grpc_chttp2_transport *t = tp;
-  grpc_chttp2_transport_global *transport_global = &t->global;
-  grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
-  grpc_chttp2_stream_global *stream_global;
-
-  GPR_TIMER_BEGIN("recv_data", 0);
-
-  lock(t);
-  i = 0;
-  GPR_ASSERT(!t->parsing_active);
-  if (!t->closed) {
-    t->parsing_active = 1;
-    /* merge stream lists */
-    grpc_chttp2_stream_map_move_into(&t->new_stream_map,
-                                     &t->parsing_stream_map);
-    grpc_chttp2_prepare_to_read(transport_global, transport_parsing);
-    gpr_mu_unlock(&t->mu);
-    GPR_TIMER_BEGIN("recv_data.parse", 0);
-    for (; i < t->read_buffer.count &&
-               grpc_chttp2_perform_read(exec_ctx, transport_parsing,
-                                        t->read_buffer.slices[i]);
-         i++)
-      ;
-    GPR_TIMER_END("recv_data.parse", 0);
-    gpr_mu_lock(&t->mu);
-    /* copy parsing qbuf to global qbuf */
-    gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf);
-    if (i != t->read_buffer.count) {
-      unlock(exec_ctx, t);
-      lock(t);
-      drop_connection(exec_ctx, t);
-    }
-    /* merge stream lists */
-    grpc_chttp2_stream_map_move_into(&t->new_stream_map,
-                                     &t->parsing_stream_map);
-    transport_global->concurrent_stream_count =
-        (uint32_t)grpc_chttp2_stream_map_size(&t->parsing_stream_map);
-    if (transport_parsing->initial_window_update != 0) {
-      grpc_chttp2_stream_map_for_each(&t->parsing_stream_map,
-                                      update_global_window, t);
-      transport_parsing->initial_window_update = 0;
-    }
-    /* handle higher level things */
-    grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing);
-    t->parsing_active = 0;
-    /* handle delayed transport ops (if there is one) */
-    if (t->post_parsing_op) {
-      grpc_transport_op *op = t->post_parsing_op;
-      t->post_parsing_op = NULL;
-      perform_transport_op_locked(exec_ctx, t, op);
-      gpr_free(op);
-    }
-    /* if a stream is in the stream map, and gets cancelled, we need to ensure
-     * we are not parsing before continuing the cancellation to keep things in
-     * a sane state */
-    while (grpc_chttp2_list_pop_closed_waiting_for_parsing(transport_global,
-                                                           &stream_global)) {
-      GPR_ASSERT(stream_global->in_stream_map);
-      GPR_ASSERT(stream_global->write_closed);
-      GPR_ASSERT(stream_global->read_closed);
-      remove_stream(exec_ctx, t, stream_global->id);
-      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
-    }
-  }
-  if (!success || i != t->read_buffer.count || t->closed) {
-    drop_connection(exec_ctx, t);
-    read_error_locked(exec_ctx, t);
-  } else if (!t->closed) {
-    keep_reading = 1;
-    REF_TRANSPORT(t, "keep_reading");
-    prevent_endpoint_shutdown(t);
-  }
-  gpr_slice_buffer_reset_and_unref(&t->read_buffer);
-  unlock(exec_ctx, t);
-
-  if (keep_reading) {
-    grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->recv_data);
-    allow_endpoint_shutdown_unlocked(exec_ctx, t);
-    UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
-  } else {
-    UNREF_TRANSPORT(exec_ctx, t, "recv_data");
-  }
-
-  GPR_TIMER_END("recv_data", 0);
-}
-
-/*******************************************************************************
- * CALLBACK LOOP
- */
-
-static void connectivity_state_set(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_connectivity_state state, const char *reason) {
-  GRPC_CHTTP2_IF_TRACING(
-      gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
-  grpc_connectivity_state_set(exec_ctx, &TRANSPORT_FROM_GLOBAL(transport_global)
-                                             ->channel_callback.state_tracker,
-                              state, reason);
-}
-
-/*******************************************************************************
- * POLLSET STUFF
- */
-
-static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
-                                  grpc_chttp2_transport *t,
-                                  grpc_pollset *pollset) {
-  if (t->ep) {
-    grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset);
-  }
-}
-
-static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx,
-                                      grpc_chttp2_transport *t,
-                                      grpc_pollset_set *pollset_set) {
-  if (t->ep) {
-    grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set);
-  }
-}
-
-static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
-                        grpc_stream *gs, grpc_pollset *pollset) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
-  lock(t);
-  add_to_pollset_locked(exec_ctx, t, pollset);
-  unlock(exec_ctx, t);
-}
-
-/*******************************************************************************
- * BYTE STREAM
- */
-
-static void incoming_byte_stream_update_flow_control(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
-    size_t have_already) {
-  uint32_t max_recv_bytes;
-
-  /* clamp max recv hint to an allowable size */
-  if (max_size_hint >= UINT32_MAX - transport_global->stream_lookahead) {
-    max_recv_bytes = UINT32_MAX - transport_global->stream_lookahead;
-  } else {
-    max_recv_bytes = (uint32_t)max_size_hint;
-  }
-
-  /* account for bytes already received but unknown to higher layers */
-  if (max_recv_bytes >= have_already) {
-    max_recv_bytes -= (uint32_t)have_already;
-  } else {
-    max_recv_bytes = 0;
-  }
-
-  /* add some small lookahead to keep pipelines flowing */
-  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - transport_global->stream_lookahead);
-  max_recv_bytes += transport_global->stream_lookahead;
-  if (stream_global->max_recv_bytes < max_recv_bytes) {
-    uint32_t add_max_recv_bytes =
-        max_recv_bytes - stream_global->max_recv_bytes;
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
-                                   max_recv_bytes, add_max_recv_bytes);
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
-                                   unannounced_incoming_window_for_parse,
-                                   add_max_recv_bytes);
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global,
-                                   unannounced_incoming_window_for_writing,
-                                   add_max_recv_bytes);
-    grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
-                                                               stream_global);
-    grpc_chttp2_become_writable(transport_global, stream_global);
-  }
-}
-
-static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx,
-                                     grpc_byte_stream *byte_stream,
-                                     gpr_slice *slice, size_t max_size_hint,
-                                     grpc_closure *on_complete) {
-  grpc_chttp2_incoming_byte_stream *bs =
-      (grpc_chttp2_incoming_byte_stream *)byte_stream;
-  grpc_chttp2_transport_global *transport_global = &bs->transport->global;
-  grpc_chttp2_stream_global *stream_global = &bs->stream->global;
-
-  lock(bs->transport);
-  if (bs->is_tail) {
-    incoming_byte_stream_update_flow_control(transport_global, stream_global,
-                                             max_size_hint, bs->slices.length);
-  }
-  if (bs->slices.count > 0) {
-    *slice = gpr_slice_buffer_take_first(&bs->slices);
-    unlock(exec_ctx, bs->transport);
-    return 1;
-  } else if (bs->failed) {
-    grpc_exec_ctx_enqueue(exec_ctx, on_complete, false, NULL);
-    unlock(exec_ctx, bs->transport);
-    return 0;
-  } else {
-    bs->on_next = on_complete;
-    bs->next = slice;
-    unlock(exec_ctx, bs->transport);
-    return 0;
-  }
-}
-
-static void incoming_byte_stream_unref(grpc_chttp2_incoming_byte_stream *bs) {
-  if (gpr_unref(&bs->refs)) {
-    gpr_slice_buffer_destroy(&bs->slices);
-    gpr_free(bs);
-  }
-}
-
-static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
-                                         grpc_byte_stream *byte_stream) {
-  incoming_byte_stream_unref((grpc_chttp2_incoming_byte_stream *)byte_stream);
-}
-
-void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
-                                           grpc_chttp2_incoming_byte_stream *bs,
-                                           gpr_slice slice) {
-  gpr_mu_lock(&bs->transport->mu);
-  if (bs->on_next != NULL) {
-    *bs->next = slice;
-    grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, true, NULL);
-    bs->on_next = NULL;
-  } else {
-    gpr_slice_buffer_add(&bs->slices, slice);
-  }
-  gpr_mu_unlock(&bs->transport->mu);
-}
-
-void grpc_chttp2_incoming_byte_stream_finished(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
-    int from_parsing_thread) {
-  if (!success) {
-    if (from_parsing_thread) {
-      gpr_mu_lock(&bs->transport->mu);
-    }
-    grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, false, NULL);
-    bs->on_next = NULL;
-    bs->failed = 1;
-    if (from_parsing_thread) {
-      gpr_mu_unlock(&bs->transport->mu);
-    }
-  } else {
-#ifndef NDEBUG
-    if (from_parsing_thread) {
-      gpr_mu_lock(&bs->transport->mu);
-    }
-    GPR_ASSERT(bs->on_next == NULL);
-    if (from_parsing_thread) {
-      gpr_mu_unlock(&bs->transport->mu);
-    }
-#endif
-  }
-  incoming_byte_stream_unref(bs);
-}
-
-grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, uint32_t frame_size,
-    uint32_t flags, grpc_chttp2_incoming_frame_queue *add_to_queue) {
-  grpc_chttp2_incoming_byte_stream *incoming_byte_stream =
-      gpr_malloc(sizeof(*incoming_byte_stream));
-  incoming_byte_stream->base.length = frame_size;
-  incoming_byte_stream->base.flags = flags;
-  incoming_byte_stream->base.next = incoming_byte_stream_next;
-  incoming_byte_stream->base.destroy = incoming_byte_stream_destroy;
-  gpr_ref_init(&incoming_byte_stream->refs, 2);
-  incoming_byte_stream->next_message = NULL;
-  incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing);
-  incoming_byte_stream->stream = STREAM_FROM_PARSING(stream_parsing);
-  gpr_slice_buffer_init(&incoming_byte_stream->slices);
-  incoming_byte_stream->on_next = NULL;
-  incoming_byte_stream->is_tail = 1;
-  incoming_byte_stream->failed = 0;
-  if (add_to_queue->head == NULL) {
-    add_to_queue->head = incoming_byte_stream;
-  } else {
-    add_to_queue->tail->is_tail = 0;
-    add_to_queue->tail->next_message = incoming_byte_stream;
-  }
-  add_to_queue->tail = incoming_byte_stream;
-  return incoming_byte_stream;
-}
-
-/*******************************************************************************
- * TRACING
- */
-
-static char *format_flowctl_context_var(const char *context, const char *var,
-                                        int64_t val, uint32_t id,
-                                        char **scope) {
-  char *underscore_pos;
-  char *result;
-  if (context == NULL) {
-    *scope = NULL;
-    gpr_asprintf(&result, "%s(%lld)", var, val);
-    return result;
-  }
-  underscore_pos = strchr(context, '_');
-  *scope = gpr_strdup(context);
-  (*scope)[underscore_pos - context] = 0;
-  if (id != 0) {
-    char *tmp = *scope;
-    gpr_asprintf(scope, "%s[%d]", tmp, id);
-    gpr_free(tmp);
-  }
-  gpr_asprintf(&result, "%s.%s(%lld)", underscore_pos + 1, var, val);
-  return result;
-}
-
-static int samestr(char *a, char *b) {
-  if (a == NULL) {
-    return b == NULL;
-  }
-  if (b == NULL) {
-    return 0;
-  }
-  return 0 == strcmp(a, b);
-}
-
-void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
-                               grpc_chttp2_flowctl_op op, const char *context1,
-                               const char *var1, const char *context2,
-                               const char *var2, int is_client,
-                               uint32_t stream_id, int64_t val1, int64_t val2) {
-  char *scope1;
-  char *scope2;
-  char *label1 =
-      format_flowctl_context_var(context1, var1, val1, stream_id, &scope1);
-  char *label2 =
-      format_flowctl_context_var(context2, var2, val2, stream_id, &scope2);
-  char *clisvr = is_client ? "client" : "server";
-  char *prefix;
-
-  gpr_asprintf(&prefix, "FLOW % 8s: %s % 11s ", phase, clisvr, scope1);
-
-  switch (op) {
-    case GRPC_CHTTP2_FLOWCTL_MOVE:
-      GPR_ASSERT(samestr(scope1, scope2));
-      if (val2 != 0) {
-        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-                "%sMOVE   % 40s <- % 40s giving %d", prefix, label1, label2,
-                val1 + val2);
-      }
-      break;
-    case GRPC_CHTTP2_FLOWCTL_CREDIT:
-      GPR_ASSERT(val2 >= 0);
-      if (val2 != 0) {
-        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-                "%sCREDIT % 40s by % 40s giving %d", prefix, label1, label2,
-                val1 + val2);
-      }
-      break;
-    case GRPC_CHTTP2_FLOWCTL_DEBIT:
-      GPR_ASSERT(val2 >= 0);
-      if (val2 != 0) {
-        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-                "%sDEBIT  % 40s by % 40s giving %d", prefix, label1, label2,
-                val1 - val2);
-      }
-      break;
-  }
-
-  gpr_free(scope1);
-  gpr_free(scope2);
-  gpr_free(label1);
-  gpr_free(label2);
-  gpr_free(prefix);
-}
-
-/*******************************************************************************
- * INTEGRATION GLUE
- */
-
-static char *chttp2_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
-  return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
-}
-
-static const grpc_transport_vtable vtable = {
-    sizeof(grpc_chttp2_stream), "chttp2", init_stream, set_pollset,
-    perform_stream_op, perform_transport_op, destroy_stream, destroy_transport,
-    chttp2_get_peer};
-
-grpc_transport *grpc_create_chttp2_transport(
-    grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
-    grpc_endpoint *ep, int is_client) {
-  grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
-  init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
-  return &t->base;
-}
-
-void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
-                                         grpc_transport *transport,
-                                         gpr_slice *slices, size_t nslices) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
-  REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */
-  gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
-  recv_data(exec_ctx, t, 1);
-}
diff --git a/src/core/transport/chttp2_transport.h b/src/core/transport/chttp2_transport.h
deleted file mode 100644
index 9a6cf0e..0000000
--- a/src/core/transport/chttp2_transport.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CHTTP2_TRANSPORT_H
-#define GRPC_CORE_TRANSPORT_CHTTP2_TRANSPORT_H
-
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/transport/transport.h"
-
-extern int grpc_http_trace;
-extern int grpc_flowctl_trace;
-
-grpc_transport *grpc_create_chttp2_transport(
-    grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
-    grpc_endpoint *ep, int is_client);
-
-void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
-                                         grpc_transport *transport,
-                                         gpr_slice *slices, size_t nslices);
-
-#endif /* GRPC_CORE_TRANSPORT_CHTTP2_TRANSPORT_H */
diff --git a/src/core/transport/connectivity_state.c b/src/core/transport/connectivity_state.c
deleted file mode 100644
index 87765b9..0000000
--- a/src/core/transport/connectivity_state.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- *
- * 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/transport/connectivity_state.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-int grpc_connectivity_state_trace = 0;
-
-const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
-  switch (state) {
-    case GRPC_CHANNEL_IDLE:
-      return "IDLE";
-    case GRPC_CHANNEL_CONNECTING:
-      return "CONNECTING";
-    case GRPC_CHANNEL_READY:
-      return "READY";
-    case GRPC_CHANNEL_TRANSIENT_FAILURE:
-      return "TRANSIENT_FAILURE";
-    case GRPC_CHANNEL_FATAL_FAILURE:
-      return "FATAL_FAILURE";
-  }
-  GPR_UNREACHABLE_CODE(return "UNKNOWN");
-}
-
-void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
-                                  grpc_connectivity_state init_state,
-                                  const char *name) {
-  tracker->current_state = init_state;
-  tracker->watchers = NULL;
-  tracker->name = gpr_strdup(name);
-}
-
-void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
-                                     grpc_connectivity_state_tracker *tracker) {
-  int success;
-  grpc_connectivity_state_watcher *w;
-  while ((w = tracker->watchers)) {
-    tracker->watchers = w->next;
-
-    if (GRPC_CHANNEL_FATAL_FAILURE != *w->current) {
-      *w->current = GRPC_CHANNEL_FATAL_FAILURE;
-      success = 1;
-    } else {
-      success = 0;
-    }
-    grpc_exec_ctx_enqueue(exec_ctx, w->notify, success, NULL);
-    gpr_free(w);
-  }
-  gpr_free(tracker->name);
-}
-
-grpc_connectivity_state grpc_connectivity_state_check(
-    grpc_connectivity_state_tracker *tracker) {
-  if (grpc_connectivity_state_trace) {
-    gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
-            grpc_connectivity_state_name(tracker->current_state));
-  }
-  return tracker->current_state;
-}
-
-int grpc_connectivity_state_notify_on_state_change(
-    grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
-    grpc_connectivity_state *current, grpc_closure *notify) {
-  if (grpc_connectivity_state_trace) {
-    if (current == NULL) {
-      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
-              tracker->name, notify);
-    } else {
-      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
-              tracker->name, grpc_connectivity_state_name(*current),
-              grpc_connectivity_state_name(tracker->current_state), notify);
-    }
-  }
-  if (current == NULL) {
-    grpc_connectivity_state_watcher *w = tracker->watchers;
-    if (w != NULL && w->notify == notify) {
-      grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
-      tracker->watchers = w->next;
-      gpr_free(w);
-      return 0;
-    }
-    while (w != NULL) {
-      grpc_connectivity_state_watcher *rm_candidate = w->next;
-      if (rm_candidate != NULL && rm_candidate->notify == notify) {
-        grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
-        w->next = w->next->next;
-        gpr_free(rm_candidate);
-        return 0;
-      }
-      w = w->next;
-    }
-    return 0;
-  } else {
-    if (tracker->current_state != *current) {
-      *current = tracker->current_state;
-      grpc_exec_ctx_enqueue(exec_ctx, notify, true, NULL);
-    } else {
-      grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w));
-      w->current = current;
-      w->notify = notify;
-      w->next = tracker->watchers;
-      tracker->watchers = w;
-    }
-    return tracker->current_state == GRPC_CHANNEL_IDLE;
-  }
-}
-
-void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
-                                 grpc_connectivity_state_tracker *tracker,
-                                 grpc_connectivity_state state,
-                                 const char *reason) {
-  grpc_connectivity_state_watcher *w;
-  if (grpc_connectivity_state_trace) {
-    gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s]", tracker, tracker->name,
-            grpc_connectivity_state_name(tracker->current_state),
-            grpc_connectivity_state_name(state), reason);
-  }
-  if (tracker->current_state == state) {
-    return;
-  }
-  GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_FATAL_FAILURE);
-  tracker->current_state = state;
-  while ((w = tracker->watchers) != NULL) {
-    *w->current = tracker->current_state;
-    tracker->watchers = w->next;
-    grpc_exec_ctx_enqueue(exec_ctx, w->notify, true, NULL);
-    gpr_free(w);
-  }
-}
diff --git a/src/core/transport/connectivity_state.h b/src/core/transport/connectivity_state.h
deleted file mode 100644
index b4a3ce9..0000000
--- a/src/core/transport/connectivity_state.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_CONNECTIVITY_STATE_H
-#define GRPC_CORE_TRANSPORT_CONNECTIVITY_STATE_H
-
-#include <grpc/grpc.h>
-#include "src/core/iomgr/exec_ctx.h"
-
-typedef struct grpc_connectivity_state_watcher {
-  /** we keep watchers in a linked list */
-  struct grpc_connectivity_state_watcher *next;
-  /** closure to notify on change */
-  grpc_closure *notify;
-  /** the current state as believed by the watcher */
-  grpc_connectivity_state *current;
-} grpc_connectivity_state_watcher;
-
-typedef struct {
-  /** current connectivity state */
-  grpc_connectivity_state current_state;
-  /** all our watchers */
-  grpc_connectivity_state_watcher *watchers;
-  /** a name to help debugging */
-  char *name;
-} grpc_connectivity_state_tracker;
-
-extern int grpc_connectivity_state_trace;
-
-const char *grpc_connectivity_state_name(grpc_connectivity_state state);
-
-void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
-                                  grpc_connectivity_state init_state,
-                                  const char *name);
-void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
-                                     grpc_connectivity_state_tracker *tracker);
-
-/** Set connectivity state; not thread safe; access must be serialized with an
- * external lock */
-void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
-                                 grpc_connectivity_state_tracker *tracker,
-                                 grpc_connectivity_state state,
-                                 const char *reason);
-
-grpc_connectivity_state grpc_connectivity_state_check(
-    grpc_connectivity_state_tracker *tracker);
-
-/** Return 1 if the channel should start connecting, 0 otherwise.
-    If current==NULL cancel notify if it is already queued (success==0 in that
-    case) */
-int grpc_connectivity_state_notify_on_state_change(
-    grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
-    grpc_connectivity_state *current, grpc_closure *notify);
-
-#endif /* GRPC_CORE_TRANSPORT_CONNECTIVITY_STATE_H */
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
deleted file mode 100644
index 807ae07..0000000
--- a/src/core/transport/metadata.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- *
- * 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/transport/metadata.h"
-
-#include <assert.h>
-#include <stddef.h>
-#include <string.h>
-
-#include <grpc/compression.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/time.h>
-
-#include "src/core/profiling/timers.h"
-#include "src/core/support/murmur_hash.h"
-#include "src/core/support/string.h"
-#include "src/core/transport/chttp2/bin_encoder.h"
-#include "src/core/transport/static_metadata.h"
-#include "src/core/iomgr/iomgr_internal.h"
-
-/* There are two kinds of mdelem and mdstr instances.
- * Static instances are declared in static_metadata.{h,c} and
- * are initialized by grpc_mdctx_global_init().
- * Dynamic instances are stored in hash tables on grpc_mdctx, and are backed
- * by internal_string and internal_element structures.
- * Internal helper functions here-in (is_mdstr_static, is_mdelem_static) are
- * used to determine which kind of element a pointer refers to.
- */
-
-#define INITIAL_STRTAB_CAPACITY 4
-#define INITIAL_MDTAB_CAPACITY 4
-
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-#define DEBUG_ARGS , const char *file, int line
-#define FWD_DEBUG_ARGS , file, line
-#define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s), __FILE__, __LINE__)
-#else
-#define DEBUG_ARGS
-#define FWD_DEBUG_ARGS
-#define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s))
-#endif
-
-#define TABLE_IDX(hash, log2_shards, capacity) \
-  (((hash) >> (log2_shards)) % (capacity))
-#define SHARD_IDX(hash, log2_shards) ((hash) & ((1 << (log2_shards)) - 1))
-
-typedef void (*destroy_user_data_func)(void *user_data);
-
-/* Shadow structure for grpc_mdstr for non-static values */
-typedef struct internal_string {
-  /* must be byte compatible with grpc_mdstr */
-  gpr_slice slice;
-  uint32_t hash;
-
-  /* private only data */
-  gpr_atm refcnt;
-
-  uint8_t has_base64_and_huffman_encoded;
-  gpr_slice_refcount refcount;
-
-  gpr_slice base64_and_huffman;
-
-  struct internal_string *bucket_next;
-} internal_string;
-
-/* Shadow structure for grpc_mdelem for non-static elements */
-typedef struct internal_metadata {
-  /* must be byte compatible with grpc_mdelem */
-  internal_string *key;
-  internal_string *value;
-
-  /* private only data */
-  gpr_atm refcnt;
-
-  gpr_mu mu_user_data;
-  gpr_atm destroy_user_data;
-  gpr_atm user_data;
-
-  struct internal_metadata *bucket_next;
-} internal_metadata;
-
-typedef struct strtab_shard {
-  gpr_mu mu;
-  internal_string **strs;
-  size_t count;
-  size_t capacity;
-} strtab_shard;
-
-typedef struct mdtab_shard {
-  gpr_mu mu;
-  internal_metadata **elems;
-  size_t count;
-  size_t capacity;
-  size_t free;
-} mdtab_shard;
-
-#define LOG2_STRTAB_SHARD_COUNT 5
-#define LOG2_MDTAB_SHARD_COUNT 4
-#define STRTAB_SHARD_COUNT ((size_t)(1 << LOG2_STRTAB_SHARD_COUNT))
-#define MDTAB_SHARD_COUNT ((size_t)(1 << LOG2_MDTAB_SHARD_COUNT))
-
-/* hash seed: decided at initialization time */
-static uint32_t g_hash_seed;
-static int g_forced_hash_seed = 0;
-
-/* linearly probed hash tables for static element lookup */
-static grpc_mdstr *g_static_strtab[GRPC_STATIC_MDSTR_COUNT * 2];
-static grpc_mdelem *g_static_mdtab[GRPC_STATIC_MDELEM_COUNT * 2];
-static size_t g_static_strtab_maxprobe;
-static size_t g_static_mdtab_maxprobe;
-
-static strtab_shard g_strtab_shard[STRTAB_SHARD_COUNT];
-static mdtab_shard g_mdtab_shard[MDTAB_SHARD_COUNT];
-
-static void gc_mdtab(mdtab_shard *shard);
-
-void grpc_test_only_set_metadata_hash_seed(uint32_t seed) {
-  g_hash_seed = seed;
-  g_forced_hash_seed = 1;
-}
-
-void grpc_mdctx_global_init(void) {
-  size_t i, j;
-  if (!g_forced_hash_seed) {
-    g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
-  }
-  g_static_strtab_maxprobe = 0;
-  g_static_mdtab_maxprobe = 0;
-  /* build static tables */
-  memset(g_static_mdtab, 0, sizeof(g_static_mdtab));
-  memset(g_static_strtab, 0, sizeof(g_static_strtab));
-  for (i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
-    grpc_mdstr *elem = &grpc_static_mdstr_table[i];
-    const char *str = grpc_static_metadata_strings[i];
-    uint32_t hash = gpr_murmur_hash3(str, strlen(str), g_hash_seed);
-    *(gpr_slice *)&elem->slice = gpr_slice_from_static_string(str);
-    *(uint32_t *)&elem->hash = hash;
-    for (j = 0;; j++) {
-      size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_strtab);
-      if (g_static_strtab[idx] == NULL) {
-        g_static_strtab[idx] = &grpc_static_mdstr_table[i];
-        break;
-      }
-    }
-    if (j > g_static_strtab_maxprobe) {
-      g_static_strtab_maxprobe = j;
-    }
-  }
-  for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
-    grpc_mdelem *elem = &grpc_static_mdelem_table[i];
-    grpc_mdstr *key =
-        &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 0]];
-    grpc_mdstr *value =
-        &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 1]];
-    uint32_t hash = GRPC_MDSTR_KV_HASH(key->hash, value->hash);
-    *(grpc_mdstr **)&elem->key = key;
-    *(grpc_mdstr **)&elem->value = value;
-    for (j = 0;; j++) {
-      size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_mdtab);
-      if (g_static_mdtab[idx] == NULL) {
-        g_static_mdtab[idx] = elem;
-        break;
-      }
-    }
-    if (j > g_static_mdtab_maxprobe) {
-      g_static_mdtab_maxprobe = j;
-    }
-  }
-  /* initialize shards */
-  for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
-    strtab_shard *shard = &g_strtab_shard[i];
-    gpr_mu_init(&shard->mu);
-    shard->count = 0;
-    shard->capacity = INITIAL_STRTAB_CAPACITY;
-    shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity);
-    memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity);
-  }
-  for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
-    mdtab_shard *shard = &g_mdtab_shard[i];
-    gpr_mu_init(&shard->mu);
-    shard->count = 0;
-    shard->free = 0;
-    shard->capacity = INITIAL_MDTAB_CAPACITY;
-    shard->elems = gpr_malloc(sizeof(*shard->elems) * shard->capacity);
-    memset(shard->elems, 0, sizeof(*shard->elems) * shard->capacity);
-  }
-}
-
-void grpc_mdctx_global_shutdown(void) {
-  size_t i;
-  for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
-    mdtab_shard *shard = &g_mdtab_shard[i];
-    gpr_mu_destroy(&shard->mu);
-    gc_mdtab(shard);
-    /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
-    if (shard->count != 0) {
-      gpr_log(GPR_DEBUG, "WARNING: %d metadata elements were leaked",
-              shard->count);
-      if (grpc_iomgr_abort_on_leaks()) {
-        abort();
-      }
-    }
-    gpr_free(shard->elems);
-  }
-  for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
-    strtab_shard *shard = &g_strtab_shard[i];
-    gpr_mu_destroy(&shard->mu);
-    /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
-    if (shard->count != 0) {
-      gpr_log(GPR_DEBUG, "WARNING: %d metadata strings were leaked",
-              shard->count);
-      if (grpc_iomgr_abort_on_leaks()) {
-        abort();
-      }
-    }
-    gpr_free(shard->strs);
-  }
-}
-
-static int is_mdstr_static(grpc_mdstr *s) {
-  return s >= &grpc_static_mdstr_table[0] &&
-         s < &grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
-}
-
-static int is_mdelem_static(grpc_mdelem *e) {
-  return e >= &grpc_static_mdelem_table[0] &&
-         e < &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
-}
-
-static void ref_md_locked(mdtab_shard *shard,
-                          internal_metadata *md DEBUG_ARGS) {
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "ELM   REF:%p:%d->%d: '%s' = '%s'", md,
-          gpr_atm_no_barrier_load(&md->refcnt),
-          gpr_atm_no_barrier_load(&md->refcnt) + 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
-#endif
-  if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 2)) {
-    shard->free--;
-  } else {
-    GPR_ASSERT(1 != gpr_atm_no_barrier_fetch_add(&md->refcnt, -1));
-  }
-}
-
-static void grow_strtab(strtab_shard *shard) {
-  size_t capacity = shard->capacity * 2;
-  size_t i;
-  internal_string **strtab;
-  internal_string *s, *next;
-
-  GPR_TIMER_BEGIN("grow_strtab", 0);
-
-  strtab = gpr_malloc(sizeof(internal_string *) * capacity);
-  memset(strtab, 0, sizeof(internal_string *) * capacity);
-
-  for (i = 0; i < shard->capacity; i++) {
-    for (s = shard->strs[i]; s; s = next) {
-      size_t idx = TABLE_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT, capacity);
-      next = s->bucket_next;
-      s->bucket_next = strtab[idx];
-      strtab[idx] = s;
-    }
-  }
-
-  gpr_free(shard->strs);
-  shard->strs = strtab;
-  shard->capacity = capacity;
-
-  GPR_TIMER_END("grow_strtab", 0);
-}
-
-static void internal_destroy_string(strtab_shard *shard, internal_string *is) {
-  internal_string **prev_next;
-  internal_string *cur;
-  GPR_TIMER_BEGIN("internal_destroy_string", 0);
-  if (is->has_base64_and_huffman_encoded) {
-    gpr_slice_unref(is->base64_and_huffman);
-  }
-  for (prev_next = &shard->strs[TABLE_IDX(is->hash, LOG2_STRTAB_SHARD_COUNT,
-                                          shard->capacity)],
-      cur = *prev_next;
-       cur != is; prev_next = &cur->bucket_next, cur = cur->bucket_next)
-    ;
-  *prev_next = cur->bucket_next;
-  shard->count--;
-  gpr_free(is);
-  GPR_TIMER_END("internal_destroy_string", 0);
-}
-
-static void slice_ref(void *p) {
-  internal_string *is =
-      (internal_string *)((char *)p - offsetof(internal_string, refcount));
-  GRPC_MDSTR_REF((grpc_mdstr *)(is));
-}
-
-static void slice_unref(void *p) {
-  internal_string *is =
-      (internal_string *)((char *)p - offsetof(internal_string, refcount));
-  GRPC_MDSTR_UNREF((grpc_mdstr *)(is));
-}
-
-grpc_mdstr *grpc_mdstr_from_string(const char *str) {
-  return grpc_mdstr_from_buffer((const uint8_t *)str, strlen(str));
-}
-
-grpc_mdstr *grpc_mdstr_from_slice(gpr_slice slice) {
-  grpc_mdstr *result = grpc_mdstr_from_buffer(GPR_SLICE_START_PTR(slice),
-                                              GPR_SLICE_LENGTH(slice));
-  gpr_slice_unref(slice);
-  return result;
-}
-
-grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
-  uint32_t hash = gpr_murmur_hash3(buf, length, g_hash_seed);
-  internal_string *s;
-  strtab_shard *shard =
-      &g_strtab_shard[SHARD_IDX(hash, LOG2_STRTAB_SHARD_COUNT)];
-  size_t i;
-  size_t idx;
-
-  GPR_TIMER_BEGIN("grpc_mdstr_from_buffer", 0);
-
-  /* search for a static string */
-  for (i = 0; i <= g_static_strtab_maxprobe; i++) {
-    grpc_mdstr *ss;
-    idx = (hash + i) % GPR_ARRAY_SIZE(g_static_strtab);
-    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)) {
-      GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
-      return ss;
-    }
-  }
-
-  gpr_mu_lock(&shard->mu);
-
-  /* search for an existing string */
-  idx = TABLE_IDX(hash, LOG2_STRTAB_SHARD_COUNT, shard->capacity);
-  for (s = shard->strs[idx]; s; s = s->bucket_next) {
-    if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length &&
-        0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) {
-      GRPC_MDSTR_REF((grpc_mdstr *)s);
-      gpr_mu_unlock(&shard->mu);
-      GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
-      return (grpc_mdstr *)s;
-    }
-  }
-
-  /* not found: create a new string */
-  if (length + 1 < GPR_SLICE_INLINED_SIZE) {
-    /* string data goes directly into the slice */
-    s = gpr_malloc(sizeof(internal_string));
-    gpr_atm_rel_store(&s->refcnt, 2);
-    s->slice.refcount = NULL;
-    memcpy(s->slice.data.inlined.bytes, buf, length);
-    s->slice.data.inlined.bytes[length] = 0;
-    s->slice.data.inlined.length = (uint8_t)length;
-  } else {
-    /* string data goes after the internal_string header, and we +1 for null
-       terminator */
-    s = gpr_malloc(sizeof(internal_string) + length + 1);
-    gpr_atm_rel_store(&s->refcnt, 2);
-    s->refcount.ref = slice_ref;
-    s->refcount.unref = slice_unref;
-    s->slice.refcount = &s->refcount;
-    s->slice.data.refcounted.bytes = (uint8_t *)(s + 1);
-    s->slice.data.refcounted.length = length;
-    memcpy(s->slice.data.refcounted.bytes, buf, length);
-    /* add a null terminator for cheap c string conversion when desired */
-    s->slice.data.refcounted.bytes[length] = 0;
-  }
-  s->has_base64_and_huffman_encoded = 0;
-  s->hash = hash;
-  s->bucket_next = shard->strs[idx];
-  shard->strs[idx] = s;
-
-  shard->count++;
-
-  if (shard->count > shard->capacity * 2) {
-    grow_strtab(shard);
-  }
-
-  gpr_mu_unlock(&shard->mu);
-  GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
-
-  return (grpc_mdstr *)s;
-}
-
-static void gc_mdtab(mdtab_shard *shard) {
-  size_t i;
-  internal_metadata **prev_next;
-  internal_metadata *md, *next;
-
-  GPR_TIMER_BEGIN("gc_mdtab", 0);
-  for (i = 0; i < shard->capacity; i++) {
-    prev_next = &shard->elems[i];
-    for (md = shard->elems[i]; md; md = next) {
-      void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data);
-      next = md->bucket_next;
-      if (gpr_atm_acq_load(&md->refcnt) == 0) {
-        GRPC_MDSTR_UNREF((grpc_mdstr *)md->key);
-        GRPC_MDSTR_UNREF((grpc_mdstr *)md->value);
-        if (md->user_data) {
-          ((destroy_user_data_func)gpr_atm_no_barrier_load(
-              &md->destroy_user_data))(user_data);
-        }
-        gpr_free(md);
-        *prev_next = next;
-        shard->free--;
-        shard->count--;
-      } else {
-        prev_next = &md->bucket_next;
-      }
-    }
-  }
-  GPR_TIMER_END("gc_mdtab", 0);
-}
-
-static void grow_mdtab(mdtab_shard *shard) {
-  size_t capacity = shard->capacity * 2;
-  size_t i;
-  internal_metadata **mdtab;
-  internal_metadata *md, *next;
-  uint32_t hash;
-
-  GPR_TIMER_BEGIN("grow_mdtab", 0);
-
-  mdtab = gpr_malloc(sizeof(internal_metadata *) * capacity);
-  memset(mdtab, 0, sizeof(internal_metadata *) * capacity);
-
-  for (i = 0; i < shard->capacity; i++) {
-    for (md = shard->elems[i]; md; md = next) {
-      size_t idx;
-      hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
-      next = md->bucket_next;
-      idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, capacity);
-      md->bucket_next = mdtab[idx];
-      mdtab[idx] = md;
-    }
-  }
-
-  gpr_free(shard->elems);
-  shard->elems = mdtab;
-  shard->capacity = capacity;
-
-  GPR_TIMER_END("grow_mdtab", 0);
-}
-
-static void rehash_mdtab(mdtab_shard *shard) {
-  if (shard->free > shard->capacity / 4) {
-    gc_mdtab(shard);
-  } else {
-    grow_mdtab(shard);
-  }
-}
-
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *mkey,
-                                               grpc_mdstr *mvalue) {
-  internal_string *key = (internal_string *)mkey;
-  internal_string *value = (internal_string *)mvalue;
-  uint32_t hash = GRPC_MDSTR_KV_HASH(mkey->hash, mvalue->hash);
-  internal_metadata *md;
-  mdtab_shard *shard = &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
-  size_t i;
-  size_t idx;
-
-  GPR_TIMER_BEGIN("grpc_mdelem_from_metadata_strings", 0);
-
-  if (is_mdstr_static(mkey) && is_mdstr_static(mvalue)) {
-    for (i = 0; i <= g_static_mdtab_maxprobe; i++) {
-      grpc_mdelem *smd;
-      idx = (hash + i) % GPR_ARRAY_SIZE(g_static_mdtab);
-      smd = g_static_mdtab[idx];
-      if (smd == NULL) break;
-      if (smd->key == mkey && smd->value == mvalue) {
-        GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
-        return smd;
-      }
-    }
-  }
-
-  gpr_mu_lock(&shard->mu);
-
-  idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, shard->capacity);
-  /* search for an existing pair */
-  for (md = shard->elems[idx]; md; md = md->bucket_next) {
-    if (md->key == key && md->value == value) {
-      REF_MD_LOCKED(shard, md);
-      GRPC_MDSTR_UNREF((grpc_mdstr *)key);
-      GRPC_MDSTR_UNREF((grpc_mdstr *)value);
-      gpr_mu_unlock(&shard->mu);
-      GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
-      return (grpc_mdelem *)md;
-    }
-  }
-
-  /* not found: create a new pair */
-  md = gpr_malloc(sizeof(internal_metadata));
-  gpr_atm_rel_store(&md->refcnt, 2);
-  md->key = key;
-  md->value = value;
-  md->user_data = 0;
-  md->destroy_user_data = 0;
-  md->bucket_next = shard->elems[idx];
-  shard->elems[idx] = md;
-  gpr_mu_init(&md->mu_user_data);
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(GPR_DEBUG, "ELM   NEW:%p:%d: '%s' = '%s'", md,
-          gpr_atm_no_barrier_load(&md->refcnt),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
-#endif
-  shard->count++;
-
-  if (shard->count > shard->capacity * 2) {
-    rehash_mdtab(shard);
-  }
-
-  gpr_mu_unlock(&shard->mu);
-
-  GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
-
-  return (grpc_mdelem *)md;
-}
-
-grpc_mdelem *grpc_mdelem_from_strings(const char *key, const char *value) {
-  return grpc_mdelem_from_metadata_strings(grpc_mdstr_from_string(key),
-                                           grpc_mdstr_from_string(value));
-}
-
-grpc_mdelem *grpc_mdelem_from_slices(gpr_slice key, gpr_slice value) {
-  return grpc_mdelem_from_metadata_strings(grpc_mdstr_from_slice(key),
-                                           grpc_mdstr_from_slice(value));
-}
-
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key,
-                                                const uint8_t *value,
-                                                size_t value_length) {
-  return grpc_mdelem_from_metadata_strings(
-      grpc_mdstr_from_string(key), grpc_mdstr_from_buffer(value, value_length));
-}
-
-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
-  internal_metadata *md = (internal_metadata *)gmd;
-  if (is_mdelem_static(gmd)) return gmd;
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "ELM   REF:%p:%d->%d: '%s' = '%s'", md,
-          gpr_atm_no_barrier_load(&md->refcnt),
-          gpr_atm_no_barrier_load(&md->refcnt) + 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
-#endif
-  /* we can assume the ref count is >= 1 as the application is calling
-     this function - meaning that no adjustment to mdtab_free is necessary,
-     simplifying the logic here to be just an atomic increment */
-  /* use C assert to have this removed in opt builds */
-  assert(gpr_atm_no_barrier_load(&md->refcnt) >= 2);
-  gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
-  return gmd;
-}
-
-void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) {
-  internal_metadata *md = (internal_metadata *)gmd;
-  if (!md) return;
-  if (is_mdelem_static(gmd)) return;
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "ELM UNREF:%p:%d->%d: '%s' = '%s'", md,
-          gpr_atm_no_barrier_load(&md->refcnt),
-          gpr_atm_no_barrier_load(&md->refcnt) - 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
-#endif
-  if (2 == gpr_atm_full_fetch_add(&md->refcnt, -1)) {
-    uint32_t hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
-    mdtab_shard *shard =
-        &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
-    GPR_TIMER_BEGIN("grpc_mdelem_unref.to_zero", 0);
-    gpr_mu_lock(&shard->mu);
-    if (1 == gpr_atm_no_barrier_load(&md->refcnt)) {
-      shard->free++;
-      gpr_atm_no_barrier_store(&md->refcnt, 0);
-    }
-    gpr_mu_unlock(&shard->mu);
-    GPR_TIMER_END("grpc_mdelem_unref.to_zero", 0);
-  }
-}
-
-const char *grpc_mdstr_as_c_string(grpc_mdstr *s) {
-  return (const char *)GPR_SLICE_START_PTR(s->slice);
-}
-
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
-  internal_string *s = (internal_string *)gs;
-  if (is_mdstr_static(gs)) return gs;
-  GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) != 0);
-  return gs;
-}
-
-void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
-  internal_string *s = (internal_string *)gs;
-  if (is_mdstr_static(gs)) return;
-  if (2 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
-    strtab_shard *shard =
-        &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
-    gpr_mu_lock(&shard->mu);
-    if (1 == gpr_atm_no_barrier_load(&s->refcnt)) {
-      internal_destroy_string(shard, s);
-    }
-    gpr_mu_unlock(&shard->mu);
-  }
-}
-
-void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) {
-  internal_metadata *im = (internal_metadata *)md;
-  void *result;
-  if (is_mdelem_static(md)) {
-    return (void *)grpc_static_mdelem_user_data[md - grpc_static_mdelem_table];
-  }
-  if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
-    return (void *)gpr_atm_no_barrier_load(&im->user_data);
-  } else {
-    return NULL;
-  }
-  return result;
-}
-
-void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
-                               void *user_data) {
-  internal_metadata *im = (internal_metadata *)md;
-  GPR_ASSERT(!is_mdelem_static(md));
-  GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
-  gpr_mu_lock(&im->mu_user_data);
-  if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
-    /* user data can only be set once */
-    gpr_mu_unlock(&im->mu_user_data);
-    if (destroy_func != NULL) {
-      destroy_func(user_data);
-    }
-    return;
-  }
-  gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
-  gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
-  gpr_mu_unlock(&im->mu_user_data);
-}
-
-gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {
-  internal_string *s = (internal_string *)gs;
-  gpr_slice slice;
-  strtab_shard *shard =
-      &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
-  gpr_mu_lock(&shard->mu);
-  if (!s->has_base64_and_huffman_encoded) {
-    s->base64_and_huffman =
-        grpc_chttp2_base64_encode_and_huffman_compress(s->slice);
-    s->has_base64_and_huffman_encoded = 1;
-  }
-  slice = s->base64_and_huffman;
-  gpr_mu_unlock(&shard->mu);
-  return slice;
-}
diff --git a/src/core/transport/metadata.h b/src/core/transport/metadata.h
deleted file mode 100644
index 5ab3978..0000000
--- a/src/core/transport/metadata.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_METADATA_H
-#define GRPC_CORE_TRANSPORT_METADATA_H
-
-#include <grpc/support/slice.h>
-#include <grpc/support/useful.h>
-
-/* This file provides a mechanism for tracking metadata through the grpc stack.
-   It's not intended for consumption outside of the library.
-
-   Metadata is tracked in the context of a grpc_mdctx. For the time being there
-   is one of these per-channel, avoiding cross channel interference with memory
-   use and lock contention.
-
-   The context tracks unique strings (grpc_mdstr) and pairs of strings
-   (grpc_mdelem). Any of these objects can be checked for equality by comparing
-   their pointers. These objects are reference counted.
-
-   grpc_mdelem can additionally store a (non-NULL) user data pointer. This
-   pointer is intended to be used to cache semantic meaning of a metadata
-   element. For example, an OAuth token may cache the credentials it represents
-   and the time at which it expires in the mdelem user data.
-
-   Combining this metadata cache and the hpack compression table allows us to
-   simply lookup complete preparsed objects quickly, incurring a few atomic
-   ops per metadata element on the fast path.
-
-   grpc_mdelem instances MAY live longer than their refcount implies, and are
-   garbage collected periodically, meaning cached data can easily outlive a
-   single request.
-
-   STATIC METADATA: in static_metadata.h we declare a set of static metadata.
-   These mdelems and mdstrs are available via pre-declared code generated macros
-   and are available to code anywhere between grpc_init() and grpc_shutdown().
-   They are not refcounted, but can be passed to _ref and _unref functions
-   declared here - in which case those functions are effectively no-ops. */
-
-/* Forward declarations */
-typedef struct grpc_mdstr grpc_mdstr;
-typedef struct grpc_mdelem grpc_mdelem;
-
-/* if changing this, make identical changes in internal_string in metadata.c */
-struct grpc_mdstr {
-  const gpr_slice slice;
-  const uint32_t hash;
-  /* there is a private part to this in metadata.c */
-};
-
-/* if changing this, make identical changes in internal_metadata in
-   metadata.c */
-struct grpc_mdelem {
-  grpc_mdstr *const key;
-  grpc_mdstr *const value;
-  /* there is a private part to this in metadata.c */
-};
-
-void grpc_test_only_set_metadata_hash_seed(uint32_t seed);
-
-/* Constructors for grpc_mdstr instances; take a variety of data types that
-   clients may have handy */
-grpc_mdstr *grpc_mdstr_from_string(const char *str);
-/* Unrefs the slice. */
-grpc_mdstr *grpc_mdstr_from_slice(gpr_slice slice);
-grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *str, size_t length);
-
-/* Returns a borrowed slice from the mdstr with its contents base64 encoded
-   and huffman compressed */
-gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *str);
-
-/* Constructors for grpc_mdelem instances; take a variety of data types that
-   clients may have handy */
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *key,
-                                               grpc_mdstr *value);
-grpc_mdelem *grpc_mdelem_from_strings(const char *key, const char *value);
-/* Unrefs the slices. */
-grpc_mdelem *grpc_mdelem_from_slices(gpr_slice key, gpr_slice value);
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key,
-                                                const uint8_t *value,
-                                                size_t value_length);
-
-/* Mutator and accessor for grpc_mdelem user data. The destructor function
-   is used as a type tag and is checked during user_data fetch. */
-void *grpc_mdelem_get_user_data(grpc_mdelem *md,
-                                void (*if_destroy_func)(void *));
-void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
-                               void *user_data);
-
-/* Reference counting */
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__)
-#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s), __FILE__, __LINE__)
-#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
-#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s), __FILE__, __LINE__)
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s, const char *file, int line);
-void grpc_mdstr_unref(grpc_mdstr *s, const char *file, int line);
-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md, const char *file, int line);
-void grpc_mdelem_unref(grpc_mdelem *md, const char *file, int line);
-#else
-#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s))
-#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s))
-#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s))
-#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s))
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s);
-void grpc_mdstr_unref(grpc_mdstr *s);
-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
-void grpc_mdelem_unref(grpc_mdelem *md);
-#endif
-
-/* Recover a char* from a grpc_mdstr. The returned string is null terminated.
-   Does not promise that the returned string has no embedded nulls however. */
-const char *grpc_mdstr_as_c_string(grpc_mdstr *s);
-
-#define GRPC_MDSTR_LENGTH(s) (GPR_SLICE_LENGTH(s->slice))
-
-int grpc_mdstr_is_legal_header(grpc_mdstr *s);
-int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s);
-int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
-
-#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash))
-
-void grpc_mdctx_global_init(void);
-void grpc_mdctx_global_shutdown(void);
-
-#endif /* GRPC_CORE_TRANSPORT_METADATA_H */
diff --git a/src/core/transport/metadata_batch.c b/src/core/transport/metadata_batch.c
deleted file mode 100644
index 1266862..0000000
--- a/src/core/transport/metadata_batch.c
+++ /dev/null
@@ -1,194 +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/transport/metadata_batch.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/profiling/timers.h"
-
-static void assert_valid_list(grpc_mdelem_list *list) {
-#ifndef NDEBUG
-  grpc_linked_mdelem *l;
-
-  GPR_ASSERT((list->head == NULL) == (list->tail == NULL));
-  if (!list->head) return;
-  GPR_ASSERT(list->head->prev == NULL);
-  GPR_ASSERT(list->tail->next == NULL);
-  GPR_ASSERT((list->head == list->tail) == (list->head->next == NULL));
-
-  for (l = list->head; l; l = l->next) {
-    GPR_ASSERT(l->md);
-    GPR_ASSERT((l->prev == NULL) == (l == list->head));
-    GPR_ASSERT((l->next == NULL) == (l == list->tail));
-    if (l->next) GPR_ASSERT(l->next->prev == l);
-    if (l->prev) GPR_ASSERT(l->prev->next == l);
-  }
-#endif /* NDEBUG */
-}
-
-#ifndef NDEBUG
-void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) {
-  assert_valid_list(&batch->list);
-}
-#endif /* NDEBUG */
-
-void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
-  batch->list.head = batch->list.tail = NULL;
-  batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
-}
-
-void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) {
-  grpc_linked_mdelem *l;
-  for (l = batch->list.head; l; l = l->next) {
-    GRPC_MDELEM_UNREF(l->md);
-  }
-}
-
-void grpc_metadata_batch_add_head(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add) {
-  GPR_ASSERT(elem_to_add);
-  storage->md = elem_to_add;
-  grpc_metadata_batch_link_head(batch, storage);
-}
-
-static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
-  assert_valid_list(list);
-  GPR_ASSERT(storage->md);
-  storage->prev = NULL;
-  storage->next = list->head;
-  if (list->head != NULL) {
-    list->head->prev = storage;
-  } else {
-    list->tail = storage;
-  }
-  list->head = storage;
-  assert_valid_list(list);
-}
-
-void grpc_metadata_batch_link_head(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage) {
-  link_head(&batch->list, storage);
-}
-
-void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add) {
-  GPR_ASSERT(elem_to_add);
-  storage->md = elem_to_add;
-  grpc_metadata_batch_link_tail(batch, storage);
-}
-
-static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
-  assert_valid_list(list);
-  GPR_ASSERT(storage->md);
-  storage->prev = list->tail;
-  storage->next = NULL;
-  storage->reserved = NULL;
-  if (list->tail != NULL) {
-    list->tail->next = storage;
-  } else {
-    list->head = storage;
-  }
-  list->tail = storage;
-  assert_valid_list(list);
-}
-
-void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage) {
-  link_tail(&batch->list, storage);
-}
-
-void grpc_metadata_batch_move(grpc_metadata_batch *dst,
-                              grpc_metadata_batch *src) {
-  *dst = *src;
-  memset(src, 0, sizeof(grpc_metadata_batch));
-}
-
-void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
-                                grpc_mdelem *(*filter)(void *user_data,
-                                                       grpc_mdelem *elem),
-                                void *user_data) {
-  grpc_linked_mdelem *l;
-  grpc_linked_mdelem *next;
-
-  GPR_TIMER_BEGIN("grpc_metadata_batch_filter", 0);
-
-  assert_valid_list(&batch->list);
-  for (l = batch->list.head; l; l = next) {
-    grpc_mdelem *orig = l->md;
-    grpc_mdelem *filt = filter(user_data, orig);
-    next = l->next;
-    if (filt == NULL) {
-      if (l->prev) {
-        l->prev->next = l->next;
-      }
-      if (l->next) {
-        l->next->prev = l->prev;
-      }
-      if (batch->list.head == l) {
-        batch->list.head = l->next;
-      }
-      if (batch->list.tail == l) {
-        batch->list.tail = l->prev;
-      }
-      assert_valid_list(&batch->list);
-      GRPC_MDELEM_UNREF(l->md);
-    } else if (filt != orig) {
-      GRPC_MDELEM_UNREF(orig);
-      l->md = filt;
-    }
-  }
-  assert_valid_list(&batch->list);
-
-  GPR_TIMER_END("grpc_metadata_batch_filter", 0);
-}
-
-static grpc_mdelem *no_metadata_for_you(void *user_data, grpc_mdelem *elem) {
-  return NULL;
-}
-
-void grpc_metadata_batch_clear(grpc_metadata_batch *batch) {
-  batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
-  grpc_metadata_batch_filter(batch, no_metadata_for_you, NULL);
-}
-
-int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
-  return batch->list.head == NULL &&
-         gpr_time_cmp(gpr_inf_future(batch->deadline.clock_type),
-                      batch->deadline) == 0;
-}
diff --git a/src/core/transport/metadata_batch.h b/src/core/transport/metadata_batch.h
deleted file mode 100644
index 9337b28..0000000
--- a/src/core/transport/metadata_batch.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_METADATA_BATCH_H
-#define GRPC_CORE_TRANSPORT_METADATA_BATCH_H
-
-#include <grpc/grpc.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/time.h>
-#include "src/core/transport/metadata.h"
-
-typedef struct grpc_linked_mdelem {
-  grpc_mdelem *md;
-  struct grpc_linked_mdelem *next;
-  struct grpc_linked_mdelem *prev;
-  void *reserved;
-} grpc_linked_mdelem;
-
-typedef struct grpc_mdelem_list {
-  grpc_linked_mdelem *head;
-  grpc_linked_mdelem *tail;
-} grpc_mdelem_list;
-
-typedef struct grpc_metadata_batch {
-  /** Metadata elements in this batch */
-  grpc_mdelem_list list;
-  /** Used to calculate grpc-timeout at the point of sending,
-      or gpr_inf_future if this batch does not need to send a
-      grpc-timeout */
-  gpr_timespec deadline;
-} grpc_metadata_batch;
-
-void grpc_metadata_batch_init(grpc_metadata_batch *batch);
-void grpc_metadata_batch_destroy(grpc_metadata_batch *batch);
-void grpc_metadata_batch_clear(grpc_metadata_batch *batch);
-int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch);
-
-/** Moves the metadata information from \a src to \a dst. Upon return, \a src is
- * zeroed. */
-void grpc_metadata_batch_move(grpc_metadata_batch *dst,
-                              grpc_metadata_batch *src);
-
-/** Add \a storage to the beginning of \a batch. storage->md is
-    assumed to be valid.
-    \a storage is owned by the caller and must survive for the
-    lifetime of batch. This usually means it should be around
-    for the lifetime of the call. */
-void grpc_metadata_batch_link_head(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage);
-/** Add \a storage to the end of \a batch. storage->md is
-    assumed to be valid.
-    \a storage is owned by the caller and must survive for the
-    lifetime of batch. This usually means it should be around
-    for the lifetime of the call. */
-void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage);
-
-/** Add \a elem_to_add as the first element in \a batch, using
-    \a storage as backing storage for the linked list element.
-    \a storage is owned by the caller and must survive for the
-    lifetime of batch. This usually means it should be around
-    for the lifetime of the call.
-    Takes ownership of \a elem_to_add */
-void grpc_metadata_batch_add_head(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add);
-/** Add \a elem_to_add as the last element in \a batch, using
-    \a storage as backing storage for the linked list element.
-    \a storage is owned by the caller and must survive for the
-    lifetime of batch. This usually means it should be around
-    for the lifetime of the call.
-    Takes ownership of \a elem_to_add */
-void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add);
-
-/** For each element in \a batch, execute \a filter.
-    The return value from \a filter will be substituted for the
-    grpc_mdelem passed to \a filter. If \a filter returns NULL,
-    the element will be moved to the garbage list. */
-void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
-                                grpc_mdelem *(*filter)(void *user_data,
-                                                       grpc_mdelem *elem),
-                                void *user_data);
-
-#ifndef NDEBUG
-void grpc_metadata_batch_assert_ok(grpc_metadata_batch *comd);
-#else
-#define grpc_metadata_batch_assert_ok(comd) \
-  do {                                      \
-  } while (0)
-#endif
-
-#endif /* GRPC_CORE_TRANSPORT_METADATA_BATCH_H */
diff --git a/src/core/transport/static_metadata.c b/src/core/transport/static_metadata.c
deleted file mode 100644
index 84abb59..0000000
--- a/src/core/transport/static_metadata.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/*
- * WARNING: Auto-generated code.
- *
- * To make changes to this file, change
- * tools/codegen/core/gen_static_metadata.py,
- * and then re-run it.
- *
- * See metadata.h for an explanation of the interface here, and metadata.c for
- * an
- * explanation of what's going on.
- */
-
-#include "src/core/transport/static_metadata.h"
-
-grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
-
-grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
-uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] =
-    {11, 35, 10, 35, 12, 35, 12, 49, 13, 35, 14, 35, 15, 35, 16, 35, 17, 35,
-     19, 35, 20, 35, 21, 35, 24, 35, 25, 35, 26, 35, 27, 35, 28, 35, 29, 35,
-     30, 18, 30, 35, 31, 35, 32, 35, 36, 35, 37, 35, 38, 35, 39, 35, 42, 33,
-     42, 34, 42, 48, 42, 53, 42, 54, 42, 55, 42, 56, 43, 33, 43, 48, 43, 53,
-     46, 0,  46, 1,  46, 2,  50, 35, 57, 35, 58, 35, 59, 35, 60, 35, 61, 35,
-     62, 35, 63, 35, 64, 35, 65, 35, 66, 40, 66, 68, 67, 78, 67, 79, 69, 35,
-     70, 35, 71, 35, 72, 35, 73, 35, 74, 35, 75, 41, 75, 51, 75, 52, 76, 35,
-     77, 35, 80, 3,  80, 4,  80, 5,  80, 6,  80, 7,  80, 8,  80, 9,  81, 35,
-     82, 83, 84, 35, 85, 35, 86, 35, 87, 35, 88, 35};
-
-const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
-    "0", "1", "2", "200", "204", "206", "304", "400", "404", "500", "accept",
-    "accept-charset", "accept-encoding", "accept-language", "accept-ranges",
-    "access-control-allow-origin", "age", "allow", "application/grpc",
-    ":authority", "authorization", "cache-control", "census-bin",
-    "census-binary-bin", "content-disposition", "content-encoding",
-    "content-language", "content-length", "content-location", "content-range",
-    "content-type", "cookie", "date", "deflate", "deflate,gzip", "", "etag",
-    "expect", "expires", "from", "GET", "grpc", "grpc-accept-encoding",
-    "grpc-encoding", "grpc-internal-encoding-request", "grpc-message",
-    "grpc-status", "grpc-timeout", "gzip", "gzip, deflate", "host", "http",
-    "https", "identity", "identity,deflate", "identity,deflate,gzip",
-    "identity,gzip", "if-match", "if-modified-since", "if-none-match",
-    "if-range", "if-unmodified-since", "last-modified", "link", "location",
-    "max-forwards", ":method", ":path", "POST", "proxy-authenticate",
-    "proxy-authorization", "range", "referer", "refresh", "retry-after",
-    ":scheme", "server", "set-cookie", "/", "/index.html", ":status",
-    "strict-transport-security", "te", "trailers", "transfer-encoding",
-    "user-agent", "vary", "via", "www-authenticate"};
-
-const uint8_t grpc_static_accept_encoding_metadata[8] = {0,  29, 26, 30,
-                                                         28, 32, 27, 31};
diff --git a/src/core/transport/static_metadata.h b/src/core/transport/static_metadata.h
deleted file mode 100644
index 85442f8..0000000
--- a/src/core/transport/static_metadata.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/*
- * WARNING: Auto-generated code.
- *
- * To make changes to this file, change
- * tools/codegen/core/gen_static_metadata.py,
- * and then re-run it.
- *
- * See metadata.h for an explanation of the interface here, and metadata.c for
- * an
- * explanation of what's going on.
- */
-
-#ifndef GRPC_CORE_TRANSPORT_STATIC_METADATA_H
-#define GRPC_CORE_TRANSPORT_STATIC_METADATA_H
-
-#include "src/core/transport/metadata.h"
-
-#define GRPC_STATIC_MDSTR_COUNT 89
-extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
-/* "0" */
-#define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0])
-/* "1" */
-#define GRPC_MDSTR_1 (&grpc_static_mdstr_table[1])
-/* "2" */
-#define GRPC_MDSTR_2 (&grpc_static_mdstr_table[2])
-/* "200" */
-#define GRPC_MDSTR_200 (&grpc_static_mdstr_table[3])
-/* "204" */
-#define GRPC_MDSTR_204 (&grpc_static_mdstr_table[4])
-/* "206" */
-#define GRPC_MDSTR_206 (&grpc_static_mdstr_table[5])
-/* "304" */
-#define GRPC_MDSTR_304 (&grpc_static_mdstr_table[6])
-/* "400" */
-#define GRPC_MDSTR_400 (&grpc_static_mdstr_table[7])
-/* "404" */
-#define GRPC_MDSTR_404 (&grpc_static_mdstr_table[8])
-/* "500" */
-#define GRPC_MDSTR_500 (&grpc_static_mdstr_table[9])
-/* "accept" */
-#define GRPC_MDSTR_ACCEPT (&grpc_static_mdstr_table[10])
-/* "accept-charset" */
-#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_mdstr_table[11])
-/* "accept-encoding" */
-#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_mdstr_table[12])
-/* "accept-language" */
-#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_mdstr_table[13])
-/* "accept-ranges" */
-#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_mdstr_table[14])
-/* "access-control-allow-origin" */
-#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_mdstr_table[15])
-/* "age" */
-#define GRPC_MDSTR_AGE (&grpc_static_mdstr_table[16])
-/* "allow" */
-#define GRPC_MDSTR_ALLOW (&grpc_static_mdstr_table[17])
-/* "application/grpc" */
-#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (&grpc_static_mdstr_table[18])
-/* ":authority" */
-#define GRPC_MDSTR_AUTHORITY (&grpc_static_mdstr_table[19])
-/* "authorization" */
-#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20])
-/* "cache-control" */
-#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21])
-/* "census-bin" */
-#define GRPC_MDSTR_CENSUS_BIN (&grpc_static_mdstr_table[22])
-/* "census-binary-bin" */
-#define GRPC_MDSTR_CENSUS_BINARY_BIN (&grpc_static_mdstr_table[23])
-/* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[24])
-/* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[25])
-/* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[26])
-/* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[27])
-/* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[28])
-/* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[29])
-/* "content-type" */
-#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[30])
-/* "cookie" */
-#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[31])
-/* "date" */
-#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[32])
-/* "deflate" */
-#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[33])
-/* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[34])
-/* "" */
-#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[35])
-/* "etag" */
-#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[36])
-/* "expect" */
-#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[37])
-/* "expires" */
-#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[38])
-/* "from" */
-#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[39])
-/* "GET" */
-#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[40])
-/* "grpc" */
-#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[41])
-/* "grpc-accept-encoding" */
-#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[42])
-/* "grpc-encoding" */
-#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[43])
-/* "grpc-internal-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[44])
-/* "grpc-message" */
-#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[45])
-/* "grpc-status" */
-#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46])
-/* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47])
-/* "gzip" */
-#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[48])
-/* "gzip, deflate" */
-#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_mdstr_table[49])
-/* "host" */
-#define GRPC_MDSTR_HOST (&grpc_static_mdstr_table[50])
-/* "http" */
-#define GRPC_MDSTR_HTTP (&grpc_static_mdstr_table[51])
-/* "https" */
-#define GRPC_MDSTR_HTTPS (&grpc_static_mdstr_table[52])
-/* "identity" */
-#define GRPC_MDSTR_IDENTITY (&grpc_static_mdstr_table[53])
-/* "identity,deflate" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (&grpc_static_mdstr_table[54])
-/* "identity,deflate,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
-  (&grpc_static_mdstr_table[55])
-/* "identity,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (&grpc_static_mdstr_table[56])
-/* "if-match" */
-#define GRPC_MDSTR_IF_MATCH (&grpc_static_mdstr_table[57])
-/* "if-modified-since" */
-#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_mdstr_table[58])
-/* "if-none-match" */
-#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_mdstr_table[59])
-/* "if-range" */
-#define GRPC_MDSTR_IF_RANGE (&grpc_static_mdstr_table[60])
-/* "if-unmodified-since" */
-#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[61])
-/* "last-modified" */
-#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[62])
-/* "link" */
-#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[63])
-/* "location" */
-#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[64])
-/* "max-forwards" */
-#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[65])
-/* ":method" */
-#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[66])
-/* ":path" */
-#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[67])
-/* "POST" */
-#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[68])
-/* "proxy-authenticate" */
-#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[69])
-/* "proxy-authorization" */
-#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[70])
-/* "range" */
-#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[71])
-/* "referer" */
-#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[72])
-/* "refresh" */
-#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[73])
-/* "retry-after" */
-#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[74])
-/* ":scheme" */
-#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[75])
-/* "server" */
-#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[76])
-/* "set-cookie" */
-#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[77])
-/* "/" */
-#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[78])
-/* "/index.html" */
-#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[79])
-/* ":status" */
-#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[80])
-/* "strict-transport-security" */
-#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[81])
-/* "te" */
-#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[82])
-/* "trailers" */
-#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[83])
-/* "transfer-encoding" */
-#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[84])
-/* "user-agent" */
-#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[85])
-/* "vary" */
-#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[86])
-/* "via" */
-#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[87])
-/* "www-authenticate" */
-#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[88])
-
-#define GRPC_STATIC_MDELEM_COUNT 78
-extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
-extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
-/* "accept-charset": "" */
-#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY (&grpc_static_mdelem_table[0])
-/* "accept": "" */
-#define GRPC_MDELEM_ACCEPT_EMPTY (&grpc_static_mdelem_table[1])
-/* "accept-encoding": "" */
-#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY (&grpc_static_mdelem_table[2])
-/* "accept-encoding": "gzip, deflate" */
-#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \
-  (&grpc_static_mdelem_table[3])
-/* "accept-language": "" */
-#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[4])
-/* "accept-ranges": "" */
-#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY (&grpc_static_mdelem_table[5])
-/* "access-control-allow-origin": "" */
-#define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \
-  (&grpc_static_mdelem_table[6])
-/* "age": "" */
-#define GRPC_MDELEM_AGE_EMPTY (&grpc_static_mdelem_table[7])
-/* "allow": "" */
-#define GRPC_MDELEM_ALLOW_EMPTY (&grpc_static_mdelem_table[8])
-/* ":authority": "" */
-#define GRPC_MDELEM_AUTHORITY_EMPTY (&grpc_static_mdelem_table[9])
-/* "authorization": "" */
-#define GRPC_MDELEM_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[10])
-/* "cache-control": "" */
-#define GRPC_MDELEM_CACHE_CONTROL_EMPTY (&grpc_static_mdelem_table[11])
-/* "content-disposition": "" */
-#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY (&grpc_static_mdelem_table[12])
-/* "content-encoding": "" */
-#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY (&grpc_static_mdelem_table[13])
-/* "content-language": "" */
-#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[14])
-/* "content-length": "" */
-#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY (&grpc_static_mdelem_table[15])
-/* "content-location": "" */
-#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY (&grpc_static_mdelem_table[16])
-/* "content-range": "" */
-#define GRPC_MDELEM_CONTENT_RANGE_EMPTY (&grpc_static_mdelem_table[17])
-/* "content-type": "application/grpc" */
-#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \
-  (&grpc_static_mdelem_table[18])
-/* "content-type": "" */
-#define GRPC_MDELEM_CONTENT_TYPE_EMPTY (&grpc_static_mdelem_table[19])
-/* "cookie": "" */
-#define GRPC_MDELEM_COOKIE_EMPTY (&grpc_static_mdelem_table[20])
-/* "date": "" */
-#define GRPC_MDELEM_DATE_EMPTY (&grpc_static_mdelem_table[21])
-/* "etag": "" */
-#define GRPC_MDELEM_ETAG_EMPTY (&grpc_static_mdelem_table[22])
-/* "expect": "" */
-#define GRPC_MDELEM_EXPECT_EMPTY (&grpc_static_mdelem_table[23])
-/* "expires": "" */
-#define GRPC_MDELEM_EXPIRES_EMPTY (&grpc_static_mdelem_table[24])
-/* "from": "" */
-#define GRPC_MDELEM_FROM_EMPTY (&grpc_static_mdelem_table[25])
-/* "grpc-accept-encoding": "deflate" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE (&grpc_static_mdelem_table[26])
-/* "grpc-accept-encoding": "deflate,gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
-  (&grpc_static_mdelem_table[27])
-/* "grpc-accept-encoding": "gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP (&grpc_static_mdelem_table[28])
-/* "grpc-accept-encoding": "identity" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
-  (&grpc_static_mdelem_table[29])
-/* "grpc-accept-encoding": "identity,deflate" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
-  (&grpc_static_mdelem_table[30])
-/* "grpc-accept-encoding": "identity,deflate,gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
-  (&grpc_static_mdelem_table[31])
-/* "grpc-accept-encoding": "identity,gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
-  (&grpc_static_mdelem_table[32])
-/* "grpc-encoding": "deflate" */
-#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE (&grpc_static_mdelem_table[33])
-/* "grpc-encoding": "gzip" */
-#define GRPC_MDELEM_GRPC_ENCODING_GZIP (&grpc_static_mdelem_table[34])
-/* "grpc-encoding": "identity" */
-#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY (&grpc_static_mdelem_table[35])
-/* "grpc-status": "0" */
-#define GRPC_MDELEM_GRPC_STATUS_0 (&grpc_static_mdelem_table[36])
-/* "grpc-status": "1" */
-#define GRPC_MDELEM_GRPC_STATUS_1 (&grpc_static_mdelem_table[37])
-/* "grpc-status": "2" */
-#define GRPC_MDELEM_GRPC_STATUS_2 (&grpc_static_mdelem_table[38])
-/* "host": "" */
-#define GRPC_MDELEM_HOST_EMPTY (&grpc_static_mdelem_table[39])
-/* "if-match": "" */
-#define GRPC_MDELEM_IF_MATCH_EMPTY (&grpc_static_mdelem_table[40])
-/* "if-modified-since": "" */
-#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[41])
-/* "if-none-match": "" */
-#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY (&grpc_static_mdelem_table[42])
-/* "if-range": "" */
-#define GRPC_MDELEM_IF_RANGE_EMPTY (&grpc_static_mdelem_table[43])
-/* "if-unmodified-since": "" */
-#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[44])
-/* "last-modified": "" */
-#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45])
-/* "link": "" */
-#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[46])
-/* "location": "" */
-#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[47])
-/* "max-forwards": "" */
-#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[48])
-/* ":method": "GET" */
-#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[49])
-/* ":method": "POST" */
-#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[50])
-/* ":path": "/" */
-#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[51])
-/* ":path": "/index.html" */
-#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[52])
-/* "proxy-authenticate": "" */
-#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[53])
-/* "proxy-authorization": "" */
-#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[54])
-/* "range": "" */
-#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[55])
-/* "referer": "" */
-#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[56])
-/* "refresh": "" */
-#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[57])
-/* "retry-after": "" */
-#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[58])
-/* ":scheme": "grpc" */
-#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[59])
-/* ":scheme": "http" */
-#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[60])
-/* ":scheme": "https" */
-#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[61])
-/* "server": "" */
-#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[62])
-/* "set-cookie": "" */
-#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[63])
-/* ":status": "200" */
-#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[64])
-/* ":status": "204" */
-#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[65])
-/* ":status": "206" */
-#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[66])
-/* ":status": "304" */
-#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[67])
-/* ":status": "400" */
-#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[68])
-/* ":status": "404" */
-#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[69])
-/* ":status": "500" */
-#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[70])
-/* "strict-transport-security": "" */
-#define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
-  (&grpc_static_mdelem_table[71])
-/* "te": "trailers" */
-#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[72])
-/* "transfer-encoding": "" */
-#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[73])
-/* "user-agent": "" */
-#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[74])
-/* "vary": "" */
-#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[75])
-/* "via": "" */
-#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[76])
-/* "www-authenticate": "" */
-#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[77])
-
-extern const uint8_t
-    grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2];
-extern const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT];
-extern const uint8_t grpc_static_accept_encoding_metadata[8];
-#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
-  (&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]])
-#endif /* GRPC_CORE_TRANSPORT_STATIC_METADATA_H */
diff --git a/src/core/transport/transport.c b/src/core/transport/transport.c
deleted file mode 100644
index 3b555fa..0000000
--- a/src/core/transport/transport.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- *
- * 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/transport/transport.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/log.h>
-#include "src/core/transport/transport_impl.h"
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) {
-  gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count);
-  gpr_log(GPR_DEBUG, "%s %p:%p   REF %d->%d %s", refcount->object_type,
-          refcount, refcount->destroy.cb_arg, val, val + 1, reason);
-#else
-void grpc_stream_ref(grpc_stream_refcount *refcount) {
-#endif
-  gpr_ref_non_zero(&refcount->refs);
-}
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount,
-                       const char *reason) {
-  gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count);
-  gpr_log(GPR_DEBUG, "%s %p:%p UNREF %d->%d %s", refcount->object_type,
-          refcount, refcount->destroy.cb_arg, val, val - 1, reason);
-#else
-void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
-                       grpc_stream_refcount *refcount) {
-#endif
-  if (gpr_unref(&refcount->refs)) {
-    grpc_exec_ctx_enqueue(exec_ctx, &refcount->destroy, true, NULL);
-  }
-}
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
-                          grpc_iomgr_cb_func cb, void *cb_arg,
-                          const char *object_type) {
-  refcount->object_type = object_type;
-#else
-void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
-                          grpc_iomgr_cb_func cb, void *cb_arg) {
-#endif
-  gpr_ref_init(&refcount->refs, initial_refs);
-  grpc_closure_init(&refcount->destroy, cb, cb_arg);
-}
-
-size_t grpc_transport_stream_size(grpc_transport *transport) {
-  return transport->vtable->sizeof_stream;
-}
-
-void grpc_transport_destroy(grpc_exec_ctx *exec_ctx,
-                            grpc_transport *transport) {
-  transport->vtable->destroy(exec_ctx, transport);
-}
-
-int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx,
-                               grpc_transport *transport, grpc_stream *stream,
-                               grpc_stream_refcount *refcount,
-                               const void *server_data) {
-  return transport->vtable->init_stream(exec_ctx, transport, stream, refcount,
-                                        server_data);
-}
-
-void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx,
-                                      grpc_transport *transport,
-                                      grpc_stream *stream,
-                                      grpc_transport_stream_op *op) {
-  transport->vtable->perform_stream_op(exec_ctx, transport, stream, op);
-}
-
-void grpc_transport_perform_op(grpc_exec_ctx *exec_ctx,
-                               grpc_transport *transport,
-                               grpc_transport_op *op) {
-  transport->vtable->perform_op(exec_ctx, transport, op);
-}
-
-void grpc_transport_set_pollset(grpc_exec_ctx *exec_ctx,
-                                grpc_transport *transport, grpc_stream *stream,
-                                grpc_pollset *pollset) {
-  transport->vtable->set_pollset(exec_ctx, transport, stream, pollset);
-}
-
-void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
-                                   grpc_transport *transport,
-                                   grpc_stream *stream) {
-  transport->vtable->destroy_stream(exec_ctx, transport, stream);
-}
-
-char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
-                              grpc_transport *transport) {
-  return transport->vtable->get_peer(exec_ctx, transport);
-}
-
-void grpc_transport_stream_op_finish_with_failure(
-    grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op) {
-  grpc_exec_ctx_enqueue(exec_ctx, op->recv_message_ready, false, NULL);
-  grpc_exec_ctx_enqueue(exec_ctx, op->recv_initial_metadata_ready, false, NULL);
-  grpc_exec_ctx_enqueue(exec_ctx, op->on_complete, false, NULL);
-}
-
-void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
-                                               grpc_status_code status) {
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-  if (op->cancel_with_status == GRPC_STATUS_OK) {
-    op->cancel_with_status = status;
-  }
-  if (op->close_with_status != GRPC_STATUS_OK) {
-    op->close_with_status = GRPC_STATUS_OK;
-    if (op->optional_close_message != NULL) {
-      gpr_slice_unref(*op->optional_close_message);
-      op->optional_close_message = NULL;
-    }
-  }
-}
-
-typedef struct {
-  gpr_slice message;
-  grpc_closure *then_call;
-  grpc_closure closure;
-} close_message_data;
-
-static void free_message(grpc_exec_ctx *exec_ctx, void *p, bool iomgr_success) {
-  close_message_data *cmd = p;
-  gpr_slice_unref(cmd->message);
-  if (cmd->then_call != NULL) {
-    cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, iomgr_success);
-  }
-  gpr_free(cmd);
-}
-
-void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
-                                        grpc_status_code status,
-                                        gpr_slice *optional_message) {
-  close_message_data *cmd;
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-  if (op->cancel_with_status != GRPC_STATUS_OK ||
-      op->close_with_status != GRPC_STATUS_OK) {
-    if (optional_message) {
-      gpr_slice_unref(*optional_message);
-    }
-    return;
-  }
-  if (optional_message) {
-    cmd = gpr_malloc(sizeof(*cmd));
-    cmd->message = *optional_message;
-    cmd->then_call = op->on_complete;
-    grpc_closure_init(&cmd->closure, free_message, cmd);
-    op->on_complete = &cmd->closure;
-    op->optional_close_message = &cmd->message;
-  }
-  op->close_with_status = status;
-}
diff --git a/src/core/transport/transport.h b/src/core/transport/transport.h
deleted file mode 100644
index 0f068dc..0000000
--- a/src/core/transport/transport.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_TRANSPORT_H
-#define GRPC_CORE_TRANSPORT_TRANSPORT_H
-
-#include <stddef.h>
-
-#include "src/core/iomgr/pollset.h"
-#include "src/core/iomgr/pollset_set.h"
-#include "src/core/transport/metadata_batch.h"
-#include "src/core/transport/byte_stream.h"
-#include "src/core/channel/context.h"
-
-/* forward declarations */
-typedef struct grpc_transport grpc_transport;
-
-/* grpc_stream doesn't actually exist. It's used as a typesafe
-   opaque pointer for whatever data the transport wants to track
-   for a stream. */
-typedef struct grpc_stream grpc_stream;
-
-/*#define GRPC_STREAM_REFCOUNT_DEBUG*/
-
-typedef struct grpc_stream_refcount {
-  gpr_refcount refs;
-  grpc_closure destroy;
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-  const char *object_type;
-#endif
-} grpc_stream_refcount;
-
-#ifdef GRPC_STREAM_REFCOUNT_DEBUG
-void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
-                          grpc_iomgr_cb_func cb, void *cb_arg,
-                          const char *object_type);
-void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason);
-void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount,
-                       const char *reason);
-#define GRPC_STREAM_REF_INIT(rc, ir, cb, cb_arg, objtype) \
-  grpc_stream_ref_init(rc, ir, cb, cb_arg, objtype)
-#else
-void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
-                          grpc_iomgr_cb_func cb, void *cb_arg);
-void grpc_stream_ref(grpc_stream_refcount *refcount);
-void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount);
-#define GRPC_STREAM_REF_INIT(rc, ir, cb, cb_arg, objtype) \
-  grpc_stream_ref_init(rc, ir, cb, cb_arg)
-#endif
-
-/* Transport stream op: a set of operations to perform on a transport
-   against a single stream */
-typedef struct grpc_transport_stream_op {
-  /** Send initial metadata to the peer, from the provided metadata batch. */
-  grpc_metadata_batch *send_initial_metadata;
-
-  /** Send trailing metadata to the peer, from the provided metadata batch. */
-  grpc_metadata_batch *send_trailing_metadata;
-
-  /** Send message data to the peer, from the provided byte stream. */
-  grpc_byte_stream *send_message;
-
-  /** Receive initial metadata from the stream, into provided metadata batch. */
-  grpc_metadata_batch *recv_initial_metadata;
-  /** Should be enqueued when initial metadata is ready to be processed. */
-  grpc_closure *recv_initial_metadata_ready;
-
-  /** Receive message data from the stream, into provided byte stream. */
-  grpc_byte_stream **recv_message;
-  /** Should be enqueued when one message is ready to be processed. */
-  grpc_closure *recv_message_ready;
-
-  /** Receive trailing metadata from the stream, into provided metadata batch.
-   */
-  grpc_metadata_batch *recv_trailing_metadata;
-
-  /** Should be enqueued when all requested operations (excluding recv_message
-      and recv_initial_metadata which have their own closures) in a given batch
-      have been completed. */
-  grpc_closure *on_complete;
-
-  /** If != GRPC_STATUS_OK, cancel this stream */
-  grpc_status_code cancel_with_status;
-
-  /** If != GRPC_STATUS_OK, send grpc-status, grpc-message, and close this
-      stream for both reading and writing */
-  grpc_status_code close_with_status;
-  gpr_slice *optional_close_message;
-
-  /* Indexes correspond to grpc_context_index enum values */
-  grpc_call_context_element *context;
-} grpc_transport_stream_op;
-
-/** Transport op: a set of operations to perform on a transport as a whole */
-typedef struct grpc_transport_op {
-  /** Called when processing of this op is done. */
-  grpc_closure *on_consumed;
-  /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
-  grpc_closure *on_connectivity_state_change;
-  grpc_connectivity_state *connectivity_state;
-  /** should the transport be disconnected */
-  int disconnect;
-  /** should we send a goaway?
-      after a goaway is sent, once there are no more active calls on
-      the transport, the transport should disconnect */
-  int send_goaway;
-  /** what should the goaway contain? */
-  grpc_status_code goaway_status;
-  gpr_slice *goaway_message;
-  /** set the callback for accepting new streams;
-      this is a permanent callback, unlike the other one-shot closures.
-      If true, the callback is set to set_accept_stream_fn, with its
-      user_data argument set to set_accept_stream_user_data */
-  bool set_accept_stream;
-  void (*set_accept_stream_fn)(grpc_exec_ctx *exec_ctx, void *user_data,
-                               grpc_transport *transport,
-                               const void *server_data);
-  void *set_accept_stream_user_data;
-  /** add this transport to a pollset */
-  grpc_pollset *bind_pollset;
-  /** add this transport to a pollset_set */
-  grpc_pollset_set *bind_pollset_set;
-  /** send a ping, call this back if not NULL */
-  grpc_closure *send_ping;
-} grpc_transport_op;
-
-/* Returns the amount of memory required to store a grpc_stream for this
-   transport */
-size_t grpc_transport_stream_size(grpc_transport *transport);
-
-/* Initialize transport data for a stream.
-
-   Returns 0 on success, any other (transport-defined) value for failure.
-
-   Arguments:
-     transport   - the transport on which to create this stream
-     stream      - a pointer to uninitialized memory to initialize
-     server_data - either NULL for a client initiated stream, or a pointer
-                   supplied from the accept_stream callback function */
-int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx,
-                               grpc_transport *transport, grpc_stream *stream,
-                               grpc_stream_refcount *refcount,
-                               const void *server_data);
-
-void grpc_transport_set_pollset(grpc_exec_ctx *exec_ctx,
-                                grpc_transport *transport, grpc_stream *stream,
-                                grpc_pollset *pollset);
-
-/* Destroy transport data for a stream.
-
-   Requires: a recv_batch with final_state == GRPC_STREAM_CLOSED has been
-   received by the up-layer. Must not be called in the same call stack as
-   recv_frame.
-
-   Arguments:
-     transport - the transport on which to create this stream
-     stream    - the grpc_stream to destroy (memory is still owned by the
-                 caller, but any child memory must be cleaned up) */
-void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
-                                   grpc_transport *transport,
-                                   grpc_stream *stream);
-
-void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
-                                                  grpc_transport_stream_op *op);
-
-void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
-                                               grpc_status_code status);
-
-void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
-                                        grpc_status_code status,
-                                        gpr_slice *optional_message);
-
-char *grpc_transport_stream_op_string(grpc_transport_stream_op *op);
-
-/* Send a batch of operations on a transport
-
-   Takes ownership of any objects contained in ops.
-
-   Arguments:
-     transport - the transport on which to initiate the stream
-     stream    - the stream on which to send the operations. This must be
-                 non-NULL and previously initialized by the same transport.
-     op        - a grpc_transport_stream_op specifying the op to perform */
-void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx,
-                                      grpc_transport *transport,
-                                      grpc_stream *stream,
-                                      grpc_transport_stream_op *op);
-
-void grpc_transport_perform_op(grpc_exec_ctx *exec_ctx,
-                               grpc_transport *transport,
-                               grpc_transport_op *op);
-
-/* Send a ping on a transport
-
-   Calls cb with user data when a response is received. */
-void grpc_transport_ping(grpc_transport *transport, grpc_closure *cb);
-
-/* Advise peer of pending connection termination. */
-void grpc_transport_goaway(grpc_transport *transport, grpc_status_code status,
-                           gpr_slice debug_data);
-
-/* Close a transport. Aborts all open streams. */
-void grpc_transport_close(grpc_transport *transport);
-
-/* Destroy the transport */
-void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport);
-
-/* Get the transports peer */
-char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
-                              grpc_transport *transport);
-
-#endif /* GRPC_CORE_TRANSPORT_TRANSPORT_H */
diff --git a/src/core/transport/transport_impl.h b/src/core/transport/transport_impl.h
deleted file mode 100644
index d9ecc4d..0000000
--- a/src/core/transport/transport_impl.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TRANSPORT_TRANSPORT_IMPL_H
-#define GRPC_CORE_TRANSPORT_TRANSPORT_IMPL_H
-
-#include "src/core/transport/transport.h"
-
-typedef struct grpc_transport_vtable {
-  /* Memory required for a single stream element - this is allocated by upper
-     layers and initialized by the transport */
-  size_t sizeof_stream; /* = sizeof(transport stream) */
-
-  /* name of this transport implementation */
-  const char *name;
-
-  /* implementation of grpc_transport_init_stream */
-  int (*init_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
-                     grpc_stream *stream, grpc_stream_refcount *refcount,
-                     const void *server_data);
-
-  /* implementation of grpc_transport_set_pollset */
-  void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
-                      grpc_stream *stream, grpc_pollset *pollset);
-
-  /* implementation of grpc_transport_perform_stream_op */
-  void (*perform_stream_op)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
-                            grpc_stream *stream, grpc_transport_stream_op *op);
-
-  /* implementation of grpc_transport_perform_op */
-  void (*perform_op)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
-                     grpc_transport_op *op);
-
-  /* implementation of grpc_transport_destroy_stream */
-  void (*destroy_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
-                         grpc_stream *stream);
-
-  /* implementation of grpc_transport_destroy */
-  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_transport *self);
-
-  /* implementation of grpc_transport_get_peer */
-  char *(*get_peer)(grpc_exec_ctx *exec_ctx, grpc_transport *self);
-} grpc_transport_vtable;
-
-/* an instance of a grpc transport */
-struct grpc_transport {
-  /* pointer to a vtable defining operations on this transport */
-  const grpc_transport_vtable *vtable;
-};
-
-#endif /* GRPC_CORE_TRANSPORT_TRANSPORT_IMPL_H */
diff --git a/src/core/transport/transport_op_string.c b/src/core/transport/transport_op_string.c
deleted file mode 100644
index 98b51af..0000000
--- a/src/core/transport/transport_op_string.c
+++ /dev/null
@@ -1,140 +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/channel/channel_stack.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
-/* These routines are here to facilitate debugging - they produce string
-   representations of various transport data structures */
-
-static void put_metadata(gpr_strvec *b, grpc_mdelem *md) {
-  gpr_strvec_add(b, gpr_strdup("key="));
-  gpr_strvec_add(b,
-                 gpr_dump_slice(md->key->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
-
-  gpr_strvec_add(b, gpr_strdup(" value="));
-  gpr_strvec_add(
-      b, gpr_dump_slice(md->value->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
-}
-
-static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {
-  grpc_linked_mdelem *m;
-  for (m = md.list.head; m != NULL; m = m->next) {
-    if (m != md.list.head) gpr_strvec_add(b, gpr_strdup(", "));
-    put_metadata(b, m->md);
-  }
-  if (gpr_time_cmp(md.deadline, gpr_inf_future(md.deadline.clock_type)) != 0) {
-    char *tmp;
-    gpr_asprintf(&tmp, " deadline=%lld.%09d", (long long)md.deadline.tv_sec,
-                 (int)md.deadline.tv_nsec);
-    gpr_strvec_add(b, tmp);
-  }
-}
-
-char *grpc_transport_stream_op_string(grpc_transport_stream_op *op) {
-  char *tmp;
-  char *out;
-  int first = 1;
-
-  gpr_strvec b;
-  gpr_strvec_init(&b);
-
-  if (op->send_initial_metadata != NULL) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = 0;
-    gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA{"));
-    put_metadata_list(&b, *op->send_initial_metadata);
-    gpr_strvec_add(&b, gpr_strdup("}"));
-  }
-
-  if (op->send_message != NULL) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = 0;
-    gpr_asprintf(&tmp, "SEND_MESSAGE:flags=0x%08x:len=%d",
-                 op->send_message->flags, op->send_message->length);
-    gpr_strvec_add(&b, tmp);
-  }
-
-  if (op->send_trailing_metadata != NULL) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = 0;
-    gpr_strvec_add(&b, gpr_strdup("SEND_TRAILING_METADATA{"));
-    put_metadata_list(&b, *op->send_trailing_metadata);
-    gpr_strvec_add(&b, gpr_strdup("}"));
-  }
-
-  if (op->recv_initial_metadata != NULL) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = 0;
-    gpr_strvec_add(&b, gpr_strdup("RECV_INITIAL_METADATA"));
-  }
-
-  if (op->recv_message != NULL) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = 0;
-    gpr_strvec_add(&b, gpr_strdup("RECV_MESSAGE"));
-  }
-
-  if (op->recv_trailing_metadata != NULL) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = 0;
-    gpr_strvec_add(&b, gpr_strdup("RECV_TRAILING_METADATA"));
-  }
-
-  if (op->cancel_with_status != GRPC_STATUS_OK) {
-    if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
-    first = 0;
-    gpr_asprintf(&tmp, "CANCEL:%d", op->cancel_with_status);
-    gpr_strvec_add(&b, tmp);
-  }
-
-  out = gpr_strvec_flatten(&b, NULL);
-  gpr_strvec_destroy(&b);
-
-  return out;
-}
-
-void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
-                      grpc_call_element *elem, grpc_transport_stream_op *op) {
-  char *str = grpc_transport_stream_op_string(op);
-  gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem, str);
-  gpr_free(str);
-}
diff --git a/src/core/tsi/fake_transport_security.c b/src/core/tsi/fake_transport_security.c
deleted file mode 100644
index 72ac32a..0000000
--- a/src/core/tsi/fake_transport_security.c
+++ /dev/null
@@ -1,525 +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/tsi/fake_transport_security.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/useful.h>
-#include "src/core/tsi/transport_security.h"
-
-/* --- Constants. ---*/
-#define TSI_FAKE_FRAME_HEADER_SIZE 4
-#define TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE 64
-#define TSI_FAKE_DEFAULT_FRAME_SIZE 16384
-
-/* --- Structure definitions. ---*/
-
-/* a frame is encoded like this:
-   | size |     data    |
-   where the size field value is the size of the size field plus the size of
-   the data encoded in little endian on 4 bytes.  */
-typedef struct {
-  unsigned char *data;
-  size_t size;
-  size_t allocated_size;
-  size_t offset;
-  int needs_draining;
-} tsi_fake_frame;
-
-typedef enum {
-  TSI_FAKE_CLIENT_INIT = 0,
-  TSI_FAKE_SERVER_INIT = 1,
-  TSI_FAKE_CLIENT_FINISHED = 2,
-  TSI_FAKE_SERVER_FINISHED = 3,
-  TSI_FAKE_HANDSHAKE_MESSAGE_MAX = 4
-} tsi_fake_handshake_message;
-
-typedef struct {
-  tsi_handshaker base;
-  int is_client;
-  tsi_fake_handshake_message next_message_to_send;
-  int needs_incoming_message;
-  tsi_fake_frame incoming;
-  tsi_fake_frame outgoing;
-  tsi_result result;
-} tsi_fake_handshaker;
-
-typedef struct {
-  tsi_frame_protector base;
-  tsi_fake_frame protect_frame;
-  tsi_fake_frame unprotect_frame;
-  size_t max_frame_size;
-} tsi_fake_frame_protector;
-
-/* --- Utils. ---*/
-
-static const char *tsi_fake_handshake_message_strings[] = {
-    "CLIENT_INIT", "SERVER_INIT", "CLIENT_FINISHED", "SERVER_FINISHED"};
-
-static const char *tsi_fake_handshake_message_to_string(int msg) {
-  if (msg < 0 || msg >= TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
-    gpr_log(GPR_ERROR, "Invalid message %d", msg);
-    return "UNKNOWN";
-  }
-  return tsi_fake_handshake_message_strings[msg];
-}
-
-static tsi_result tsi_fake_handshake_message_from_string(
-    const char *msg_string, tsi_fake_handshake_message *msg) {
-  tsi_fake_handshake_message i;
-  for (i = 0; i < TSI_FAKE_HANDSHAKE_MESSAGE_MAX; i++) {
-    if (strncmp(msg_string, tsi_fake_handshake_message_strings[i],
-                strlen(tsi_fake_handshake_message_strings[i])) == 0) {
-      *msg = i;
-      return TSI_OK;
-    }
-  }
-  gpr_log(GPR_ERROR, "Invalid handshake message.");
-  return TSI_DATA_CORRUPTED;
-}
-
-static uint32_t load32_little_endian(const unsigned char *buf) {
-  return ((uint32_t)(buf[0]) | (uint32_t)(buf[1] << 8) |
-          (uint32_t)(buf[2] << 16) | (uint32_t)(buf[3] << 24));
-}
-
-static void store32_little_endian(uint32_t value, unsigned char *buf) {
-  buf[3] = (unsigned char)((value >> 24) & 0xFF);
-  buf[2] = (unsigned char)((value >> 16) & 0xFF);
-  buf[1] = (unsigned char)((value >> 8) & 0xFF);
-  buf[0] = (unsigned char)((value)&0xFF);
-}
-
-static void tsi_fake_frame_reset(tsi_fake_frame *frame, int needs_draining) {
-  frame->offset = 0;
-  frame->needs_draining = needs_draining;
-  if (!needs_draining) frame->size = 0;
-}
-
-/* Returns 1 if successful, 0 otherwise. */
-static int tsi_fake_frame_ensure_size(tsi_fake_frame *frame) {
-  if (frame->data == NULL) {
-    frame->allocated_size = frame->size;
-    frame->data = malloc(frame->allocated_size);
-    if (frame->data == NULL) return 0;
-  } else if (frame->size > frame->allocated_size) {
-    unsigned char *new_data = realloc(frame->data, frame->size);
-    if (new_data == NULL) {
-      free(frame->data);
-      frame->data = NULL;
-      return 0;
-    }
-    frame->data = new_data;
-    frame->allocated_size = frame->size;
-  }
-  return 1;
-}
-
-/* This method should not be called if frame->needs_framing is not 0.  */
-static tsi_result fill_frame_from_bytes(const unsigned char *incoming_bytes,
-                                        size_t *incoming_bytes_size,
-                                        tsi_fake_frame *frame) {
-  size_t available_size = *incoming_bytes_size;
-  size_t to_read_size = 0;
-  const unsigned char *bytes_cursor = incoming_bytes;
-
-  if (frame->needs_draining) return TSI_INTERNAL_ERROR;
-  if (frame->data == NULL) {
-    frame->allocated_size = TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE;
-    frame->data = malloc(frame->allocated_size);
-    if (frame->data == NULL) return TSI_OUT_OF_RESOURCES;
-  }
-
-  if (frame->offset < TSI_FAKE_FRAME_HEADER_SIZE) {
-    to_read_size = TSI_FAKE_FRAME_HEADER_SIZE - frame->offset;
-    if (to_read_size > available_size) {
-      /* Just fill what we can and exit. */
-      memcpy(frame->data + frame->offset, bytes_cursor, available_size);
-      bytes_cursor += available_size;
-      frame->offset += available_size;
-      *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
-      return TSI_INCOMPLETE_DATA;
-    }
-    memcpy(frame->data + frame->offset, bytes_cursor, to_read_size);
-    bytes_cursor += to_read_size;
-    frame->offset += to_read_size;
-    available_size -= to_read_size;
-    frame->size = load32_little_endian(frame->data);
-    if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES;
-  }
-
-  to_read_size = frame->size - frame->offset;
-  if (to_read_size > available_size) {
-    memcpy(frame->data + frame->offset, bytes_cursor, available_size);
-    frame->offset += available_size;
-    bytes_cursor += available_size;
-    *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
-    return TSI_INCOMPLETE_DATA;
-  }
-  memcpy(frame->data + frame->offset, bytes_cursor, to_read_size);
-  bytes_cursor += to_read_size;
-  *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
-  tsi_fake_frame_reset(frame, 1 /* needs_draining */);
-  return TSI_OK;
-}
-
-/* This method should not be called if frame->needs_framing is 0.  */
-static tsi_result drain_frame_to_bytes(unsigned char *outgoing_bytes,
-                                       size_t *outgoing_bytes_size,
-                                       tsi_fake_frame *frame) {
-  size_t to_write_size = frame->size - frame->offset;
-  if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
-  if (*outgoing_bytes_size < to_write_size) {
-    memcpy(outgoing_bytes, frame->data + frame->offset, *outgoing_bytes_size);
-    frame->offset += *outgoing_bytes_size;
-    return TSI_INCOMPLETE_DATA;
-  }
-  memcpy(outgoing_bytes, frame->data + frame->offset, to_write_size);
-  *outgoing_bytes_size = to_write_size;
-  tsi_fake_frame_reset(frame, 0 /* needs_draining */);
-  return TSI_OK;
-}
-
-static tsi_result bytes_to_frame(unsigned char *bytes, size_t bytes_size,
-                                 tsi_fake_frame *frame) {
-  frame->offset = 0;
-  frame->size = bytes_size + TSI_FAKE_FRAME_HEADER_SIZE;
-  if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES;
-  store32_little_endian((uint32_t)frame->size, frame->data);
-  memcpy(frame->data + TSI_FAKE_FRAME_HEADER_SIZE, bytes, bytes_size);
-  tsi_fake_frame_reset(frame, 1 /* needs draining */);
-  return TSI_OK;
-}
-
-static void tsi_fake_frame_destruct(tsi_fake_frame *frame) {
-  if (frame->data != NULL) free(frame->data);
-}
-
-/* --- tsi_frame_protector methods implementation. ---*/
-
-static tsi_result fake_protector_protect(tsi_frame_protector *self,
-                                         const unsigned char *unprotected_bytes,
-                                         size_t *unprotected_bytes_size,
-                                         unsigned char *protected_output_frames,
-                                         size_t *protected_output_frames_size) {
-  tsi_result result = TSI_OK;
-  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
-  unsigned char frame_header[TSI_FAKE_FRAME_HEADER_SIZE];
-  tsi_fake_frame *frame = &impl->protect_frame;
-  size_t saved_output_size = *protected_output_frames_size;
-  size_t drained_size = 0;
-  size_t *num_bytes_written = protected_output_frames_size;
-  *num_bytes_written = 0;
-
-  /* Try to drain first. */
-  if (frame->needs_draining) {
-    drained_size = saved_output_size - *num_bytes_written;
-    result =
-        drain_frame_to_bytes(protected_output_frames, &drained_size, frame);
-    *num_bytes_written += drained_size;
-    protected_output_frames += drained_size;
-    if (result != TSI_OK) {
-      if (result == TSI_INCOMPLETE_DATA) {
-        *unprotected_bytes_size = 0;
-        result = TSI_OK;
-      }
-      return result;
-    }
-  }
-
-  /* Now process the unprotected_bytes. */
-  if (frame->needs_draining) return TSI_INTERNAL_ERROR;
-  if (frame->size == 0) {
-    /* New frame, create a header. */
-    size_t written_in_frame_size = 0;
-    store32_little_endian((uint32_t)impl->max_frame_size, frame_header);
-    written_in_frame_size = TSI_FAKE_FRAME_HEADER_SIZE;
-    result = fill_frame_from_bytes(frame_header, &written_in_frame_size, frame);
-    if (result != TSI_INCOMPLETE_DATA) {
-      gpr_log(GPR_ERROR, "fill_frame_from_bytes returned %s",
-              tsi_result_to_string(result));
-      return result;
-    }
-  }
-  result =
-      fill_frame_from_bytes(unprotected_bytes, unprotected_bytes_size, frame);
-  if (result != TSI_OK) {
-    if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
-    return result;
-  }
-
-  /* Try to drain again. */
-  if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
-  if (frame->offset != 0) return TSI_INTERNAL_ERROR;
-  drained_size = saved_output_size - *num_bytes_written;
-  result = drain_frame_to_bytes(protected_output_frames, &drained_size, frame);
-  *num_bytes_written += drained_size;
-  if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
-  return result;
-}
-
-static tsi_result fake_protector_protect_flush(
-    tsi_frame_protector *self, unsigned char *protected_output_frames,
-    size_t *protected_output_frames_size, size_t *still_pending_size) {
-  tsi_result result = TSI_OK;
-  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
-  tsi_fake_frame *frame = &impl->protect_frame;
-  if (!frame->needs_draining) {
-    /* Create a short frame. */
-    frame->size = frame->offset;
-    frame->offset = 0;
-    frame->needs_draining = 1;
-    store32_little_endian((uint32_t)frame->size,
-                          frame->data); /* Overwrite header. */
-  }
-  result = drain_frame_to_bytes(protected_output_frames,
-                                protected_output_frames_size, frame);
-  if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
-  *still_pending_size = frame->size - frame->offset;
-  return result;
-}
-
-static tsi_result fake_protector_unprotect(
-    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
-    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
-    size_t *unprotected_bytes_size) {
-  tsi_result result = TSI_OK;
-  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
-  tsi_fake_frame *frame = &impl->unprotect_frame;
-  size_t saved_output_size = *unprotected_bytes_size;
-  size_t drained_size = 0;
-  size_t *num_bytes_written = unprotected_bytes_size;
-  *num_bytes_written = 0;
-
-  /* Try to drain first. */
-  if (frame->needs_draining) {
-    /* Go past the header if needed. */
-    if (frame->offset == 0) frame->offset = TSI_FAKE_FRAME_HEADER_SIZE;
-    drained_size = saved_output_size - *num_bytes_written;
-    result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame);
-    unprotected_bytes += drained_size;
-    *num_bytes_written += drained_size;
-    if (result != TSI_OK) {
-      if (result == TSI_INCOMPLETE_DATA) {
-        *protected_frames_bytes_size = 0;
-        result = TSI_OK;
-      }
-      return result;
-    }
-  }
-
-  /* Now process the protected_bytes. */
-  if (frame->needs_draining) return TSI_INTERNAL_ERROR;
-  result = fill_frame_from_bytes(protected_frames_bytes,
-                                 protected_frames_bytes_size, frame);
-  if (result != TSI_OK) {
-    if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
-    return result;
-  }
-
-  /* Try to drain again. */
-  if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
-  if (frame->offset != 0) return TSI_INTERNAL_ERROR;
-  frame->offset = TSI_FAKE_FRAME_HEADER_SIZE; /* Go past the header. */
-  drained_size = saved_output_size - *num_bytes_written;
-  result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame);
-  *num_bytes_written += drained_size;
-  if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
-  return result;
-}
-
-static void fake_protector_destroy(tsi_frame_protector *self) {
-  tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
-  tsi_fake_frame_destruct(&impl->protect_frame);
-  tsi_fake_frame_destruct(&impl->unprotect_frame);
-  free(self);
-}
-
-static const tsi_frame_protector_vtable frame_protector_vtable = {
-    fake_protector_protect, fake_protector_protect_flush,
-    fake_protector_unprotect, fake_protector_destroy,
-};
-
-/* --- tsi_handshaker methods implementation. ---*/
-
-static tsi_result fake_handshaker_get_bytes_to_send_to_peer(
-    tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size) {
-  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
-  tsi_result result = TSI_OK;
-  if (impl->needs_incoming_message || impl->result == TSI_OK) {
-    *bytes_size = 0;
-    return TSI_OK;
-  }
-  if (!impl->outgoing.needs_draining) {
-    tsi_fake_handshake_message next_message_to_send =
-        impl->next_message_to_send + 2;
-    const char *msg_string =
-        tsi_fake_handshake_message_to_string(impl->next_message_to_send);
-    result = bytes_to_frame((unsigned char *)msg_string, strlen(msg_string),
-                            &impl->outgoing);
-    if (result != TSI_OK) return result;
-    if (next_message_to_send > TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
-      next_message_to_send = TSI_FAKE_HANDSHAKE_MESSAGE_MAX;
-    }
-    if (tsi_tracing_enabled) {
-      gpr_log(GPR_INFO, "%s prepared %s.",
-              impl->is_client ? "Client" : "Server",
-              tsi_fake_handshake_message_to_string(impl->next_message_to_send));
-    }
-    impl->next_message_to_send = next_message_to_send;
-  }
-  result = drain_frame_to_bytes(bytes, bytes_size, &impl->outgoing);
-  if (result != TSI_OK) return result;
-  if (!impl->is_client &&
-      impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
-    /* We're done. */
-    if (tsi_tracing_enabled) {
-      gpr_log(GPR_INFO, "Server is done.");
-    }
-    impl->result = TSI_OK;
-  } else {
-    impl->needs_incoming_message = 1;
-  }
-  return TSI_OK;
-}
-
-static tsi_result fake_handshaker_process_bytes_from_peer(
-    tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
-  tsi_result result = TSI_OK;
-  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
-  tsi_fake_handshake_message expected_msg = impl->next_message_to_send - 1;
-  tsi_fake_handshake_message received_msg;
-
-  if (!impl->needs_incoming_message || impl->result == TSI_OK) {
-    *bytes_size = 0;
-    return TSI_OK;
-  }
-  result = fill_frame_from_bytes(bytes, bytes_size, &impl->incoming);
-  if (result != TSI_OK) return result;
-
-  /* We now have a complete frame. */
-  result = tsi_fake_handshake_message_from_string(
-      (const char *)impl->incoming.data + TSI_FAKE_FRAME_HEADER_SIZE,
-      &received_msg);
-  if (result != TSI_OK) {
-    impl->result = result;
-    return result;
-  }
-  if (received_msg != expected_msg) {
-    gpr_log(GPR_ERROR, "Invalid received message (%s instead of %s)",
-            tsi_fake_handshake_message_to_string(received_msg),
-            tsi_fake_handshake_message_to_string(expected_msg));
-  }
-  if (tsi_tracing_enabled) {
-    gpr_log(GPR_INFO, "%s received %s.", impl->is_client ? "Client" : "Server",
-            tsi_fake_handshake_message_to_string(received_msg));
-  }
-  tsi_fake_frame_reset(&impl->incoming, 0 /* needs_draining */);
-  impl->needs_incoming_message = 0;
-  if (impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
-    /* We're done. */
-    if (tsi_tracing_enabled) {
-      gpr_log(GPR_INFO, "%s is done.", impl->is_client ? "Client" : "Server");
-    }
-    impl->result = TSI_OK;
-  }
-  return TSI_OK;
-}
-
-static tsi_result fake_handshaker_get_result(tsi_handshaker *self) {
-  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
-  return impl->result;
-}
-
-static tsi_result fake_handshaker_extract_peer(tsi_handshaker *self,
-                                               tsi_peer *peer) {
-  tsi_result result = tsi_construct_peer(1, peer);
-  if (result != TSI_OK) return result;
-  result = tsi_construct_string_peer_property_from_cstring(
-      TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_FAKE_CERTIFICATE_TYPE,
-      &peer->properties[0]);
-  if (result != TSI_OK) tsi_peer_destruct(peer);
-  return result;
-}
-
-static tsi_result fake_handshaker_create_frame_protector(
-    tsi_handshaker *self, size_t *max_protected_frame_size,
-    tsi_frame_protector **protector) {
-  *protector = tsi_create_fake_protector(max_protected_frame_size);
-  if (*protector == NULL) return TSI_OUT_OF_RESOURCES;
-  return TSI_OK;
-}
-
-static void fake_handshaker_destroy(tsi_handshaker *self) {
-  tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
-  tsi_fake_frame_destruct(&impl->incoming);
-  tsi_fake_frame_destruct(&impl->outgoing);
-  free(self);
-}
-
-static const tsi_handshaker_vtable handshaker_vtable = {
-    fake_handshaker_get_bytes_to_send_to_peer,
-    fake_handshaker_process_bytes_from_peer, fake_handshaker_get_result,
-    fake_handshaker_extract_peer, fake_handshaker_create_frame_protector,
-    fake_handshaker_destroy,
-};
-
-tsi_handshaker *tsi_create_fake_handshaker(int is_client) {
-  tsi_fake_handshaker *impl = calloc(1, sizeof(tsi_fake_handshaker));
-  impl->base.vtable = &handshaker_vtable;
-  impl->is_client = is_client;
-  impl->result = TSI_HANDSHAKE_IN_PROGRESS;
-  if (is_client) {
-    impl->needs_incoming_message = 0;
-    impl->next_message_to_send = TSI_FAKE_CLIENT_INIT;
-  } else {
-    impl->needs_incoming_message = 1;
-    impl->next_message_to_send = TSI_FAKE_SERVER_INIT;
-  }
-  return &impl->base;
-}
-
-tsi_frame_protector *tsi_create_fake_protector(
-    size_t *max_protected_frame_size) {
-  tsi_fake_frame_protector *impl = calloc(1, sizeof(tsi_fake_frame_protector));
-  if (impl == NULL) return NULL;
-  impl->max_frame_size = (max_protected_frame_size == NULL)
-                             ? TSI_FAKE_DEFAULT_FRAME_SIZE
-                             : *max_protected_frame_size;
-  impl->base.vtable = &frame_protector_vtable;
-  return &impl->base;
-}
diff --git a/src/core/tsi/fake_transport_security.h b/src/core/tsi/fake_transport_security.h
deleted file mode 100644
index 6b8e596..0000000
--- a/src/core/tsi/fake_transport_security.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TSI_FAKE_TRANSPORT_SECURITY_H
-#define GRPC_CORE_TSI_FAKE_TRANSPORT_SECURITY_H
-
-#include "src/core/tsi/transport_security_interface.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for FAKE certs. */
-#define TSI_FAKE_CERTIFICATE_TYPE "FAKE"
-
-/* Creates a fake handshaker that will create a fake frame protector.
-
-   No cryptography is performed in these objects. They just simulate handshake
-   messages going back and forth for the handshaker and do some framing on
-   cleartext data for the protector.  */
-tsi_handshaker *tsi_create_fake_handshaker(int is_client);
-
-/* Creates a protector directly without going through the handshake phase. */
-tsi_frame_protector *tsi_create_fake_protector(
-    size_t *max_protected_frame_size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_TSI_FAKE_TRANSPORT_SECURITY_H */
diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c
deleted file mode 100644
index 42d25ca..0000000
--- a/src/core/tsi/ssl_transport_security.c
+++ /dev/null
@@ -1,1534 +0,0 @@
-/*
- *
- * 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/tsi/ssl_transport_security.h"
-
-#include <grpc/support/port_platform.h>
-
-#include <limits.h>
-#include <string.h>
-
-/* TODO(jboeuf): refactor inet_ntop into a portability header. */
-#ifdef GPR_WINSOCK_SOCKET
-#include <ws2tcpip.h>
-#else
-#include <arpa/inet.h>
-#endif
-
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/useful.h>
-
-#include <openssl/bio.h>
-#include <openssl/crypto.h> /* For OPENSSL_free */
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "src/core/tsi/ssl_types.h"
-#include "src/core/tsi/transport_security.h"
-
-/* --- Constants. ---*/
-
-#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384
-#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024
-
-/* Putting a macro like this and littering the source file with #if is really
-   bad practice.
-   TODO(jboeuf): refactor all the #if / #endif in a separate module. */
-#ifndef TSI_OPENSSL_ALPN_SUPPORT
-#define TSI_OPENSSL_ALPN_SUPPORT 1
-#endif
-
-/* TODO(jboeuf): I have not found a way to get this number dynamically from the
-   SSL structure. This is what we would ultimately want though... */
-#define TSI_SSL_MAX_PROTECTION_OVERHEAD 100
-
-/* --- Structure definitions. ---*/
-
-struct tsi_ssl_handshaker_factory {
-  tsi_result (*create_handshaker)(tsi_ssl_handshaker_factory *self,
-                                  const char *server_name_indication,
-                                  tsi_handshaker **handshaker);
-  void (*destroy)(tsi_ssl_handshaker_factory *self);
-};
-
-typedef struct {
-  tsi_ssl_handshaker_factory base;
-  SSL_CTX *ssl_context;
-  unsigned char *alpn_protocol_list;
-  size_t alpn_protocol_list_length;
-} tsi_ssl_client_handshaker_factory;
-
-typedef struct {
-  tsi_ssl_handshaker_factory base;
-
-  /* Several contexts to support SNI.
-     The tsi_peer array contains the subject names of the server certificates
-     associated with the contexts at the same index.  */
-  SSL_CTX **ssl_contexts;
-  tsi_peer *ssl_context_x509_subject_names;
-  size_t ssl_context_count;
-  unsigned char *alpn_protocol_list;
-  size_t alpn_protocol_list_length;
-} tsi_ssl_server_handshaker_factory;
-
-typedef struct {
-  tsi_handshaker base;
-  SSL *ssl;
-  BIO *into_ssl;
-  BIO *from_ssl;
-  tsi_result result;
-} tsi_ssl_handshaker;
-
-typedef struct {
-  tsi_frame_protector base;
-  SSL *ssl;
-  BIO *into_ssl;
-  BIO *from_ssl;
-  unsigned char *buffer;
-  size_t buffer_size;
-  size_t buffer_offset;
-} tsi_ssl_frame_protector;
-
-/* --- Library Initialization. ---*/
-
-static gpr_once init_openssl_once = GPR_ONCE_INIT;
-static gpr_mu *openssl_mutexes = NULL;
-
-static void openssl_locking_cb(int mode, int type, const char *file, int line) {
-  if (mode & CRYPTO_LOCK) {
-    gpr_mu_lock(&openssl_mutexes[type]);
-  } else {
-    gpr_mu_unlock(&openssl_mutexes[type]);
-  }
-}
-
-static unsigned long openssl_thread_id_cb(void) {
-  return (unsigned long)gpr_thd_currentid();
-}
-
-static void init_openssl(void) {
-  int i;
-  int num_locks;
-  SSL_library_init();
-  SSL_load_error_strings();
-  OpenSSL_add_all_algorithms();
-  num_locks = CRYPTO_num_locks();
-  GPR_ASSERT(num_locks > 0);
-  openssl_mutexes = malloc((size_t)num_locks * sizeof(gpr_mu));
-  GPR_ASSERT(openssl_mutexes != NULL);
-  for (i = 0; i < CRYPTO_num_locks(); i++) {
-    gpr_mu_init(&openssl_mutexes[i]);
-  }
-  CRYPTO_set_locking_callback(openssl_locking_cb);
-  CRYPTO_set_id_callback(openssl_thread_id_cb);
-}
-
-/* --- Ssl utils. ---*/
-
-static const char *ssl_error_string(int error) {
-  switch (error) {
-    case SSL_ERROR_NONE:
-      return "SSL_ERROR_NONE";
-    case SSL_ERROR_ZERO_RETURN:
-      return "SSL_ERROR_ZERO_RETURN";
-    case SSL_ERROR_WANT_READ:
-      return "SSL_ERROR_WANT_READ";
-    case SSL_ERROR_WANT_WRITE:
-      return "SSL_ERROR_WANT_WRITE";
-    case SSL_ERROR_WANT_CONNECT:
-      return "SSL_ERROR_WANT_CONNECT";
-    case SSL_ERROR_WANT_ACCEPT:
-      return "SSL_ERROR_WANT_ACCEPT";
-    case SSL_ERROR_WANT_X509_LOOKUP:
-      return "SSL_ERROR_WANT_X509_LOOKUP";
-    case SSL_ERROR_SYSCALL:
-      return "SSL_ERROR_SYSCALL";
-    case SSL_ERROR_SSL:
-      return "SSL_ERROR_SSL";
-    default:
-      return "Unknown error";
-  }
-}
-
-/* TODO(jboeuf): Remove when we are past the debugging phase with this code. */
-static void ssl_log_where_info(const SSL *ssl, int where, int flag,
-                               const char *msg) {
-  if ((where & flag) && tsi_tracing_enabled) {
-    gpr_log(GPR_INFO, "%20.20s - %30.30s  - %5.10s", msg,
-            SSL_state_string_long(ssl), SSL_state_string(ssl));
-  }
-}
-
-/* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
-static void ssl_info_callback(const SSL *ssl, int where, int ret) {
-  if (ret == 0) {
-    gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
-    return;
-  }
-
-  ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP");
-  ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
-  ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
-}
-
-/* Returns 1 if name looks like an IP address, 0 otherwise.
-   This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */
-static int looks_like_ip_address(const char *name) {
-  size_t i;
-  size_t dot_count = 0;
-  size_t num_size = 0;
-  for (i = 0; i < strlen(name); i++) {
-    if (name[i] == ':') {
-      /* IPv6 Address in hexadecimal form, : is not allowed in DNS names. */
-      return 1;
-    }
-    if (name[i] >= '0' && name[i] <= '9') {
-      if (num_size > 3) return 0;
-      num_size++;
-    } else if (name[i] == '.') {
-      if (dot_count > 3 || num_size == 0) return 0;
-      dot_count++;
-      num_size = 0;
-    } else {
-      return 0;
-    }
-  }
-  if (dot_count < 3 || num_size == 0) return 0;
-  return 1;
-}
-
-/* Gets the subject CN from an X509 cert. */
-static tsi_result ssl_get_x509_common_name(X509 *cert, unsigned char **utf8,
-                                           size_t *utf8_size) {
-  int common_name_index = -1;
-  X509_NAME_ENTRY *common_name_entry = NULL;
-  ASN1_STRING *common_name_asn1 = NULL;
-  X509_NAME *subject_name = X509_get_subject_name(cert);
-  int utf8_returned_size = 0;
-  if (subject_name == NULL) {
-    gpr_log(GPR_ERROR, "Could not get subject name from certificate.");
-    return TSI_NOT_FOUND;
-  }
-  common_name_index =
-      X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
-  if (common_name_index == -1) {
-    gpr_log(GPR_ERROR,
-            "Could not get common name of subject from certificate.");
-    return TSI_NOT_FOUND;
-  }
-  common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
-  if (common_name_entry == NULL) {
-    gpr_log(GPR_ERROR, "Could not get common name entry from certificate.");
-    return TSI_INTERNAL_ERROR;
-  }
-  common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
-  if (common_name_asn1 == NULL) {
-    gpr_log(GPR_ERROR,
-            "Could not get common name entry asn1 from certificate.");
-    return TSI_INTERNAL_ERROR;
-  }
-  utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
-  if (utf8_returned_size < 0) {
-    gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string.");
-    return TSI_OUT_OF_RESOURCES;
-  }
-  *utf8_size = (size_t)utf8_returned_size;
-  return TSI_OK;
-}
-
-/* Gets the subject CN of an X509 cert as a tsi_peer_property. */
-static tsi_result peer_property_from_x509_common_name(
-    X509 *cert, tsi_peer_property *property) {
-  unsigned char *common_name;
-  size_t common_name_size;
-  tsi_result result =
-      ssl_get_x509_common_name(cert, &common_name, &common_name_size);
-  if (result != TSI_OK) {
-    if (result == TSI_NOT_FOUND) {
-      common_name = NULL;
-      common_name_size = 0;
-    } else {
-      return result;
-    }
-  }
-  result = tsi_construct_string_peer_property(
-      TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
-      common_name == NULL ? "" : (const char *)common_name, common_name_size,
-      property);
-  OPENSSL_free(common_name);
-  return result;
-}
-
-/* Gets the X509 cert in PEM format as a tsi_peer_property. */
-static tsi_result add_pem_certificate(X509 *cert, tsi_peer_property *property) {
-  BIO *bio = BIO_new(BIO_s_mem());
-  if (!PEM_write_bio_X509(bio, cert)) {
-    BIO_free(bio);
-    return TSI_INTERNAL_ERROR;
-  }
-  char *contents;
-  long len = BIO_get_mem_data(bio, &contents);
-  if (len <= 0) {
-    BIO_free(bio);
-    return TSI_INTERNAL_ERROR;
-  }
-  tsi_result result = tsi_construct_string_peer_property(
-      TSI_X509_PEM_CERT_PROPERTY, (const char *)contents, (size_t)len,
-      property);
-  BIO_free(bio);
-  return result;
-}
-
-/* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
-static tsi_result add_subject_alt_names_properties_to_peer(
-    tsi_peer *peer, GENERAL_NAMES *subject_alt_names,
-    size_t subject_alt_name_count) {
-  size_t i;
-  tsi_result result = TSI_OK;
-
-  /* Reset for DNS entries filtering. */
-  peer->property_count -= subject_alt_name_count;
-
-  for (i = 0; i < subject_alt_name_count; i++) {
-    GENERAL_NAME *subject_alt_name =
-        sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
-    /* Filter out the non-dns entries names. */
-    if (subject_alt_name->type == GEN_DNS) {
-      unsigned char *name = NULL;
-      int name_size;
-      name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName);
-      if (name_size < 0) {
-        gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
-        result = TSI_INTERNAL_ERROR;
-        break;
-      }
-      result = tsi_construct_string_peer_property(
-          TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *)name,
-          (size_t)name_size, &peer->properties[peer->property_count++]);
-      OPENSSL_free(name);
-    } else if (subject_alt_name->type == GEN_IPADD) {
-      char ntop_buf[INET6_ADDRSTRLEN];
-      int af;
-
-      if (subject_alt_name->d.iPAddress->length == 4) {
-        af = AF_INET;
-      } else if (subject_alt_name->d.iPAddress->length == 16) {
-        af = AF_INET6;
-      } else {
-        gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP");
-        result = TSI_INTERNAL_ERROR;
-        break;
-      }
-      const char *name = inet_ntop(af, subject_alt_name->d.iPAddress->data,
-                                   ntop_buf, INET6_ADDRSTRLEN);
-      if (name == NULL) {
-        gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet.");
-        result = TSI_INTERNAL_ERROR;
-        break;
-      }
-
-      result = tsi_construct_string_peer_property_from_cstring(
-          TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name,
-          &peer->properties[peer->property_count++]);
-    }
-    if (result != TSI_OK) break;
-  }
-  return result;
-}
-
-/* Gets information about the peer's X509 cert as a tsi_peer object. */
-static tsi_result peer_from_x509(X509 *cert, int include_certificate_type,
-                                 tsi_peer *peer) {
-  /* TODO(jboeuf): Maybe add more properties. */
-  GENERAL_NAMES *subject_alt_names =
-      X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
-  int subject_alt_name_count = (subject_alt_names != NULL)
-                                   ? (int)sk_GENERAL_NAME_num(subject_alt_names)
-                                   : 0;
-  size_t property_count;
-  tsi_result result;
-  GPR_ASSERT(subject_alt_name_count >= 0);
-  property_count = (include_certificate_type ? (size_t)1 : 0) +
-                   2 /* common name, certificate */ +
-                   (size_t)subject_alt_name_count;
-  result = tsi_construct_peer(property_count, peer);
-  if (result != TSI_OK) return result;
-  do {
-    if (include_certificate_type) {
-      result = tsi_construct_string_peer_property_from_cstring(
-          TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
-          &peer->properties[0]);
-      if (result != TSI_OK) break;
-    }
-    result = peer_property_from_x509_common_name(
-        cert, &peer->properties[include_certificate_type ? 1 : 0]);
-    if (result != TSI_OK) break;
-
-    result = add_pem_certificate(
-        cert, &peer->properties[include_certificate_type ? 2 : 1]);
-    if (result != TSI_OK) break;
-
-    if (subject_alt_name_count != 0) {
-      result = add_subject_alt_names_properties_to_peer(
-          peer, subject_alt_names, (size_t)subject_alt_name_count);
-      if (result != TSI_OK) break;
-    }
-  } while (0);
-
-  if (subject_alt_names != NULL) {
-    sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
-  }
-  if (result != TSI_OK) tsi_peer_destruct(peer);
-  return result;
-}
-
-/* Logs the SSL error stack. */
-static void log_ssl_error_stack(void) {
-  unsigned long err;
-  while ((err = ERR_get_error()) != 0) {
-    char details[256];
-    ERR_error_string_n((uint32_t)err, details, sizeof(details));
-    gpr_log(GPR_ERROR, "%s", details);
-  }
-}
-
-/* Performs an SSL_read and handle errors. */
-static tsi_result do_ssl_read(SSL *ssl, unsigned char *unprotected_bytes,
-                              size_t *unprotected_bytes_size) {
-  int read_from_ssl;
-  GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
-  read_from_ssl =
-      SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size);
-  if (read_from_ssl == 0) {
-    gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly.");
-    return TSI_INTERNAL_ERROR;
-  }
-  if (read_from_ssl < 0) {
-    read_from_ssl = SSL_get_error(ssl, read_from_ssl);
-    switch (read_from_ssl) {
-      case SSL_ERROR_WANT_READ:
-        /* We need more data to finish the frame. */
-        *unprotected_bytes_size = 0;
-        return TSI_OK;
-      case SSL_ERROR_WANT_WRITE:
-        gpr_log(
-            GPR_ERROR,
-            "Peer tried to renegotiate SSL connection. This is unsupported.");
-        return TSI_UNIMPLEMENTED;
-      case SSL_ERROR_SSL:
-        gpr_log(GPR_ERROR, "Corruption detected.");
-        log_ssl_error_stack();
-        return TSI_DATA_CORRUPTED;
-      default:
-        gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
-                ssl_error_string(read_from_ssl));
-        return TSI_PROTOCOL_FAILURE;
-    }
-  }
-  *unprotected_bytes_size = (size_t)read_from_ssl;
-  return TSI_OK;
-}
-
-/* Performs an SSL_write and handle errors. */
-static tsi_result do_ssl_write(SSL *ssl, unsigned char *unprotected_bytes,
-                               size_t unprotected_bytes_size) {
-  int ssl_write_result;
-  GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
-  ssl_write_result =
-      SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size);
-  if (ssl_write_result < 0) {
-    ssl_write_result = SSL_get_error(ssl, ssl_write_result);
-    if (ssl_write_result == SSL_ERROR_WANT_READ) {
-      gpr_log(GPR_ERROR,
-              "Peer tried to renegotiate SSL connection. This is unsupported.");
-      return TSI_UNIMPLEMENTED;
-    } else {
-      gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
-              ssl_error_string(ssl_write_result));
-      return TSI_INTERNAL_ERROR;
-    }
-  }
-  return TSI_OK;
-}
-
-/* Loads an in-memory PEM certificate chain into the SSL context. */
-static tsi_result ssl_ctx_use_certificate_chain(
-    SSL_CTX *context, const unsigned char *pem_cert_chain,
-    size_t pem_cert_chain_size) {
-  tsi_result result = TSI_OK;
-  X509 *certificate = NULL;
-  BIO *pem;
-  GPR_ASSERT(pem_cert_chain_size <= INT_MAX);
-  pem = BIO_new_mem_buf((void *)pem_cert_chain, (int)pem_cert_chain_size);
-  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
-
-  do {
-    certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
-    if (certificate == NULL) {
-      result = TSI_INVALID_ARGUMENT;
-      break;
-    }
-    if (!SSL_CTX_use_certificate(context, certificate)) {
-      result = TSI_INVALID_ARGUMENT;
-      break;
-    }
-    while (1) {
-      X509 *certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, "");
-      if (certificate_authority == NULL) {
-        ERR_clear_error();
-        break; /* Done reading. */
-      }
-      if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) {
-        X509_free(certificate_authority);
-        result = TSI_INVALID_ARGUMENT;
-        break;
-      }
-      /* We don't need to free certificate_authority as its ownership has been
-         transfered to the context. That is not the case for certificate though.
-       */
-    }
-  } while (0);
-
-  if (certificate != NULL) X509_free(certificate);
-  BIO_free(pem);
-  return result;
-}
-
-/* Loads an in-memory PEM private key into the SSL context. */
-static tsi_result ssl_ctx_use_private_key(SSL_CTX *context,
-                                          const unsigned char *pem_key,
-                                          size_t pem_key_size) {
-  tsi_result result = TSI_OK;
-  EVP_PKEY *private_key = NULL;
-  BIO *pem;
-  GPR_ASSERT(pem_key_size <= INT_MAX);
-  pem = BIO_new_mem_buf((void *)pem_key, (int)pem_key_size);
-  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
-  do {
-    private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
-    if (private_key == NULL) {
-      result = TSI_INVALID_ARGUMENT;
-      break;
-    }
-    if (!SSL_CTX_use_PrivateKey(context, private_key)) {
-      result = TSI_INVALID_ARGUMENT;
-      break;
-    }
-  } while (0);
-  if (private_key != NULL) EVP_PKEY_free(private_key);
-  BIO_free(pem);
-  return result;
-}
-
-/* Loads in-memory PEM verification certs into the SSL context and optionally
-   returns the verification cert names (root_names can be NULL). */
-static tsi_result ssl_ctx_load_verification_certs(
-    SSL_CTX *context, const unsigned char *pem_roots, size_t pem_roots_size,
-    STACK_OF(X509_NAME) * *root_names) {
-  tsi_result result = TSI_OK;
-  size_t num_roots = 0;
-  X509 *root = NULL;
-  X509_NAME *root_name = NULL;
-  BIO *pem;
-  X509_STORE *root_store;
-  GPR_ASSERT(pem_roots_size <= INT_MAX);
-  pem = BIO_new_mem_buf((void *)pem_roots, (int)pem_roots_size);
-  root_store = SSL_CTX_get_cert_store(context);
-  if (root_store == NULL) return TSI_INVALID_ARGUMENT;
-  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
-  if (root_names != NULL) {
-    *root_names = sk_X509_NAME_new_null();
-    if (*root_names == NULL) return TSI_OUT_OF_RESOURCES;
-  }
-
-  while (1) {
-    root = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
-    if (root == NULL) {
-      ERR_clear_error();
-      break; /* We're at the end of stream. */
-    }
-    if (root_names != NULL) {
-      root_name = X509_get_subject_name(root);
-      if (root_name == NULL) {
-        gpr_log(GPR_ERROR, "Could not get name from root certificate.");
-        result = TSI_INVALID_ARGUMENT;
-        break;
-      }
-      root_name = X509_NAME_dup(root_name);
-      if (root_name == NULL) {
-        result = TSI_OUT_OF_RESOURCES;
-        break;
-      }
-      sk_X509_NAME_push(*root_names, root_name);
-      root_name = NULL;
-    }
-    if (!X509_STORE_add_cert(root_store, root)) {
-      gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
-      result = TSI_INTERNAL_ERROR;
-      break;
-    }
-    X509_free(root);
-    num_roots++;
-  }
-
-  if (num_roots == 0) {
-    gpr_log(GPR_ERROR, "Could not load any root certificate.");
-    result = TSI_INVALID_ARGUMENT;
-  }
-
-  if (result != TSI_OK) {
-    if (root != NULL) X509_free(root);
-    if (root_names != NULL) {
-      sk_X509_NAME_pop_free(*root_names, X509_NAME_free);
-      *root_names = NULL;
-      if (root_name != NULL) X509_NAME_free(root_name);
-    }
-  }
-  BIO_free(pem);
-  return result;
-}
-
-/* Populates the SSL context with a private key and a cert chain, and sets the
-   cipher list and the ephemeral ECDH key. */
-static tsi_result populate_ssl_context(
-    SSL_CTX *context, const unsigned char *pem_private_key,
-    size_t pem_private_key_size, const unsigned char *pem_certificate_chain,
-    size_t pem_certificate_chain_size, const char *cipher_list) {
-  tsi_result result = TSI_OK;
-  if (pem_certificate_chain != NULL) {
-    result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain,
-                                           pem_certificate_chain_size);
-    if (result != TSI_OK) {
-      gpr_log(GPR_ERROR, "Invalid cert chain file.");
-      return result;
-    }
-  }
-  if (pem_private_key != NULL) {
-    result =
-        ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size);
-    if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
-      gpr_log(GPR_ERROR, "Invalid private key.");
-      return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
-    }
-  }
-  if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) {
-    gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
-    return TSI_INVALID_ARGUMENT;
-  }
-  {
-    EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
-    if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
-      gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
-      EC_KEY_free(ecdh);
-      return TSI_INTERNAL_ERROR;
-    }
-    SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
-    EC_KEY_free(ecdh);
-  }
-  return TSI_OK;
-}
-
-/* Extracts the CN and the SANs from an X509 cert as a peer object. */
-static tsi_result extract_x509_subject_names_from_pem_cert(
-    const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer *peer) {
-  tsi_result result = TSI_OK;
-  X509 *cert = NULL;
-  BIO *pem;
-  GPR_ASSERT(pem_cert_size <= INT_MAX);
-  pem = BIO_new_mem_buf((void *)pem_cert, (int)pem_cert_size);
-  if (pem == NULL) return TSI_OUT_OF_RESOURCES;
-
-  cert = PEM_read_bio_X509(pem, NULL, NULL, "");
-  if (cert == NULL) {
-    gpr_log(GPR_ERROR, "Invalid certificate");
-    result = TSI_INVALID_ARGUMENT;
-  } else {
-    result = peer_from_x509(cert, 0, peer);
-  }
-  if (cert != NULL) X509_free(cert);
-  BIO_free(pem);
-  return result;
-}
-
-/* Builds the alpn protocol name list according to rfc 7301. */
-static tsi_result build_alpn_protocol_name_list(
-    const unsigned char **alpn_protocols,
-    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
-    unsigned char **protocol_name_list, size_t *protocol_name_list_length) {
-  uint16_t i;
-  unsigned char *current;
-  *protocol_name_list = NULL;
-  *protocol_name_list_length = 0;
-  if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
-  for (i = 0; i < num_alpn_protocols; i++) {
-    if (alpn_protocols_lengths[i] == 0) {
-      gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
-      return TSI_INVALID_ARGUMENT;
-    }
-    *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1;
-  }
-  *protocol_name_list = malloc(*protocol_name_list_length);
-  if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES;
-  current = *protocol_name_list;
-  for (i = 0; i < num_alpn_protocols; i++) {
-    *(current++) = alpn_protocols_lengths[i];
-    memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]);
-    current += alpn_protocols_lengths[i];
-  }
-  /* Safety check. */
-  if ((current < *protocol_name_list) ||
-      ((uintptr_t)(current - *protocol_name_list) !=
-       *protocol_name_list_length)) {
-    return TSI_INTERNAL_ERROR;
-  }
-  return TSI_OK;
-}
-
-/* --- tsi_frame_protector methods implementation. ---*/
-
-static tsi_result ssl_protector_protect(tsi_frame_protector *self,
-                                        const unsigned char *unprotected_bytes,
-                                        size_t *unprotected_bytes_size,
-                                        unsigned char *protected_output_frames,
-                                        size_t *protected_output_frames_size) {
-  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
-  int read_from_ssl;
-  size_t available;
-  tsi_result result = TSI_OK;
-
-  /* First see if we have some pending data in the SSL BIO. */
-  int pending_in_ssl = (int)BIO_pending(impl->from_ssl);
-  if (pending_in_ssl > 0) {
-    *unprotected_bytes_size = 0;
-    GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
-    read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
-                             (int)*protected_output_frames_size);
-    if (read_from_ssl < 0) {
-      gpr_log(GPR_ERROR,
-              "Could not read from BIO even though some data is pending");
-      return TSI_INTERNAL_ERROR;
-    }
-    *protected_output_frames_size = (size_t)read_from_ssl;
-    return TSI_OK;
-  }
-
-  /* Now see if we can send a complete frame. */
-  available = impl->buffer_size - impl->buffer_offset;
-  if (available > *unprotected_bytes_size) {
-    /* If we cannot, just copy the data in our internal buffer. */
-    memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes,
-           *unprotected_bytes_size);
-    impl->buffer_offset += *unprotected_bytes_size;
-    *protected_output_frames_size = 0;
-    return TSI_OK;
-  }
-
-  /* If we can, prepare the buffer, send it to SSL_write and read. */
-  memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available);
-  result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size);
-  if (result != TSI_OK) return result;
-
-  GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
-  read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
-                           (int)*protected_output_frames_size);
-  if (read_from_ssl < 0) {
-    gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
-    return TSI_INTERNAL_ERROR;
-  }
-  *protected_output_frames_size = (size_t)read_from_ssl;
-  *unprotected_bytes_size = available;
-  impl->buffer_offset = 0;
-  return TSI_OK;
-}
-
-static tsi_result ssl_protector_protect_flush(
-    tsi_frame_protector *self, unsigned char *protected_output_frames,
-    size_t *protected_output_frames_size, size_t *still_pending_size) {
-  tsi_result result = TSI_OK;
-  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
-  int read_from_ssl = 0;
-  int pending;
-
-  if (impl->buffer_offset != 0) {
-    result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset);
-    if (result != TSI_OK) return result;
-    impl->buffer_offset = 0;
-  }
-
-  pending = (int)BIO_pending(impl->from_ssl);
-  GPR_ASSERT(pending >= 0);
-  *still_pending_size = (size_t)pending;
-  if (*still_pending_size == 0) return TSI_OK;
-
-  GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
-  read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
-                           (int)*protected_output_frames_size);
-  if (read_from_ssl <= 0) {
-    gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
-    return TSI_INTERNAL_ERROR;
-  }
-  *protected_output_frames_size = (size_t)read_from_ssl;
-  pending = (int)BIO_pending(impl->from_ssl);
-  GPR_ASSERT(pending >= 0);
-  *still_pending_size = (size_t)pending;
-  return TSI_OK;
-}
-
-static tsi_result ssl_protector_unprotect(
-    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
-    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
-    size_t *unprotected_bytes_size) {
-  tsi_result result = TSI_OK;
-  int written_into_ssl = 0;
-  size_t output_bytes_size = *unprotected_bytes_size;
-  size_t output_bytes_offset = 0;
-  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
-
-  /* First, try to read remaining data from ssl. */
-  result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
-  if (result != TSI_OK) return result;
-  if (*unprotected_bytes_size == output_bytes_size) {
-    /* We have read everything we could and cannot process any more input. */
-    *protected_frames_bytes_size = 0;
-    return TSI_OK;
-  }
-  output_bytes_offset = *unprotected_bytes_size;
-  unprotected_bytes += output_bytes_offset;
-  *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
-
-  /* Then, try to write some data to ssl. */
-  GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
-  written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes,
-                               (int)*protected_frames_bytes_size);
-  if (written_into_ssl < 0) {
-    gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
-            written_into_ssl);
-    return TSI_INTERNAL_ERROR;
-  }
-  *protected_frames_bytes_size = (size_t)written_into_ssl;
-
-  /* Now try to read some data again. */
-  result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
-  if (result == TSI_OK) {
-    /* Don't forget to output the total number of bytes read. */
-    *unprotected_bytes_size += output_bytes_offset;
-  }
-  return result;
-}
-
-static void ssl_protector_destroy(tsi_frame_protector *self) {
-  tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
-  if (impl->buffer != NULL) free(impl->buffer);
-  if (impl->ssl != NULL) SSL_free(impl->ssl);
-  free(self);
-}
-
-static const tsi_frame_protector_vtable frame_protector_vtable = {
-    ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
-    ssl_protector_destroy,
-};
-
-/* --- tsi_handshaker methods implementation. ---*/
-
-static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
-                                                           unsigned char *bytes,
-                                                           size_t *bytes_size) {
-  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
-  int bytes_read_from_ssl = 0;
-  if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
-      *bytes_size > INT_MAX) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  GPR_ASSERT(*bytes_size <= INT_MAX);
-  bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size);
-  if (bytes_read_from_ssl < 0) {
-    *bytes_size = 0;
-    if (!BIO_should_retry(impl->from_ssl)) {
-      impl->result = TSI_INTERNAL_ERROR;
-      return impl->result;
-    } else {
-      return TSI_OK;
-    }
-  }
-  *bytes_size = (size_t)bytes_read_from_ssl;
-  return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
-}
-
-static tsi_result ssl_handshaker_get_result(tsi_handshaker *self) {
-  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
-  if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
-      SSL_is_init_finished(impl->ssl)) {
-    impl->result = TSI_OK;
-  }
-  return impl->result;
-}
-
-static tsi_result ssl_handshaker_process_bytes_from_peer(
-    tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
-  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
-  int bytes_written_into_ssl_size = 0;
-  if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  GPR_ASSERT(*bytes_size <= INT_MAX);
-  bytes_written_into_ssl_size =
-      BIO_write(impl->into_ssl, bytes, (int)*bytes_size);
-  if (bytes_written_into_ssl_size < 0) {
-    gpr_log(GPR_ERROR, "Could not write to memory BIO.");
-    impl->result = TSI_INTERNAL_ERROR;
-    return impl->result;
-  }
-  *bytes_size = (size_t)bytes_written_into_ssl_size;
-
-  if (!tsi_handshaker_is_in_progress(self)) {
-    impl->result = TSI_OK;
-    return impl->result;
-  } else {
-    /* Get ready to get some bytes from SSL. */
-    int ssl_result = SSL_do_handshake(impl->ssl);
-    ssl_result = SSL_get_error(impl->ssl, ssl_result);
-    switch (ssl_result) {
-      case SSL_ERROR_WANT_READ:
-        if (BIO_pending(impl->from_ssl) == 0) {
-          /* We need more data. */
-          return TSI_INCOMPLETE_DATA;
-        } else {
-          return TSI_OK;
-        }
-      case SSL_ERROR_NONE:
-        return TSI_OK;
-      default: {
-        char err_str[256];
-        ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
-        gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
-                ssl_error_string(ssl_result), err_str);
-        impl->result = TSI_PROTOCOL_FAILURE;
-        return impl->result;
-      }
-    }
-  }
-}
-
-static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self,
-                                              tsi_peer *peer) {
-  tsi_result result = TSI_OK;
-  const unsigned char *alpn_selected = NULL;
-  unsigned int alpn_selected_len;
-  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
-  X509 *peer_cert = SSL_get_peer_certificate(impl->ssl);
-  if (peer_cert != NULL) {
-    result = peer_from_x509(peer_cert, 1, peer);
-    X509_free(peer_cert);
-    if (result != TSI_OK) return result;
-  }
-#if TSI_OPENSSL_ALPN_SUPPORT
-  SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len);
-#endif /* TSI_OPENSSL_ALPN_SUPPORT */
-  if (alpn_selected == NULL) {
-    /* Try npn. */
-    SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
-                                   &alpn_selected_len);
-  }
-  if (alpn_selected != NULL) {
-    size_t i;
-    tsi_peer_property *new_properties =
-        calloc(1, sizeof(tsi_peer_property) * (peer->property_count + 1));
-    if (new_properties == NULL) return TSI_OUT_OF_RESOURCES;
-    for (i = 0; i < peer->property_count; i++) {
-      new_properties[i] = peer->properties[i];
-    }
-    result = tsi_construct_string_peer_property(
-        TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *)alpn_selected,
-        alpn_selected_len, &new_properties[peer->property_count]);
-    if (result != TSI_OK) {
-      free(new_properties);
-      return result;
-    }
-    if (peer->properties != NULL) free(peer->properties);
-    peer->property_count++;
-    peer->properties = new_properties;
-  }
-  return result;
-}
-
-static tsi_result ssl_handshaker_create_frame_protector(
-    tsi_handshaker *self, size_t *max_output_protected_frame_size,
-    tsi_frame_protector **protector) {
-  size_t actual_max_output_protected_frame_size =
-      TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
-  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
-  tsi_ssl_frame_protector *protector_impl =
-      calloc(1, sizeof(tsi_ssl_frame_protector));
-  if (protector_impl == NULL) {
-    return TSI_OUT_OF_RESOURCES;
-  }
-
-  if (max_output_protected_frame_size != NULL) {
-    if (*max_output_protected_frame_size >
-        TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) {
-      *max_output_protected_frame_size =
-          TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
-    } else if (*max_output_protected_frame_size <
-               TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) {
-      *max_output_protected_frame_size =
-          TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
-    }
-    actual_max_output_protected_frame_size = *max_output_protected_frame_size;
-  }
-  protector_impl->buffer_size =
-      actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
-  protector_impl->buffer = malloc(protector_impl->buffer_size);
-  if (protector_impl->buffer == NULL) {
-    gpr_log(GPR_ERROR,
-            "Could not allocated buffer for tsi_ssl_frame_protector.");
-    free(protector_impl);
-    return TSI_INTERNAL_ERROR;
-  }
-
-  /* Transfer ownership of ssl to the frame protector. It is OK as the caller
-   * cannot call anything else but destroy on the handshaker after this call. */
-  protector_impl->ssl = impl->ssl;
-  impl->ssl = NULL;
-  protector_impl->into_ssl = impl->into_ssl;
-  protector_impl->from_ssl = impl->from_ssl;
-
-  protector_impl->base.vtable = &frame_protector_vtable;
-  *protector = &protector_impl->base;
-  return TSI_OK;
-}
-
-static void ssl_handshaker_destroy(tsi_handshaker *self) {
-  tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
-  SSL_free(impl->ssl); /* The BIO objects are owned by ssl */
-  free(impl);
-}
-
-static const tsi_handshaker_vtable handshaker_vtable = {
-    ssl_handshaker_get_bytes_to_send_to_peer,
-    ssl_handshaker_process_bytes_from_peer, ssl_handshaker_get_result,
-    ssl_handshaker_extract_peer, ssl_handshaker_create_frame_protector,
-    ssl_handshaker_destroy,
-};
-
-/* --- tsi_ssl_handshaker_factory common methods. --- */
-
-tsi_result tsi_ssl_handshaker_factory_create_handshaker(
-    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
-    tsi_handshaker **handshaker) {
-  if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
-  return self->create_handshaker(self, server_name_indication, handshaker);
-}
-
-void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self) {
-  if (self == NULL) return;
-  self->destroy(self);
-}
-
-static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
-                                            const char *server_name_indication,
-                                            tsi_handshaker **handshaker) {
-  SSL *ssl = SSL_new(ctx);
-  BIO *into_ssl = NULL;
-  BIO *from_ssl = NULL;
-  tsi_ssl_handshaker *impl = NULL;
-  *handshaker = NULL;
-  if (ctx == NULL) {
-    gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
-    return TSI_INTERNAL_ERROR;
-  }
-  if (ssl == NULL) {
-    return TSI_OUT_OF_RESOURCES;
-  }
-  SSL_set_info_callback(ssl, ssl_info_callback);
-
-  into_ssl = BIO_new(BIO_s_mem());
-  from_ssl = BIO_new(BIO_s_mem());
-  if (into_ssl == NULL || from_ssl == NULL) {
-    gpr_log(GPR_ERROR, "BIO_new failed.");
-    SSL_free(ssl);
-    if (into_ssl != NULL) BIO_free(into_ssl);
-    if (from_ssl != NULL) BIO_free(into_ssl);
-    return TSI_OUT_OF_RESOURCES;
-  }
-  SSL_set_bio(ssl, into_ssl, from_ssl);
-  if (is_client) {
-    int ssl_result;
-    SSL_set_connect_state(ssl);
-    if (server_name_indication != NULL) {
-      if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) {
-        gpr_log(GPR_ERROR, "Invalid server name indication %s.",
-                server_name_indication);
-        SSL_free(ssl);
-        return TSI_INTERNAL_ERROR;
-      }
-    }
-    ssl_result = SSL_do_handshake(ssl);
-    ssl_result = SSL_get_error(ssl, ssl_result);
-    if (ssl_result != SSL_ERROR_WANT_READ) {
-      gpr_log(GPR_ERROR,
-              "Unexpected error received from first SSL_do_handshake call: %s",
-              ssl_error_string(ssl_result));
-      SSL_free(ssl);
-      return TSI_INTERNAL_ERROR;
-    }
-  } else {
-    SSL_set_accept_state(ssl);
-  }
-
-  impl = calloc(1, sizeof(tsi_ssl_handshaker));
-  if (impl == NULL) {
-    SSL_free(ssl);
-    return TSI_OUT_OF_RESOURCES;
-  }
-  impl->ssl = ssl;
-  impl->into_ssl = into_ssl;
-  impl->from_ssl = from_ssl;
-  impl->result = TSI_HANDSHAKE_IN_PROGRESS;
-  impl->base.vtable = &handshaker_vtable;
-  *handshaker = &impl->base;
-  return TSI_OK;
-}
-
-static int select_protocol_list(const unsigned char **out,
-                                unsigned char *outlen,
-                                const unsigned char *client_list,
-                                size_t client_list_len,
-                                const unsigned char *server_list,
-                                size_t server_list_len) {
-  const unsigned char *client_current = client_list;
-  while ((unsigned int)(client_current - client_list) < client_list_len) {
-    unsigned char client_current_len = *(client_current++);
-    const unsigned char *server_current = server_list;
-    while ((server_current >= server_list) &&
-           (uintptr_t)(server_current - server_list) < server_list_len) {
-      unsigned char server_current_len = *(server_current++);
-      if ((client_current_len == server_current_len) &&
-          !memcmp(client_current, server_current, server_current_len)) {
-        *out = server_current;
-        *outlen = server_current_len;
-        return SSL_TLSEXT_ERR_OK;
-      }
-      server_current += server_current_len;
-    }
-    client_current += client_current_len;
-  }
-  return SSL_TLSEXT_ERR_NOACK;
-}
-
-/* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
-
-static tsi_result ssl_client_handshaker_factory_create_handshaker(
-    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
-    tsi_handshaker **handshaker) {
-  tsi_ssl_client_handshaker_factory *impl =
-      (tsi_ssl_client_handshaker_factory *)self;
-  return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
-                                   handshaker);
-}
-
-static void ssl_client_handshaker_factory_destroy(
-    tsi_ssl_handshaker_factory *self) {
-  tsi_ssl_client_handshaker_factory *impl =
-      (tsi_ssl_client_handshaker_factory *)self;
-  if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
-  if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
-  free(impl);
-}
-
-static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out,
-                                                  unsigned char *outlen,
-                                                  const unsigned char *in,
-                                                  unsigned int inlen,
-                                                  void *arg) {
-  tsi_ssl_client_handshaker_factory *factory =
-      (tsi_ssl_client_handshaker_factory *)arg;
-  return select_protocol_list((const unsigned char **)out, outlen,
-                              factory->alpn_protocol_list,
-                              factory->alpn_protocol_list_length, in, inlen);
-}
-
-/* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
-
-static tsi_result ssl_server_handshaker_factory_create_handshaker(
-    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
-    tsi_handshaker **handshaker) {
-  tsi_ssl_server_handshaker_factory *impl =
-      (tsi_ssl_server_handshaker_factory *)self;
-  if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  /* Create the handshaker with the first context. We will switch if needed
-     because of SNI in ssl_server_handshaker_factory_servername_callback.  */
-  return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
-}
-
-static void ssl_server_handshaker_factory_destroy(
-    tsi_ssl_handshaker_factory *self) {
-  tsi_ssl_server_handshaker_factory *impl =
-      (tsi_ssl_server_handshaker_factory *)self;
-  size_t i;
-  for (i = 0; i < impl->ssl_context_count; i++) {
-    if (impl->ssl_contexts[i] != NULL) {
-      SSL_CTX_free(impl->ssl_contexts[i]);
-      tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
-    }
-  }
-  if (impl->ssl_contexts != NULL) free(impl->ssl_contexts);
-  if (impl->ssl_context_x509_subject_names != NULL) {
-    free(impl->ssl_context_x509_subject_names);
-  }
-  if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
-  free(impl);
-}
-
-static int does_entry_match_name(const char *entry, size_t entry_length,
-                                 const char *name) {
-  const char *dot;
-  const char *name_subdomain = NULL;
-  size_t name_length = strlen(name);
-  size_t name_subdomain_length;
-  if (entry_length == 0) return 0;
-
-  /* Take care of '.' terminations. */
-  if (name[name_length - 1] == '.') {
-    name_length--;
-  }
-  if (entry[entry_length - 1] == '.') {
-    entry_length--;
-    if (entry_length == 0) return 0;
-  }
-
-  if ((name_length == entry_length) &&
-      strncmp(name, entry, entry_length) == 0) {
-    return 1; /* Perfect match. */
-  }
-  if (entry[0] != '*') return 0;
-
-  /* Wildchar subdomain matching. */
-  if (entry_length < 3 || entry[1] != '.') { /* At least *.x */
-    gpr_log(GPR_ERROR, "Invalid wildchar entry.");
-    return 0;
-  }
-  name_subdomain = strchr(name, '.');
-  if (name_subdomain == NULL) return 0;
-  name_subdomain_length = strlen(name_subdomain);
-  if (name_subdomain_length < 2) return 0;
-  name_subdomain++; /* Starts after the dot. */
-  name_subdomain_length--;
-  entry += 2; /* Remove *. */
-  entry_length -= 2;
-  dot = strchr(name_subdomain, '.');
-  if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
-    gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
-    return 0;
-  }
-  if (name_subdomain[name_subdomain_length - 1] == '.') {
-    name_subdomain_length--;
-  }
-  return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
-          strncmp(entry, name_subdomain, entry_length) == 0);
-}
-
-static int ssl_server_handshaker_factory_servername_callback(SSL *ssl, int *ap,
-                                                             void *arg) {
-  tsi_ssl_server_handshaker_factory *impl =
-      (tsi_ssl_server_handshaker_factory *)arg;
-  size_t i = 0;
-  const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-  if (servername == NULL || strlen(servername) == 0) {
-    return SSL_TLSEXT_ERR_NOACK;
-  }
-
-  for (i = 0; i < impl->ssl_context_count; i++) {
-    if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i],
-                                  servername)) {
-      SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]);
-      return SSL_TLSEXT_ERR_OK;
-    }
-  }
-  gpr_log(GPR_ERROR, "No match found for server name: %s.", servername);
-  return SSL_TLSEXT_ERR_ALERT_WARNING;
-}
-
-#if TSI_OPENSSL_ALPN_SUPPORT
-static int server_handshaker_factory_alpn_callback(
-    SSL *ssl, const unsigned char **out, unsigned char *outlen,
-    const unsigned char *in, unsigned int inlen, void *arg) {
-  tsi_ssl_server_handshaker_factory *factory =
-      (tsi_ssl_server_handshaker_factory *)arg;
-  return select_protocol_list(out, outlen, in, inlen,
-                              factory->alpn_protocol_list,
-                              factory->alpn_protocol_list_length);
-}
-#endif /* TSI_OPENSSL_ALPN_SUPPORT */
-
-static int server_handshaker_factory_npn_advertised_callback(
-    SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) {
-  tsi_ssl_server_handshaker_factory *factory =
-      (tsi_ssl_server_handshaker_factory *)arg;
-  *out = factory->alpn_protocol_list;
-  GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX);
-  *outlen = (unsigned int)factory->alpn_protocol_list_length;
-  return SSL_TLSEXT_ERR_OK;
-}
-
-/* --- tsi_ssl_handshaker_factory constructors. --- */
-
-tsi_result tsi_create_ssl_client_handshaker_factory(
-    const unsigned char *pem_private_key, size_t pem_private_key_size,
-    const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
-    const unsigned char *pem_root_certs, size_t pem_root_certs_size,
-    const char *cipher_list, const unsigned char **alpn_protocols,
-    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
-    tsi_ssl_handshaker_factory **factory) {
-  SSL_CTX *ssl_context = NULL;
-  tsi_ssl_client_handshaker_factory *impl = NULL;
-  tsi_result result = TSI_OK;
-
-  gpr_once_init(&init_openssl_once, init_openssl);
-
-  if (factory == NULL) return TSI_INVALID_ARGUMENT;
-  *factory = NULL;
-  if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT;
-
-  ssl_context = SSL_CTX_new(TLSv1_2_method());
-  if (ssl_context == NULL) {
-    gpr_log(GPR_ERROR, "Could not create ssl context.");
-    return TSI_INVALID_ARGUMENT;
-  }
-
-  impl = calloc(1, sizeof(tsi_ssl_client_handshaker_factory));
-  if (impl == NULL) {
-    SSL_CTX_free(ssl_context);
-    return TSI_OUT_OF_RESOURCES;
-  }
-  impl->ssl_context = ssl_context;
-
-  do {
-    result =
-        populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size,
-                             pem_cert_chain, pem_cert_chain_size, cipher_list);
-    if (result != TSI_OK) break;
-    result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
-                                             pem_root_certs_size, NULL);
-    if (result != TSI_OK) {
-      gpr_log(GPR_ERROR, "Cannot load server root certificates.");
-      break;
-    }
-
-    if (num_alpn_protocols != 0) {
-      result = build_alpn_protocol_name_list(
-          alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
-          &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
-      if (result != TSI_OK) {
-        gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
-                tsi_result_to_string(result));
-        break;
-      }
-#if TSI_OPENSSL_ALPN_SUPPORT
-      GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX);
-      if (SSL_CTX_set_alpn_protos(
-              ssl_context, impl->alpn_protocol_list,
-              (unsigned int)impl->alpn_protocol_list_length)) {
-        gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
-        result = TSI_INVALID_ARGUMENT;
-        break;
-      }
-#endif /* TSI_OPENSSL_ALPN_SUPPORT */
-      SSL_CTX_set_next_proto_select_cb(
-          ssl_context, client_handshaker_factory_npn_callback, impl);
-    }
-  } while (0);
-  if (result != TSI_OK) {
-    ssl_client_handshaker_factory_destroy(&impl->base);
-    return result;
-  }
-  SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
-  /* TODO(jboeuf): Add revocation verification. */
-
-  impl->base.create_handshaker =
-      ssl_client_handshaker_factory_create_handshaker;
-  impl->base.destroy = ssl_client_handshaker_factory_destroy;
-  *factory = &impl->base;
-  return TSI_OK;
-}
-
-tsi_result tsi_create_ssl_server_handshaker_factory(
-    const unsigned char **pem_private_keys,
-    const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
-    const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
-    const unsigned char *pem_client_root_certs,
-    size_t pem_client_root_certs_size, int force_client_auth,
-    const char *cipher_list, const unsigned char **alpn_protocols,
-    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
-    tsi_ssl_handshaker_factory **factory) {
-  tsi_ssl_server_handshaker_factory *impl = NULL;
-  tsi_result result = TSI_OK;
-  size_t i = 0;
-
-  gpr_once_init(&init_openssl_once, init_openssl);
-
-  if (factory == NULL) return TSI_INVALID_ARGUMENT;
-  *factory = NULL;
-  if (key_cert_pair_count == 0 || pem_private_keys == NULL ||
-      pem_cert_chains == NULL) {
-    return TSI_INVALID_ARGUMENT;
-  }
-
-  impl = calloc(1, sizeof(tsi_ssl_server_handshaker_factory));
-  if (impl == NULL) return TSI_OUT_OF_RESOURCES;
-  impl->base.create_handshaker =
-      ssl_server_handshaker_factory_create_handshaker;
-  impl->base.destroy = ssl_server_handshaker_factory_destroy;
-  impl->ssl_contexts = calloc(key_cert_pair_count, sizeof(SSL_CTX *));
-  impl->ssl_context_x509_subject_names =
-      calloc(key_cert_pair_count, sizeof(tsi_peer));
-  if (impl->ssl_contexts == NULL ||
-      impl->ssl_context_x509_subject_names == NULL) {
-    tsi_ssl_handshaker_factory_destroy(&impl->base);
-    return TSI_OUT_OF_RESOURCES;
-  }
-  impl->ssl_context_count = key_cert_pair_count;
-
-  if (num_alpn_protocols > 0) {
-    result = build_alpn_protocol_name_list(
-        alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
-        &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
-    if (result != TSI_OK) {
-      tsi_ssl_handshaker_factory_destroy(&impl->base);
-      return result;
-    }
-  }
-
-  for (i = 0; i < key_cert_pair_count; i++) {
-    do {
-      impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
-      if (impl->ssl_contexts[i] == NULL) {
-        gpr_log(GPR_ERROR, "Could not create ssl context.");
-        result = TSI_OUT_OF_RESOURCES;
-        break;
-      }
-      result = populate_ssl_context(
-          impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i],
-          pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
-      if (result != TSI_OK) break;
-
-      if (pem_client_root_certs != NULL) {
-        int flags = SSL_VERIFY_PEER;
-        STACK_OF(X509_NAME) *root_names = NULL;
-        result = ssl_ctx_load_verification_certs(
-            impl->ssl_contexts[i], pem_client_root_certs,
-            pem_client_root_certs_size, &root_names);
-        if (result != TSI_OK) {
-          gpr_log(GPR_ERROR, "Invalid verification certs.");
-          break;
-        }
-        SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
-        if (force_client_auth) flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
-        SSL_CTX_set_verify(impl->ssl_contexts[i], flags, NULL);
-        /* TODO(jboeuf): Add revocation verification. */
-      }
-
-      result = extract_x509_subject_names_from_pem_cert(
-          pem_cert_chains[i], pem_cert_chains_sizes[i],
-          &impl->ssl_context_x509_subject_names[i]);
-      if (result != TSI_OK) break;
-
-      SSL_CTX_set_tlsext_servername_callback(
-          impl->ssl_contexts[i],
-          ssl_server_handshaker_factory_servername_callback);
-      SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl);
-#if TSI_OPENSSL_ALPN_SUPPORT
-      SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i],
-                                 server_handshaker_factory_alpn_callback, impl);
-#endif /* TSI_OPENSSL_ALPN_SUPPORT */
-      SSL_CTX_set_next_protos_advertised_cb(
-          impl->ssl_contexts[i],
-          server_handshaker_factory_npn_advertised_callback, impl);
-    } while (0);
-
-    if (result != TSI_OK) {
-      tsi_ssl_handshaker_factory_destroy(&impl->base);
-      return result;
-    }
-  }
-  *factory = &impl->base;
-  return TSI_OK;
-}
-
-/* --- tsi_ssl utils. --- */
-
-int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
-  size_t i = 0;
-  size_t san_count = 0;
-  const tsi_peer_property *cn_property = NULL;
-  int like_ip = looks_like_ip_address(name);
-
-  /* Check the SAN first. */
-  for (i = 0; i < peer->property_count; i++) {
-    const tsi_peer_property *property = &peer->properties[i];
-    if (property->name == NULL) continue;
-    if (strcmp(property->name,
-               TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
-      san_count++;
-
-      if (!like_ip && does_entry_match_name(property->value.data,
-                                            property->value.length, name)) {
-        return 1;
-      } else if (like_ip &&
-                 strncmp(name, property->value.data, property->value.length) ==
-                     0 &&
-                 strlen(name) == property->value.length) {
-        /* IP Addresses are exact matches only. */
-        return 1;
-      }
-    } else if (strcmp(property->name,
-                      TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
-      cn_property = property;
-    }
-  }
-
-  /* If there's no SAN, try the CN, but only if its not like an IP Address */
-  if (san_count == 0 && cn_property != NULL && !like_ip) {
-    if (does_entry_match_name(cn_property->value.data,
-                              cn_property->value.length, name)) {
-      return 1;
-    }
-  }
-
-  return 0; /* Not found. */
-}
diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h
deleted file mode 100644
index 612f5c6..0000000
--- a/src/core/tsi/ssl_transport_security.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H
-#define GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H
-
-#include "src/core/tsi/transport_security_interface.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for X509 certs. */
-#define TSI_X509_CERTIFICATE_TYPE "X509"
-
-/* This property is of type TSI_PEER_PROPERTY_STRING.  */
-#define TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY "x509_subject_common_name"
-#define TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY \
-  "x509_subject_alternative_name"
-
-#define TSI_X509_PEM_CERT_PROPERTY "x509_pem_cert"
-
-#define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol"
-
-/* --- tsi_ssl_handshaker_factory object ---
-
-   This object creates tsi_handshaker objects implemented in terms of the
-   TLS 1.2 specificiation.  */
-
-typedef struct tsi_ssl_handshaker_factory tsi_ssl_handshaker_factory;
-
-/* Creates a client handshaker factory.
-   - pem_private_key is the buffer containing the PEM encoding of the client's
-     private key. This parameter can be NULL if the client does not have a
-     private key.
-   - pem_private_key_size is the size of the associated buffer.
-   - pem_cert_chain is the buffer containing the PEM encoding of the client's
-     certificate chain. This parameter can be NULL if the client does not have
-     a certificate chain.
-   - pem_cert_chain_size is the size of the associated buffer.
-   - pem_roots_cert is the buffer containing the PEM encoding of the server
-     root certificates. This parameter cannot be NULL.
-   - pem_roots_cert_size is the size of the associated buffer.
-   - cipher_suites contains an optional list of the ciphers that the client
-     supports. The format of this string is described in:
-     https://www.openssl.org/docs/apps/ciphers.html.
-     This parameter can be set to NULL to use the default set of ciphers.
-     TODO(jboeuf): Revisit the format of this parameter.
-   - alpn_protocols is an array containing the protocol names that the
-     handshakers created with this factory support. This parameter can be NULL.
-   - alpn_protocols_lengths is an array containing the lengths of the alpn
-     protocols specified in alpn_protocols. This parameter can be NULL.
-   - num_alpn_protocols is the number of alpn protocols and associated lengths
-     specified. If this parameter is 0, the other alpn parameters must be NULL.
-   - factory is the address of the factory pointer to be created.
-
-   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
-     where a parameter is invalid.  */
-tsi_result tsi_create_ssl_client_handshaker_factory(
-    const unsigned char *pem_private_key, size_t pem_private_key_size,
-    const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
-    const unsigned char *pem_root_certs, size_t pem_root_certs_size,
-    const char *cipher_suites, const unsigned char **alpn_protocols,
-    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
-    tsi_ssl_handshaker_factory **factory);
-
-/* Creates a server handshaker factory.
-   - version indicates which version of the specification to use.
-   - pem_private_keys is an array containing the PEM encoding of the server's
-     private keys.  This parameter cannot be NULL. The size of the array is
-     given by the key_cert_pair_count parameter.
-   - pem_private_keys_sizes is the array containing the sizes of the associated
-     buffers.
-   - pem_cert_chains is an array containing the PEM encoding of the server's
-     cert chains.  This parameter cannot be NULL. The size of the array is
-     given by the key_cert_pair_count parameter.
-   - pem_cert_chains_sizes is the array containing the sizes of the associated
-     buffers.
-   - key_cert_pair_count indicates the number of items in the private_key_files
-     and cert_chain_files parameters.
-   - pem_client_roots is the buffer containing the PEM encoding of the client
-     root certificates. This parameter may be NULL in which case the server will
-     not authenticate the client. If not NULL, the force_client_auth parameter
-     specifies if the server will accept only authenticated clients or both
-     authenticated and non-authenticated clients.
-   - pem_client_root_certs_size is the size of the associated buffer.
-   - force_client_auth, if set to non-zero will force the client to authenticate
-     with an SSL cert. Note that this option is ignored if pem_client_root_certs
-     is NULL or pem_client_roots_certs_size is 0
-   - cipher_suites contains an optional list of the ciphers that the server
-     supports. The format of this string is described in:
-     https://www.openssl.org/docs/apps/ciphers.html.
-     This parameter can be set to NULL to use the default set of ciphers.
-     TODO(jboeuf): Revisit the format of this parameter.
-   - alpn_protocols is an array containing the protocol names that the
-     handshakers created with this factory support. This parameter can be NULL.
-   - alpn_protocols_lengths is an array containing the lengths of the alpn
-     protocols specified in alpn_protocols. This parameter can be NULL.
-   - num_alpn_protocols is the number of alpn protocols and associated lengths
-     specified. If this parameter is 0, the other alpn parameters must be NULL.
-   - factory is the address of the factory pointer to be created.
-
-   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
-     where a parameter is invalid.  */
-tsi_result tsi_create_ssl_server_handshaker_factory(
-    const unsigned char **pem_private_keys,
-    const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
-    const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
-    const unsigned char *pem_client_root_certs,
-    size_t pem_client_root_certs_size, int force_client_auth,
-    const char *cipher_suites, const unsigned char **alpn_protocols,
-    const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
-    tsi_ssl_handshaker_factory **factory);
-
-/* Creates a handshaker.
-  - self is the factory from which the handshaker will be created.
-  - server_name_indication indicates the name of the server the client is
-    trying to connect to which will be relayed to the server using the SNI
-    extension.
-    This parameter must be NULL for a server handshaker factory.
-  - handhshaker is the address of the handshaker pointer to be created.
-
-  - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
-    where a parameter is invalid.  */
-tsi_result tsi_ssl_handshaker_factory_create_handshaker(
-    tsi_ssl_handshaker_factory *self, const char *server_name_indication,
-    tsi_handshaker **handshaker);
-
-/* Destroys the handshaker factory. WARNING: it is unsafe to destroy a factory
-   while handshakers created with this factory are still in use.  */
-void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self);
-
-/* Util that checks that an ssl peer matches a specific name.
-   Still TODO(jboeuf):
-   - handle mixed case.
-   - handle %encoded chars.
-   - handle public suffix wildchar more strictly (e.g. *.co.uk) */
-int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H */
diff --git a/src/core/tsi/ssl_types.h b/src/core/tsi/ssl_types.h
deleted file mode 100644
index 6ea85fe..0000000
--- a/src/core/tsi/ssl_types.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TSI_SSL_TYPES_H
-#define GRPC_CORE_TSI_SSL_TYPES_H
-
-/* A collection of macros to cast between various integer types that are
- * used differently between BoringSSL and OpenSSL:
- * TSI_INT_AS_SIZE(x):  convert 'int x' to a length parameter for an OpenSSL
- *                      function
- * TSI_SIZE_AS_SIZE(x): convert 'size_t x' to a length parameter for an OpenSSL
- *                      function
- */
-
-#include <openssl/ssl.h>
-
-#ifdef OPENSSL_IS_BORINGSSL
-#define TSI_INT_AS_SIZE(x) ((size_t)(x))
-#define TSI_SIZE_AS_SIZE(x) (x)
-#else
-#define TSI_INT_AS_SIZE(x) (x)
-#define TSI_SIZE_AS_SIZE(x) ((int)(x))
-#endif
-
-#endif /* GRPC_CORE_TSI_SSL_TYPES_H */
diff --git a/src/core/tsi/transport_security.c b/src/core/tsi/transport_security.c
deleted file mode 100644
index db219a5..0000000
--- a/src/core/tsi/transport_security.c
+++ /dev/null
@@ -1,284 +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/tsi/transport_security.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/* --- Tracing. --- */
-
-int tsi_tracing_enabled = 0;
-
-/* --- Utils. --- */
-
-char *tsi_strdup(const char *src) {
-  char *dst;
-  size_t len;
-  if (!src) return NULL;
-  len = strlen(src) + 1;
-  dst = malloc(len);
-  if (!dst) return NULL;
-  memcpy(dst, src, len);
-  return dst;
-}
-
-/* --- tsi_result common implementation. --- */
-
-const char *tsi_result_to_string(tsi_result result) {
-  switch (result) {
-    case TSI_OK:
-      return "TSI_OK";
-    case TSI_UNKNOWN_ERROR:
-      return "TSI_UNKNOWN_ERROR";
-    case TSI_INVALID_ARGUMENT:
-      return "TSI_INVALID_ARGUMENT";
-    case TSI_PERMISSION_DENIED:
-      return "TSI_PERMISSION_DENIED";
-    case TSI_INCOMPLETE_DATA:
-      return "TSI_INCOMPLETE_DATA";
-    case TSI_FAILED_PRECONDITION:
-      return "TSI_FAILED_PRECONDITION";
-    case TSI_UNIMPLEMENTED:
-      return "TSI_UNIMPLEMENTED";
-    case TSI_INTERNAL_ERROR:
-      return "TSI_INTERNAL_ERROR";
-    case TSI_DATA_CORRUPTED:
-      return "TSI_DATA_CORRUPTED";
-    case TSI_NOT_FOUND:
-      return "TSI_NOT_FOUND";
-    case TSI_PROTOCOL_FAILURE:
-      return "TSI_PROTOCOL_FAILURE";
-    case TSI_HANDSHAKE_IN_PROGRESS:
-      return "TSI_HANDSHAKE_IN_PROGRESS";
-    case TSI_OUT_OF_RESOURCES:
-      return "TSI_OUT_OF_RESOURCES";
-    default:
-      return "UNKNOWN";
-  }
-}
-
-/* --- tsi_frame_protector common implementation. ---
-
-   Calls specific implementation after state/input validation. */
-
-tsi_result tsi_frame_protector_protect(tsi_frame_protector *self,
-                                       const unsigned char *unprotected_bytes,
-                                       size_t *unprotected_bytes_size,
-                                       unsigned char *protected_output_frames,
-                                       size_t *protected_output_frames_size) {
-  if (self == NULL || unprotected_bytes == NULL ||
-      unprotected_bytes_size == NULL || protected_output_frames == NULL ||
-      protected_output_frames_size == NULL) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  return self->vtable->protect(self, unprotected_bytes, unprotected_bytes_size,
-                               protected_output_frames,
-                               protected_output_frames_size);
-}
-
-tsi_result tsi_frame_protector_protect_flush(
-    tsi_frame_protector *self, unsigned char *protected_output_frames,
-    size_t *protected_output_frames_size, size_t *still_pending_size) {
-  if (self == NULL || protected_output_frames == NULL ||
-      protected_output_frames == NULL || still_pending_size == NULL) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  return self->vtable->protect_flush(self, protected_output_frames,
-                                     protected_output_frames_size,
-                                     still_pending_size);
-}
-
-tsi_result tsi_frame_protector_unprotect(
-    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
-    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
-    size_t *unprotected_bytes_size) {
-  if (self == NULL || protected_frames_bytes == NULL ||
-      protected_frames_bytes_size == NULL || unprotected_bytes == NULL ||
-      unprotected_bytes_size == NULL) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  return self->vtable->unprotect(self, protected_frames_bytes,
-                                 protected_frames_bytes_size, unprotected_bytes,
-                                 unprotected_bytes_size);
-}
-
-void tsi_frame_protector_destroy(tsi_frame_protector *self) {
-  if (self == NULL) return;
-  self->vtable->destroy(self);
-}
-
-/* --- tsi_handshaker common implementation. ---
-
-   Calls specific implementation after state/input validation. */
-
-tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
-                                                    unsigned char *bytes,
-                                                    size_t *bytes_size) {
-  if (self == NULL || bytes == NULL || bytes_size == NULL) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
-  return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size);
-}
-
-tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self,
-                                                  const unsigned char *bytes,
-                                                  size_t *bytes_size) {
-  if (self == NULL || bytes == NULL || bytes_size == NULL) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
-  return self->vtable->process_bytes_from_peer(self, bytes, bytes_size);
-}
-
-tsi_result tsi_handshaker_get_result(tsi_handshaker *self) {
-  if (self == NULL) return TSI_INVALID_ARGUMENT;
-  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
-  return self->vtable->get_result(self);
-}
-
-tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) {
-  if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT;
-  memset(peer, 0, sizeof(tsi_peer));
-  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
-  if (tsi_handshaker_get_result(self) != TSI_OK) {
-    return TSI_FAILED_PRECONDITION;
-  }
-  return self->vtable->extract_peer(self, peer);
-}
-
-tsi_result tsi_handshaker_create_frame_protector(
-    tsi_handshaker *self, size_t *max_protected_frame_size,
-    tsi_frame_protector **protector) {
-  tsi_result result;
-  if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT;
-  if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
-  if (tsi_handshaker_get_result(self) != TSI_OK) {
-    return TSI_FAILED_PRECONDITION;
-  }
-  result = self->vtable->create_frame_protector(self, max_protected_frame_size,
-                                                protector);
-  if (result == TSI_OK) {
-    self->frame_protector_created = 1;
-  }
-  return result;
-}
-
-void tsi_handshaker_destroy(tsi_handshaker *self) {
-  if (self == NULL) return;
-  self->vtable->destroy(self);
-}
-
-/* --- tsi_peer implementation. --- */
-
-tsi_peer_property tsi_init_peer_property(void) {
-  tsi_peer_property property;
-  memset(&property, 0, sizeof(tsi_peer_property));
-  return property;
-}
-
-static void tsi_peer_destroy_list_property(tsi_peer_property *children,
-                                           size_t child_count) {
-  size_t i;
-  for (i = 0; i < child_count; i++) {
-    tsi_peer_property_destruct(&children[i]);
-  }
-  free(children);
-}
-
-void tsi_peer_property_destruct(tsi_peer_property *property) {
-  if (property->name != NULL) {
-    free(property->name);
-  }
-  if (property->value.data != NULL) {
-    free(property->value.data);
-  }
-  *property = tsi_init_peer_property(); /* Reset everything to 0. */
-}
-
-void tsi_peer_destruct(tsi_peer *self) {
-  if (self == NULL) return;
-  if (self->properties != NULL) {
-    tsi_peer_destroy_list_property(self->properties, self->property_count);
-    self->properties = NULL;
-  }
-  self->property_count = 0;
-}
-
-tsi_result tsi_construct_allocated_string_peer_property(
-    const char *name, size_t value_length, tsi_peer_property *property) {
-  *property = tsi_init_peer_property();
-  if (name != NULL) {
-    property->name = tsi_strdup(name);
-    if (property->name == NULL) return TSI_OUT_OF_RESOURCES;
-  }
-  if (value_length > 0) {
-    property->value.data = calloc(1, value_length);
-    if (property->value.data == NULL) {
-      tsi_peer_property_destruct(property);
-      return TSI_OUT_OF_RESOURCES;
-    }
-    property->value.length = value_length;
-  }
-  return TSI_OK;
-}
-
-tsi_result tsi_construct_string_peer_property_from_cstring(
-    const char *name, const char *value, tsi_peer_property *property) {
-  return tsi_construct_string_peer_property(name, value, strlen(value),
-                                            property);
-}
-
-tsi_result tsi_construct_string_peer_property(const char *name,
-                                              const char *value,
-                                              size_t value_length,
-                                              tsi_peer_property *property) {
-  tsi_result result = tsi_construct_allocated_string_peer_property(
-      name, value_length, property);
-  if (result != TSI_OK) return result;
-  if (value_length > 0) {
-    memcpy(property->value.data, value, value_length);
-  }
-  return TSI_OK;
-}
-
-tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer) {
-  memset(peer, 0, sizeof(tsi_peer));
-  if (property_count > 0) {
-    peer->properties = calloc(property_count, sizeof(tsi_peer_property));
-    if (peer->properties == NULL) return TSI_OUT_OF_RESOURCES;
-    peer->property_count = property_count;
-  }
-  return TSI_OK;
-}
diff --git a/src/core/tsi/transport_security.h b/src/core/tsi/transport_security.h
deleted file mode 100644
index ecc0371..0000000
--- a/src/core/tsi/transport_security.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_H
-#define GRPC_CORE_TSI_TRANSPORT_SECURITY_H
-
-#include "src/core/tsi/transport_security_interface.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int tsi_tracing_enabled;
-
-/* Base for tsi_frame_protector implementations.
-   See transport_security_interface.h for documentation. */
-typedef struct {
-  tsi_result (*protect)(tsi_frame_protector *self,
-                        const unsigned char *unprotected_bytes,
-                        size_t *unprotected_bytes_size,
-                        unsigned char *protected_output_frames,
-                        size_t *protected_output_frames_size);
-  tsi_result (*protect_flush)(tsi_frame_protector *self,
-                              unsigned char *protected_output_frames,
-                              size_t *protected_output_frames_size,
-                              size_t *still_pending_size);
-  tsi_result (*unprotect)(tsi_frame_protector *self,
-                          const unsigned char *protected_frames_bytes,
-                          size_t *protected_frames_bytes_size,
-                          unsigned char *unprotected_bytes,
-                          size_t *unprotected_bytes_size);
-  void (*destroy)(tsi_frame_protector *self);
-} tsi_frame_protector_vtable;
-
-struct tsi_frame_protector {
-  const tsi_frame_protector_vtable *vtable;
-};
-
-/* Base for tsi_handshaker implementations.
-   See transport_security_interface.h for documentation. */
-typedef struct {
-  tsi_result (*get_bytes_to_send_to_peer)(tsi_handshaker *self,
-                                          unsigned char *bytes,
-                                          size_t *bytes_size);
-  tsi_result (*process_bytes_from_peer)(tsi_handshaker *self,
-                                        const unsigned char *bytes,
-                                        size_t *bytes_size);
-  tsi_result (*get_result)(tsi_handshaker *self);
-  tsi_result (*extract_peer)(tsi_handshaker *self, tsi_peer *peer);
-  tsi_result (*create_frame_protector)(tsi_handshaker *self,
-                                       size_t *max_protected_frame_size,
-                                       tsi_frame_protector **protector);
-  void (*destroy)(tsi_handshaker *self);
-} tsi_handshaker_vtable;
-
-struct tsi_handshaker {
-  const tsi_handshaker_vtable *vtable;
-  int frame_protector_created;
-};
-
-/* Peer and property construction/destruction functions. */
-tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer);
-tsi_peer_property tsi_init_peer_property(void);
-void tsi_peer_property_destruct(tsi_peer_property *property);
-tsi_result tsi_construct_string_peer_property(const char *name,
-                                              const char *value,
-                                              size_t value_length,
-                                              tsi_peer_property *property);
-tsi_result tsi_construct_allocated_string_peer_property(
-    const char *name, size_t value_length, tsi_peer_property *property);
-tsi_result tsi_construct_string_peer_property_from_cstring(
-    const char *name, const char *value, tsi_peer_property *property);
-
-/* Utils. */
-char *tsi_strdup(const char *src); /* Sadly, no strdup in C89. */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_H */
diff --git a/src/core/tsi/transport_security_interface.h b/src/core/tsi/transport_security_interface.h
deleted file mode 100644
index 0850180..0000000
--- a/src/core/tsi/transport_security_interface.h
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H
-#define GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* --- tsi result ---  */
-
-typedef enum {
-  TSI_OK = 0,
-  TSI_UNKNOWN_ERROR = 1,
-  TSI_INVALID_ARGUMENT = 2,
-  TSI_PERMISSION_DENIED = 3,
-  TSI_INCOMPLETE_DATA = 4,
-  TSI_FAILED_PRECONDITION = 5,
-  TSI_UNIMPLEMENTED = 6,
-  TSI_INTERNAL_ERROR = 7,
-  TSI_DATA_CORRUPTED = 8,
-  TSI_NOT_FOUND = 9,
-  TSI_PROTOCOL_FAILURE = 10,
-  TSI_HANDSHAKE_IN_PROGRESS = 11,
-  TSI_OUT_OF_RESOURCES = 12
-} tsi_result;
-
-const char *tsi_result_to_string(tsi_result result);
-
-/* --- tsi tracing --- */
-
-/* Set this early to avoid races */
-extern int tsi_tracing_enabled;
-
-/* --- tsi_frame_protector object ---
-
-  This object protects and unprotects buffers once the handshake is done.
-  Implementations of this object must be thread compatible.  */
-
-typedef struct tsi_frame_protector tsi_frame_protector;
-
-/* Outputs protected frames.
-   - unprotected_bytes is an input only parameter and points to the data
-     to be protected.
-   - unprotected_bytes_size is an input/output parameter used by the caller to
-     specify how many bytes are available in unprotected_bytes. The output
-     value is the number of bytes consumed during the call.
-   - protected_output_frames points to a buffer allocated by the caller that
-     will be written.
-   - protected_output_frames_size is an input/output parameter used by the
-     caller to specify how many bytes are available in protected_output_frames.
-     As an output, this value indicates the number of bytes written.
-   - This method returns TSI_OK in case of success or a specific error code in
-     case of failure. Note that even if all the input unprotected bytes are
-     consumed, they may not have been processed into the returned protected
-     output frames. The caller should call the protect_flush method
-     to make sure that there are no more protected bytes buffered in the
-     protector.
-
-   A typical way to call this method would be:
-
-   ------------------------------------------------------------------------
-   unsigned char protected_buffer[4096];
-   size_t protected_buffer_size = sizeof(protected_buffer);
-   tsi_result result = TSI_OK;
-   while (message_size > 0) {
-     size_t protected_buffer_size_to_send = protected_buffer_size;
-     size_t processed_message_size = message_size;
-     result = tsi_frame_protector_protect(protector,
-                                          message_bytes,
-                                          &processed_message_size,
-                                          protected_buffer,
-                                          &protected_buffer_size_to_send);
-     if (result != TSI_OK) break;
-     send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
-     message_bytes += processed_message_size;
-     message_size -= processed_message_size;
-
-     // Don't forget to flush.
-     if (message_size == 0) {
-       size_t still_pending_size;
-       do {
-         protected_buffer_size_to_send = protected_buffer_size;
-         result = tsi_frame_protector_protect_flush(
-             protector, protected_buffer,
-             &protected_buffer_size_to_send, &still_pending_size);
-         if (result != TSI_OK) break;
-         send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send);
-       } while (still_pending_size > 0);
-     }
-   }
-
-   if (result != TSI_OK) HandleError(result);
-   ------------------------------------------------------------------------  */
-tsi_result tsi_frame_protector_protect(tsi_frame_protector *self,
-                                       const unsigned char *unprotected_bytes,
-                                       size_t *unprotected_bytes_size,
-                                       unsigned char *protected_output_frames,
-                                       size_t *protected_output_frames_size);
-
-/* Indicates that we need to flush the bytes buffered in the protector and get
-   the resulting frame.
-   - protected_output_frames points to a buffer allocated by the caller that
-     will be written.
-   - protected_output_frames_size is an input/output parameter used by the
-     caller to specify how many bytes are available in protected_output_frames.
-   - still_pending_bytes is an output parameter indicating the number of bytes
-     that still need to be flushed from the protector.*/
-tsi_result tsi_frame_protector_protect_flush(
-    tsi_frame_protector *self, unsigned char *protected_output_frames,
-    size_t *protected_output_frames_size, size_t *still_pending_size);
-
-/* Outputs unprotected bytes.
-   - protected_frames_bytes is an input only parameter and points to the
-     protected frames to be unprotected.
-   - protected_frames_bytes_size is an input/output only parameter used by the
-     caller to specify how many bytes are available in protected_bytes. The
-     output value is the number of bytes consumed during the call.
-     Implementations will buffer up to a frame of protected data.
-   - unprotected_bytes points to a buffer allocated by the caller that will be
-     written.
-   - unprotected_bytes_size is an input/output parameter used by the caller to
-     specify how many bytes are available in unprotected_bytes. This
-     value is expected to be at most max_protected_frame_size minus overhead
-     which means that max_protected_frame_size is a safe bet. The output value
-     is the number of bytes actually written.
-     If *unprotected_bytes_size is unchanged, there may be more data remaining
-     to unprotect, and the caller should call this function again.
-
-   - This method returns TSI_OK in case of success. Success includes cases where
-     there is not enough data to output a frame in which case
-     unprotected_bytes_size will be set to 0 and cases where the internal buffer
-     needs to be read before new protected data can be processed in which case
-     protected_frames_size will be set to 0.  */
-tsi_result tsi_frame_protector_unprotect(
-    tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
-    size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
-    size_t *unprotected_bytes_size);
-
-/* Destroys the tsi_frame_protector object.  */
-void tsi_frame_protector_destroy(tsi_frame_protector *self);
-
-/* --- tsi_peer objects ---
-
-   tsi_peer objects are a set of properties. The peer owns the properties.  */
-
-/* This property is of type TSI_PEER_PROPERTY_STRING.  */
-#define TSI_CERTIFICATE_TYPE_PEER_PROPERTY "certificate_type"
-
-/* Property values may contain NULL characters just like C++ strings.
-   The length field gives the length of the string. */
-typedef struct tsi_peer_property {
-  char *name;
-  struct {
-    char *data;
-    size_t length;
-  } value;
-} tsi_peer_property;
-
-typedef struct {
-  tsi_peer_property *properties;
-  size_t property_count;
-} tsi_peer;
-
-/* Destructs the tsi_peer object. */
-void tsi_peer_destruct(tsi_peer *self);
-
-/* --- tsi_handshaker objects ----
-
-   Implementations of this object must be thread compatible.
-
-   A typical usage of this object would be:
-
-   ------------------------------------------------------------------------
-   tsi_result result = TSI_OK;
-   unsigned char buf[4096];
-   size_t buf_offset;
-   size_t buf_size;
-   while (1) {
-     // See if we need to send some bytes to the peer.
-     do {
-       size_t buf_size_to_send = sizeof(buf);
-       result = tsi_handshaker_get_bytes_to_send_to_peer(handshaker, buf,
-                                                         &buf_size_to_send);
-       if (buf_size_to_send > 0) send_bytes_to_peer(buf, buf_size_to_send);
-     } while (result == TSI_INCOMPLETE_DATA);
-     if (result != TSI_OK) return result;
-     if (!tsi_handshaker_is_in_progress(handshaker)) break;
-
-     do {
-       // Read bytes from the peer.
-       buf_size = sizeof(buf);
-       buf_offset = 0;
-       read_bytes_from_peer(buf, &buf_size);
-       if (buf_size == 0) break;
-
-       // Process the bytes from the peer. We have to be careful as these bytes
-       // may contain non-handshake data (protected data). If this is the case,
-       // we will exit from the loop with buf_size > 0.
-       size_t consumed_by_handshaker = buf_size;
-       result = tsi_handshaker_process_bytes_from_peer(
-           handshaker, buf, &consumed_by_handshaker);
-       buf_size -= consumed_by_handshaker;
-       buf_offset += consumed_by_handshaker;
-     } while (result == TSI_INCOMPLETE_DATA);
-
-     if (result != TSI_OK) return result;
-     if (!tsi_handshaker_is_in_progress(handshaker)) break;
-   }
-
-   // Check the Peer.
-   tsi_peer peer;
-   do {
-     result = tsi_handshaker_extract_peer(handshaker, &peer);
-     if (result != TSI_OK) break;
-     result = check_peer(&peer);
-   } while (0);
-   tsi_peer_destruct(&peer);
-   if (result != TSI_OK) return result;
-
-   // Create the protector.
-   tsi_frame_protector* protector = NULL;
-   result = tsi_handshaker_create_frame_protector(handshaker, NULL,
-                                                  &protector);
-   if (result != TSI_OK) return result;
-
-   // Do not forget to unprotect outstanding data if any.
-   if (buf_size > 0) {
-     result = tsi_frame_protector_unprotect(protector, buf + buf_offset,
-                                            buf_size, ..., ...);
-     ....
-   }
-   ...
-   ------------------------------------------------------------------------   */
-typedef struct tsi_handshaker tsi_handshaker;
-
-/* Gets bytes that need to be sent to the peer.
-   - bytes is the buffer that will be written with the data to be sent to the
-     peer.
-   - bytes_size is an input/output parameter specifying the capacity of the
-     bytes parameter as input and the number of bytes written as output.
-   Returns TSI_OK if all the data to send to the peer has been written or if
-   nothing has to be sent to the peer (in which base bytes_size outputs to 0),
-   otherwise returns TSI_INCOMPLETE_DATA which indicates that this method
-   needs to be called again to get all the bytes to send to the peer (there
-   was more data to write than the specified bytes_size). In case of a fatal
-   error in the handshake, another specific error code is returned.  */
-tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
-                                                    unsigned char *bytes,
-                                                    size_t *bytes_size);
-
-/* Processes bytes received from the peer.
-   - bytes is the buffer containing the data.
-   - bytes_size is an input/output parameter specifying the size of the data as
-     input and the number of bytes consumed as output.
-   Return TSI_OK if the handshake has all the data it needs to process,
-   otherwise return TSI_INCOMPLETE_DATA which indicates that this method
-   needs to be called again to complete the data needed for processing. In
-   case of a fatal error in the handshake, another specific error code is
-   returned.  */
-tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self,
-                                                  const unsigned char *bytes,
-                                                  size_t *bytes_size);
-
-/* Gets the result of the handshaker.
-   Returns TSI_OK if the hanshake completed successfully and there has been no
-   errors. Returns TSI_HANDSHAKE_IN_PROGRESS if the handshaker is not done yet
-   but no error has been encountered so far. Otherwise the handshaker failed
-   with the returned error.  */
-tsi_result tsi_handshaker_get_result(tsi_handshaker *self);
-
-/* Returns 1 if the handshake is in progress, 0 otherwise.  */
-#define tsi_handshaker_is_in_progress(h) \
-  (tsi_handshaker_get_result((h)) == TSI_HANDSHAKE_IN_PROGRESS)
-
-/* This method may return TSI_FAILED_PRECONDITION if
-   tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise
-   assuming the handshaker is not in a fatal error state.
-   The caller is responsible for destructing the peer.  */
-tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer);
-
-/* This method creates a tsi_frame_protector object after the handshake phase
-   is done. After this method has been called successfully, the only method
-   that can be called on this object is Destroy.
-   - max_output_protected_frame_size is an input/output parameter specifying the
-     desired max output protected frame size as input and outputing the actual
-     max output frame size as the output. Passing NULL is OK and will result in
-     the implementation choosing the default maximum protected frame size. Note
-     that this size only applies to outgoing frames (generated with
-     tsi_frame_protector_protect) and not incoming frames (input of
-     tsi_frame_protector_unprotect).
-   - protector is an output parameter pointing to the newly created
-     tsi_frame_protector object.
-   This method may return TSI_FAILED_PRECONDITION if
-   tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming
-   the handshaker is not in a fatal error state.
-   The caller is responsible for destroying the protector.  */
-tsi_result tsi_handshaker_create_frame_protector(
-    tsi_handshaker *self, size_t *max_output_protected_frame_size,
-    tsi_frame_protector **protector);
-
-/* This method releases the tsi_handshaker object. After this method is called,
-   no other method can be called on the object.  */
-void tsi_handshaker_destroy(tsi_handshaker *self);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H */
diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc
index ae20392..43b3875 100644
--- a/src/cpp/client/channel.cc
+++ b/src/cpp/client/channel.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,7 @@
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
-#include "src/core/profiling/timers.h"
+#include "src/core/lib/profiling/timers.h"
 
 namespace grpc {
 
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index 73147fd..32c7794 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,16 +33,15 @@
 
 #include <grpc++/client_context.h>
 
+#include <grpc++/security/credentials.h>
+#include <grpc++/server_context.h>
+#include <grpc++/support/time.h>
 #include <grpc/compression.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
-#include <grpc++/security/credentials.h>
-#include <grpc++/server_context.h>
-#include <grpc++/support/time.h>
 
-#include "src/core/channel/compress_filter.h"
-#include "src/cpp/common/create_auth_context.h"
+#include "src/core/lib/channel/compress_filter.h"
 
 namespace grpc {
 
@@ -60,6 +59,8 @@
 
 ClientContext::ClientContext()
     : initial_metadata_received_(false),
+      fail_fast_(true),
+      idempotent_(false),
       call_(nullptr),
       call_canceled_(false),
       deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
@@ -114,13 +115,6 @@
   AddMetadata(GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, algorithm_name);
 }
 
-std::shared_ptr<const AuthContext> ClientContext::auth_context() const {
-  if (auth_context_.get() == nullptr) {
-    auth_context_ = CreateAuthContext(call_);
-  }
-  return auth_context_;
-}
-
 void ClientContext::TryCancel() {
   grpc::unique_lock<grpc::mutex> lock(mu_);
   if (call_) {
diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc
index 76a1b31..d0cc33b 100644
--- a/src/cpp/client/create_channel.cc
+++ b/src/cpp/client/create_channel.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc
index 6fb620b..e6a4f81 100644
--- a/src/cpp/client/credentials.cc
+++ b/src/cpp/client/credentials.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc
index 1293203..13019a7 100644
--- a/src/cpp/client/insecure_credentials.cc
+++ b/src/cpp/client/insecure_credentials.cc
@@ -33,11 +33,11 @@
 
 #include <grpc++/security/credentials.h>
 
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
 #include <grpc++/channel.h>
 #include <grpc++/support/channel_arguments.h>
 #include <grpc++/support/config.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
 #include "src/cpp/client/create_channel_internal.h"
 
 namespace grpc {
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index c34b840..269c523 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,12 +31,12 @@
  *
  */
 
+#include "src/cpp/client/secure_credentials.h"
 #include <grpc++/channel.h>
 #include <grpc++/impl/grpc_library.h>
 #include <grpc++/support/channel_arguments.h>
 #include <grpc/support/log.h>
 #include "src/cpp/client/create_channel_internal.h"
-#include "src/cpp/client/secure_credentials.h"
 #include "src/cpp/common/secure_auth_context.h"
 
 namespace grpc {
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index 9e84102..ae41ef8 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,8 +36,8 @@
 
 #include <grpc/grpc_security.h>
 
-#include <grpc++/support/config.h>
 #include <grpc++/security/credentials.h>
+#include <grpc++/support/config.h>
 
 #include "src/cpp/server/thread_pool_interface.h"
 
diff --git a/src/cpp/common/channel_arguments.cc b/src/cpp/common/channel_arguments.cc
index d7faa5e..db3558f 100644
--- a/src/cpp/common/channel_arguments.cc
+++ b/src/cpp/common/channel_arguments.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@
 
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/support/log.h>
-#include "src/core/channel/channel_args.h"
+#include "src/core/lib/channel/channel_args.h"
 
 namespace grpc {
 
diff --git a/src/cpp/common/completion_queue.cc b/src/cpp/common/completion_queue.cc
index 729dc33..00cc102 100644
--- a/src/cpp/common/completion_queue.cc
+++ b/src/cpp/common/completion_queue.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc
index 45e9e27..33a8f75 100644
--- a/src/cpp/common/core_codegen.cc
+++ b/src/cpp/common/core_codegen.cc
@@ -46,7 +46,7 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/slice_buffer.h>
 
-#include "src/core/profiling/timers.h"
+#include "src/core/lib/profiling/timers.h"
 
 namespace {
 
diff --git a/src/cpp/common/core_codegen.h b/src/cpp/common/core_codegen.h
index 0d8c6b7..e15cb4c 100644
--- a/src/cpp/common/core_codegen.h
+++ b/src/cpp/common/core_codegen.h
@@ -34,8 +34,8 @@
 // This file should be compiled as part of grpc++.
 
 #include <grpc++/impl/codegen/core_codegen_interface.h>
-#include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/byte_buffer.h>
+#include <grpc/impl/codegen/grpc_types.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/create_auth_context.h b/src/cpp/common/create_auth_context.h
deleted file mode 100644
index 4f3da39..0000000
--- a/src/cpp/common/create_auth_context.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.
- *
- */
-#include <memory>
-
-#include <grpc/grpc.h>
-#include <grpc++/security/auth_context.h>
-
-namespace grpc {
-
-std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
-
-}  // namespace grpc
diff --git a/src/cpp/common/insecure_create_auth_context.cc b/src/cpp/common/insecure_create_auth_context.cc
index b2e1532..258f02c 100644
--- a/src/cpp/common/insecure_create_auth_context.cc
+++ b/src/cpp/common/insecure_create_auth_context.cc
@@ -32,8 +32,8 @@
  */
 #include <memory>
 
-#include <grpc/grpc.h>
 #include <grpc++/security/auth_context.h>
+#include <grpc/grpc.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/secure_channel_arguments.cc b/src/cpp/common/secure_channel_arguments.cc
index e17d3b5..81ec251 100644
--- a/src/cpp/common/secure_channel_arguments.cc
+++ b/src/cpp/common/secure_channel_arguments.cc
@@ -34,7 +34,7 @@
 #include <grpc++/support/channel_arguments.h>
 
 #include <grpc/grpc_security.h>
-#include "src/core/channel/channel_args.h"
+#include "src/core/lib/channel/channel_args.h"
 
 namespace grpc {
 
diff --git a/src/cpp/common/secure_create_auth_context.cc b/src/cpp/common/secure_create_auth_context.cc
index 40bc298..51ddea4 100644
--- a/src/cpp/common/secure_create_auth_context.cc
+++ b/src/cpp/common/secure_create_auth_context.cc
@@ -32,9 +32,9 @@
  */
 #include <memory>
 
+#include <grpc++/security/auth_context.h>
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
-#include <grpc++/security/auth_context.h>
 #include "src/cpp/common/secure_auth_context.h"
 
 namespace grpc {
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index d472667..33bdc2a 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -130,10 +130,14 @@
                                     key_cert_pair->cert_chain.c_str()};
     pem_key_cert_pairs.push_back(p);
   }
-  grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create(
+  grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create_ex(
       options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
       pem_key_cert_pairs.empty() ? nullptr : &pem_key_cert_pairs[0],
-      pem_key_cert_pairs.size(), options.force_client_auth, nullptr);
+      pem_key_cert_pairs.size(),
+      options.force_client_auth
+          ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+          : options.client_certificate_request,
+      nullptr);
   return std::shared_ptr<ServerCredentials>(
       new SecureServerCredentials(c_creds));
 }
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index 6d31a60..fafe31e 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/profiling/timers.h"
+#include "src/core/lib/profiling/timers.h"
 #include "src/cpp/server/thread_pool_interface.h"
 
 namespace grpc {
@@ -264,6 +264,7 @@
   void* const tag_;
   bool in_flight_;
   const bool has_request_payload_;
+  uint32_t incoming_flags_;
   grpc_call* call_;
   grpc_call_details* call_details_;
   gpr_timespec deadline_;
@@ -320,6 +321,19 @@
   g_callbacks.reset(callbacks);
 }
 
+static grpc_server_register_method_payload_handling PayloadHandlingForMethod(
+    RpcServiceMethod* method) {
+  switch (method->method_type()) {
+    case RpcMethod::NORMAL_RPC:
+    case RpcMethod::SERVER_STREAMING:
+      return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER;
+    case RpcMethod::CLIENT_STREAMING:
+    case RpcMethod::BIDI_STREAMING:
+      return GRPC_SRM_PAYLOAD_NONE;
+  }
+  GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;);
+}
+
 bool Server::RegisterService(const grpc::string* host, Service* service) {
   bool has_async_methods = service->has_async_methods();
   if (has_async_methods) {
@@ -333,8 +347,9 @@
       continue;
     }
     RpcServiceMethod* method = it->get();
-    void* tag = grpc_server_register_method(server_, method->name(),
-                                            host ? host->c_str() : nullptr);
+    void* tag = grpc_server_register_method(
+        server_, method->name(), host ? host->c_str() : nullptr,
+        PayloadHandlingForMethod(method), 0);
     if (tag == nullptr) {
       gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
               method->name());
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 134e5f1..68cc382 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,10 +33,10 @@
 
 #include <grpc++/server_builder.h>
 
-#include <grpc/support/cpu.h>
-#include <grpc/support/log.h>
 #include <grpc++/impl/service_type.h>
 #include <grpc++/server.h>
+#include <grpc/support/cpu.h>
+#include <grpc/support/log.h>
 #include "src/cpp/server/thread_pool_interface.h"
 
 namespace grpc {
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index 5d12ce2..204fef1 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,9 +42,8 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/channel/compress_filter.h"
-#include "src/core/surface/call.h"
-#include "src/cpp/common/create_auth_context.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/surface/call.h"
 
 namespace grpc {
 
@@ -214,18 +213,6 @@
   AddInitialMetadata(GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, algorithm_name);
 }
 
-void ServerContext::set_call(grpc_call* call) {
-  call_ = call;
-  auth_context_ = CreateAuthContext(call);
-}
-
-std::shared_ptr<const AuthContext> ServerContext::auth_context() const {
-  if (auth_context_.get() == nullptr) {
-    auth_context_ = CreateAuthContext(call_);
-  }
-  return auth_context_;
-}
-
 grpc::string ServerContext::peer() const {
   grpc::string peer;
   if (call_) {
diff --git a/src/cpp/util/byte_buffer.cc b/src/cpp/util/byte_buffer.cc
index 3a2318d..c0a14de 100644
--- a/src/cpp/util/byte_buffer.cc
+++ b/src/cpp/util/byte_buffer.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/cpp/util/string_ref.cc b/src/cpp/util/string_ref.cc
index b55019b..a16601d 100644
--- a/src/cpp/util/string_ref.cc
+++ b/src/cpp/util/string_ref.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/cpp/util/time.cc b/src/cpp/util/time.cc
index 2685e31..c43d848 100644
--- a/src/cpp/util/time.cc
+++ b/src/cpp/util/time.cc
@@ -35,8 +35,8 @@
 
 #ifndef GRPC_CXX0X_NO_CHRONO
 
-#include <grpc/support/time.h>
 #include <grpc++/support/time.h>
+#include <grpc/support/time.h>
 
 using std::chrono::duration_cast;
 using std::chrono::nanoseconds;
diff --git a/src/csharp/.nuget/packages.config b/src/csharp/.nuget/packages.config
index 89a310a..6154b35 100644
--- a/src/csharp/.nuget/packages.config
+++ b/src/csharp/.nuget/packages.config
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="NUnit.Runners" version="2.6.4" />
-  <package id="OpenCover" version="4.6.166" />
-  <package id="ReportGenerator" version="2.3.2.0" />
+  <package id="NUnit.ConsoleRunner" version="3.2.0" />
+  <package id="OpenCover" version="4.6.519" />
+  <package id="ReportGenerator" version="2.4.4.0" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs b/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs
index 1837f5c..96d6ee8 100644
--- a/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs
+++ b/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
index 8dd12b5..3acea7d 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
@@ -9,7 +9,7 @@
     <AssemblyName>Grpc.Auth</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <DocumentationFile>bin\$(Configuration)\Grpc.Auth.Xml</DocumentationFile>
-    <NuGetPackageImportStamp>4f8487a9</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>455903a2</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -39,43 +39,30 @@
     <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="Google.Apis.Auth, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.dll</HintPath>
+      <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Core, Version=1.10.0.25331, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Core.1.10.0\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+    </Reference>
+    <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Net" />
     <Reference Include="System.Net.Http" />
     <Reference Include="System.Net.Http.WebRequest" />
-    <Reference Include="BouncyCastle.Crypto">
-      <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
-    </Reference>
-    <Reference Include="Newtonsoft.Json">
-      <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Net.Http.Extensions">
-      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Net.Http.Primitives">
-      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
-    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="..\Grpc.Core\Version.cs">
@@ -93,15 +80,7 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <None Include="app.config" />
     <None Include="Grpc.Auth.nuspec" />
     <None Include="packages.config" />
   </ItemGroup>
-  <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.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\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
-  </Target>
 </Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
index f1f8f7c..4baed37 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
@@ -15,7 +15,7 @@
     <copyright>Copyright 2015, Google Inc.</copyright>
     <tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags>
 	<dependencies>
-	  <dependency id="Google.Apis.Auth" version="1.9.3" />
+	  <dependency id="Google.Apis.Auth" version="1.11.1" />
 	  <dependency id="Grpc.Core" version="$version$" />
     </dependencies>
   </metadata>
diff --git a/src/csharp/Grpc.Auth/app.config b/src/csharp/Grpc.Auth/app.config
deleted file mode 100644
index 84d7534..0000000
--- a/src/csharp/Grpc.Auth/app.config
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-</configuration>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Auth/packages.config b/src/csharp/Grpc.Auth/packages.config
index 5fe8ca6..c20d9ce 100644
--- a/src/csharp/Grpc.Auth/packages.config
+++ b/src/csharp/Grpc.Auth/packages.config
@@ -1,11 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
-  <package id="Google.Apis.Auth" version="1.10.0" targetFramework="net45" />
-  <package id="Google.Apis.Core" version="1.10.0" targetFramework="net45" />
-  <package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
-  <package id="Microsoft.Net.Http" version="2.2.29" 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="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
index a3a613b..99a2d47 100644
--- a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
+++ b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
@@ -54,10 +54,20 @@
             var deadline = DateTime.UtcNow;
             Assert.AreEqual(deadline, options.WithDeadline(deadline).Deadline.Value);
 
-            var token = new CancellationTokenSource().Token;
-            Assert.AreEqual(token, options.WithCancellationToken(token).CancellationToken);
+            var cancellationToken = new CancellationTokenSource().Token;
+            Assert.AreEqual(cancellationToken, options.WithCancellationToken(cancellationToken).CancellationToken);
 
-            // Change original instance is unchanged.
+            var writeOptions = new WriteOptions();
+            Assert.AreSame(writeOptions, options.WithWriteOptions(writeOptions).WriteOptions);
+
+            var propagationToken = new ContextPropagationToken(CallSafeHandle.NullInstance, DateTime.UtcNow, 
+                CancellationToken.None, ContextPropagationOptions.Default);
+            Assert.AreSame(propagationToken, options.WithPropagationToken(propagationToken).PropagationToken);
+
+            var credentials = new FakeCallCredentials();
+            Assert.AreSame(credentials, options.WithCredentials(credentials).Credentials);
+
+            // Check that the original instance is unchanged.
             Assert.IsNull(options.Headers);
             Assert.IsNull(options.Deadline);
             Assert.AreEqual(CancellationToken.None, options.CancellationToken);
diff --git a/src/csharp/Grpc.Core.Tests/ChannelTest.cs b/src/csharp/Grpc.Core.Tests/ChannelTest.cs
index ed0ec14..6330f50 100644
--- a/src/csharp/Grpc.Core.Tests/ChannelTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ChannelTest.cs
@@ -70,7 +70,7 @@
         public void WaitForStateChangedAsync_InvalidArgument()
         {
             var channel = new Channel("localhost", ChannelCredentials.Insecure);
-            Assert.Throws(typeof(ArgumentException), () => channel.WaitForStateChangedAsync(ChannelState.FatalFailure));
+            Assert.ThrowsAsync(typeof(ArgumentException), async () => await channel.WaitForStateChangedAsync(ChannelState.FatalFailure));
             channel.ShutdownAsync().Wait();
         }
 
@@ -87,7 +87,7 @@
         {
             var channel = new Channel("localhost", ChannelCredentials.Insecure);
             channel.ShutdownAsync().Wait();
-            Assert.Throws(typeof(InvalidOperationException), () => channel.ShutdownAsync().GetAwaiter().GetResult());
+            Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await channel.ShutdownAsync());
         }
     }
 }
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 77f6a63..6c13a4f 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -93,7 +93,7 @@
             var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
             Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); 
 
-            var ex2 = Assert.Throws<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
+            var ex2 = Assert.ThrowsAsync<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
             Assert.AreEqual(StatusCode.Unknown, ex2.Status.StatusCode);
         }
 
@@ -108,7 +108,7 @@
             var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
             Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode);
 
-            var ex2 = Assert.Throws<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
+            var ex2 = Assert.ThrowsAsync<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
             Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode);
         }
 
@@ -124,7 +124,7 @@
             var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
             Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode);
 
-            var ex2 = Assert.Throws<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
+            var ex2 = Assert.ThrowsAsync<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
             Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode);
         }
 
@@ -204,7 +204,7 @@
             await barrier.Task;  // make sure the handler has started.
             cts.Cancel();
 
-            var ex = Assert.Throws<RpcException>(async () => await call.ResponseAsync);
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseAsync);
             Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
         }
 
@@ -290,7 +290,7 @@
                 return request;
             });
 
-            Assert.Throws(typeof(TaskCanceledException), 
+            Assert.ThrowsAsync(typeof(TaskCanceledException), 
                 async () => await channel.WaitForStateChangedAsync(channel.State, DateTime.UtcNow.AddMilliseconds(10)));
 
             var stateChangedTask = channel.WaitForStateChangedAsync(channel.State);
diff --git a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
index 90c510e..cec8c7c 100644
--- a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
@@ -105,7 +105,7 @@
             var parentCall = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token)));
             await readyToCancelTcs.Task;
             cts.Cancel();
-            Assert.Throws(typeof(RpcException), async () => await parentCall);
+            Assert.ThrowsAsync(typeof(RpcException), async () => await parentCall);
             Assert.AreEqual("CHILD_CALL_CANCELLED", await successTcs.Task);
         }
 
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index 7e73c4f..0cd059c 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -4,7 +4,7 @@
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{86EC5CB4-4EA2-40A2-8057-86542A0353BB}</ProjectGuid>
-    <OutputType>Library</OutputType>
+    <OutputType>Exe</OutputType>
     <RootNamespace>Grpc.Core.Tests</RootNamespace>
     <AssemblyName>Grpc.Core.Tests</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
@@ -35,30 +35,19 @@
     <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="nunit.core">
-      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="nunit.core.interfaces">
-      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="nunit.framework">
-      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
-    </Reference>
-    <Reference Include="nunit.util">
-      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="NUnit.VisualStudio.TestAdapter">
-      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
     <Reference Include="System" />
-    <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="nunit.framework">
+      <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Interactive.Async">
       <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
     </Reference>
+    <Reference Include="nunitlite">
+      <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="..\Grpc.Core\Version.cs">
@@ -93,6 +82,8 @@
     <Compile Include="MetadataTest.cs" />
     <Compile Include="PerformanceTest.cs" />
     <Compile Include="SanityTest.cs" />
+    <Compile Include="HalfcloseTest.cs" />
+    <Compile Include="NUnitMain.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
index fac93fc..ab12c12 100644
--- a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
+++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core.Tests/HalfcloseTest.cs b/src/csharp/Grpc.Core.Tests/HalfcloseTest.cs
new file mode 100644
index 0000000..b4cb451
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/HalfcloseTest.cs
@@ -0,0 +1,97 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+    public class HalfcloseTest
+    {
+        MockServiceHelper helper;
+        Server server;
+        Channel channel;
+
+        [SetUp]
+        public void Init()
+        {
+            helper = new MockServiceHelper();
+
+            server = helper.GetServer();
+            server.Start();
+            channel = helper.GetChannel();
+        }
+
+        [TearDown]
+        public void Cleanup()
+        {
+            channel.ShutdownAsync().Wait();
+            server.ShutdownAsync().Wait();
+        }
+
+        /// <summary>
+        /// For client streaming and duplex streaming calls, if server does a full close
+        /// before we halfclose the request stream, an attempt to halfclose
+        /// (complete the request stream) shouldn't be treated as an error.
+        /// </summary>
+        [Test]
+        public async Task HalfcloseAfterFullclose_ClientStreamingCall()
+        {
+            helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
+            {
+                return "PASS";
+            });
+
+            var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall());
+            // make sure server has fullclosed on us
+            Assert.AreEqual("PASS", await call.ResponseAsync);
+
+            // sending close from client should be still fine because server can finish
+            // the call anytime and we cannot do anything about it on the client side.
+            await call.RequestStream.CompleteAsync();
+
+            // Second attempt to close from client is not allowed.
+            Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await call.RequestStream.CompleteAsync());
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
index d5a1eeb..60530d3 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -84,7 +84,7 @@
 
             Assert.AreEqual(StatusCode.Internal, asyncCall.GetStatus().StatusCode);
             Assert.IsNull(asyncCall.GetTrailers());
-            var ex = Assert.Throws<RpcException>(() => resultTask.GetAwaiter().GetResult());
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await resultTask);
             Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
         }
 
diff --git a/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs
index 37fb369..0663e77 100644
--- a/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs
+++ b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs
@@ -112,7 +112,7 @@
             });
 
             var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "REQUEST");
-            var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
             Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
         }
 
@@ -134,7 +134,7 @@
         {
             helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
             {
-                Assert.Throws<IOException>(async () => await requestStream.MoveNext());
+                Assert.ThrowsAsync<IOException>(async () => await requestStream.MoveNext());
                 return "RESPONSE";
             });
 
@@ -153,7 +153,7 @@
         [Test]
         public void RequestSerializationError_AsyncUnary()
         {
-            Assert.Throws<IOException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE"));
+            Assert.ThrowsAsync<IOException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE"));
         }
 
         [Test]
@@ -166,7 +166,7 @@
             });
             var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall());
             await call.RequestStream.WriteAsync("A");
-            Assert.Throws<IOException>(async () => await call.RequestStream.WriteAsync("UNSERIALIZABLE_VALUE"));
+            Assert.ThrowsAsync<IOException>(async () => await call.RequestStream.WriteAsync("UNSERIALIZABLE_VALUE"));
             await call.RequestStream.WriteAsync("B");
             await call.RequestStream.CompleteAsync();
 
diff --git a/src/csharp/Grpc.Core.Tests/NUnitMain.cs b/src/csharp/Grpc.Core.Tests/NUnitMain.cs
new file mode 100644
index 0000000..9c1d7bf
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/NUnitMain.cs
@@ -0,0 +1,59 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Reflection;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using NUnit.Common;
+using NUnitLite;
+
+namespace Grpc.Core.Tests
+{
+    /// <summary>
+    /// Provides entry point for NUnitLite
+    /// </summary>
+    public class NUnitMain
+    {
+        public static int Main(string[] args)
+        {
+            // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
+            GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
+#if DOTNET5_4
+            return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
+#else
+            return new AutoRun().Execute(args);
+#endif
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
index da0ea2e..d2b2fc6 100644
--- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -74,6 +74,8 @@
         /// (~110ns .NET Windows)
         /// </summary>
         [Test]
+        [Category("Performance")]
+        [Ignore("Prevent running on Jenkins")]
         public void NativeCallbackBenchmark()
         {
             OpCompletionDelegate handler = Handler;
@@ -95,6 +97,8 @@
         /// (~1.1us on .NET Windows)
         /// </summary>
         [Test]
+        [Category("Performance")]
+        [Ignore("Prevent running on Jenkins")]
         public void NewNativeCallbackBenchmark()
         {
             counter = 0;
@@ -112,6 +116,8 @@
         /// (~46ns .NET Windows)
         /// </summary>
         [Test]
+        [Category("Performance")]
+        [Ignore("Prevent running on Jenkins")]
         public void NopPInvokeBenchmark()
         {
             BenchmarkUtil.RunBenchmark(
diff --git a/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs b/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs
index a1648f3..772bead 100644
--- a/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs
@@ -155,7 +155,7 @@
         {
             helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
             {
-                Assert.Throws(typeof(ArgumentNullException), async () => await context.WriteResponseHeadersAsync(null));
+                Assert.ThrowsAsync(typeof(ArgumentNullException), async () => await context.WriteResponseHeadersAsync(null));
                 return "PASS";
             });
 
diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs
index 343ab1e..3830f0c 100644
--- a/src/csharp/Grpc.Core.Tests/SanityTest.cs
+++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs
@@ -38,6 +38,7 @@
 using Grpc.Core;
 using Grpc.Core.Internal;
 using Grpc.Core.Utils;
+using Newtonsoft.Json;
 using NUnit.Framework;
 
 namespace Grpc.Core.Tests
@@ -55,27 +56,23 @@
         [Test]
         public void TestsJsonUpToDate()
         {
-            var testClasses = DiscoverAllTestClasses();
-            string testsJson = GetTestsJson();
+            var discoveredTests = DiscoverAllTestClasses();
+            string discoveredTestsJson = JsonConvert.SerializeObject(discoveredTests, Formatting.Indented);
 
-            // we don't have a JSON parser at hand, but check that the test class
-            // name is contained in the file instead.
-            foreach (var className in testClasses) {
-                Assert.IsTrue(testsJson.Contains(className),
-                    string.Format("Test class \"{0}\" is missing in C# tests.json file", className));
-            }
+            Assert.AreEqual(discoveredTestsJson, ReadTestsJson());
         }
 
         /// <summary>
         /// Gets list of all test classes obtained by inspecting all the test assemblies.
         /// </summary>
-        private List<string> DiscoverAllTestClasses()
+        private Dictionary<string, List<string>> DiscoverAllTestClasses()
         {
             var assemblies = GetTestAssemblies();
 
-            var testClasses = new List<string>();
+            var testsByAssembly = new Dictionary<string, List<string>>();
             foreach (var assembly in assemblies)
             {
+                var testClasses = new List<string>();
                 foreach (var t in assembly.GetTypes())
                 {
                     foreach (var m in t.GetMethods())
@@ -89,16 +86,19 @@
 
                     }
                 }
+                testClasses.Sort();
+                testsByAssembly.Add(assembly.GetName().Name, testClasses);
             }
-            testClasses.Sort();
-            return testClasses;
+            return testsByAssembly;
         }
 
-        private string GetTestsJson()
+        /// <summary>
+        /// Reads contents of tests.json file.
+        /// </summary>
+        private string ReadTestsJson()
         {
             var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
             var testsJsonFile = Path.Combine(assemblyDir, "..", "..", "..", "tests.json");
-
             return File.ReadAllText(testsJsonFile);
         }
 
diff --git a/src/csharp/Grpc.Core.Tests/packages.config b/src/csharp/Grpc.Core.Tests/packages.config
index 610831d..aa7d951 100644
--- a/src/csharp/Grpc.Core.Tests/packages.config
+++ b/src/csharp/Grpc.Core.Tests/packages.config
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
-  <package id="NUnit" version="2.6.4" targetFramework="net45" />
-  <package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" />
+  <package id="Newtonsoft.Json" version="7.0.1" 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.Core/AsyncAuthInterceptor.cs b/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs
index 5ba06d6..1ad2290 100644
--- a/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs
+++ b/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs
index 7cd41d0..7476b0c 100644
--- a/src/csharp/Grpc.Core/CallCredentials.cs
+++ b/src/csharp/Grpc.Core/CallCredentials.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/CallInvocationDetails.cs b/src/csharp/Grpc.Core/CallInvocationDetails.cs
index 52bfbe6..98db854 100644
--- a/src/csharp/Grpc.Core/CallInvocationDetails.cs
+++ b/src/csharp/Grpc.Core/CallInvocationDetails.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/CallInvoker.cs b/src/csharp/Grpc.Core/CallInvoker.cs
new file mode 100644
index 0000000..39199b1
--- /dev/null
+++ b/src/csharp/Grpc.Core/CallInvoker.cs
@@ -0,0 +1,84 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System.Threading.Tasks;
+using Grpc.Core.Internal;
+
+namespace Grpc.Core
+{
+    /// <summary>
+    /// Abstraction of client-side RPC invocation.
+    /// </summary>
+    /// <seealso cref="Calls"/>
+    public abstract class CallInvoker
+    {
+        /// <summary>
+        /// Invokes a simple remote call in a blocking fashion.
+        /// </summary>
+        public abstract TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+            where TRequest : class
+            where TResponse : class;
+
+        /// <summary>
+        /// Invokes a simple remote call asynchronously.
+        /// </summary>
+        public abstract AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+            where TRequest : class
+            where TResponse : class;
+
+        /// <summary>
+        /// Invokes a server streaming call asynchronously.
+        /// In server streaming scenario, client sends on request and server responds with a stream of responses.
+        /// </summary>
+        public abstract AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+            where TRequest : class
+            where TResponse : class;
+
+        /// <summary>
+        /// Invokes a client streaming call asynchronously.
+        /// In client streaming scenario, client sends a stream of requests and server responds with a single response.
+        /// </summary>
+        public abstract AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+            where TRequest : class
+            where TResponse : class;
+
+        /// <summary>
+        /// Invokes a duplex streaming call asynchronously.
+        /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
+        /// The response stream is completely independent and both side can be sending messages at the same time.
+        /// </summary>
+        public abstract AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+            where TRequest : class
+            where TResponse : class;
+    }
+}
diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs
index 7bd95d4..9ca8884 100644
--- a/src/csharp/Grpc.Core/CallOptions.cs
+++ b/src/csharp/Grpc.Core/CallOptions.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -100,10 +100,7 @@
         /// </summary>
         public WriteOptions WriteOptions
         {
-            get
-            {
-                return this.writeOptions;
-            }
+            get { return this.writeOptions; }
         }
 
         /// <summary>
@@ -111,10 +108,7 @@
         /// </summary>
         public ContextPropagationToken PropagationToken
         {
-            get
-            {
-                return this.propagationToken;
-            }
+            get { return this.propagationToken; }
         }
 
         /// <summary>
@@ -122,10 +116,7 @@
         /// </summary>
         public CallCredentials Credentials
         {
-            get
-            {
-                return this.credentials;
-            }
+            get { return this.credentials; }
         }
 
         /// <summary>
@@ -165,6 +156,42 @@
         }
 
         /// <summary>
+        /// Returns new instance of <see cref="CallOptions"/> with
+        /// <c>WriteOptions</c> set to the value provided. Values of all other fields are preserved.
+        /// </summary>
+        /// <param name="writeOptions">The write options.</param>
+        public CallOptions WithWriteOptions(WriteOptions writeOptions)
+        {
+            var newOptions = this;
+            newOptions.writeOptions = writeOptions;
+            return newOptions;
+        }
+
+        /// <summary>
+        /// Returns new instance of <see cref="CallOptions"/> with
+        /// <c>PropagationToken</c> set to the value provided. Values of all other fields are preserved.
+        /// </summary>
+        /// <param name="propagationToken">The context propagation token.</param>
+        public CallOptions WithPropagationToken(ContextPropagationToken propagationToken)
+        {
+            var newOptions = this;
+            newOptions.propagationToken = propagationToken;
+            return newOptions;
+        }
+
+        /// <summary>
+        /// Returns new instance of <see cref="CallOptions"/> with
+        /// <c>Credentials</c> set to the value provided. Values of all other fields are preserved.
+        /// </summary>
+        /// <param name="credentials">The call credentials.</param>
+        public CallOptions WithCredentials(CallCredentials credentials)
+        {
+            var newOptions = this;
+            newOptions.credentials = credentials;
+            return newOptions;
+        }
+
+        /// <summary>
         /// Returns a new instance of <see cref="CallOptions"/> with 
         /// all previously unset values set to their defaults and deadline and cancellation
         /// token propagated when appropriate.
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index d7a482d..89981b1 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs
index 03cda28..db0cefe 100644
--- a/src/csharp/Grpc.Core/ChannelCredentials.cs
+++ b/src/csharp/Grpc.Core/ChannelCredentials.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/ChannelOptions.cs b/src/csharp/Grpc.Core/ChannelOptions.cs
index 65e15e2..b6eecea 100644
--- a/src/csharp/Grpc.Core/ChannelOptions.cs
+++ b/src/csharp/Grpc.Core/ChannelOptions.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/ClientBase.cs b/src/csharp/Grpc.Core/ClientBase.cs
index e5b3980..5517233 100644
--- a/src/csharp/Grpc.Core/ClientBase.cs
+++ b/src/csharp/Grpc.Core/ClientBase.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -31,93 +31,156 @@
 
 #endregion
 
-using System;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
 
 namespace Grpc.Core
 {
     /// <summary>
-    /// Interceptor for call headers.
+    /// Generic base class for client-side stubs.
     /// </summary>
-    /// <remarks>Header interceptor is no longer to recommented way to perform authentication.
-    /// For header (initial metadata) based auth such as OAuth2 or JWT access token, use <see cref="MetadataCredentials"/>.
-    /// </remarks>
-    public delegate void HeaderInterceptor(IMethod method, Metadata metadata);
+    public abstract class ClientBase<T> : ClientBase
+        where T : ClientBase<T>
+    {
+        /// <summary>
+        /// Initializes a new instance of <c>ClientBase</c> class that
+        /// throws <c>NotImplementedException</c> upon invocation of any RPC.
+        /// This constructor is only provided to allow creation of test doubles
+        /// for client classes (e.g. mocking requires a parameterless constructor).
+        /// </summary>
+        protected ClientBase() : base()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of <c>ClientBase</c> class.
+        /// </summary>
+        /// <param name="configuration">The configuration.</param>
+        protected ClientBase(ClientBaseConfiguration configuration) : base(configuration)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of <c>ClientBase</c> class.
+        /// </summary>
+        /// <param name="channel">The channel to use for remote call invocation.</param>
+        public ClientBase(Channel channel) : base(channel)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of <c>ClientBase</c> class.
+        /// </summary>
+        /// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param>
+        public ClientBase(CallInvoker callInvoker) : base(callInvoker)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new client that sets host field for calls explicitly.
+        /// gRPC supports multiple "hosts" being served by a single server.
+        /// By default (if a client was not created by calling this method),
+        /// host <c>null</c> with the meaning "use default host" is used.
+        /// </summary>
+        public T WithHost(string host)
+        {
+            var newConfiguration = this.Configuration.WithHost(host);
+            return NewInstance(newConfiguration);
+        }
+
+        /// <summary>
+        /// Creates a new instance of client from given <c>ClientBaseConfiguration</c>.
+        /// </summary>
+        protected abstract T NewInstance(ClientBaseConfiguration configuration);
+    }
 
     /// <summary>
     /// Base class for client-side stubs.
     /// </summary>
     public abstract class ClientBase
     {
-        readonly Channel channel;
+        readonly ClientBaseConfiguration configuration;
+        readonly CallInvoker callInvoker;
+
+        /// <summary>
+        /// Initializes a new instance of <c>ClientBase</c> class that
+        /// throws <c>NotImplementedException</c> upon invocation of any RPC.
+        /// This constructor is only provided to allow creation of test doubles
+        /// for client classes (e.g. mocking requires a parameterless constructor).
+        /// </summary>
+        protected ClientBase() : this(new UnimplementedCallInvoker())
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of <c>ClientBase</c> class.
+        /// </summary>
+        /// <param name="configuration">The configuration.</param>
+        protected ClientBase(ClientBaseConfiguration configuration)
+        {
+            this.configuration = GrpcPreconditions.CheckNotNull(configuration, "configuration");
+            this.callInvoker = configuration.CreateDecoratedCallInvoker();
+        }
 
         /// <summary>
         /// Initializes a new instance of <c>ClientBase</c> class.
         /// </summary>
         /// <param name="channel">The channel to use for remote call invocation.</param>
-        public ClientBase(Channel channel)
+        public ClientBase(Channel channel) : this(new DefaultCallInvoker(channel))
         {
-            this.channel = channel;
         }
 
         /// <summary>
-        /// Can be used to register a custom header interceptor.
-        /// The interceptor is invoked each time a new call on this client is started.
-        /// It is not recommented to use header interceptor to add auth headers to RPC calls.
+        /// Initializes a new instance of <c>ClientBase</c> class.
         /// </summary>
-        /// <seealso cref="HeaderInterceptor"/>
-        public HeaderInterceptor HeaderInterceptor
+        /// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param>
+        public ClientBase(CallInvoker callInvoker) : this(new ClientBaseConfiguration(callInvoker, null))
         {
-            get;
-            set;
         }
 
         /// <summary>
-        /// gRPC supports multiple "hosts" being served by a single server. 
-        /// This property can be used to set the target host explicitly.
-        /// By default, this will be set to <c>null</c> with the meaning
-        /// "use default host".
+        /// Gets the call invoker.
         /// </summary>
-        public string Host
+        protected CallInvoker CallInvoker
         {
-            get;
-            set;
+            get { return this.callInvoker; }
         }
 
         /// <summary>
-        /// Channel associated with this client.
+        /// Gets the configuration.
         /// </summary>
-        public Channel Channel
+        internal ClientBaseConfiguration Configuration
         {
-            get
+            get { return this.configuration; }
+        }
+
+        /// <summary>
+        /// Represents configuration of ClientBase. The class itself is visible to
+        /// subclasses, but contents are marked as internal to make the instances opaque.
+        /// The verbose name of this class was chosen to make name clash in generated code 
+        /// less likely.
+        /// </summary>
+        protected internal class ClientBaseConfiguration
+        {
+            readonly CallInvoker undecoratedCallInvoker;
+            readonly string host;
+
+            internal ClientBaseConfiguration(CallInvoker undecoratedCallInvoker, string host)
             {
-                return this.channel;
+                this.undecoratedCallInvoker = GrpcPreconditions.CheckNotNull(undecoratedCallInvoker);
+                this.host = host;
             }
-        }
 
-        /// <summary>
-        /// Creates a new call to given method.
-        /// </summary>
-        /// <param name="method">The method to invoke.</param>
-        /// <param name="options">The call options.</param>
-        /// <typeparam name="TRequest">Request message type.</typeparam>
-        /// <typeparam name="TResponse">Response message type.</typeparam>
-        /// <returns>The call invocation details.</returns>
-        protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options)
-            where TRequest : class
-            where TResponse : class
-        {
-            var interceptor = HeaderInterceptor;
-            if (interceptor != null)
+            internal CallInvoker CreateDecoratedCallInvoker()
             {
-                if (options.Headers == null)
-                {
-                    options = options.WithHeaders(new Metadata());
-                }
-                interceptor(method, options.Headers);
+                return new InterceptingCallInvoker(undecoratedCallInvoker, hostInterceptor: (h) => host);
             }
-            return new CallInvocationDetails<TRequest, TResponse>(channel, method, Host, options);
+
+            internal ClientBaseConfiguration WithHost(string host)
+            {
+                GrpcPreconditions.CheckNotNull(host, "host");
+                return new ClientBaseConfiguration(this.undecoratedCallInvoker, host);
+            }
         }
     }
 }
diff --git a/src/csharp/Grpc.Core/ContextPropagationToken.cs b/src/csharp/Grpc.Core/ContextPropagationToken.cs
index c0f638f..9354982 100644
--- a/src/csharp/Grpc.Core/ContextPropagationToken.cs
+++ b/src/csharp/Grpc.Core/ContextPropagationToken.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/DefaultCallInvoker.cs b/src/csharp/Grpc.Core/DefaultCallInvoker.cs
new file mode 100644
index 0000000..1a99e41
--- /dev/null
+++ b/src/csharp/Grpc.Core/DefaultCallInvoker.cs
@@ -0,0 +1,112 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System.Threading.Tasks;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+    /// <summary>
+    /// Invokes client RPCs using <see cref="Calls"/>.
+    /// </summary>
+    public class DefaultCallInvoker : CallInvoker
+    {
+        readonly Channel channel;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Grpc.Core.DefaultCallInvoker"/> class.
+        /// </summary>
+        /// <param name="channel">Channel to use.</param>
+        public DefaultCallInvoker(Channel channel)
+        {
+            this.channel = GrpcPreconditions.CheckNotNull(channel);
+        }
+
+        /// <summary>
+        /// Invokes a simple remote call in a blocking fashion.
+        /// </summary>
+        public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            var call = CreateCall(method, host, options);
+            return Calls.BlockingUnaryCall(call, request);
+        }
+
+        /// <summary>
+        /// Invokes a simple remote call asynchronously.
+        /// </summary>
+        public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            var call = CreateCall(method, host, options);
+            return Calls.AsyncUnaryCall(call, request);
+        }
+
+        /// <summary>
+        /// Invokes a server streaming call asynchronously.
+        /// In server streaming scenario, client sends on request and server responds with a stream of responses.
+        /// </summary>
+        public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            var call = CreateCall(method, host, options);
+            return Calls.AsyncServerStreamingCall(call, request);
+        }
+
+        /// <summary>
+        /// Invokes a client streaming call asynchronously.
+        /// In client streaming scenario, client sends a stream of requests and server responds with a single response.
+        /// </summary>
+        public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+        {
+            var call = CreateCall(method, host, options);
+            return Calls.AsyncClientStreamingCall(call);
+        }
+
+        /// <summary>
+        /// Invokes a duplex streaming call asynchronously.
+        /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
+        /// The response stream is completely independent and both side can be sending messages at the same time.
+        /// </summary>
+        public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+        {
+            var call = CreateCall(method, host, options);
+            return Calls.AsyncDuplexStreamingCall(call);
+        }
+
+        protected virtual CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+                where TRequest : class
+                where TResponse : class
+        {
+            return new CallInvocationDetails<TRequest, TResponse>(channel, method, host, options);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 3189835..95077a6 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -58,6 +58,7 @@
     <Compile Include="IServerStreamWriter.cs" />
     <Compile Include="IAsyncStreamWriter.cs" />
     <Compile Include="IAsyncStreamReader.cs" />
+    <Compile Include="Logging\TextWriterLogger.cs" />
     <Compile Include="Logging\NullLogger.cs" />
     <Compile Include="ServerPort.cs" />
     <Compile Include="Version.cs" />
@@ -129,6 +130,10 @@
     <Compile Include="Profiling\Profilers.cs" />
     <Compile Include="Internal\DefaultSslRootsOverride.cs" />
     <Compile Include="Utils\GrpcPreconditions.cs" />
+    <Compile Include="CallInvoker.cs" />
+    <Compile Include="DefaultCallInvoker.cs" />
+    <Compile Include="Internal\UnimplementedCallInvoker.cs" />
+    <Compile Include="Internal\InterceptingCallInvoker.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="Grpc.Core.nuspec" />
@@ -136,9 +141,7 @@
   </ItemGroup>
   <Import Project="NativeDeps.targets" />
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-  <ItemGroup>
-    <Folder Include="Resources\" />
-  </ItemGroup>
+  <ItemGroup />
   <ItemGroup>
     <EmbeddedResource Include="..\..\..\etc\roots.pem">
       <Link>Resources\roots.pem</Link>
diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec
index 49bccb0..0ada004 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec
@@ -16,7 +16,6 @@
     <tags>gRPC RPC Protocol HTTP/2</tags>
     <dependencies>
       <dependency id="Ix-Async" version="1.2.5" />
-      <dependency id="grpc.native.csharp" version="$version$" />
     </dependencies>
   </metadata>
   <files>
@@ -24,5 +23,12 @@
     <file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" />
     <file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" />
     <file src="**\*.cs" target="src" />
+    <file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" />
+    <file src="windows_x86/grpc_csharp_ext.dll" target="/build/native/bin/windows_x86/grpc_csharp_ext.dll" />
+    <file src="windows_x64/grpc_csharp_ext.dll" target="/build/native/bin/windows_x64/grpc_csharp_ext.dll" />
+    <file src="linux_x86/libgrpc_csharp_ext.so" target="/build/native/bin/linux_x86/libgrpc_csharp_ext.so" />
+    <file src="linux_x64/libgrpc_csharp_ext.so" target="/build/native/bin/linux_x64/libgrpc_csharp_ext.so" />
+    <file src="macosx_x86/libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x86/libgrpc_csharp_ext.dylib" />
+    <file src="macosx_x64/libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x64/libgrpc_csharp_ext.dylib" />
   </files>
 </package>
diff --git a/src/csharp/grpc.native.csharp/grpc.native.csharp.targets b/src/csharp/Grpc.Core/Grpc.Core.targets
similarity index 100%
rename from src/csharp/grpc.native.csharp/grpc.native.csharp.targets
rename to src/csharp/Grpc.Core/Grpc.Core.targets
diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs
index 86b37b8..a5c78cc 100644
--- a/src/csharp/Grpc.Core/GrpcEnvironment.cs
+++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 2caba26..016e1b8 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
@@ -258,9 +258,19 @@
             lock (myLock)
             {
                 GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
-                CheckSendingAllowed();
+                CheckSendingAllowed(allowFinished: true);
 
-                call.StartSendCloseFromClient(HandleHalfclosed);
+                if (!disposed && !finished)
+                {
+                    call.StartSendCloseFromClient(HandleSendCloseFromClientFinished);
+                }
+                else
+                {
+                    // 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));
+                }
 
                 halfcloseRequested = true;
                 sendCompletionDelegate = completionDelegate;
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index 45d4c3e..ccd047f 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
@@ -136,7 +136,7 @@
             lock (myLock)
             {
                 GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
-                CheckSendingAllowed();
+                CheckSendingAllowed(allowFinished: false);
 
                 call.StartSendMessage(HandleSendFinished, payload, writeFlags, !initialMetadataSent);
 
@@ -202,14 +202,14 @@
         {
         }
 
-        protected void CheckSendingAllowed()
+        protected void CheckSendingAllowed(bool allowFinished)
         {
             GrpcPreconditions.CheckState(started);
             CheckNotCancelled();
-            GrpcPreconditions.CheckState(!disposed);
+            GrpcPreconditions.CheckState(!disposed || allowFinished);
 
             GrpcPreconditions.CheckState(!halfcloseRequested, "Already halfclosed.");
-            GrpcPreconditions.CheckState(!finished, "Already finished.");
+            GrpcPreconditions.CheckState(!finished || allowFinished, "Already finished.");
             GrpcPreconditions.CheckState(sendCompletionDelegate == null, "Only one write can be pending at a time");
         }
 
@@ -294,9 +294,9 @@
         }
 
         /// <summary>
-        /// Handles halfclose completion.
+        /// Handles halfclose (send close from client) completion.
         /// </summary>
-        protected void HandleHalfclosed(bool success)
+        protected void HandleSendCloseFromClientFinished(bool success)
         {
             AsyncCompletionDelegate<object> origCompletionDelegate = null;
             lock (myLock)
@@ -309,7 +309,31 @@
 
             if (!success)
             {
-                FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Halfclose failed"));
+                FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Sending close from client has failed."));
+            }
+            else
+            {
+                FireCompletion(origCompletionDelegate, null, null);
+            }
+        }
+
+        /// <summary>
+        /// Handles send status from server completion.
+        /// </summary>
+        protected void HandleSendStatusFromServerFinished(bool success)
+        {
+            AsyncCompletionDelegate<object> origCompletionDelegate = null;
+            lock (myLock)
+            {
+                origCompletionDelegate = sendCompletionDelegate;
+                sendCompletionDelegate = null;
+
+                ReleaseResourcesIfPossible();
+            }
+
+            if (!success)
+            {
+                FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Error sending status from server."));
             }
             else
             {
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
index 9380c0d..bea2b36 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
@@ -113,7 +113,7 @@
 
                 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();
+                CheckSendingAllowed(allowFinished: false);
 
                 GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
 
@@ -137,11 +137,11 @@
             lock (myLock)
             {
                 GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
-                CheckSendingAllowed();
+                CheckSendingAllowed(allowFinished: false);
 
                 using (var metadataArray = MetadataArraySafeHandle.Create(trailers))
                 {
-                    call.StartSendStatusFromServer(HandleHalfclosed, status, metadataArray, !initialMetadataSent);
+                    call.StartSendStatusFromServer(HandleSendStatusFromServerFinished, status, metadataArray, !initialMetadataSent);
                 }
                 halfcloseRequested = true;
                 readingDone = true;
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
index d5bbf67..7e86fdd 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
index 0e2108f..66d2a66 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs
index 4ae57aa..0221798 100644
--- a/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs
index 0f36337..3095a34 100644
--- a/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index bc045b6..500653b 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
index f6aa710..0038024 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
index 65cc2e0..c85f552 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
index 2199905..1dbd1f4 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs
index 36a92ec..2886807 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
index 5c75b52..91364cd 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
index 3a293e1..628844f 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs
index dfaee5d..aa4dafd 100644
--- a/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs
+++ b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/Enums.cs b/src/csharp/Grpc.Core/Internal/Enums.cs
index 098e7c0..74f86d2 100644
--- a/src/csharp/Grpc.Core/Internal/Enums.cs
+++ b/src/csharp/Grpc.Core/Internal/Enums.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs b/src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs
new file mode 100644
index 0000000..ef48dc7
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs
@@ -0,0 +1,134 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// Decorates an underlying <c>CallInvoker</c> to intercept call invocations.
+    /// </summary>
+    internal class InterceptingCallInvoker : CallInvoker
+    {
+        readonly CallInvoker callInvoker;
+        readonly Func<string, string> hostInterceptor;
+        readonly Func<CallOptions, CallOptions> callOptionsInterceptor;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Grpc.Core.InterceptingCallInvoker"/> class.
+        /// </summary>
+        public InterceptingCallInvoker(CallInvoker callInvoker,
+            Func<string, string> hostInterceptor = null,
+            Func<CallOptions, CallOptions> callOptionsInterceptor = null)
+        {
+            this.callInvoker = GrpcPreconditions.CheckNotNull(callInvoker);
+            this.hostInterceptor = hostInterceptor;
+            this.callOptionsInterceptor = callOptionsInterceptor;
+        }
+
+        /// <summary>
+        /// Intercepts a unary call.
+        /// </summary>
+        public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            host = InterceptHost(host);
+            options = InterceptCallOptions(options);
+            return callInvoker.BlockingUnaryCall(method, host, options, request);
+        }
+
+        /// <summary>
+        /// Invokes a simple remote call asynchronously.
+        /// </summary>
+        public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            host = InterceptHost(host);
+            options = InterceptCallOptions(options);
+            return callInvoker.AsyncUnaryCall(method, host, options, request);
+        }
+
+        /// <summary>
+        /// Invokes a server streaming call asynchronously.
+        /// In server streaming scenario, client sends on request and server responds with a stream of responses.
+        /// </summary>
+        public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            host = InterceptHost(host);
+            options = InterceptCallOptions(options);
+            return callInvoker.AsyncServerStreamingCall(method, host, options, request);
+        }
+
+        /// <summary>
+        /// Invokes a client streaming call asynchronously.
+        /// In client streaming scenario, client sends a stream of requests and server responds with a single response.
+        /// </summary>
+        public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+        {
+            host = InterceptHost(host);
+            options = InterceptCallOptions(options);
+            return callInvoker.AsyncClientStreamingCall(method, host, options);
+        }
+
+        /// <summary>
+        /// Invokes a duplex streaming call asynchronously.
+        /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
+        /// The response stream is completely independent and both side can be sending messages at the same time.
+        /// </summary>
+        public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+        {
+            host = InterceptHost(host);
+            options = InterceptCallOptions(options);
+            return callInvoker.AsyncDuplexStreamingCall(method, host, options);
+        }
+
+        private string InterceptHost(string host)
+        {
+            if (hostInterceptor == null)
+            {
+                return host;
+            }
+            return hostInterceptor(host);
+        }
+
+        private CallOptions InterceptCallOptions(CallOptions options)
+        {
+            if (callOptionsInterceptor == null)
+            {
+                return options;
+            }
+            return callOptionsInterceptor(options);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
index 81760d7..25735d5 100644
--- a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs
index 282816d..b45ba19 100644
--- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,6 @@
 #endregion
 
 using System;
-using System.Globalization;
 using System.IO;
 using System.Reflection;
 
@@ -46,6 +45,7 @@
     internal sealed class NativeExtension
     {
         const string NativeLibrariesDir = "nativelibs";
+        const string DnxStyleNativeLibrariesDir = "../../build/native/bin/";
 
         static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeExtension>();
         static readonly object staticLock = new object();
@@ -100,31 +100,48 @@
             // TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property).
 
             var libraryFlavor = string.Format("{0}_{1}", GetPlatformString(), GetArchitectureString());
-            var fullPath = Path.Combine(Path.GetDirectoryName(GetAssemblyPath()),
-                NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename());
-            return new UnmanagedLibrary(fullPath);
+
+            var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath());
+
+            // With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder
+            // alongside the compiled assembly.
+            var classicPath = Path.Combine(assemblyDirectory, NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename());
+
+            // DNX-style project.json projects will use Grpc.Core assembly directly in the location where it got restored
+            // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package.
+            var dnxStylePath = Path.Combine(assemblyDirectory, DnxStyleNativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename());
+
+            return new UnmanagedLibrary(new string[] {classicPath, dnxStylePath});
         }
 
         private static string GetAssemblyPath()
         {
             var assembly = typeof(NativeExtension).GetTypeInfo().Assembly;
-
+#if DOTNET5_4
+            // Assembly.EscapedCodeBase does not exit under CoreCLR, but assemblies imported from a nuget package
+            // don't seem to be shadowed by DNX-based projects at all.
+            return assembly.Location;
+#else
             // If assembly is shadowed (e.g. in a webapp), EscapedCodeBase is pointing
             // to the original location of the assembly, and Location is pointing
             // to the shadow copy. We care about the original location because
             // the native dlls don't get shadowed.
+
             var escapedCodeBase = assembly.EscapedCodeBase;
             if (IsFileUri(escapedCodeBase))
             {
                 return new Uri(escapedCodeBase).LocalPath;
             }
             return assembly.Location;
+#endif
         }
 
+#if !DOTNET5_4
         private static bool IsFileUri(string uri)
         {
             return uri.ToLowerInvariant().StartsWith(Uri.UriSchemeFile);
         }
+#endif
 
         private static string GetPlatformString()
         {
diff --git a/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs b/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs
index 4bbbb48..3fcf867 100644
--- a/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
index e810ffc..26af631 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -87,7 +87,7 @@
             }
         }
 
-        private async void StartGetMetadata(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr)
+        private async Task StartGetMetadata(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr)
         {
             try
             {
diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
index 19a5735..9ee0ba3 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/PlatformApis.cs b/src/csharp/Grpc.Core/Internal/PlatformApis.cs
index fb1acfb..5d8c44b 100644
--- a/src/csharp/Grpc.Core/Internal/PlatformApis.cs
+++ b/src/csharp/Grpc.Core/Internal/PlatformApis.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index ccf144d..1f83e51 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
index a50f357..24f686f 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index a57fb3b..6b5f70e 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs
index 754be4e..56172a5 100644
--- a/src/csharp/Grpc.Core/Internal/Timespec.cs
+++ b/src/csharp/Grpc.Core/Internal/Timespec.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs b/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs
new file mode 100644
index 0000000..0c73408
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs
@@ -0,0 +1,75 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// Call invoker that throws <c>NotImplementedException</c> for all requests.
+    /// </summary>
+    internal class UnimplementedCallInvoker : CallInvoker
+    {
+        public UnimplementedCallInvoker()
+        {
+        }
+
+        public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs
index e763c15..5a80746 100644
--- a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs
+++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -32,8 +32,6 @@
 #endregion
 
 using System;
-using System.Collections.Concurrent;
-using System.Diagnostics;
 using System.IO;
 using System.Reflection;
 using System.Runtime.InteropServices;
@@ -63,14 +61,9 @@
         readonly string libraryPath;
         readonly IntPtr handle;
 
-        public UnmanagedLibrary(string libraryPath)
+        public UnmanagedLibrary(string[] libraryPathAlternatives)
         {
-            this.libraryPath = GrpcPreconditions.CheckNotNull(libraryPath);
-
-            if (!File.Exists(this.libraryPath))
-            {
-                throw new FileNotFoundException("Error loading native library. File does not exist.", this.libraryPath);
-            }
+            this.libraryPath = FirstValidLibraryPath(libraryPathAlternatives);
 
             Logger.Debug("Attempting to load native library \"{0}\"", this.libraryPath);
 
@@ -139,6 +132,19 @@
             throw new InvalidOperationException("Unsupported platform.");
         }
 
+        private static string FirstValidLibraryPath(string[] libraryPathAlternatives)
+        {
+            GrpcPreconditions.CheckArgument(libraryPathAlternatives.Length > 0, "libraryPathAlternatives cannot be empty.");
+            foreach (var path in libraryPathAlternatives)
+            {
+                if (File.Exists(path))
+                {
+                    return path;
+                }
+            }
+            throw new FileNotFoundException(String.Format("Error loading native library. Not found in any of the possible locations {0}", libraryPathAlternatives));
+        }
+
         private static class Windows
         {
             [DllImport("kernel32.dll")]
diff --git a/src/csharp/Grpc.Core/KeyCertificatePair.cs b/src/csharp/Grpc.Core/KeyCertificatePair.cs
index 0fb6817..a8f3bb0 100644
--- a/src/csharp/Grpc.Core/KeyCertificatePair.cs
+++ b/src/csharp/Grpc.Core/KeyCertificatePair.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs b/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs
index d41b1b9..5e8dced 100644
--- a/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs
+++ b/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -38,117 +38,28 @@
 namespace Grpc.Core.Logging
 {
     /// <summary>Logger that logs to System.Console.</summary>
-    public class ConsoleLogger : ILogger
+    public class ConsoleLogger : TextWriterLogger
     {
-        // Format similar enough to C core log format except nanosecond precision is not supported.
-        const string DateTimeFormatString = "MMdd HH:mm:ss.ffffff";
-
-        readonly Type forType;
-        readonly string forTypeString;
-
         /// <summary>Creates a console logger not associated to any specific type.</summary>
         public ConsoleLogger() : this(null)
         {
         }
 
         /// <summary>Creates a console logger that logs messsage specific for given type.</summary>
-        private ConsoleLogger(Type forType)
+        private ConsoleLogger(Type forType) : base(() => Console.Error, forType)
         {
-            this.forType = forType;
-            if (forType != null)
-            {
-                var namespaceStr = forType.Namespace ?? "";
-                if (namespaceStr.Length > 0)
-                {
-                     namespaceStr += ".";
-                }
-                this.forTypeString = namespaceStr + forType.Name + " ";
-            }
-            else
-            {
-                this.forTypeString = "";
-            }
         }
  
         /// <summary>
         /// Returns a logger associated with the specified type.
         /// </summary>
-        public ILogger ForType<T>()
+        public override ILogger ForType<T>()
         {
-            if (typeof(T) == forType)
+            if (typeof(T) == AssociatedType)
             {
                 return this;
             }
             return new ConsoleLogger(typeof(T));
         }
-
-        /// <summary>Logs a message with severity Debug.</summary>
-        public void Debug(string message)
-        {
-            Log("D", message);
-        }
-
-        /// <summary>Logs a formatted message with severity Debug.</summary>
-        public void Debug(string format, params object[] formatArgs)
-        {
-            Debug(string.Format(format, formatArgs));
-        }
-
-        /// <summary>Logs a message with severity Info.</summary>
-        public void Info(string message)
-        {
-            Log("I", message);
-        }
-
-        /// <summary>Logs a formatted message with severity Info.</summary>
-        public void Info(string format, params object[] formatArgs)
-        {
-            Info(string.Format(format, formatArgs));
-        }
-
-        /// <summary>Logs a message with severity Warning.</summary>
-        public void Warning(string message)
-        {
-            Log("W", message);
-        }
-
-        /// <summary>Logs a formatted message with severity Warning.</summary>
-        public void Warning(string format, params object[] formatArgs)
-        {
-            Warning(string.Format(format, formatArgs));
-        }
-
-        /// <summary>Logs a message and an associated exception with severity Warning.</summary>
-        public void Warning(Exception exception, string message)
-        {
-            Warning(message + " " + exception);
-        }
-
-        /// <summary>Logs a message with severity Error.</summary>
-        public void Error(string message)
-        {
-            Log("E", message);
-        }
-
-        /// <summary>Logs a formatted message with severity Error.</summary>
-        public void Error(string format, params object[] formatArgs)
-        {
-            Error(string.Format(format, formatArgs));
-        }
-
-        /// <summary>Logs a message and an associated exception with severity Error.</summary>
-        public void Error(Exception exception, string message)
-        {
-            Error(message + " " + exception);
-        }
-
-        private void Log(string severityString, string message)
-        {
-            Console.Error.WriteLine("{0}{1} {2}{3}",
-                severityString,
-                DateTime.Now.ToString(DateTimeFormatString, CultureInfo.InvariantCulture),
-                forTypeString,
-                message);
-        }
     }
 }
diff --git a/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs b/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs
new file mode 100644
index 0000000..397320d
--- /dev/null
+++ b/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs
@@ -0,0 +1,176 @@
+#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.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Logging
+{
+    /// <summary>Logger that logs to an arbitrary <c>System.IO.TextWriter</c>.</summary>
+    public class TextWriterLogger : ILogger
+    {
+        // Format similar enough to C core log format except nanosecond precision is not supported.
+        const string DateTimeFormatString = "MMdd HH:mm:ss.ffffff";
+
+        readonly Func<TextWriter> textWriterProvider;
+        readonly Type forType;
+        readonly string forTypeString;
+
+        /// <summary>
+        /// Creates a console logger not associated to any specific type and writes to given <c>System.IO.TextWriter</c>.
+        /// User is responsible for providing an instance of TextWriter that is thread-safe.
+        /// </summary>
+        public TextWriterLogger(TextWriter textWriter) : this(() => textWriter)
+        {
+            GrpcPreconditions.CheckNotNull(textWriter);
+        }
+
+        /// <summary>
+        /// Creates a console logger not associated to any specific type and writes to a <c>System.IO.TextWriter</c> obtained from given provider.
+        /// User is responsible for providing an instance of TextWriter that is thread-safe.
+        /// </summary>
+        public TextWriterLogger(Func<TextWriter> textWriterProvider) : this(textWriterProvider, null)
+        {
+        }
+
+        /// <summary>Creates a console logger that logs messsage specific for given type.</summary>
+        protected TextWriterLogger(Func<TextWriter> textWriterProvider, Type forType)
+        {
+            this.textWriterProvider = GrpcPreconditions.CheckNotNull(textWriterProvider);
+            this.forType = forType;
+            if (forType != null)
+            {
+                var namespaceStr = forType.Namespace ?? "";
+                if (namespaceStr.Length > 0)
+                {
+                     namespaceStr += ".";
+                }
+                this.forTypeString = namespaceStr + forType.Name + " ";
+            }
+            else
+            {
+                this.forTypeString = "";
+            }
+        }
+
+        /// <summary>
+        /// Returns a logger associated with the specified type.
+        /// </summary>
+        public virtual ILogger ForType<T>()
+        {
+            if (typeof(T) == forType)
+            {
+                return this;
+            }
+            return new TextWriterLogger(this.textWriterProvider, typeof(T));
+        }
+
+        /// <summary>Logs a message with severity Debug.</summary>
+        public void Debug(string message)
+        {
+            Log("D", message);
+        }
+
+        /// <summary>Logs a formatted message with severity Debug.</summary>
+        public void Debug(string format, params object[] formatArgs)
+        {
+            Debug(string.Format(format, formatArgs));
+        }
+
+        /// <summary>Logs a message with severity Info.</summary>
+        public void Info(string message)
+        {
+            Log("I", message);
+        }
+
+        /// <summary>Logs a formatted message with severity Info.</summary>
+        public void Info(string format, params object[] formatArgs)
+        {
+            Info(string.Format(format, formatArgs));
+        }
+
+        /// <summary>Logs a message with severity Warning.</summary>
+        public void Warning(string message)
+        {
+            Log("W", message);
+        }
+
+        /// <summary>Logs a formatted message with severity Warning.</summary>
+        public void Warning(string format, params object[] formatArgs)
+        {
+            Warning(string.Format(format, formatArgs));
+        }
+
+        /// <summary>Logs a message and an associated exception with severity Warning.</summary>
+        public void Warning(Exception exception, string message)
+        {
+            Warning(message + " " + exception);
+        }
+
+        /// <summary>Logs a message with severity Error.</summary>
+        public void Error(string message)
+        {
+            Log("E", message);
+        }
+
+        /// <summary>Logs a formatted message with severity Error.</summary>
+        public void Error(string format, params object[] formatArgs)
+        {
+            Error(string.Format(format, formatArgs));
+        }
+
+        /// <summary>Logs a message and an associated exception with severity Error.</summary>
+        public void Error(Exception exception, string message)
+        {
+            Error(message + " " + exception);
+        }
+
+        /// <summary>Gets the type associated with this logger.</summary>
+        protected Type AssociatedType
+        {
+            get { return forType; }
+        }
+
+        private void Log(string severityString, string message)
+        {
+            textWriterProvider().WriteLine("{0}{1} {2}{3}",
+                severityString,
+                DateTime.Now.ToString(DateTimeFormatString, CultureInfo.InvariantCulture),
+                forTypeString,
+                message);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs
index 5847248..d86e75b 100644
--- a/src/csharp/Grpc.Core/Marshaller.cs
+++ b/src/csharp/Grpc.Core/Marshaller.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs
index 52cef96..e982fa0 100644
--- a/src/csharp/Grpc.Core/Metadata.cs
+++ b/src/csharp/Grpc.Core/Metadata.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Method.cs b/src/csharp/Grpc.Core/Method.cs
index 3870076..0cf041b 100644
--- a/src/csharp/Grpc.Core/Method.cs
+++ b/src/csharp/Grpc.Core/Method.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Profiling/Profilers.cs b/src/csharp/Grpc.Core/Profiling/Profilers.cs
index 8a18144..aa0d96c 100644
--- a/src/csharp/Grpc.Core/Profiling/Profilers.cs
+++ b/src/csharp/Grpc.Core/Profiling/Profilers.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 5d0fc6b..5b61b7f 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/ServerCredentials.cs b/src/csharp/Grpc.Core/ServerCredentials.cs
index 456d331..ace4820 100644
--- a/src/csharp/Grpc.Core/ServerCredentials.cs
+++ b/src/csharp/Grpc.Core/ServerCredentials.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/ServerPort.cs b/src/csharp/Grpc.Core/ServerPort.cs
index 10ddcb7..afae084 100644
--- a/src/csharp/Grpc.Core/ServerPort.cs
+++ b/src/csharp/Grpc.Core/ServerPort.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Utils/GrpcPreconditions.cs b/src/csharp/Grpc.Core/Utils/GrpcPreconditions.cs
index 76bf04c..fcfe97a 100644
--- a/src/csharp/Grpc.Core/Utils/GrpcPreconditions.cs
+++ b/src/csharp/Grpc.Core/Utils/GrpcPreconditions.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/Version.cs b/src/csharp/Grpc.Core/Version.cs
index 6d88438..8a26bd8 100644
--- a/src/csharp/Grpc.Core/Version.cs
+++ b/src/csharp/Grpc.Core/Version.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index 4bd4f20..9014a13 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs
index 64e429e..aadef68 100644
--- a/src/csharp/Grpc.Examples.MathClient/MathClient.cs
+++ b/src/csharp/Grpc.Examples.MathClient/MathClient.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@
         public static void Main(string[] args)
         {
             var channel = new Channel("127.0.0.1", 23456, ChannelCredentials.Insecure);
-            Math.IMathClient client = new Math.MathClient(channel);
+            Math.MathClient client = new Math.MathClient(channel);
             MathExamples.DivExample(client);
 
             MathExamples.DivAsyncExample(client).Wait();
diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
index 9aeab05..cfe668b 100644
--- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
+++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
@@ -3,10 +3,8 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>10.0.0</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}</ProjectGuid>
-    <OutputType>Library</OutputType>
+    <OutputType>Exe</OutputType>
     <RootNamespace>Grpc.Examples.Tests</RootNamespace>
     <AssemblyName>Grpc.Examples.Tests</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
@@ -37,18 +35,19 @@
     <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <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>
     </Reference>
     <Reference Include="nunit.framework">
-      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+      <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
     </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="System.Interactive.Async">
       <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
     </Reference>
+    <Reference Include="nunitlite">
+      <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="..\Grpc.Core\Version.cs">
@@ -56,6 +55,7 @@
     </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="MathClientServerTests.cs" />
+    <Compile Include="NUnitMain.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
index 290d428..875202b 100644
--- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
+++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
@@ -149,7 +149,7 @@
             using (var call = client.Fib(new FibArgs { Limit = 0 }, 
                 deadline: DateTime.UtcNow.AddMilliseconds(500)))
             {
-                var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.ToListAsync());
+                var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.ToListAsync());
 
                 // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
                 Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
diff --git a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs
new file mode 100644
index 0000000..ea87802
--- /dev/null
+++ b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs
@@ -0,0 +1,59 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Reflection;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using NUnit.Common;
+using NUnitLite;
+
+namespace Grpc.Examples.Tests
+{
+    /// <summary>
+    /// Provides entry point for NUnitLite
+    /// </summary>
+    public class NUnitMain
+    {
+        public static int Main(string[] args)
+        {
+            // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
+            GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
+#if DOTNET5_4
+            return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
+#else
+            return new AutoRun().Execute(args);
+#endif
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config
index ed30d2d..ce030f9 100644
--- a/src/csharp/Grpc.Examples.Tests/packages.config
+++ b/src/csharp/Grpc.Examples.Tests/packages.config
@@ -1,6 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>

-<packages>

-  <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />

-  <package id="Ix-Async" version="1.2.5" targetFramework="net45" />

-  <package id="NUnit" version="2.6.4" targetFramework="net45" />

+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Google.Protobuf" version="3.0.0-beta2" 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" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
index 15b04c8..f0a0aa3 100644
--- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj
+++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
@@ -41,6 +41,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="nunit.framework">
+      <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Data.Linq" />
     <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs
index 8009ccb..6075420 100644
--- a/src/csharp/Grpc.Examples/MathExamples.cs
+++ b/src/csharp/Grpc.Examples/MathExamples.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -38,19 +38,19 @@
 {
     public static class MathExamples
     {
-        public static void DivExample(Math.IMathClient client)
+        public static void DivExample(Math.MathClient client)
         {
             DivReply result = client.Div(new DivArgs { Dividend = 10, Divisor = 3 });
             Console.WriteLine("Div Result: " + result);
         }
 
-        public static async Task DivAsyncExample(Math.IMathClient client)
+        public static async Task DivAsyncExample(Math.MathClient client)
         {
             DivReply result = await client.DivAsync(new DivArgs { Dividend = 4, Divisor = 5 });
             Console.WriteLine("DivAsync Result: " + result);
         }
 
-        public static async Task FibExample(Math.IMathClient client)
+        public static async Task FibExample(Math.MathClient client)
         {
             using (var call = client.Fib(new FibArgs { Limit = 5 }))
             {
@@ -59,7 +59,7 @@
             }
         }
 
-        public static async Task SumExample(Math.IMathClient client)
+        public static async Task SumExample(Math.MathClient client)
         {
             var numbers = new List<Num>
             {
@@ -75,7 +75,7 @@
             }
         }
 
-        public static async Task DivManyExample(Math.IMathClient client)
+        public static async Task DivManyExample(Math.MathClient client)
         {
             var divArgsList = new List<DivArgs>
             {
@@ -90,7 +90,7 @@
             }
         }
 
-        public static async Task DependendRequestsExample(Math.IMathClient client)
+        public static async Task DependendRequestsExample(Math.MathClient client)
         {
             var numbers = new List<Num>
             {
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index a6e878d..f3bb0d1 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -52,6 +52,7 @@
     }
 
     // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IMathClient
     {
       global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@@ -67,6 +68,7 @@
     }
 
     // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IMath
     {
       Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context);
@@ -75,61 +77,92 @@
       Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context);
     }
 
+    // server-side abstract class
+    public abstract class MathBase
+    {
+      public virtual Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
     // client stub
-    public class MathClient : ClientBase, IMathClient
+    public class MathClient : ClientBase<MathClient>, IMathClient
     {
       public MathClient(Channel channel) : base(channel)
       {
       }
-      public global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public MathClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected MathClient() : base()
       {
-        var call = CreateCall(__Method_Div, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected MathClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
+
+      public virtual global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_Div, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return Div(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
       {
-        var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncDuplexStreamingCall(call);
+        return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request);
       }
-      public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
+      public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_DivMany, options);
-        return Calls.AsyncDuplexStreamingCall(call);
+        return DivAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
       {
-        var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncServerStreamingCall(call, request);
+        return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request);
       }
-      public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
+      public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_Fib, options);
-        return Calls.AsyncServerStreamingCall(call, request);
+        return DivMany(new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
       {
-        var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncClientStreamingCall(call);
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options);
       }
-      public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
+      public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_Sum, options);
-        return Calls.AsyncClientStreamingCall(call);
+        return Fib(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
+      {
+        return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request);
+      }
+      public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return Sum(new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
+      {
+        return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options);
+      }
+      protected override MathClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new MathClient(configuration);
       }
     }
 
@@ -143,6 +176,16 @@
           .AddMethod(__Method_Sum, serviceImpl.Sum).Build();
     }
 
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(MathBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_Div, serviceImpl.Div)
+          .AddMethod(__Method_DivMany, serviceImpl.DivMany)
+          .AddMethod(__Method_Fib, serviceImpl.Fib)
+          .AddMethod(__Method_Sum, serviceImpl.Sum).Build();
+    }
+
     // creates a new client
     public static MathClient NewClient(Channel channel)
     {
diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs
index 71dc655..79c56e5 100644
--- a/src/csharp/Grpc.Examples/MathServiceImpl.cs
+++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -43,14 +43,14 @@
     /// <summary>
     /// Implementation of MathService server
     /// </summary>
-    public class MathServiceImpl : Math.IMath
+    public class MathServiceImpl : Math.MathBase
     {
-        public Task<DivReply> Div(DivArgs request, ServerCallContext context)
+        public override Task<DivReply> Div(DivArgs request, ServerCallContext context)
         {
             return Task.FromResult(DivInternal(request));
         }
 
-        public async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
+        public override async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
         {
             if (request.Limit <= 0)
             {
@@ -72,7 +72,7 @@
             }
         }
 
-        public async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context)
+        public override async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context)
         {
             long sum = 0;
             await requestStream.ForEachAsync(async num =>
@@ -82,7 +82,7 @@
             return new Num { Num_ = sum };
         }
 
-        public async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context)
+        public override async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context)
         {
             await requestStream.ForEachAsync(async divArgs => await responseStream.WriteAsync(DivInternal(divArgs)));
         }
diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config
index dfb8304..a424cd2 100644
--- a/src/csharp/Grpc.Examples/packages.config
+++ b/src/csharp/Grpc.Examples/packages.config
@@ -2,5 +2,5 @@
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
-  <package id="NUnit" version="2.6.4" 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 bb6488b..0bea9c0 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
+++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}</ProjectGuid>
-    <OutputType>Library</OutputType>
+    <OutputType>Exe</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>Grpc.HealthCheck.Tests</RootNamespace>
     <AssemblyName>Grpc.HealthCheck.Tests</AssemblyName>
@@ -37,13 +37,6 @@
     <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <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>
-    </Reference>
-    <Reference Include="nunit.framework">
-      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
-    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Xml.Linq" />
@@ -51,6 +44,15 @@
     <Reference Include="Microsoft.CSharp" />
     <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>
+    </Reference>
+    <Reference Include="nunit.framework">
+      <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="nunitlite">
+      <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="..\Grpc.Core\Version.cs">
@@ -59,14 +61,15 @@
     <Compile Include="HealthServiceImplTest.cs" />
     <Compile Include="HealthClientServerTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="NUnitMain.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
-      <Project>{ccc4440e-49f7-4790-b0af-feabb0837ae7}</Project>
+      <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
       <Name>Grpc.Core</Name>
     </ProjectReference>
     <ProjectReference Include="..\Grpc.HealthCheck\Grpc.HealthCheck.csproj">
-      <Project>{aa5e328a-8835-49d7-98ed-c29f2b3049f0}</Project>
+      <Project>{AA5E328A-8835-49D7-98ED-C29F2B3049F0}</Project>
       <Name>Grpc.HealthCheck</Name>
     </ProjectReference>
   </ItemGroup>
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
index c3fac05..fb29294 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,7 @@
         const string Host = "localhost";
         Server server;
         Channel channel;
-        Grpc.Health.V1.Health.IHealthClient client;
+        Grpc.Health.V1.Health.HealthClient client;
         Grpc.HealthCheck.HealthServiceImpl serviceImpl;
 
         [TestFixtureSetUp]
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
index 47e4b7c..a4b79e3 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs
new file mode 100644
index 0000000..0820523
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs
@@ -0,0 +1,59 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Reflection;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using NUnit.Common;
+using NUnitLite;
+
+namespace Grpc.HealthCheck.Tests
+{
+    /// <summary>
+    /// Provides entry point for NUnitLite
+    /// </summary>
+    public class NUnitMain
+    {
+        public static int Main(string[] args)
+        {
+            // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
+            GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
+#if DOTNET5_4
+            return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
+#else
+            return new AutoRun().Execute(args);
+#endif
+        }
+    }
+}
diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config
index 4728093..8066d8f 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/packages.config
+++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
-  <package id="NUnit" version="2.6.4" 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/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
index 68320eb..72e11cc 100644
--- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -29,6 +29,7 @@
     }
 
     // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IHealthClient
     {
       global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@@ -38,36 +39,59 @@
     }
 
     // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IHealth
     {
       Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context);
     }
 
+    // server-side abstract class
+    public abstract class HealthBase
+    {
+      public virtual Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
     // client stub
-    public class HealthClient : ClientBase, IHealthClient
+    public class HealthClient : ClientBase<HealthClient>, IHealthClient
     {
       public HealthClient(Channel channel) : base(channel)
       {
       }
-      public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public HealthClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected HealthClient() : base()
       {
-        var call = CreateCall(__Method_Check, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected HealthClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
+
+      public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_Check, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return Check(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request);
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return CheckAsync(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request);
+      }
+      protected override HealthClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new HealthClient(configuration);
       }
     }
 
@@ -78,6 +102,13 @@
           .AddMethod(__Method_Check, serviceImpl.Check).Build();
     }
 
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(HealthBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_Check, serviceImpl.Check).Build();
+    }
+
     // creates a new client
     public static HealthClient NewClient(Channel channel)
     {
diff --git a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
index 21482b3..d0406ec 100644
--- a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -51,7 +51,7 @@
     /// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl));
     /// </code>
     /// </summary>
-    public class HealthServiceImpl : Grpc.Health.V1.Health.IHealth
+    public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase
     {
         private readonly object myLock = new object();
         private readonly Dictionary<string, HealthCheckResponse.Types.ServingStatus> statusMap = 
@@ -99,7 +99,7 @@
         /// <param name="request">The check request.</param>
         /// <param name="context">The call context.</param>
         /// <returns>The asynchronous response.</returns>
-        public Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)
+        public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)
         {
             lock (myLock)
             {
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
index f37c146..339a754 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
@@ -9,7 +9,7 @@
     <AssemblyName>Grpc.IntegrationTesting.Client</AssemblyName>
     <StartupObject>Grpc.IntegrationTesting.Client.Program</StartupObject>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <NuGetPackageImportStamp>6d22e68f</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>dfa56e6c</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -43,28 +43,17 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Core, Version=1.10.0.25331, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Core.1.10.0\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -73,12 +62,6 @@
     <Reference Include="System" />
     <Reference Include="System.Net" />
     <Reference Include="System.Net.Http" />
-    <Reference Include="System.Net.Http.Extensions">
-      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Net.Http.Primitives">
-      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
-    </Reference>
     <Reference Include="System.Net.Http.WebRequest" />
   </ItemGroup>
   <ItemGroup>
@@ -100,14 +83,6 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <None Include="app.config" />
     <None Include="packages.config" />
   </ItemGroup>
-  <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.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\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
-  </Target>
 </Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/app.config b/src/csharp/Grpc.IntegrationTesting.Client/app.config
deleted file mode 100644
index 84d7534..0000000
--- a/src/csharp/Grpc.IntegrationTesting.Client/app.config
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-</configuration>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/packages.config b/src/csharp/Grpc.IntegrationTesting.Client/packages.config
index 5fe8ca6..c20d9ce 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting.Client/packages.config
@@ -1,11 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
-  <package id="Google.Apis.Auth" version="1.10.0" targetFramework="net45" />
-  <package id="Google.Apis.Core" version="1.10.0" targetFramework="net45" />
-  <package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
-  <package id="Microsoft.Net.Http" version="2.2.29" 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="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config b/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
index 940d25c..e204447 100644
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
@@ -6,6 +6,10 @@
         <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
         <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
       </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-1.11.1.0" newVersion="1.11.1.0" />
+      </dependentAssembly>
     </assemblyBinding>
   </runtime>
 </configuration>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
index f27b96a..27a5650 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
@@ -9,7 +9,7 @@
     <AssemblyName>Grpc.IntegrationTesting.Server</AssemblyName>
     <StartupObject>Grpc.IntegrationTesting.Server.Program</StartupObject>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <NuGetPackageImportStamp>d9ee8e52</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>7ceb739e</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -43,28 +43,17 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Core, Version=1.10.0.25331, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
+    <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Core.1.10.0\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
+      <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -73,12 +62,6 @@
     <Reference Include="System" />
     <Reference Include="System.Net" />
     <Reference Include="System.Net.Http" />
-    <Reference Include="System.Net.Http.Extensions">
-      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Net.Http.Primitives">
-      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
-    </Reference>
     <Reference Include="System.Net.Http.WebRequest" />
   </ItemGroup>
   <ItemGroup>
@@ -100,14 +83,6 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <None Include="app.config" />
     <None Include="packages.config" />
   </ItemGroup>
-  <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.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\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
-  </Target>
 </Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/app.config b/src/csharp/Grpc.IntegrationTesting.Server/app.config
deleted file mode 100644
index 84d7534..0000000
--- a/src/csharp/Grpc.IntegrationTesting.Server/app.config
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-</configuration>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/packages.config b/src/csharp/Grpc.IntegrationTesting.Server/packages.config
index 5fe8ca6..c20d9ce 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting.Server/packages.config
@@ -1,11 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
-  <package id="Google.Apis.Auth" version="1.10.0" targetFramework="net45" />
-  <package id="Google.Apis.Core" version="1.10.0" targetFramework="net45" />
-  <package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
-  <package id="Microsoft.Net.Http" version="2.2.29" 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="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore b/src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore
new file mode 100644
index 0000000..a382af2
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore
@@ -0,0 +1,3 @@
+bin
+obj
+
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj b/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj
new file mode 100644
index 0000000..d6eba74
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{ADEBA147-80AE-4710-82E9-5B7F93690266}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Grpc.IntegrationTesting.StressClient</RootNamespace>
+    <AssemblyName>Grpc.IntegrationTesting.StressClient</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\ReleaseSigned</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Grpc.Core\Version.cs">
+      <Link>Version.cs</Link>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
+      <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
+      <Name>Grpc.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Grpc.IntegrationTesting\Grpc.IntegrationTesting.csproj">
+      <Project>{C61154BA-DD4A-4838-8420-0162A28925E0}</Project>
+      <Name>Grpc.IntegrationTesting</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs b/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs
new file mode 100644
index 0000000..dffdf22
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs
@@ -0,0 +1,45 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+
+namespace Grpc.IntegrationTesting.StressClient
+{
+    class MainClass
+    {
+        public static void Main(string[] args)
+        {
+            StressTestClient.Run(args);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e845bbf
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.IntegrationTesting.StressClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
index 47a1522..07f2703 100644
--- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -44,26 +44,23 @@
     /// <summary>
     /// Implementation of BenchmarkService server
     /// </summary>
-    public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService
+    public class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase
     {
-        private readonly int responseSize;
-
-        public BenchmarkServiceImpl(int responseSize)
+        public BenchmarkServiceImpl()
         {
-            this.responseSize = responseSize;
         }
 
-        public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
+        public override Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
         {
-            var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
+            var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) };
             return Task.FromResult(response);
         }
 
-        public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
+        public override async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
         {
             await requestStream.ForEachAsync(async request =>
             {
-                var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
+                var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) };
                 await responseStream.WriteAsync(response);
             });
         }
diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
index c401601..b457275 100644
--- a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
 using System.Threading.Tasks;
 using Google.Protobuf;
 using Grpc.Core;
+using Grpc.Core.Logging;
 using Grpc.Core.Utils;
 using NUnit.Framework;
 using Grpc.Testing;
@@ -50,58 +51,101 @@
     /// <summary>
     /// Helper methods to start client runners for performance testing.
     /// </summary>
-    public static class ClientRunners
+    public class ClientRunners
     {
+        static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<ClientRunners>();
+
         /// <summary>
         /// Creates a started client runner.
         /// </summary>
         public static IClientRunner CreateStarted(ClientConfig config)
         {
-            string target = config.ServerTargets.Single();
-            GrpcPreconditions.CheckArgument(config.LoadParams.LoadCase == LoadParams.LoadOneofCase.ClosedLoop);
+            Logger.Debug("ClientConfig: {0}", config);
 
-            var credentials = config.SecurityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
-            var channel = new Channel(target, credentials);
-
-            switch (config.RpcType)
+            if (config.AsyncClientThreads != 0)
             {
-                case RpcType.UNARY:
-                    return new SyncUnaryClientRunner(channel,
-                        config.PayloadConfig.SimpleParams.ReqSize,
-                        config.HistogramParams);
-
-                case RpcType.STREAMING:
-                default:
-                    throw new ArgumentException("Unsupported RpcType.");
+                Logger.Warning("ClientConfig.AsyncClientThreads is not supported for C#. Ignoring the value");
             }
+            if (config.CoreLimit != 0)
+            {
+                Logger.Warning("ClientConfig.CoreLimit is not supported for C#. Ignoring the value");
+            }
+            if (config.CoreList.Count > 0)
+            {
+                Logger.Warning("ClientConfig.CoreList is not supported for C#. Ignoring the value");
+            }
+
+            var channels = CreateChannels(config.ClientChannels, config.ServerTargets, config.SecurityParams);
+
+            return new ClientRunnerImpl(channels,
+                config.ClientType,
+                config.RpcType,
+                config.OutstandingRpcsPerChannel,
+                config.LoadParams,
+                config.PayloadConfig,
+                config.HistogramParams);
+        }
+
+        private static List<Channel> CreateChannels(int clientChannels, IEnumerable<string> serverTargets, SecurityParams securityParams)
+        {
+            GrpcPreconditions.CheckArgument(clientChannels > 0, "clientChannels needs to be at least 1.");
+            GrpcPreconditions.CheckArgument(serverTargets.Count() > 0, "at least one serverTarget needs to be specified.");
+
+            var credentials = securityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
+            List<ChannelOption> channelOptions = null;
+            if (securityParams != null && securityParams.ServerHostOverride != "")
+            {
+                channelOptions = new List<ChannelOption>
+                {
+                    new ChannelOption(ChannelOptions.SslTargetNameOverride, securityParams.ServerHostOverride)
+                };
+            }
+
+            var result = new List<Channel>();
+            for (int i = 0; i < clientChannels; i++)
+            {
+                var target = serverTargets.ElementAt(i % serverTargets.Count());
+                var channel = new Channel(target, credentials, channelOptions);
+                result.Add(channel);
+            }
+            return result;
         }
     }
 
-    /// <summary>
-    /// Client that starts synchronous unary calls in a closed loop.
-    /// </summary>
-    public class SyncUnaryClientRunner : IClientRunner
+    public class ClientRunnerImpl : IClientRunner
     {
         const double SecondsToNanos = 1e9;
 
-        readonly Channel channel;
-        readonly int payloadSize;
+        readonly List<Channel> channels;
+        readonly ClientType clientType;
+        readonly RpcType rpcType;
+        readonly PayloadConfig payloadConfig;
         readonly Histogram histogram;
 
-        readonly BenchmarkService.IBenchmarkServiceClient client;
-        readonly Task runnerTask;
-        readonly CancellationTokenSource stoppedCts;
+        readonly List<Task> runnerTasks;
+        readonly CancellationTokenSource stoppedCts = new CancellationTokenSource();
         readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
         
-        public SyncUnaryClientRunner(Channel channel, int payloadSize, HistogramParams histogramParams)
+        public ClientRunnerImpl(List<Channel> channels, ClientType clientType, RpcType rpcType, int outstandingRpcsPerChannel, LoadParams loadParams, PayloadConfig payloadConfig, HistogramParams histogramParams)
         {
-            this.channel = GrpcPreconditions.CheckNotNull(channel);
-            this.payloadSize = payloadSize;
+            GrpcPreconditions.CheckArgument(outstandingRpcsPerChannel > 0, "outstandingRpcsPerChannel");
+            GrpcPreconditions.CheckNotNull(histogramParams, "histogramParams");
+            this.channels = new List<Channel>(channels);
+            this.clientType = clientType;
+            this.rpcType = rpcType;
+            this.payloadConfig = payloadConfig;
             this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible);
 
-            this.stoppedCts = new CancellationTokenSource();
-            this.client = BenchmarkService.NewClient(channel);
-            this.runnerTask = Task.Factory.StartNew(Run, TaskCreationOptions.LongRunning);
+            this.runnerTasks = new List<Task>();
+            foreach (var channel in this.channels)
+            {
+                for (int i = 0; i < outstandingRpcsPerChannel; i++)
+                {
+                    var timer = CreateTimer(loadParams, 1.0 / this.channels.Count / outstandingRpcsPerChannel);
+                    var threadBody = GetThreadBody(channel, timer);
+                    this.runnerTasks.Add(Task.Factory.StartNew(threadBody, TaskCreationOptions.LongRunning));
+                }
+            }
         }
 
         public ClientStats GetStats(bool reset)
@@ -122,16 +166,20 @@
         public async Task StopAsync()
         {
             stoppedCts.Cancel();
-            await runnerTask;
-            await channel.ShutdownAsync();
+            foreach (var runnerTask in runnerTasks)
+            {
+                await runnerTask;
+            }
+            foreach (var channel in channels)
+            {
+                await channel.ShutdownAsync();
+            }
         }
 
-        private void Run()
+        private void RunUnary(Channel channel, IInterarrivalTimer timer)
         {
-            var request = new SimpleRequest
-            {
-                Payload = CreateZerosPayload(payloadSize)
-            };
+            var client = BenchmarkService.NewClient(channel);
+            var request = CreateSimpleRequest();
             var stopwatch = new Stopwatch();
 
             while (!stoppedCts.Token.IsCancellationRequested)
@@ -142,12 +190,153 @@
 
                 // spec requires data point in nanoseconds.
                 histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+
+                timer.WaitForNext();
             }
         }
 
+        private async Task RunUnaryAsync(Channel channel, IInterarrivalTimer timer)
+        {
+            var client = BenchmarkService.NewClient(channel);
+            var request = CreateSimpleRequest();
+            var stopwatch = new Stopwatch();
+
+            while (!stoppedCts.Token.IsCancellationRequested)
+            {
+                stopwatch.Restart();
+                await client.UnaryCallAsync(request);
+                stopwatch.Stop();
+
+                // spec requires data point in nanoseconds.
+                histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+
+                await timer.WaitForNextAsync();
+            }
+        }
+
+        private async Task RunStreamingPingPongAsync(Channel channel, IInterarrivalTimer timer)
+        {
+            var client = BenchmarkService.NewClient(channel);
+            var request = CreateSimpleRequest();
+            var stopwatch = new Stopwatch();
+
+            using (var call = client.StreamingCall())
+            {
+                while (!stoppedCts.Token.IsCancellationRequested)
+                {
+                    stopwatch.Restart();
+                    await call.RequestStream.WriteAsync(request);
+                    await call.ResponseStream.MoveNext();
+                    stopwatch.Stop();
+
+                    // spec requires data point in nanoseconds.
+                    histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+
+                    await timer.WaitForNextAsync();
+                }
+
+                // finish the streaming call
+                await call.RequestStream.CompleteAsync();
+                Assert.IsFalse(await call.ResponseStream.MoveNext());
+            }
+        }
+
+        private async Task RunGenericStreamingAsync(Channel channel, IInterarrivalTimer timer)
+        {
+            var request = CreateByteBufferRequest();
+            var stopwatch = new Stopwatch();
+
+            var callDetails = new CallInvocationDetails<byte[], byte[]>(channel, GenericService.StreamingCallMethod, new CallOptions());
+
+            using (var call = Calls.AsyncDuplexStreamingCall(callDetails))
+            {
+                while (!stoppedCts.Token.IsCancellationRequested)
+                {
+                    stopwatch.Restart();
+                    await call.RequestStream.WriteAsync(request);
+                    await call.ResponseStream.MoveNext();
+                    stopwatch.Stop();
+
+                    // spec requires data point in nanoseconds.
+                    histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+
+                    await timer.WaitForNextAsync();
+                }
+
+                // finish the streaming call
+                await call.RequestStream.CompleteAsync();
+                Assert.IsFalse(await call.ResponseStream.MoveNext());
+            }
+        }
+
+        private Action GetThreadBody(Channel channel, IInterarrivalTimer timer)
+        {
+            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");
+                return () =>
+                {
+                    RunGenericStreamingAsync(channel, timer).Wait();
+                };
+            }
+
+            GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams);
+            if (clientType == ClientType.SYNC_CLIENT)
+            {
+                GrpcPreconditions.CheckArgument(rpcType == RpcType.UNARY, "Sync client can only be used for Unary calls in C#");
+                return () => RunUnary(channel, timer);
+            }
+            else if (clientType == ClientType.ASYNC_CLIENT)
+            {
+                switch (rpcType)
+                {
+                    case RpcType.UNARY:
+                        return () =>
+                        {
+                            RunUnaryAsync(channel, timer).Wait();
+                        };
+                    case RpcType.STREAMING:
+                        return () =>
+                        {
+                            RunStreamingPingPongAsync(channel, timer).Wait();
+                        };
+                }
+            }
+            throw new ArgumentException("Unsupported configuration.");
+        }
+
+        private SimpleRequest CreateSimpleRequest()
+        {
+            GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams);
+            return new SimpleRequest
+            {
+                Payload = CreateZerosPayload(payloadConfig.SimpleParams.ReqSize),
+                ResponseSize = payloadConfig.SimpleParams.RespSize
+            };
+        }
+
+        private byte[] CreateByteBufferRequest()
+        {
+            return new byte[payloadConfig.BytebufParams.ReqSize];
+        }
+
         private static Payload CreateZerosPayload(int size)
         {
             return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
         }
+
+        private static IInterarrivalTimer CreateTimer(LoadParams loadParams, double loadMultiplier)
+        {
+            switch (loadParams.LoadCase)
+            {
+                case LoadParams.LoadOneofCase.ClosedLoop:
+                    return new ClosedLoopInterarrivalTimer();
+                case LoadParams.LoadOneofCase.Poisson:
+                    return new PoissonInterarrivalTimer(loadParams.Poisson.OfferedLoad * loadMultiplier);
+                default:
+                    throw new ArgumentException("Unknown load type");
+            }
+        }
     }
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index 291bc75..3fa8d43 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -26,69 +26,84 @@
             "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2NvbnRyb2wucHJvdG8SDGdycGMu",
             "dGVzdGluZxolc3JjL3Byb3RvL2dycGMvdGVzdGluZy9wYXlsb2Fkcy5wcm90",
             "bxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9zdGF0cy5wcm90byIlCg1Qb2lz",
-            "c29uUGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASJBCg1Vbmlmb3JtUGFy",
-            "YW1zEhcKD2ludGVyYXJyaXZhbF9sbxgBIAEoARIXCg9pbnRlcmFycml2YWxf",
-            "aGkYAiABKAEiKwoTRGV0ZXJtaW5pc3RpY1BhcmFtcxIUCgxvZmZlcmVkX2xv",
-            "YWQYASABKAEiOAoMUGFyZXRvUGFyYW1zEhkKEWludGVyYXJyaXZhbF9iYXNl",
-            "GAEgASgBEg0KBWFscGhhGAIgASgBIhIKEENsb3NlZExvb3BQYXJhbXMijgIK",
-            "CkxvYWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5ncnBjLnRlc3Rp",
-            "bmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiABKAsyGy5ncnBj",
-            "LnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAEi4KB3VuaWZvcm0YAyABKAsyGy5n",
-            "cnBjLnRlc3RpbmcuVW5pZm9ybVBhcmFtc0gAEjMKBmRldGVybRgEIAEoCzIh",
-            "LmdycGMudGVzdGluZy5EZXRlcm1pbmlzdGljUGFyYW1zSAASLAoGcGFyZXRv",
-            "GAUgASgLMhouZ3JwYy50ZXN0aW5nLlBhcmV0b1BhcmFtc0gAQgYKBGxvYWQi",
-            "QwoOU2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2Vy",
-            "dmVyX2hvc3Rfb3ZlcnJpZGUYAiABKAki1gMKDENsaWVudENvbmZpZxIWCg5z",
-            "ZXJ2ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdy",
-            "cGMudGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEo",
-            "CzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGlu",
-            "Z19ycGNzX3Blcl9jaGFubmVsGAQgASgFEhcKD2NsaWVudF9jaGFubmVscxgF",
-            "IAEoBRIcChRhc3luY19jbGllbnRfdGhyZWFkcxgHIAEoBRInCghycGNfdHlw",
-            "ZRgIIAEoDjIVLmdycGMudGVzdGluZy5ScGNUeXBlEi0KC2xvYWRfcGFyYW1z",
-            "GAogASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9j",
-            "b25maWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBo",
-            "aXN0b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3Jh",
-            "bVBhcmFtcxIRCgljb3JlX2xpc3QYDSADKAUSEgoKY29yZV9saW1pdBgOIAEo",
-            "BSI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRlc3Rp",
-            "bmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJoCgpDbGll",
-            "bnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVudENv",
-            "bmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkK",
-            "B2FyZ3R5cGUi/AEKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlwZRgBIAEo",
-            "DjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5X3BhcmFt",
-            "cxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIMCgRwb3J0",
-            "GAQgASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRzGAcgASgFEhIKCmNvcmVf",
-            "bGltaXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcYCSABKAsyGy5ncnBjLnRl",
-            "c3RpbmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xpc3QYCiADKAUiaAoKU2Vy",
-            "dmVyQXJncxIrCgVzZXR1cBgBIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2ZXJD",
-            "b25maWdIABIiCgRtYXJrGAIgASgLMhIuZ3JwYy50ZXN0aW5nLk1hcmtIAEIJ",
-            "Cgdhcmd0eXBlIlUKDFNlcnZlclN0YXR1cxIoCgVzdGF0cxgBIAEoCzIZLmdy",
-            "cGMudGVzdGluZy5TZXJ2ZXJTdGF0cxIMCgRwb3J0GAIgASgFEg0KBWNvcmVz",
-            "GAMgASgFIg0KC0NvcmVSZXF1ZXN0Ih0KDENvcmVSZXNwb25zZRINCgVjb3Jl",
-            "cxgBIAEoBSIGCgRWb2lkKi8KCkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQ",
-            "ABIQCgxBU1lOQ19DTElFTlQQASpJCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VS",
-            "VkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJW",
-            "RVIQAiojCgdScGNUeXBlEgkKBVVOQVJZEAASDQoJU1RSRUFNSU5HEAFiBnBy",
-            "b3RvMw=="));
+            "c29uUGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASISChBDbG9zZWRMb29w",
+            "UGFyYW1zInsKCkxvYWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5n",
+            "cnBjLnRlc3RpbmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiAB",
+            "KAsyGy5ncnBjLnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAQgYKBGxvYWQiQwoO",
+            "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
+            "X2hvc3Rfb3ZlcnJpZGUYAiABKAki8AMKDENsaWVudENvbmZpZxIWCg5zZXJ2",
+            "ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdycGMu",
+            "dGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEoCzIc",
+            "LmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGluZ19y",
+            "cGNzX3Blcl9jaGFubmVsGAQgASgFEhcKD2NsaWVudF9jaGFubmVscxgFIAEo",
+            "BRIcChRhc3luY19jbGllbnRfdGhyZWFkcxgHIAEoBRInCghycGNfdHlwZRgI",
+            "IAEoDjIVLmdycGMudGVzdGluZy5ScGNUeXBlEi0KC2xvYWRfcGFyYW1zGAog",
+            "ASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9jb25m",
+            "aWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBoaXN0",
+            "b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbVBh",
+            "cmFtcxIRCgljb3JlX2xpc3QYDSADKAUSEgoKY29yZV9saW1pdBgOIAEoBRIY",
+            "ChBvdGhlcl9jbGllbnRfYXBpGA8gASgJIjgKDENsaWVudFN0YXR1cxIoCgVz",
+            "dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
+            "Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
+            "Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
+            "LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSKWAgoMU2VydmVyQ29u",
+            "ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
+            "clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
+            "LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
+            "X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
+            "X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
+            "CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJImgK",
+            "ClNlcnZlckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2Vy",
+            "dmVyQ29uZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJr",
+            "SABCCQoHYXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsy",
+            "GS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVj",
+            "b3JlcxgDIAEoBSINCgtDb3JlUmVxdWVzdCIdCgxDb3JlUmVzcG9uc2USDQoF",
+            "Y29yZXMYASABKAUiBgoEVm9pZCL9AQoIU2NlbmFyaW8SDAoEbmFtZRgBIAEo",
+            "CRIxCg1jbGllbnRfY29uZmlnGAIgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVu",
+            "dENvbmZpZxITCgtudW1fY2xpZW50cxgDIAEoBRIxCg1zZXJ2ZXJfY29uZmln",
+            "GAQgASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZxITCgtudW1fc2Vy",
+            "dmVycxgFIAEoBRIWCg53YXJtdXBfc2Vjb25kcxgGIAEoBRIZChFiZW5jaG1h",
+            "cmtfc2Vjb25kcxgHIAEoBRIgChhzcGF3bl9sb2NhbF93b3JrZXJfY291bnQY",
+            "CCABKAUiNgoJU2NlbmFyaW9zEikKCXNjZW5hcmlvcxgBIAMoCzIWLmdycGMu",
+            "dGVzdGluZy5TY2VuYXJpbyKSAgoVU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EgsK",
+            "A3FwcxgBIAEoARIbChNxcHNfcGVyX3NlcnZlcl9jb3JlGAIgASgBEhoKEnNl",
+            "cnZlcl9zeXN0ZW1fdGltZRgDIAEoARIYChBzZXJ2ZXJfdXNlcl90aW1lGAQg",
+            "ASgBEhoKEmNsaWVudF9zeXN0ZW1fdGltZRgFIAEoARIYChBjbGllbnRfdXNl",
+            "cl90aW1lGAYgASgBEhIKCmxhdGVuY3lfNTAYByABKAESEgoKbGF0ZW5jeV85",
+            "MBgIIAEoARISCgpsYXRlbmN5Xzk1GAkgASgBEhIKCmxhdGVuY3lfOTkYCiAB",
+            "KAESEwoLbGF0ZW5jeV85OTkYCyABKAEimAIKDlNjZW5hcmlvUmVzdWx0EigK",
+            "CHNjZW5hcmlvGAEgASgLMhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxh",
+            "dGVuY2llcxgCIAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8K",
+            "DGNsaWVudF9zdGF0cxgDIAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0",
+            "cxIvCgxzZXJ2ZXJfc3RhdHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVy",
+            "U3RhdHMSFAoMc2VydmVyX2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsy",
+            "Iy5ncnBjLnRlc3RpbmcuU2NlbmFyaW9SZXN1bHRTdW1tYXJ5KkEKCkNsaWVu",
+            "dFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQARIQCgxP",
+            "VEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VSVkVSEAAS",
+            "EAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJWRVIQAhIQ",
+            "CgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAASDQoJU1RS",
+            "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.UniformParams), global::Grpc.Testing.UniformParams.Parser, new[]{ "InterarrivalLo", "InterarrivalHi" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.DeterministicParams), global::Grpc.Testing.DeterministicParams.Parser, new[]{ "OfferedLoad" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ParetoParams), global::Grpc.Testing.ParetoParams.Parser, new[]{ "InterarrivalBase", "Alpha" }, 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", "Uniform", "Determ", "Pareto" }, new[]{ "Load" }, 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" }, 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" }, null, 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.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)
           }));
     }
     #endregion
@@ -96,14 +111,26 @@
   }
   #region Enums
   public enum ClientType {
+    /// <summary>
+    ///  Many languages support a basic distinction between using
+    ///  sync or async client, and this allows the specification
+    /// </summary>
     SYNC_CLIENT = 0,
     ASYNC_CLIENT = 1,
+    /// <summary>
+    ///  used for some language-specific variants
+    /// </summary>
+    OTHER_CLIENT = 2,
   }
 
   public enum ServerType {
     SYNC_SERVER = 0,
     ASYNC_SERVER = 1,
     ASYNC_GENERIC_SERVER = 2,
+    /// <summary>
+    ///  used for some language-specific variants
+    /// </summary>
+    OTHER_SERVER = 3,
   }
 
   public enum RpcType {
@@ -224,369 +251,6 @@
 
   }
 
-  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class UniformParams : pb::IMessage<UniformParams> {
-    private static readonly pb::MessageParser<UniformParams> _parser = new pb::MessageParser<UniformParams>(() => new UniformParams());
-    public static pb::MessageParser<UniformParams> Parser { get { return _parser; } }
-
-    public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[1]; }
-    }
-
-    pbr::MessageDescriptor pb::IMessage.Descriptor {
-      get { return Descriptor; }
-    }
-
-    public UniformParams() {
-      OnConstruction();
-    }
-
-    partial void OnConstruction();
-
-    public UniformParams(UniformParams other) : this() {
-      interarrivalLo_ = other.interarrivalLo_;
-      interarrivalHi_ = other.interarrivalHi_;
-    }
-
-    public UniformParams Clone() {
-      return new UniformParams(this);
-    }
-
-    /// <summary>Field number for the "interarrival_lo" field.</summary>
-    public const int InterarrivalLoFieldNumber = 1;
-    private double interarrivalLo_;
-    public double InterarrivalLo {
-      get { return interarrivalLo_; }
-      set {
-        interarrivalLo_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "interarrival_hi" field.</summary>
-    public const int InterarrivalHiFieldNumber = 2;
-    private double interarrivalHi_;
-    public double InterarrivalHi {
-      get { return interarrivalHi_; }
-      set {
-        interarrivalHi_ = value;
-      }
-    }
-
-    public override bool Equals(object other) {
-      return Equals(other as UniformParams);
-    }
-
-    public bool Equals(UniformParams other) {
-      if (ReferenceEquals(other, null)) {
-        return false;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (InterarrivalLo != other.InterarrivalLo) return false;
-      if (InterarrivalHi != other.InterarrivalHi) return false;
-      return true;
-    }
-
-    public override int GetHashCode() {
-      int hash = 1;
-      if (InterarrivalLo != 0D) hash ^= InterarrivalLo.GetHashCode();
-      if (InterarrivalHi != 0D) hash ^= InterarrivalHi.GetHashCode();
-      return hash;
-    }
-
-    public override string ToString() {
-      return pb::JsonFormatter.ToDiagnosticString(this);
-    }
-
-    public void WriteTo(pb::CodedOutputStream output) {
-      if (InterarrivalLo != 0D) {
-        output.WriteRawTag(9);
-        output.WriteDouble(InterarrivalLo);
-      }
-      if (InterarrivalHi != 0D) {
-        output.WriteRawTag(17);
-        output.WriteDouble(InterarrivalHi);
-      }
-    }
-
-    public int CalculateSize() {
-      int size = 0;
-      if (InterarrivalLo != 0D) {
-        size += 1 + 8;
-      }
-      if (InterarrivalHi != 0D) {
-        size += 1 + 8;
-      }
-      return size;
-    }
-
-    public void MergeFrom(UniformParams other) {
-      if (other == null) {
-        return;
-      }
-      if (other.InterarrivalLo != 0D) {
-        InterarrivalLo = other.InterarrivalLo;
-      }
-      if (other.InterarrivalHi != 0D) {
-        InterarrivalHi = other.InterarrivalHi;
-      }
-    }
-
-    public void MergeFrom(pb::CodedInputStream input) {
-      uint tag;
-      while ((tag = input.ReadTag()) != 0) {
-        switch(tag) {
-          default:
-            input.SkipLastField();
-            break;
-          case 9: {
-            InterarrivalLo = input.ReadDouble();
-            break;
-          }
-          case 17: {
-            InterarrivalHi = input.ReadDouble();
-            break;
-          }
-        }
-      }
-    }
-
-  }
-
-  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class DeterministicParams : pb::IMessage<DeterministicParams> {
-    private static readonly pb::MessageParser<DeterministicParams> _parser = new pb::MessageParser<DeterministicParams>(() => new DeterministicParams());
-    public static pb::MessageParser<DeterministicParams> Parser { get { return _parser; } }
-
-    public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[2]; }
-    }
-
-    pbr::MessageDescriptor pb::IMessage.Descriptor {
-      get { return Descriptor; }
-    }
-
-    public DeterministicParams() {
-      OnConstruction();
-    }
-
-    partial void OnConstruction();
-
-    public DeterministicParams(DeterministicParams other) : this() {
-      offeredLoad_ = other.offeredLoad_;
-    }
-
-    public DeterministicParams Clone() {
-      return new DeterministicParams(this);
-    }
-
-    /// <summary>Field number for the "offered_load" field.</summary>
-    public const int OfferedLoadFieldNumber = 1;
-    private double offeredLoad_;
-    public double OfferedLoad {
-      get { return offeredLoad_; }
-      set {
-        offeredLoad_ = value;
-      }
-    }
-
-    public override bool Equals(object other) {
-      return Equals(other as DeterministicParams);
-    }
-
-    public bool Equals(DeterministicParams other) {
-      if (ReferenceEquals(other, null)) {
-        return false;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (OfferedLoad != other.OfferedLoad) return false;
-      return true;
-    }
-
-    public override int GetHashCode() {
-      int hash = 1;
-      if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
-      return hash;
-    }
-
-    public override string ToString() {
-      return pb::JsonFormatter.ToDiagnosticString(this);
-    }
-
-    public void WriteTo(pb::CodedOutputStream output) {
-      if (OfferedLoad != 0D) {
-        output.WriteRawTag(9);
-        output.WriteDouble(OfferedLoad);
-      }
-    }
-
-    public int CalculateSize() {
-      int size = 0;
-      if (OfferedLoad != 0D) {
-        size += 1 + 8;
-      }
-      return size;
-    }
-
-    public void MergeFrom(DeterministicParams other) {
-      if (other == null) {
-        return;
-      }
-      if (other.OfferedLoad != 0D) {
-        OfferedLoad = other.OfferedLoad;
-      }
-    }
-
-    public void MergeFrom(pb::CodedInputStream input) {
-      uint tag;
-      while ((tag = input.ReadTag()) != 0) {
-        switch(tag) {
-          default:
-            input.SkipLastField();
-            break;
-          case 9: {
-            OfferedLoad = input.ReadDouble();
-            break;
-          }
-        }
-      }
-    }
-
-  }
-
-  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ParetoParams : pb::IMessage<ParetoParams> {
-    private static readonly pb::MessageParser<ParetoParams> _parser = new pb::MessageParser<ParetoParams>(() => new ParetoParams());
-    public static pb::MessageParser<ParetoParams> Parser { get { return _parser; } }
-
-    public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[3]; }
-    }
-
-    pbr::MessageDescriptor pb::IMessage.Descriptor {
-      get { return Descriptor; }
-    }
-
-    public ParetoParams() {
-      OnConstruction();
-    }
-
-    partial void OnConstruction();
-
-    public ParetoParams(ParetoParams other) : this() {
-      interarrivalBase_ = other.interarrivalBase_;
-      alpha_ = other.alpha_;
-    }
-
-    public ParetoParams Clone() {
-      return new ParetoParams(this);
-    }
-
-    /// <summary>Field number for the "interarrival_base" field.</summary>
-    public const int InterarrivalBaseFieldNumber = 1;
-    private double interarrivalBase_;
-    public double InterarrivalBase {
-      get { return interarrivalBase_; }
-      set {
-        interarrivalBase_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "alpha" field.</summary>
-    public const int AlphaFieldNumber = 2;
-    private double alpha_;
-    public double Alpha {
-      get { return alpha_; }
-      set {
-        alpha_ = value;
-      }
-    }
-
-    public override bool Equals(object other) {
-      return Equals(other as ParetoParams);
-    }
-
-    public bool Equals(ParetoParams other) {
-      if (ReferenceEquals(other, null)) {
-        return false;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (InterarrivalBase != other.InterarrivalBase) return false;
-      if (Alpha != other.Alpha) return false;
-      return true;
-    }
-
-    public override int GetHashCode() {
-      int hash = 1;
-      if (InterarrivalBase != 0D) hash ^= InterarrivalBase.GetHashCode();
-      if (Alpha != 0D) hash ^= Alpha.GetHashCode();
-      return hash;
-    }
-
-    public override string ToString() {
-      return pb::JsonFormatter.ToDiagnosticString(this);
-    }
-
-    public void WriteTo(pb::CodedOutputStream output) {
-      if (InterarrivalBase != 0D) {
-        output.WriteRawTag(9);
-        output.WriteDouble(InterarrivalBase);
-      }
-      if (Alpha != 0D) {
-        output.WriteRawTag(17);
-        output.WriteDouble(Alpha);
-      }
-    }
-
-    public int CalculateSize() {
-      int size = 0;
-      if (InterarrivalBase != 0D) {
-        size += 1 + 8;
-      }
-      if (Alpha != 0D) {
-        size += 1 + 8;
-      }
-      return size;
-    }
-
-    public void MergeFrom(ParetoParams other) {
-      if (other == null) {
-        return;
-      }
-      if (other.InterarrivalBase != 0D) {
-        InterarrivalBase = other.InterarrivalBase;
-      }
-      if (other.Alpha != 0D) {
-        Alpha = other.Alpha;
-      }
-    }
-
-    public void MergeFrom(pb::CodedInputStream input) {
-      uint tag;
-      while ((tag = input.ReadTag()) != 0) {
-        switch(tag) {
-          default:
-            input.SkipLastField();
-            break;
-          case 9: {
-            InterarrivalBase = input.ReadDouble();
-            break;
-          }
-          case 17: {
-            Alpha = input.ReadDouble();
-            break;
-          }
-        }
-      }
-    }
-
-  }
-
   /// <summary>
   ///  Once an RPC finishes, immediately start a new one.
   ///  No configuration parameters needed.
@@ -597,7 +261,7 @@
     public static pb::MessageParser<ClosedLoopParams> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[1]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -673,7 +337,7 @@
     public static pb::MessageParser<LoadParams> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[2]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -694,15 +358,6 @@
         case LoadOneofCase.Poisson:
           Poisson = other.Poisson.Clone();
           break;
-        case LoadOneofCase.Uniform:
-          Uniform = other.Uniform.Clone();
-          break;
-        case LoadOneofCase.Determ:
-          Determ = other.Determ.Clone();
-          break;
-        case LoadOneofCase.Pareto:
-          Pareto = other.Pareto.Clone();
-          break;
       }
 
     }
@@ -731,45 +386,12 @@
       }
     }
 
-    /// <summary>Field number for the "uniform" field.</summary>
-    public const int UniformFieldNumber = 3;
-    public global::Grpc.Testing.UniformParams Uniform {
-      get { return loadCase_ == LoadOneofCase.Uniform ? (global::Grpc.Testing.UniformParams) load_ : null; }
-      set {
-        load_ = value;
-        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Uniform;
-      }
-    }
-
-    /// <summary>Field number for the "determ" field.</summary>
-    public const int DetermFieldNumber = 4;
-    public global::Grpc.Testing.DeterministicParams Determ {
-      get { return loadCase_ == LoadOneofCase.Determ ? (global::Grpc.Testing.DeterministicParams) load_ : null; }
-      set {
-        load_ = value;
-        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Determ;
-      }
-    }
-
-    /// <summary>Field number for the "pareto" field.</summary>
-    public const int ParetoFieldNumber = 5;
-    public global::Grpc.Testing.ParetoParams Pareto {
-      get { return loadCase_ == LoadOneofCase.Pareto ? (global::Grpc.Testing.ParetoParams) load_ : null; }
-      set {
-        load_ = value;
-        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Pareto;
-      }
-    }
-
     private object load_;
     /// <summary>Enum of possible cases for the "load" oneof.</summary>
     public enum LoadOneofCase {
       None = 0,
       ClosedLoop = 1,
       Poisson = 2,
-      Uniform = 3,
-      Determ = 4,
-      Pareto = 5,
     }
     private LoadOneofCase loadCase_ = LoadOneofCase.None;
     public LoadOneofCase LoadCase {
@@ -794,9 +416,6 @@
       }
       if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false;
       if (!object.Equals(Poisson, other.Poisson)) return false;
-      if (!object.Equals(Uniform, other.Uniform)) return false;
-      if (!object.Equals(Determ, other.Determ)) return false;
-      if (!object.Equals(Pareto, other.Pareto)) return false;
       if (LoadCase != other.LoadCase) return false;
       return true;
     }
@@ -805,9 +424,6 @@
       int hash = 1;
       if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
       if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
-      if (loadCase_ == LoadOneofCase.Uniform) hash ^= Uniform.GetHashCode();
-      if (loadCase_ == LoadOneofCase.Determ) hash ^= Determ.GetHashCode();
-      if (loadCase_ == LoadOneofCase.Pareto) hash ^= Pareto.GetHashCode();
       hash ^= (int) loadCase_;
       return hash;
     }
@@ -825,18 +441,6 @@
         output.WriteRawTag(18);
         output.WriteMessage(Poisson);
       }
-      if (loadCase_ == LoadOneofCase.Uniform) {
-        output.WriteRawTag(26);
-        output.WriteMessage(Uniform);
-      }
-      if (loadCase_ == LoadOneofCase.Determ) {
-        output.WriteRawTag(34);
-        output.WriteMessage(Determ);
-      }
-      if (loadCase_ == LoadOneofCase.Pareto) {
-        output.WriteRawTag(42);
-        output.WriteMessage(Pareto);
-      }
     }
 
     public int CalculateSize() {
@@ -847,15 +451,6 @@
       if (loadCase_ == LoadOneofCase.Poisson) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson);
       }
-      if (loadCase_ == LoadOneofCase.Uniform) {
-        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Uniform);
-      }
-      if (loadCase_ == LoadOneofCase.Determ) {
-        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Determ);
-      }
-      if (loadCase_ == LoadOneofCase.Pareto) {
-        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Pareto);
-      }
       return size;
     }
 
@@ -870,15 +465,6 @@
         case LoadOneofCase.Poisson:
           Poisson = other.Poisson;
           break;
-        case LoadOneofCase.Uniform:
-          Uniform = other.Uniform;
-          break;
-        case LoadOneofCase.Determ:
-          Determ = other.Determ;
-          break;
-        case LoadOneofCase.Pareto:
-          Pareto = other.Pareto;
-          break;
       }
 
     }
@@ -908,33 +494,6 @@
             Poisson = subBuilder;
             break;
           }
-          case 26: {
-            global::Grpc.Testing.UniformParams subBuilder = new global::Grpc.Testing.UniformParams();
-            if (loadCase_ == LoadOneofCase.Uniform) {
-              subBuilder.MergeFrom(Uniform);
-            }
-            input.ReadMessage(subBuilder);
-            Uniform = subBuilder;
-            break;
-          }
-          case 34: {
-            global::Grpc.Testing.DeterministicParams subBuilder = new global::Grpc.Testing.DeterministicParams();
-            if (loadCase_ == LoadOneofCase.Determ) {
-              subBuilder.MergeFrom(Determ);
-            }
-            input.ReadMessage(subBuilder);
-            Determ = subBuilder;
-            break;
-          }
-          case 42: {
-            global::Grpc.Testing.ParetoParams subBuilder = new global::Grpc.Testing.ParetoParams();
-            if (loadCase_ == LoadOneofCase.Pareto) {
-              subBuilder.MergeFrom(Pareto);
-            }
-            input.ReadMessage(subBuilder);
-            Pareto = subBuilder;
-            break;
-          }
         }
       }
     }
@@ -950,7 +509,7 @@
     public static pb::MessageParser<SecurityParams> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[3]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -1080,7 +639,7 @@
     public static pb::MessageParser<ClientConfig> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -1106,6 +665,7 @@
       HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null;
       coreList_ = other.coreList_.Clone();
       coreLimit_ = other.coreLimit_;
+      otherClientApi_ = other.otherClientApi_;
     }
 
     public ClientConfig Clone() {
@@ -1250,6 +810,19 @@
       }
     }
 
+    /// <summary>Field number for the "other_client_api" field.</summary>
+    public const int OtherClientApiFieldNumber = 15;
+    private string otherClientApi_ = "";
+    /// <summary>
+    ///  If we use an OTHER_CLIENT client_type, this string gives more detail
+    /// </summary>
+    public string OtherClientApi {
+      get { return otherClientApi_; }
+      set {
+        otherClientApi_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
     public override bool Equals(object other) {
       return Equals(other as ClientConfig);
     }
@@ -1273,6 +846,7 @@
       if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
       if(!coreList_.Equals(other.coreList_)) return false;
       if (CoreLimit != other.CoreLimit) return false;
+      if (OtherClientApi != other.OtherClientApi) return false;
       return true;
     }
 
@@ -1290,6 +864,7 @@
       if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
       hash ^= coreList_.GetHashCode();
       if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
+      if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode();
       return hash;
     }
 
@@ -1340,6 +915,10 @@
         output.WriteRawTag(112);
         output.WriteInt32(CoreLimit);
       }
+      if (OtherClientApi.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteString(OtherClientApi);
+      }
     }
 
     public int CalculateSize() {
@@ -1376,6 +955,9 @@
       if (CoreLimit != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
       }
+      if (OtherClientApi.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi);
+      }
       return size;
     }
 
@@ -1427,6 +1009,9 @@
       if (other.CoreLimit != 0) {
         CoreLimit = other.CoreLimit;
       }
+      if (other.OtherClientApi.Length != 0) {
+        OtherClientApi = other.OtherClientApi;
+      }
     }
 
     public void MergeFrom(pb::CodedInputStream input) {
@@ -1497,6 +1082,10 @@
             CoreLimit = input.ReadInt32();
             break;
           }
+          case 122: {
+            OtherClientApi = input.ReadString();
+            break;
+          }
         }
       }
     }
@@ -1509,7 +1098,7 @@
     public static pb::MessageParser<ClientStatus> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -1621,7 +1210,7 @@
     public static pb::MessageParser<Mark> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -1727,7 +1316,7 @@
     public static pb::MessageParser<ClientArgs> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -1896,7 +1485,7 @@
     public static pb::MessageParser<ServerConfig> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -1917,6 +1506,7 @@
       coreLimit_ = other.coreLimit_;
       PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
       coreList_ = other.coreList_.Clone();
+      otherServerApi_ = other.otherServerApi_;
     }
 
     public ServerConfig Clone() {
@@ -2007,6 +1597,19 @@
       get { return coreList_; }
     }
 
+    /// <summary>Field number for the "other_server_api" field.</summary>
+    public const int OtherServerApiFieldNumber = 11;
+    private string otherServerApi_ = "";
+    /// <summary>
+    ///  If we use an OTHER_SERVER client_type, this string gives more detail
+    /// </summary>
+    public string OtherServerApi {
+      get { return otherServerApi_; }
+      set {
+        otherServerApi_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
     public override bool Equals(object other) {
       return Equals(other as ServerConfig);
     }
@@ -2025,6 +1628,7 @@
       if (CoreLimit != other.CoreLimit) return false;
       if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
       if(!coreList_.Equals(other.coreList_)) return false;
+      if (OtherServerApi != other.OtherServerApi) return false;
       return true;
     }
 
@@ -2037,6 +1641,7 @@
       if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
       if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
       hash ^= coreList_.GetHashCode();
+      if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode();
       return hash;
     }
 
@@ -2070,6 +1675,10 @@
         output.WriteMessage(PayloadConfig);
       }
       coreList_.WriteTo(output, _repeated_coreList_codec);
+      if (OtherServerApi.Length != 0) {
+        output.WriteRawTag(90);
+        output.WriteString(OtherServerApi);
+      }
     }
 
     public int CalculateSize() {
@@ -2093,6 +1702,9 @@
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
       }
       size += coreList_.CalculateSize(_repeated_coreList_codec);
+      if (OtherServerApi.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi);
+      }
       return size;
     }
 
@@ -2125,6 +1737,9 @@
         PayloadConfig.MergeFrom(other.PayloadConfig);
       }
       coreList_.Add(other.coreList_);
+      if (other.OtherServerApi.Length != 0) {
+        OtherServerApi = other.OtherServerApi;
+      }
     }
 
     public void MergeFrom(pb::CodedInputStream input) {
@@ -2169,6 +1784,10 @@
             coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
             break;
           }
+          case 90: {
+            OtherServerApi = input.ReadString();
+            break;
+          }
         }
       }
     }
@@ -2181,7 +1800,7 @@
     public static pb::MessageParser<ServerArgs> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -2350,7 +1969,7 @@
     public static pb::MessageParser<ServerStatus> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -2519,7 +2138,7 @@
     public static pb::MessageParser<CoreRequest> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -2595,7 +2214,7 @@
     public static pb::MessageParser<CoreResponse> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -2701,7 +2320,7 @@
     public static pb::MessageParser<Void> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; }
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -2771,6 +2390,1087 @@
 
   }
 
+  /// <summary>
+  ///  A single performance scenario: input to qps_json_driver
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Scenario : pb::IMessage<Scenario> {
+    private static readonly pb::MessageParser<Scenario> _parser = new pb::MessageParser<Scenario>(() => new Scenario());
+    public static pb::MessageParser<Scenario> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Scenario() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Scenario(Scenario other) : this() {
+      name_ = other.name_;
+      ClientConfig = other.clientConfig_ != null ? other.ClientConfig.Clone() : null;
+      numClients_ = other.numClients_;
+      ServerConfig = other.serverConfig_ != null ? other.ServerConfig.Clone() : null;
+      numServers_ = other.numServers_;
+      warmupSeconds_ = other.warmupSeconds_;
+      benchmarkSeconds_ = other.benchmarkSeconds_;
+      spawnLocalWorkerCount_ = other.spawnLocalWorkerCount_;
+    }
+
+    public Scenario Clone() {
+      return new Scenario(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  Human readable name for this scenario
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "client_config" field.</summary>
+    public const int ClientConfigFieldNumber = 2;
+    private global::Grpc.Testing.ClientConfig clientConfig_;
+    /// <summary>
+    ///  Client configuration
+    /// </summary>
+    public global::Grpc.Testing.ClientConfig ClientConfig {
+      get { return clientConfig_; }
+      set {
+        clientConfig_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "num_clients" field.</summary>
+    public const int NumClientsFieldNumber = 3;
+    private int numClients_;
+    /// <summary>
+    ///  Number of clients to start for the test
+    /// </summary>
+    public int NumClients {
+      get { return numClients_; }
+      set {
+        numClients_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "server_config" field.</summary>
+    public const int ServerConfigFieldNumber = 4;
+    private global::Grpc.Testing.ServerConfig serverConfig_;
+    /// <summary>
+    ///  Server configuration
+    /// </summary>
+    public global::Grpc.Testing.ServerConfig ServerConfig {
+      get { return serverConfig_; }
+      set {
+        serverConfig_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "num_servers" field.</summary>
+    public const int NumServersFieldNumber = 5;
+    private int numServers_;
+    /// <summary>
+    ///  Number of servers to start for the test
+    /// </summary>
+    public int NumServers {
+      get { return numServers_; }
+      set {
+        numServers_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "warmup_seconds" field.</summary>
+    public const int WarmupSecondsFieldNumber = 6;
+    private int warmupSeconds_;
+    /// <summary>
+    ///  Warmup period, in seconds
+    /// </summary>
+    public int WarmupSeconds {
+      get { return warmupSeconds_; }
+      set {
+        warmupSeconds_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "benchmark_seconds" field.</summary>
+    public const int BenchmarkSecondsFieldNumber = 7;
+    private int benchmarkSeconds_;
+    /// <summary>
+    ///  Benchmark time, in seconds
+    /// </summary>
+    public int BenchmarkSeconds {
+      get { return benchmarkSeconds_; }
+      set {
+        benchmarkSeconds_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "spawn_local_worker_count" field.</summary>
+    public const int SpawnLocalWorkerCountFieldNumber = 8;
+    private int spawnLocalWorkerCount_;
+    /// <summary>
+    ///  Number of workers to spawn locally (usually zero)
+    /// </summary>
+    public int SpawnLocalWorkerCount {
+      get { return spawnLocalWorkerCount_; }
+      set {
+        spawnLocalWorkerCount_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Scenario);
+    }
+
+    public bool Equals(Scenario other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (!object.Equals(ClientConfig, other.ClientConfig)) return false;
+      if (NumClients != other.NumClients) return false;
+      if (!object.Equals(ServerConfig, other.ServerConfig)) return false;
+      if (NumServers != other.NumServers) return false;
+      if (WarmupSeconds != other.WarmupSeconds) return false;
+      if (BenchmarkSeconds != other.BenchmarkSeconds) return false;
+      if (SpawnLocalWorkerCount != other.SpawnLocalWorkerCount) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (clientConfig_ != null) hash ^= ClientConfig.GetHashCode();
+      if (NumClients != 0) hash ^= NumClients.GetHashCode();
+      if (serverConfig_ != null) hash ^= ServerConfig.GetHashCode();
+      if (NumServers != 0) hash ^= NumServers.GetHashCode();
+      if (WarmupSeconds != 0) hash ^= WarmupSeconds.GetHashCode();
+      if (BenchmarkSeconds != 0) hash ^= BenchmarkSeconds.GetHashCode();
+      if (SpawnLocalWorkerCount != 0) hash ^= SpawnLocalWorkerCount.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (clientConfig_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(ClientConfig);
+      }
+      if (NumClients != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(NumClients);
+      }
+      if (serverConfig_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(ServerConfig);
+      }
+      if (NumServers != 0) {
+        output.WriteRawTag(40);
+        output.WriteInt32(NumServers);
+      }
+      if (WarmupSeconds != 0) {
+        output.WriteRawTag(48);
+        output.WriteInt32(WarmupSeconds);
+      }
+      if (BenchmarkSeconds != 0) {
+        output.WriteRawTag(56);
+        output.WriteInt32(BenchmarkSeconds);
+      }
+      if (SpawnLocalWorkerCount != 0) {
+        output.WriteRawTag(64);
+        output.WriteInt32(SpawnLocalWorkerCount);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (clientConfig_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClientConfig);
+      }
+      if (NumClients != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumClients);
+      }
+      if (serverConfig_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ServerConfig);
+      }
+      if (NumServers != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumServers);
+      }
+      if (WarmupSeconds != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(WarmupSeconds);
+      }
+      if (BenchmarkSeconds != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(BenchmarkSeconds);
+      }
+      if (SpawnLocalWorkerCount != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(SpawnLocalWorkerCount);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Scenario other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.clientConfig_ != null) {
+        if (clientConfig_ == null) {
+          clientConfig_ = new global::Grpc.Testing.ClientConfig();
+        }
+        ClientConfig.MergeFrom(other.ClientConfig);
+      }
+      if (other.NumClients != 0) {
+        NumClients = other.NumClients;
+      }
+      if (other.serverConfig_ != null) {
+        if (serverConfig_ == null) {
+          serverConfig_ = new global::Grpc.Testing.ServerConfig();
+        }
+        ServerConfig.MergeFrom(other.ServerConfig);
+      }
+      if (other.NumServers != 0) {
+        NumServers = other.NumServers;
+      }
+      if (other.WarmupSeconds != 0) {
+        WarmupSeconds = other.WarmupSeconds;
+      }
+      if (other.BenchmarkSeconds != 0) {
+        BenchmarkSeconds = other.BenchmarkSeconds;
+      }
+      if (other.SpawnLocalWorkerCount != 0) {
+        SpawnLocalWorkerCount = other.SpawnLocalWorkerCount;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            if (clientConfig_ == null) {
+              clientConfig_ = new global::Grpc.Testing.ClientConfig();
+            }
+            input.ReadMessage(clientConfig_);
+            break;
+          }
+          case 24: {
+            NumClients = input.ReadInt32();
+            break;
+          }
+          case 34: {
+            if (serverConfig_ == null) {
+              serverConfig_ = new global::Grpc.Testing.ServerConfig();
+            }
+            input.ReadMessage(serverConfig_);
+            break;
+          }
+          case 40: {
+            NumServers = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            WarmupSeconds = input.ReadInt32();
+            break;
+          }
+          case 56: {
+            BenchmarkSeconds = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            SpawnLocalWorkerCount = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  A set of scenarios to be run with qps_json_driver
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Scenarios : pb::IMessage<Scenarios> {
+    private static readonly pb::MessageParser<Scenarios> _parser = new pb::MessageParser<Scenarios>(() => new Scenarios());
+    public static pb::MessageParser<Scenarios> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Scenarios() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Scenarios(Scenarios other) : this() {
+      scenarios_ = other.scenarios_.Clone();
+    }
+
+    public Scenarios Clone() {
+      return new Scenarios(this);
+    }
+
+    /// <summary>Field number for the "scenarios" field.</summary>
+    public const int Scenarios_FieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Grpc.Testing.Scenario> _repeated_scenarios_codec
+        = pb::FieldCodec.ForMessage(10, global::Grpc.Testing.Scenario.Parser);
+    private readonly pbc::RepeatedField<global::Grpc.Testing.Scenario> scenarios_ = new pbc::RepeatedField<global::Grpc.Testing.Scenario>();
+    public pbc::RepeatedField<global::Grpc.Testing.Scenario> Scenarios_ {
+      get { return scenarios_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Scenarios);
+    }
+
+    public bool Equals(Scenarios other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!scenarios_.Equals(other.scenarios_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= scenarios_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      scenarios_.WriteTo(output, _repeated_scenarios_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += scenarios_.CalculateSize(_repeated_scenarios_codec);
+      return size;
+    }
+
+    public void MergeFrom(Scenarios other) {
+      if (other == null) {
+        return;
+      }
+      scenarios_.Add(other.scenarios_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            scenarios_.AddEntriesFrom(input, _repeated_scenarios_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Basic summary that can be computed from ClientStats and ServerStats
+  ///  once the scenario has finished.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ScenarioResultSummary : pb::IMessage<ScenarioResultSummary> {
+    private static readonly pb::MessageParser<ScenarioResultSummary> _parser = new pb::MessageParser<ScenarioResultSummary>(() => new ScenarioResultSummary());
+    public static pb::MessageParser<ScenarioResultSummary> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ScenarioResultSummary() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ScenarioResultSummary(ScenarioResultSummary other) : this() {
+      qps_ = other.qps_;
+      qpsPerServerCore_ = other.qpsPerServerCore_;
+      serverSystemTime_ = other.serverSystemTime_;
+      serverUserTime_ = other.serverUserTime_;
+      clientSystemTime_ = other.clientSystemTime_;
+      clientUserTime_ = other.clientUserTime_;
+      latency50_ = other.latency50_;
+      latency90_ = other.latency90_;
+      latency95_ = other.latency95_;
+      latency99_ = other.latency99_;
+      latency999_ = other.latency999_;
+    }
+
+    public ScenarioResultSummary Clone() {
+      return new ScenarioResultSummary(this);
+    }
+
+    /// <summary>Field number for the "qps" field.</summary>
+    public const int QpsFieldNumber = 1;
+    private double qps_;
+    /// <summary>
+    ///  Total number of operations per second over all clients.
+    /// </summary>
+    public double Qps {
+      get { return qps_; }
+      set {
+        qps_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "qps_per_server_core" field.</summary>
+    public const int QpsPerServerCoreFieldNumber = 2;
+    private double qpsPerServerCore_;
+    /// <summary>
+    ///  QPS per one server core.
+    /// </summary>
+    public double QpsPerServerCore {
+      get { return qpsPerServerCore_; }
+      set {
+        qpsPerServerCore_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "server_system_time" field.</summary>
+    public const int ServerSystemTimeFieldNumber = 3;
+    private double serverSystemTime_;
+    /// <summary>
+    ///  server load based on system_time (0.85 => 85%)
+    /// </summary>
+    public double ServerSystemTime {
+      get { return serverSystemTime_; }
+      set {
+        serverSystemTime_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "server_user_time" field.</summary>
+    public const int ServerUserTimeFieldNumber = 4;
+    private double serverUserTime_;
+    /// <summary>
+    ///  server load based on user_time (0.85 => 85%)
+    /// </summary>
+    public double ServerUserTime {
+      get { return serverUserTime_; }
+      set {
+        serverUserTime_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "client_system_time" field.</summary>
+    public const int ClientSystemTimeFieldNumber = 5;
+    private double clientSystemTime_;
+    /// <summary>
+    ///  client load based on system_time (0.85 => 85%)
+    /// </summary>
+    public double ClientSystemTime {
+      get { return clientSystemTime_; }
+      set {
+        clientSystemTime_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "client_user_time" field.</summary>
+    public const int ClientUserTimeFieldNumber = 6;
+    private double clientUserTime_;
+    /// <summary>
+    ///  client load based on user_time (0.85 => 85%)
+    /// </summary>
+    public double ClientUserTime {
+      get { return clientUserTime_; }
+      set {
+        clientUserTime_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "latency_50" field.</summary>
+    public const int Latency50FieldNumber = 7;
+    private double latency50_;
+    /// <summary>
+    ///  X% latency percentiles (in nanoseconds)
+    /// </summary>
+    public double Latency50 {
+      get { return latency50_; }
+      set {
+        latency50_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "latency_90" field.</summary>
+    public const int Latency90FieldNumber = 8;
+    private double latency90_;
+    public double Latency90 {
+      get { return latency90_; }
+      set {
+        latency90_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "latency_95" field.</summary>
+    public const int Latency95FieldNumber = 9;
+    private double latency95_;
+    public double Latency95 {
+      get { return latency95_; }
+      set {
+        latency95_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "latency_99" field.</summary>
+    public const int Latency99FieldNumber = 10;
+    private double latency99_;
+    public double Latency99 {
+      get { return latency99_; }
+      set {
+        latency99_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "latency_999" field.</summary>
+    public const int Latency999FieldNumber = 11;
+    private double latency999_;
+    public double Latency999 {
+      get { return latency999_; }
+      set {
+        latency999_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ScenarioResultSummary);
+    }
+
+    public bool Equals(ScenarioResultSummary other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Qps != other.Qps) return false;
+      if (QpsPerServerCore != other.QpsPerServerCore) return false;
+      if (ServerSystemTime != other.ServerSystemTime) return false;
+      if (ServerUserTime != other.ServerUserTime) return false;
+      if (ClientSystemTime != other.ClientSystemTime) return false;
+      if (ClientUserTime != other.ClientUserTime) return false;
+      if (Latency50 != other.Latency50) return false;
+      if (Latency90 != other.Latency90) return false;
+      if (Latency95 != other.Latency95) return false;
+      if (Latency99 != other.Latency99) return false;
+      if (Latency999 != other.Latency999) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Qps != 0D) hash ^= Qps.GetHashCode();
+      if (QpsPerServerCore != 0D) hash ^= QpsPerServerCore.GetHashCode();
+      if (ServerSystemTime != 0D) hash ^= ServerSystemTime.GetHashCode();
+      if (ServerUserTime != 0D) hash ^= ServerUserTime.GetHashCode();
+      if (ClientSystemTime != 0D) hash ^= ClientSystemTime.GetHashCode();
+      if (ClientUserTime != 0D) hash ^= ClientUserTime.GetHashCode();
+      if (Latency50 != 0D) hash ^= Latency50.GetHashCode();
+      if (Latency90 != 0D) hash ^= Latency90.GetHashCode();
+      if (Latency95 != 0D) hash ^= Latency95.GetHashCode();
+      if (Latency99 != 0D) hash ^= Latency99.GetHashCode();
+      if (Latency999 != 0D) hash ^= Latency999.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Qps != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(Qps);
+      }
+      if (QpsPerServerCore != 0D) {
+        output.WriteRawTag(17);
+        output.WriteDouble(QpsPerServerCore);
+      }
+      if (ServerSystemTime != 0D) {
+        output.WriteRawTag(25);
+        output.WriteDouble(ServerSystemTime);
+      }
+      if (ServerUserTime != 0D) {
+        output.WriteRawTag(33);
+        output.WriteDouble(ServerUserTime);
+      }
+      if (ClientSystemTime != 0D) {
+        output.WriteRawTag(41);
+        output.WriteDouble(ClientSystemTime);
+      }
+      if (ClientUserTime != 0D) {
+        output.WriteRawTag(49);
+        output.WriteDouble(ClientUserTime);
+      }
+      if (Latency50 != 0D) {
+        output.WriteRawTag(57);
+        output.WriteDouble(Latency50);
+      }
+      if (Latency90 != 0D) {
+        output.WriteRawTag(65);
+        output.WriteDouble(Latency90);
+      }
+      if (Latency95 != 0D) {
+        output.WriteRawTag(73);
+        output.WriteDouble(Latency95);
+      }
+      if (Latency99 != 0D) {
+        output.WriteRawTag(81);
+        output.WriteDouble(Latency99);
+      }
+      if (Latency999 != 0D) {
+        output.WriteRawTag(89);
+        output.WriteDouble(Latency999);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Qps != 0D) {
+        size += 1 + 8;
+      }
+      if (QpsPerServerCore != 0D) {
+        size += 1 + 8;
+      }
+      if (ServerSystemTime != 0D) {
+        size += 1 + 8;
+      }
+      if (ServerUserTime != 0D) {
+        size += 1 + 8;
+      }
+      if (ClientSystemTime != 0D) {
+        size += 1 + 8;
+      }
+      if (ClientUserTime != 0D) {
+        size += 1 + 8;
+      }
+      if (Latency50 != 0D) {
+        size += 1 + 8;
+      }
+      if (Latency90 != 0D) {
+        size += 1 + 8;
+      }
+      if (Latency95 != 0D) {
+        size += 1 + 8;
+      }
+      if (Latency99 != 0D) {
+        size += 1 + 8;
+      }
+      if (Latency999 != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(ScenarioResultSummary other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Qps != 0D) {
+        Qps = other.Qps;
+      }
+      if (other.QpsPerServerCore != 0D) {
+        QpsPerServerCore = other.QpsPerServerCore;
+      }
+      if (other.ServerSystemTime != 0D) {
+        ServerSystemTime = other.ServerSystemTime;
+      }
+      if (other.ServerUserTime != 0D) {
+        ServerUserTime = other.ServerUserTime;
+      }
+      if (other.ClientSystemTime != 0D) {
+        ClientSystemTime = other.ClientSystemTime;
+      }
+      if (other.ClientUserTime != 0D) {
+        ClientUserTime = other.ClientUserTime;
+      }
+      if (other.Latency50 != 0D) {
+        Latency50 = other.Latency50;
+      }
+      if (other.Latency90 != 0D) {
+        Latency90 = other.Latency90;
+      }
+      if (other.Latency95 != 0D) {
+        Latency95 = other.Latency95;
+      }
+      if (other.Latency99 != 0D) {
+        Latency99 = other.Latency99;
+      }
+      if (other.Latency999 != 0D) {
+        Latency999 = other.Latency999;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            Qps = input.ReadDouble();
+            break;
+          }
+          case 17: {
+            QpsPerServerCore = input.ReadDouble();
+            break;
+          }
+          case 25: {
+            ServerSystemTime = input.ReadDouble();
+            break;
+          }
+          case 33: {
+            ServerUserTime = input.ReadDouble();
+            break;
+          }
+          case 41: {
+            ClientSystemTime = input.ReadDouble();
+            break;
+          }
+          case 49: {
+            ClientUserTime = input.ReadDouble();
+            break;
+          }
+          case 57: {
+            Latency50 = input.ReadDouble();
+            break;
+          }
+          case 65: {
+            Latency90 = input.ReadDouble();
+            break;
+          }
+          case 73: {
+            Latency95 = input.ReadDouble();
+            break;
+          }
+          case 81: {
+            Latency99 = input.ReadDouble();
+            break;
+          }
+          case 89: {
+            Latency999 = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Results of a single benchmark scenario.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ScenarioResult : pb::IMessage<ScenarioResult> {
+    private static readonly pb::MessageParser<ScenarioResult> _parser = new pb::MessageParser<ScenarioResult>(() => new ScenarioResult());
+    public static pb::MessageParser<ScenarioResult> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[17]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ScenarioResult() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ScenarioResult(ScenarioResult other) : this() {
+      Scenario = other.scenario_ != null ? other.Scenario.Clone() : null;
+      Latencies = other.latencies_ != null ? other.Latencies.Clone() : null;
+      clientStats_ = other.clientStats_.Clone();
+      serverStats_ = other.serverStats_.Clone();
+      serverCores_ = other.serverCores_.Clone();
+      Summary = other.summary_ != null ? other.Summary.Clone() : null;
+    }
+
+    public ScenarioResult Clone() {
+      return new ScenarioResult(this);
+    }
+
+    /// <summary>Field number for the "scenario" field.</summary>
+    public const int ScenarioFieldNumber = 1;
+    private global::Grpc.Testing.Scenario scenario_;
+    /// <summary>
+    ///  Inputs used to run the scenario.
+    /// </summary>
+    public global::Grpc.Testing.Scenario Scenario {
+      get { return scenario_; }
+      set {
+        scenario_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "latencies" field.</summary>
+    public const int LatenciesFieldNumber = 2;
+    private global::Grpc.Testing.HistogramData latencies_;
+    /// <summary>
+    ///  Histograms from all clients merged into one histogram.
+    /// </summary>
+    public global::Grpc.Testing.HistogramData Latencies {
+      get { return latencies_; }
+      set {
+        latencies_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "client_stats" field.</summary>
+    public const int ClientStatsFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Grpc.Testing.ClientStats> _repeated_clientStats_codec
+        = pb::FieldCodec.ForMessage(26, global::Grpc.Testing.ClientStats.Parser);
+    private readonly pbc::RepeatedField<global::Grpc.Testing.ClientStats> clientStats_ = new pbc::RepeatedField<global::Grpc.Testing.ClientStats>();
+    /// <summary>
+    ///  Client stats for each client
+    /// </summary>
+    public pbc::RepeatedField<global::Grpc.Testing.ClientStats> ClientStats {
+      get { return clientStats_; }
+    }
+
+    /// <summary>Field number for the "server_stats" field.</summary>
+    public const int ServerStatsFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Grpc.Testing.ServerStats> _repeated_serverStats_codec
+        = pb::FieldCodec.ForMessage(34, global::Grpc.Testing.ServerStats.Parser);
+    private readonly pbc::RepeatedField<global::Grpc.Testing.ServerStats> serverStats_ = new pbc::RepeatedField<global::Grpc.Testing.ServerStats>();
+    /// <summary>
+    ///  Server stats for each server
+    /// </summary>
+    public pbc::RepeatedField<global::Grpc.Testing.ServerStats> ServerStats {
+      get { return serverStats_; }
+    }
+
+    /// <summary>Field number for the "server_cores" field.</summary>
+    public const int ServerCoresFieldNumber = 5;
+    private static readonly pb::FieldCodec<int> _repeated_serverCores_codec
+        = pb::FieldCodec.ForInt32(42);
+    private readonly pbc::RepeatedField<int> serverCores_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Number of cores available to each server
+    /// </summary>
+    public pbc::RepeatedField<int> ServerCores {
+      get { return serverCores_; }
+    }
+
+    /// <summary>Field number for the "summary" field.</summary>
+    public const int SummaryFieldNumber = 6;
+    private global::Grpc.Testing.ScenarioResultSummary summary_;
+    /// <summary>
+    ///  An after-the-fact computed summary
+    /// </summary>
+    public global::Grpc.Testing.ScenarioResultSummary Summary {
+      get { return summary_; }
+      set {
+        summary_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ScenarioResult);
+    }
+
+    public bool Equals(ScenarioResult other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Scenario, other.Scenario)) return false;
+      if (!object.Equals(Latencies, other.Latencies)) return false;
+      if(!clientStats_.Equals(other.clientStats_)) return false;
+      if(!serverStats_.Equals(other.serverStats_)) return false;
+      if(!serverCores_.Equals(other.serverCores_)) return false;
+      if (!object.Equals(Summary, other.Summary)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (scenario_ != null) hash ^= Scenario.GetHashCode();
+      if (latencies_ != null) hash ^= Latencies.GetHashCode();
+      hash ^= clientStats_.GetHashCode();
+      hash ^= serverStats_.GetHashCode();
+      hash ^= serverCores_.GetHashCode();
+      if (summary_ != null) hash ^= Summary.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (scenario_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Scenario);
+      }
+      if (latencies_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Latencies);
+      }
+      clientStats_.WriteTo(output, _repeated_clientStats_codec);
+      serverStats_.WriteTo(output, _repeated_serverStats_codec);
+      serverCores_.WriteTo(output, _repeated_serverCores_codec);
+      if (summary_ != null) {
+        output.WriteRawTag(50);
+        output.WriteMessage(Summary);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (scenario_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Scenario);
+      }
+      if (latencies_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies);
+      }
+      size += clientStats_.CalculateSize(_repeated_clientStats_codec);
+      size += serverStats_.CalculateSize(_repeated_serverStats_codec);
+      size += serverCores_.CalculateSize(_repeated_serverCores_codec);
+      if (summary_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Summary);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ScenarioResult other) {
+      if (other == null) {
+        return;
+      }
+      if (other.scenario_ != null) {
+        if (scenario_ == null) {
+          scenario_ = new global::Grpc.Testing.Scenario();
+        }
+        Scenario.MergeFrom(other.Scenario);
+      }
+      if (other.latencies_ != null) {
+        if (latencies_ == null) {
+          latencies_ = new global::Grpc.Testing.HistogramData();
+        }
+        Latencies.MergeFrom(other.Latencies);
+      }
+      clientStats_.Add(other.clientStats_);
+      serverStats_.Add(other.serverStats_);
+      serverCores_.Add(other.serverCores_);
+      if (other.summary_ != null) {
+        if (summary_ == null) {
+          summary_ = new global::Grpc.Testing.ScenarioResultSummary();
+        }
+        Summary.MergeFrom(other.Summary);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (scenario_ == null) {
+              scenario_ = new global::Grpc.Testing.Scenario();
+            }
+            input.ReadMessage(scenario_);
+            break;
+          }
+          case 18: {
+            if (latencies_ == null) {
+              latencies_ = new global::Grpc.Testing.HistogramData();
+            }
+            input.ReadMessage(latencies_);
+            break;
+          }
+          case 26: {
+            clientStats_.AddEntriesFrom(input, _repeated_clientStats_codec);
+            break;
+          }
+          case 34: {
+            serverStats_.AddEntriesFrom(input, _repeated_serverStats_codec);
+            break;
+          }
+          case 42:
+          case 40: {
+            serverCores_.AddEntriesFrom(input, _repeated_serverCores_codec);
+            break;
+          }
+          case 50: {
+            if (summary_ == null) {
+              summary_ = new global::Grpc.Testing.ScenarioResultSummary();
+            }
+            input.ReadMessage(summary_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
   #endregion
 
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs
new file mode 100644
index 0000000..37786b6
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs
@@ -0,0 +1,106 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using Moq;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+    public class GeneratedClientTest
+    {
+        TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient();
+
+        [Test]
+        public void ExpandedParamOverloadCanBeMocked()
+        {
+            var expected = new SimpleResponse();
+
+            var mockClient = new Mock<TestService.TestServiceClient>();
+            // mocking is relatively clumsy because one needs to specify value for all the optional params.
+            mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), null, null, CancellationToken.None)).Returns(expected);
+
+            Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest()));
+        }
+
+        [Test]
+        public void CallOptionsOverloadCanBeMocked()
+        {
+            var expected = new SimpleResponse();
+
+            var mockClient = new Mock<TestService.TestServiceClient>();
+            mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<CallOptions>())).Returns(expected);
+
+            Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest(), new CallOptions()));
+        }
+
+        [Test]
+        public void DefaultMethodStubThrows_UnaryCall()
+        {
+            Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.UnaryCall(new SimpleRequest()));
+        }
+
+        [Test]
+        public void DefaultMethodStubThrows_ClientStreaming()
+        {
+            Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingInputCall());
+        }
+
+        [Test]
+        public void DefaultMethodStubThrows_ServerStreaming()
+        {
+            Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingOutputCall(new StreamingOutputCallRequest()));
+        }
+
+        [Test]
+        public void DefaultMethodStubThrows_DuplexStreaming()
+        {
+            Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.FullDuplexCall());
+        }
+
+        /// <summary>
+        /// Subclass of the generated client that doesn't override any method stubs.
+        /// </summary>
+        private class UnimplementedTestServiceClient : TestService.TestServiceClient
+        {
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs
new file mode 100644
index 0000000..5fd0e14
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs
@@ -0,0 +1,116 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using Moq;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+    public class GeneratedServiceBaseTest
+    {
+        const string Host = "localhost";
+        Server server;
+        Channel channel;
+        TestService.TestServiceClient client;
+
+        [SetUp]
+        public void Init()
+        {
+            server = new Server
+            {
+                Services = { TestService.BindService(new UnimplementedTestServiceImpl()) },
+                Ports = { { Host, ServerPort.PickUnused, SslServerCredentials.Insecure } }
+            };
+            server.Start();
+            channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
+            client = TestService.NewClient(channel);
+        }
+
+        [TearDown]
+        public void Cleanup()
+        {
+            channel.ShutdownAsync().Wait();
+            server.ShutdownAsync().Wait();
+        }
+
+        [Test]
+        public void UnimplementedByDefault_Unary()
+        {
+            var ex = Assert.Throws<RpcException>(() => client.UnaryCall(new SimpleRequest { }));
+            Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
+        }
+
+        [Test]
+        public async Task UnimplementedByDefault_ClientStreaming()
+        {
+            var call = client.StreamingInputCall();
+
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await call);
+            Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
+        }
+
+        [Test]
+        public async Task UnimplementedByDefault_ServerStreamingCall()
+        {
+            var call = client.StreamingOutputCall(new StreamingOutputCallRequest());
+
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
+            Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
+        }
+
+        [Test]
+        public async Task UnimplementedByDefault_DuplexStreamingCall()
+        {
+            var call = client.FullDuplexCall();
+
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
+            Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
+        }
+
+        /// <summary>
+        /// Implementation of TestService that doesn't override any methods.
+        /// </summary>
+        private class UnimplementedTestServiceImpl : TestService.TestServiceBase
+        {
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/GenericService.cs b/src/csharp/Grpc.IntegrationTesting/GenericService.cs
new file mode 100644
index 0000000..c612826
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/GenericService.cs
@@ -0,0 +1,71 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Utility methods for defining and calling a service that doesn't use protobufs
+    /// for serialization/deserialization.
+    /// </summary>
+    public static class GenericService
+    {
+        readonly static Marshaller<byte[]> ByteArrayMarshaller = new Marshaller<byte[]>((b) => b, (b) => b);
+
+        public readonly static Method<byte[], byte[]> StreamingCallMethod = new Method<byte[], byte[]>(
+            MethodType.DuplexStreaming,
+            "grpc.testing.BenchmarkService",
+            "StreamingCall",
+            ByteArrayMarshaller,
+            ByteArrayMarshaller
+        );
+
+        public static ServerServiceDefinition BindHandler(DuplexStreamingServerMethod<byte[], byte[]> handler)
+        {
+            return ServerServiceDefinition.CreateBuilder(StreamingCallMethod.ServiceName)
+                .AddMethod(StreamingCallMethod, handler).Build();
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 3729913..9685cf1 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -4,11 +4,11 @@
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{C61154BA-DD4A-4838-8420-0162A28925E0}</ProjectGuid>
-    <OutputType>Library</OutputType>
+    <OutputType>Exe</OutputType>
     <RootNamespace>Grpc.IntegrationTesting</RootNamespace>
     <AssemblyName>Grpc.IntegrationTesting</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <NuGetPackageImportStamp>6566287f</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>3a1c655d</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -41,57 +41,45 @@
     <Reference Include="CommandLine">
       <HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.dll</HintPath>
-    </Reference>
-    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.10.0.25333, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Auth.1.10.0\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
-    </Reference>
-    <Reference Include="Google.Apis.Core, Version=1.10.0.25331, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Apis.Core.1.10.0\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
-    </Reference>
-    <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>
-    </Reference>
     <Reference Include="Moq">
       <HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
     </Reference>
-    <Reference Include="nunit.framework">
-      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
-    </Reference>
     <Reference Include="System" />
-    <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
-    </Reference>
     <Reference Include="System.Net" />
     <Reference Include="System.Net.Http" />
     <Reference Include="System.Net.Http.WebRequest" />
     <Reference Include="BouncyCastle.Crypto">
       <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
     </Reference>
-    <Reference Include="Microsoft.Threading.Tasks">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
+    <Reference Include="Google.Apis.Auth">
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
     </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
+    <Reference Include="Google.Apis.Auth.PlatformServices">
+      <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
     </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
-      <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
+    <Reference Include="Google.Apis.Core">
+      <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>
     </Reference>
     <Reference Include="Newtonsoft.Json">
       <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
+    <Reference Include="nunit.framework">
+      <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Interactive.Async">
+      <HintPath>..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
+    </Reference>
+    <Reference Include="nunitlite">
+      <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="..\Grpc.Core\Version.cs">
       <Link>Version.cs</Link>
     </Compile>
-    <Compile Include="HeaderInterceptorTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Empty.cs" />
     <Compile Include="Messages.cs" />
@@ -120,6 +108,14 @@
     <Compile Include="WorkerServiceImpl.cs" />
     <Compile Include="QpsWorker.cs" />
     <Compile Include="WallClockStopwatch.cs" />
+    <Compile Include="GenericService.cs" />
+    <Compile Include="GeneratedServiceBaseTest.cs" />
+    <Compile Include="GeneratedClientTest.cs" />
+    <Compile Include="InterarrivalTimers.cs" />
+    <Compile Include="NUnitMain.cs" />
+    <Compile Include="StressTestClient.cs" />
+    <Compile Include="Metrics.cs" />
+    <Compile Include="MetricsGrpc.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
@@ -133,8 +129,9 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <None Include="app.config" />
-    <None Include="packages.config" />
+    <None Include="packages.config">
+      <SubType>Designer</SubType>
+    </None>
     <None Include="data\README">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
@@ -151,11 +148,4 @@
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
-  <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.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\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
-  </Target>
 </Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/HeaderInterceptorTest.cs b/src/csharp/Grpc.IntegrationTesting/HeaderInterceptorTest.cs
deleted file mode 100644
index 1d758b7..0000000
--- a/src/csharp/Grpc.IntegrationTesting/HeaderInterceptorTest.cs
+++ /dev/null
@@ -1,113 +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.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Grpc.Core;
-using Grpc.Core.Utils;
-using Grpc.Testing;
-using NUnit.Framework;
-
-namespace Grpc.IntegrationTesting
-{
-    public class HeaderInterceptorTest
-    {
-        const string Host = "localhost";
-        Server server;
-        Channel channel;
-        TestService.TestServiceClient client;
-
-        [TestFixtureSetUp]
-        public void Init()
-        {
-            server = new Server
-            {
-                Services = { TestService.BindService(new TestServiceImpl()) },
-                Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
-            };
-            server.Start();
-
-            channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
-            client = TestService.NewClient(channel);
-        }
-
-        [TestFixtureTearDown]
-        public void Cleanup()
-        {
-            channel.ShutdownAsync().Wait();
-            server.ShutdownAsync().Wait();
-        }
-
-        [Test]
-        public async Task HeaderInterceptor_CreateMetadata()
-        {
-            var key = "x-grpc-test-echo-initial";
-            client.HeaderInterceptor = new HeaderInterceptor((method, metadata) =>
-            {
-                metadata.Add(key, "ABC");
-            });
-
-            var call = client.UnaryCallAsync(new SimpleRequest());
-            await call;
-
-           var responseHeaders = await call.ResponseHeadersAsync;
-           Assert.AreEqual("ABC", responseHeaders.First((entry) => entry.Key == key).Value);
-        }
-
-        [Test]
-        public async Task HeaderInterceptor_AppendMetadata()
-        {
-            var initialKey = "x-grpc-test-echo-initial";
-            var trailingKey = "x-grpc-test-echo-trailing-bin";
-
-            client.HeaderInterceptor = new HeaderInterceptor((method, metadata) =>
-            {
-                metadata.Add(initialKey, "ABC");
-            });
-
-            var headers = new Metadata
-            {
-                { trailingKey, new byte[] {0xaa} }
-            };
-            var call = client.UnaryCallAsync(new SimpleRequest(), headers: headers);
-            await call;
-
-            var responseHeaders = await call.ResponseHeadersAsync;
-            Assert.AreEqual("ABC", responseHeaders.First((entry) => entry.Key == initialKey).Value);
-            CollectionAssert.AreEqual(new byte[] {0xaa}, call.GetTrailers().First((entry) => entry.Key == trailingKey).ValueBytes);
-        }
-    }
-}
diff --git a/src/csharp/Grpc.IntegrationTesting/Histogram.cs b/src/csharp/Grpc.IntegrationTesting/Histogram.cs
index 08a674d..28d1f07 100644
--- a/src/csharp/Grpc.IntegrationTesting/Histogram.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Histogram.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs b/src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs
new file mode 100644
index 0000000..6492d34
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs
@@ -0,0 +1,148 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    public interface IInterarrivalTimer
+    {
+        void WaitForNext();
+
+        Task WaitForNextAsync();
+    }
+
+    /// <summary>
+    /// Interarrival timer that doesn't wait at all.
+    /// </summary>
+    public class ClosedLoopInterarrivalTimer : IInterarrivalTimer
+    {
+        public ClosedLoopInterarrivalTimer()
+        {
+        }
+
+        public void WaitForNext()
+        {
+            // NOP
+        }
+
+        public Task WaitForNextAsync()
+        {
+            return Task.FromResult<object>(null);
+        }
+    }
+
+    /// <summary>
+    /// Interarrival timer that generates Poisson process load.
+    /// </summary>
+    public class PoissonInterarrivalTimer : IInterarrivalTimer
+    {
+        readonly ExponentialDistribution exponentialDistribution;
+        DateTime? lastEventTime;
+
+        public PoissonInterarrivalTimer(double offeredLoad)
+        {
+            this.exponentialDistribution = new ExponentialDistribution(new Random(), offeredLoad);
+            this.lastEventTime = DateTime.UtcNow;
+        }
+
+        public void WaitForNext()
+        {
+            var waitDuration = GetNextWaitDuration();
+            int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds);
+            if (millisTimeout > 0)
+            {
+                // TODO(jtattermusch): probably only works well for a relatively low interarrival rate
+                Thread.Sleep(millisTimeout);
+            }
+        }
+
+        public async Task WaitForNextAsync()
+        {
+            var waitDuration = GetNextWaitDuration();
+            int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds);
+            if (millisTimeout > 0)
+            {
+                // TODO(jtattermusch): probably only works well for a relatively low interarrival rate
+                await Task.Delay(millisTimeout);
+            }
+        }
+
+        private TimeSpan GetNextWaitDuration()
+        {
+            if (!lastEventTime.HasValue)
+            {
+                this.lastEventTime = DateTime.Now;
+            }
+
+            var origLastEventTime = this.lastEventTime.Value;
+            this.lastEventTime = origLastEventTime + TimeSpan.FromSeconds(exponentialDistribution.Next());
+            return this.lastEventTime.Value - origLastEventTime;
+        }
+
+        /// <summary>
+        /// Exp generator.
+        /// </summary>
+        private class ExponentialDistribution
+        {
+            readonly Random random;
+            readonly double lambda;
+            readonly double lambdaReciprocal;
+
+            public ExponentialDistribution(Random random, double lambda)
+            {
+                this.random = random;
+                this.lambda = lambda;
+                this.lambdaReciprocal = 1.0 / lambda;
+            }
+
+            public double Next()
+            {
+                double uniform = random.NextDouble();
+                // Use 1.0-uni above to avoid NaN if uni is 0
+                return lambdaReciprocal * (-Math.Log(1.0 - uniform));
+            }
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index b0e33e4..5436517 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -217,7 +217,7 @@
             }
         }
 
-        public static void RunEmptyUnary(TestService.ITestServiceClient client)
+        public static void RunEmptyUnary(TestService.TestServiceClient client)
         {
             Console.WriteLine("running empty_unary");
             var response = client.EmptyCall(new Empty());
@@ -225,7 +225,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static void RunLargeUnary(TestService.ITestServiceClient client)
+        public static void RunLargeUnary(TestService.TestServiceClient client)
         {
             Console.WriteLine("running large_unary");
             var request = new SimpleRequest
@@ -241,7 +241,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunClientStreamingAsync(TestService.ITestServiceClient client)
+        public static async Task RunClientStreamingAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running client_streaming");
 
@@ -257,7 +257,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunServerStreamingAsync(TestService.ITestServiceClient client)
+        public static async Task RunServerStreamingAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running server_streaming");
 
@@ -281,7 +281,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunPingPongAsync(TestService.ITestServiceClient client)
+        public static async Task RunPingPongAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running ping_pong");
 
@@ -338,7 +338,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunEmptyStreamAsync(TestService.ITestServiceClient client)
+        public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running empty_stream");
             using (var call = client.FullDuplexCall())
@@ -434,7 +434,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunCancelAfterBeginAsync(TestService.ITestServiceClient client)
+        public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running cancel_after_begin");
 
@@ -445,13 +445,13 @@
                 await Task.Delay(1000);
                 cts.Cancel();
 
-                var ex = Assert.Throws<RpcException>(async () => await call.ResponseAsync);
+                var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseAsync);
                 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
             }
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunCancelAfterFirstResponseAsync(TestService.ITestServiceClient client)
+        public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running cancel_after_first_response");
 
@@ -471,13 +471,13 @@
 
                 cts.Cancel();
 
-                var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
+                var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
                 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
             }
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunTimeoutOnSleepingServerAsync(TestService.ITestServiceClient client)
+        public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running timeout_on_sleeping_server");
 
@@ -493,13 +493,13 @@
                     // Deadline was reached before write has started. Eat the exception and continue.
                 }
 
-                var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
+                var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
                 Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode);
             }
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunCustomMetadataAsync(TestService.ITestServiceClient client)
+        public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running custom_metadata");
             {
@@ -546,7 +546,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static async Task RunStatusCodeAndMessageAsync(TestService.ITestServiceClient client)
+        public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client)
         {
             Console.WriteLine("running status_code_and_message");
             var echoStatus = new EchoStatus
@@ -572,7 +572,7 @@
                 await call.RequestStream.WriteAsync(request);
                 await call.RequestStream.CompleteAsync();
 
-                var e = Assert.Throws<RpcException>(async () => await call.ResponseStream.ToListAsync());
+                var e = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.ToListAsync());
                 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
                 Assert.AreEqual(echoStatus.Message, e.Status.Detail);
             }
@@ -580,7 +580,7 @@
             Console.WriteLine("Passed!");
         }
 
-        public static void RunUnimplementedMethod(UnimplementedService.IUnimplementedServiceClient client)
+        public static void RunUnimplementedMethod(UnimplementedService.UnimplementedServiceClient client)
         {
             Console.WriteLine("running unimplemented_method");
             var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 0d12c41..4ee1ff5 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -51,7 +51,7 @@
         const string Host = "localhost";
         Server server;
         Channel channel;
-        TestService.ITestServiceClient client;
+        TestService.TestServiceClient client;
 
         [TestFixtureSetUp]
         public void Init()
diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs
index 7ca4786..fcff475 100644
--- a/src/csharp/Grpc.IntegrationTesting/Messages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs
@@ -47,11 +47,12 @@
             "c3Npb24YBiABKA4yHS5ncnBjLnRlc3RpbmcuQ29tcHJlc3Npb25UeXBlEjEK",
             "D3Jlc3BvbnNlX3N0YXR1cxgHIAEoCzIYLmdycGMudGVzdGluZy5FY2hvU3Rh",
             "dHVzIkUKG1N0cmVhbWluZ091dHB1dENhbGxSZXNwb25zZRImCgdwYXlsb2Fk",
-            "GAEgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQiMwoNUmVjb25uZWN0SW5m",
-            "bxIOCgZwYXNzZWQYASABKAgSEgoKYmFja29mZl9tcxgCIAMoBSo/CgtQYXls",
-            "b2FkVHlwZRIQCgxDT01QUkVTU0FCTEUQABISCg5VTkNPTVBSRVNTQUJMRRAB",
-            "EgoKBlJBTkRPTRACKjIKD0NvbXByZXNzaW9uVHlwZRIICgROT05FEAASCAoE",
-            "R1pJUBABEgsKB0RFRkxBVEUQAmIGcHJvdG8z"));
+            "GAEgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQiMwoPUmVjb25uZWN0UGFy",
+            "YW1zEiAKGG1heF9yZWNvbm5lY3RfYmFja29mZl9tcxgBIAEoBSIzCg1SZWNv",
+            "bm5lY3RJbmZvEg4KBnBhc3NlZBgBIAEoCBISCgpiYWNrb2ZmX21zGAIgAygF",
+            "Kj8KC1BheWxvYWRUeXBlEhAKDENPTVBSRVNTQUJMRRAAEhIKDlVOQ09NUFJF",
+            "U1NBQkxFEAESCgoGUkFORE9NEAIqMgoPQ29tcHJlc3Npb25UeXBlEggKBE5P",
+            "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[] {
@@ -64,6 +65,7 @@
             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)
           }));
     }
@@ -1574,6 +1576,113 @@
 
   /// <summary>
   ///  For reconnect interop test only.
+  ///  Client tells server what reconnection parameters it used.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ReconnectParams : pb::IMessage<ReconnectParams> {
+    private static readonly pb::MessageParser<ReconnectParams> _parser = new pb::MessageParser<ReconnectParams>(() => new ReconnectParams());
+    public static pb::MessageParser<ReconnectParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[9]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ReconnectParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ReconnectParams(ReconnectParams other) : this() {
+      maxReconnectBackoffMs_ = other.maxReconnectBackoffMs_;
+    }
+
+    public ReconnectParams Clone() {
+      return new ReconnectParams(this);
+    }
+
+    /// <summary>Field number for the "max_reconnect_backoff_ms" field.</summary>
+    public const int MaxReconnectBackoffMsFieldNumber = 1;
+    private int maxReconnectBackoffMs_;
+    public int MaxReconnectBackoffMs {
+      get { return maxReconnectBackoffMs_; }
+      set {
+        maxReconnectBackoffMs_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ReconnectParams);
+    }
+
+    public bool Equals(ReconnectParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (MaxReconnectBackoffMs != other.MaxReconnectBackoffMs) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (MaxReconnectBackoffMs != 0) hash ^= MaxReconnectBackoffMs.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (MaxReconnectBackoffMs != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(MaxReconnectBackoffMs);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (MaxReconnectBackoffMs != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaxReconnectBackoffMs);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ReconnectParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.MaxReconnectBackoffMs != 0) {
+        MaxReconnectBackoffMs = other.MaxReconnectBackoffMs;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            MaxReconnectBackoffMs = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  For reconnect interop test only.
   ///  Server tells client whether its reconnects are following the spec and the
   ///  reconnect backoffs it saw.
   /// </summary>
@@ -1583,7 +1692,7 @@
     public static pb::MessageParser<ReconnectInfo> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[9]; }
+      get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[10]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
diff --git a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
index 1c8bfed..f95af50 100644
--- a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -50,15 +50,15 @@
         const string Host = "localhost";
         Server server;
         Channel channel;
-        TestService.ITestServiceClient client;
+        TestService.TestServiceClient client;
         List<ChannelOption> options;
-        Mock<TestService.ITestService> serviceMock;
+        Mock<TestService.TestServiceBase> serviceMock;
         AsyncAuthInterceptor asyncAuthInterceptor;
 
         [SetUp]
         public void Init()
         {
-            serviceMock = new Mock<TestService.ITestService>();
+            serviceMock = new Mock<TestService.TestServiceBase>();
             serviceMock.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<ServerCallContext>()))
                 .Returns(new Func<SimpleRequest, ServerCallContext, Task<SimpleResponse>>(UnaryCallHandler));
 
diff --git a/src/csharp/Grpc.IntegrationTesting/Metrics.cs b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
new file mode 100644
index 0000000..3163949
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
@@ -0,0 +1,452 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: src/proto/grpc/testing/metrics.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/metrics.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class MetricsReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for src/proto/grpc/testing/metrics.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static MetricsReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21ldHJpY3MucHJvdG8SDGdycGMu",
+            "dGVzdGluZyJsCg1HYXVnZVJlc3BvbnNlEgwKBG5hbWUYASABKAkSFAoKbG9u",
+            "Z192YWx1ZRgCIAEoA0gAEhYKDGRvdWJsZV92YWx1ZRgDIAEoAUgAEhYKDHN0",
+            "cmluZ192YWx1ZRgEIAEoCUgAQgcKBXZhbHVlIhwKDEdhdWdlUmVxdWVzdBIM",
+            "CgRuYW1lGAEgASgJIg4KDEVtcHR5TWVzc2FnZTKgAQoOTWV0cmljc1NlcnZp",
+            "Y2USSQoMR2V0QWxsR2F1Z2VzEhouZ3JwYy50ZXN0aW5nLkVtcHR5TWVzc2Fn",
+            "ZRobLmdycGMudGVzdGluZy5HYXVnZVJlc3BvbnNlMAESQwoIR2V0R2F1Z2US",
+            "Gi5ncnBjLnRlc3RpbmcuR2F1Z2VSZXF1ZXN0GhsuZ3JwYy50ZXN0aW5nLkdh",
+            "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)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  Reponse message containing the gauge name and value
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class GaugeResponse : pb::IMessage<GaugeResponse> {
+    private static readonly pb::MessageParser<GaugeResponse> _parser = new pb::MessageParser<GaugeResponse>(() => new GaugeResponse());
+    public static pb::MessageParser<GaugeResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public GaugeResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public GaugeResponse(GaugeResponse other) : this() {
+      name_ = other.name_;
+      switch (other.ValueCase) {
+        case ValueOneofCase.LongValue:
+          LongValue = other.LongValue;
+          break;
+        case ValueOneofCase.DoubleValue:
+          DoubleValue = other.DoubleValue;
+          break;
+        case ValueOneofCase.StringValue:
+          StringValue = other.StringValue;
+          break;
+      }
+
+    }
+
+    public GaugeResponse Clone() {
+      return new GaugeResponse(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "long_value" field.</summary>
+    public const int LongValueFieldNumber = 2;
+    public long LongValue {
+      get { return valueCase_ == ValueOneofCase.LongValue ? (long) value_ : 0L; }
+      set {
+        value_ = value;
+        valueCase_ = ValueOneofCase.LongValue;
+      }
+    }
+
+    /// <summary>Field number for the "double_value" field.</summary>
+    public const int DoubleValueFieldNumber = 3;
+    public double DoubleValue {
+      get { return valueCase_ == ValueOneofCase.DoubleValue ? (double) value_ : 0D; }
+      set {
+        value_ = value;
+        valueCase_ = ValueOneofCase.DoubleValue;
+      }
+    }
+
+    /// <summary>Field number for the "string_value" field.</summary>
+    public const int StringValueFieldNumber = 4;
+    public string StringValue {
+      get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; }
+      set {
+        value_ = pb::Preconditions.CheckNotNull(value, "value");
+        valueCase_ = ValueOneofCase.StringValue;
+      }
+    }
+
+    private object value_;
+    /// <summary>Enum of possible cases for the "value" oneof.</summary>
+    public enum ValueOneofCase {
+      None = 0,
+      LongValue = 2,
+      DoubleValue = 3,
+      StringValue = 4,
+    }
+    private ValueOneofCase valueCase_ = ValueOneofCase.None;
+    public ValueOneofCase ValueCase {
+      get { return valueCase_; }
+    }
+
+    public void ClearValue() {
+      valueCase_ = ValueOneofCase.None;
+      value_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as GaugeResponse);
+    }
+
+    public bool Equals(GaugeResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (LongValue != other.LongValue) return false;
+      if (DoubleValue != other.DoubleValue) return false;
+      if (StringValue != other.StringValue) return false;
+      if (ValueCase != other.ValueCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (valueCase_ == ValueOneofCase.LongValue) hash ^= LongValue.GetHashCode();
+      if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= DoubleValue.GetHashCode();
+      if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode();
+      hash ^= (int) valueCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (valueCase_ == ValueOneofCase.LongValue) {
+        output.WriteRawTag(16);
+        output.WriteInt64(LongValue);
+      }
+      if (valueCase_ == ValueOneofCase.DoubleValue) {
+        output.WriteRawTag(25);
+        output.WriteDouble(DoubleValue);
+      }
+      if (valueCase_ == ValueOneofCase.StringValue) {
+        output.WriteRawTag(34);
+        output.WriteString(StringValue);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (valueCase_ == ValueOneofCase.LongValue) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(LongValue);
+      }
+      if (valueCase_ == ValueOneofCase.DoubleValue) {
+        size += 1 + 8;
+      }
+      if (valueCase_ == ValueOneofCase.StringValue) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
+      }
+      return size;
+    }
+
+    public void MergeFrom(GaugeResponse other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      switch (other.ValueCase) {
+        case ValueOneofCase.LongValue:
+          LongValue = other.LongValue;
+          break;
+        case ValueOneofCase.DoubleValue:
+          DoubleValue = other.DoubleValue;
+          break;
+        case ValueOneofCase.StringValue:
+          StringValue = other.StringValue;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            LongValue = input.ReadInt64();
+            break;
+          }
+          case 25: {
+            DoubleValue = input.ReadDouble();
+            break;
+          }
+          case 34: {
+            StringValue = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Request message containing the gauge name
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class GaugeRequest : pb::IMessage<GaugeRequest> {
+    private static readonly pb::MessageParser<GaugeRequest> _parser = new pb::MessageParser<GaugeRequest>(() => new GaugeRequest());
+    public static pb::MessageParser<GaugeRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public GaugeRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public GaugeRequest(GaugeRequest other) : this() {
+      name_ = other.name_;
+    }
+
+    public GaugeRequest Clone() {
+      return new GaugeRequest(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as GaugeRequest);
+    }
+
+    public bool Equals(GaugeRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      return size;
+    }
+
+    public void MergeFrom(GaugeRequest other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class EmptyMessage : pb::IMessage<EmptyMessage> {
+    private static readonly pb::MessageParser<EmptyMessage> _parser = new pb::MessageParser<EmptyMessage>(() => new EmptyMessage());
+    public static pb::MessageParser<EmptyMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public EmptyMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public EmptyMessage(EmptyMessage other) : this() {
+    }
+
+    public EmptyMessage Clone() {
+      return new EmptyMessage(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as EmptyMessage);
+    }
+
+    public bool Equals(EmptyMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(EmptyMessage other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
new file mode 100644
index 0000000..cc01ae9
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
@@ -0,0 +1,146 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: src/proto/grpc/testing/metrics.proto
+#region Designer generated code
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Testing {
+  public static class MetricsService
+  {
+    static readonly string __ServiceName = "grpc.testing.MetricsService";
+
+    static readonly Marshaller<global::Grpc.Testing.EmptyMessage> __Marshaller_EmptyMessage = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.EmptyMessage.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.GaugeResponse> __Marshaller_GaugeResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeResponse.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.GaugeRequest> __Marshaller_GaugeRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeRequest.Parser.ParseFrom);
+
+    static readonly Method<global::Grpc.Testing.EmptyMessage, global::Grpc.Testing.GaugeResponse> __Method_GetAllGauges = new Method<global::Grpc.Testing.EmptyMessage, global::Grpc.Testing.GaugeResponse>(
+        MethodType.ServerStreaming,
+        __ServiceName,
+        "GetAllGauges",
+        __Marshaller_EmptyMessage,
+        __Marshaller_GaugeResponse);
+
+    static readonly Method<global::Grpc.Testing.GaugeRequest, global::Grpc.Testing.GaugeResponse> __Method_GetGauge = new Method<global::Grpc.Testing.GaugeRequest, global::Grpc.Testing.GaugeResponse>(
+        MethodType.Unary,
+        __ServiceName,
+        "GetGauge",
+        __Marshaller_GaugeRequest,
+        __Marshaller_GaugeResponse);
+
+    // service descriptor
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Grpc.Testing.MetricsReflection.Descriptor.Services[0]; }
+    }
+
+    // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
+    public interface IMetricsServiceClient
+    {
+      AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, CallOptions options);
+      global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, CallOptions options);
+      AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, CallOptions options);
+    }
+
+    // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
+    public interface IMetricsService
+    {
+      Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context);
+      Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context);
+    }
+
+    // server-side abstract class
+    public abstract class MetricsServiceBase
+    {
+      public virtual Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    // client stub
+    public class MetricsServiceClient : ClientBase<MetricsServiceClient>, IMetricsServiceClient
+    {
+      public MetricsServiceClient(Channel channel) : base(channel)
+      {
+      }
+      public MetricsServiceClient(CallInvoker callInvoker) : base(callInvoker)
+      {
+      }
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected MetricsServiceClient() : base()
+      {
+      }
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected MetricsServiceClient(ClientBaseConfiguration configuration) : base(configuration)
+      {
+      }
+
+      public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return GetAllGauges(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, CallOptions options)
+      {
+        return CallInvoker.AsyncServerStreamingCall(__Method_GetAllGauges, null, options, request);
+      }
+      public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return GetGauge(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_GetGauge, null, options, request);
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return GetGaugeAsync(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_GetGauge, null, options, request);
+      }
+      protected override MetricsServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new MetricsServiceClient(configuration);
+      }
+    }
+
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(IMetricsService serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges)
+          .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
+    }
+
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(MetricsServiceBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges)
+          .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
+    }
+
+    // creates a new client
+    public static MetricsServiceClient NewClient(Channel channel)
+    {
+      return new MetricsServiceClient(channel);
+    }
+
+  }
+}
+#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs
new file mode 100644
index 0000000..d8902de
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs
@@ -0,0 +1,59 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Reflection;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using NUnit.Common;
+using NUnitLite;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Provides entry point for NUnitLite
+    /// </summary>
+    public class NUnitMain
+    {
+        public static int Main(string[] args)
+        {
+            // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
+            GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
+#if DOTNET5_4
+            return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
+#else
+            return new AutoRun().Execute(args);
+#endif
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
index e407792..a7c9fa8 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
index 06d5ee9..13ab5a2 100644
--- a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -55,14 +55,7 @@
         {
             var serverConfig = new ServerConfig
             {
-                ServerType = ServerType.ASYNC_SERVER,
-                PayloadConfig = new PayloadConfig
-                {
-                    SimpleParams = new SimpleProtoParams
-                    {
-                        RespSize = 100
-                    }
-                }
+                ServerType = ServerType.ASYNC_SERVER
             };
             serverRunner = ServerRunners.CreateStarted(serverConfig);
         }
@@ -88,7 +81,8 @@
                 {
                     SimpleParams = new SimpleProtoParams
                     {
-                        ReqSize = 100
+                        ReqSize = 100,
+                        RespSize = 100
                     }
                 },
                 HistogramParams = new HistogramParams
diff --git a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
index 4a73645..d785944 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
 using System.Threading.Tasks;
 using Google.Protobuf;
 using Grpc.Core;
+using Grpc.Core.Logging;
 using Grpc.Core.Utils;
 using NUnit.Framework;
 using Grpc.Testing;
@@ -50,27 +51,78 @@
     /// <summary>
     /// Helper methods to start server runners for performance testing.
     /// </summary>
-    public static class ServerRunners
+    public class ServerRunners
     {
+        static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<ServerRunners>();
+
         /// <summary>
         /// Creates a started server runner.
         /// </summary>
         public static IServerRunner CreateStarted(ServerConfig config)
         {
-            GrpcPreconditions.CheckArgument(config.ServerType == ServerType.ASYNC_SERVER);
+            Logger.Debug("ServerConfig: {0}", config);
             var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure;
 
-            // TODO: qps_driver needs to setup payload properly...
-            int responseSize = config.PayloadConfig != null ? config.PayloadConfig.SimpleParams.RespSize : 0;
+            if (config.AsyncServerThreads != 0)
+            {
+                Logger.Warning("ServerConfig.AsyncServerThreads is not supported for C#. Ignoring the value");
+            }
+            if (config.CoreLimit != 0)
+            {
+                Logger.Warning("ServerConfig.CoreLimit is not supported for C#. Ignoring the value");
+            }
+            if (config.CoreList.Count > 0)
+            {
+                Logger.Warning("ServerConfig.CoreList is not supported for C#. Ignoring the value");
+            }
+
+            ServerServiceDefinition service = null;
+            if (config.ServerType == ServerType.ASYNC_SERVER)
+            {
+                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)
+            {
+                var genericService = new GenericServiceImpl(config.PayloadConfig.BytebufParams.RespSize);
+                service = GenericService.BindHandler(genericService.StreamingCall);
+            }
+            else
+            {
+                throw new ArgumentException("Unsupported ServerType");
+            }
+
             var server = new Server
             {
-                Services = { BenchmarkService.BindService(new BenchmarkServiceImpl(responseSize)) },
+                Services = { service },
                 Ports = { new ServerPort("[::]", config.Port, credentials) }
             };
 
             server.Start();
             return new ServerRunnerImpl(server);
         }
+
+        private class GenericServiceImpl
+        {
+            readonly byte[] response;
+
+            public GenericServiceImpl(int responseSize)
+            {
+                this.response = new byte[responseSize];
+            }
+
+            /// <summary>
+            /// Generic streaming call handler.
+            /// </summary>
+            public async Task StreamingCall(IAsyncStreamReader<byte[]> requestStream, IServerStreamWriter<byte[]> responseStream, ServerCallContext context)
+            {
+                await requestStream.ForEachAsync(async request =>
+                {
+                    await responseStream.WriteAsync(response);
+                });
+            }
+        }
     }
 
     /// <summary>
@@ -119,6 +171,5 @@
         {
             return server.ShutdownAsync();
         }
-    }
-        
+    }        
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
index 996439a..46b16cf 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
@@ -36,6 +36,7 @@
     }
 
     // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IBenchmarkServiceClient
     {
       global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@@ -47,47 +48,73 @@
     }
 
     // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IBenchmarkService
     {
       Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
       Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context);
     }
 
+    // server-side abstract class
+    public abstract class BenchmarkServiceBase
+    {
+      public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
     // client stub
-    public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient
+    public class BenchmarkServiceClient : ClientBase<BenchmarkServiceClient>, IBenchmarkServiceClient
     {
       public BenchmarkServiceClient(Channel channel) : base(channel)
       {
       }
-      public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public BenchmarkServiceClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected BenchmarkServiceClient() : base()
       {
-        var call = CreateCall(__Method_UnaryCall, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+
+      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_UnaryCall, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
-        var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncDuplexStreamingCall(call);
+        return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
+      public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_StreamingCall, options);
-        return Calls.AsyncDuplexStreamingCall(call);
+        return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
+      }
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return StreamingCall(new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
+      }
+      protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new BenchmarkServiceClient(configuration);
       }
     }
 
@@ -99,6 +126,14 @@
           .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
     }
 
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
+          .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
+    }
+
     // creates a new client
     public static BenchmarkServiceClient NewClient(Channel channel)
     {
@@ -153,6 +188,7 @@
     }
 
     // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IWorkerServiceClient
     {
       AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@@ -170,6 +206,7 @@
     }
 
     // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IWorkerService
     {
       Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
@@ -178,71 +215,100 @@
       Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context);
     }
 
+    // server-side abstract class
+    public abstract class WorkerServiceBase
+    {
+      public virtual Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
     // client stub
-    public class WorkerServiceClient : ClientBase, IWorkerServiceClient
+    public class WorkerServiceClient : ClientBase<WorkerServiceClient>, IWorkerServiceClient
     {
       public WorkerServiceClient(Channel channel) : base(channel)
       {
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public WorkerServiceClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncDuplexStreamingCall(call);
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected WorkerServiceClient() : base()
       {
-        var call = CreateCall(__Method_RunServer, options);
-        return Calls.AsyncDuplexStreamingCall(call);
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncDuplexStreamingCall(call);
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
+
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_RunClient, options);
-        return Calls.AsyncDuplexStreamingCall(call);
+        return RunServer(new CallOptions(headers, deadline, cancellationToken));
       }
-      public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
       {
-        var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options);
       }
-      public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_CoreCount, options);
-        return Calls.BlockingUnaryCall(call, request);
+        return RunClient(new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
       {
-        var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
+      public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_CoreCount, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return CoreCount(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
       {
-        var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
+        return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request);
       }
-      public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
+      public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_QuitWorker, options);
-        return Calls.BlockingUnaryCall(call, request);
+        return CoreCountAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
       {
-        var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
+        return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
+      public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_QuitWorker, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return QuitWorker(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request);
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return QuitWorkerAsync(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request);
+      }
+      protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new WorkerServiceClient(configuration);
       }
     }
 
@@ -256,6 +322,16 @@
           .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
     }
 
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_RunServer, serviceImpl.RunServer)
+          .AddMethod(__Method_RunClient, serviceImpl.RunClient)
+          .AddMethod(__Method_CoreCount, serviceImpl.CoreCount)
+          .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
+    }
+
     // creates a new client
     public static WorkerServiceClient NewClient(Channel channel)
     {
diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
index 37b2518..3df45b5 100644
--- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -53,7 +53,7 @@
         const string Host = "localhost";
         Server server;
         Channel channel;
-        TestService.ITestServiceClient client;
+        TestService.TestServiceClient client;
 
         [TestFixtureSetUp]
         public void Init()
diff --git a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
new file mode 100644
index 0000000..8db691c
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
@@ -0,0 +1,318 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using CommandLine;
+using CommandLine.Text;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    public class StressTestClient
+    {
+        static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<StressTestClient>();
+        const double SecondsToNanos = 1e9;
+
+        private class ClientOptions
+        {
+            [Option("server_addresses", DefaultValue = "localhost:8080")]
+            public string ServerAddresses { get; set; }
+
+            [Option("test_cases", DefaultValue = "large_unary:100")]
+            public string TestCases { get; set; }
+
+            [Option("test_duration_secs", DefaultValue = -1)]
+            public int TestDurationSecs { get; set; }
+
+            [Option("num_channels_per_server", DefaultValue = 1)]
+            public int NumChannelsPerServer { get; set; }
+
+            [Option("num_stubs_per_channel", DefaultValue = 1)]
+            public int NumStubsPerChannel { get; set; }
+
+            [Option("metrics_port", DefaultValue = 8081)]
+            public int MetricsPort { get; set; }
+
+            [HelpOption]
+            public string GetUsage()
+            {
+                var help = new HelpText
+                {
+                    Heading = "gRPC C# stress test client",
+                    AddDashesToOption = true
+                };
+                help.AddPreOptionsLine("Usage:");
+                help.AddOptions(this);
+                return help;
+            }
+        }
+
+        ClientOptions options;
+        List<string> serverAddresses;
+        Dictionary<string, int> weightedTestCases;
+        WeightedRandomGenerator testCaseGenerator;
+
+        // cancellation will be emitted once test_duration_secs has elapsed.
+        CancellationTokenSource finishedTokenSource = new CancellationTokenSource();
+        Histogram histogram = new Histogram(0.01, 60 * SecondsToNanos);
+
+        private StressTestClient(ClientOptions options, List<string> serverAddresses, Dictionary<string, int> weightedTestCases)
+        {
+            this.options = options;
+            this.serverAddresses = serverAddresses;
+            this.weightedTestCases = weightedTestCases;
+            this.testCaseGenerator = new WeightedRandomGenerator(this.weightedTestCases);
+        }
+
+        public static void Run(string[] args)
+        {
+            var options = new ClientOptions();
+            if (!Parser.Default.ParseArguments(args, options))
+            {
+                Environment.Exit(1);
+            }
+
+            GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0);
+            GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0);
+
+            var serverAddresses = options.ServerAddresses.Split(',');
+            GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address");
+
+            var testCases = ParseWeightedTestCases(options.TestCases);
+            GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case");
+
+            var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases);
+            interopClient.Run().Wait();
+        }
+
+        async Task Run()
+        {
+            var metricsServer = new Server()
+            {
+                Services = { MetricsService.BindService(new MetricsServiceImpl(histogram)) },
+                Ports = { { "[::]", options.MetricsPort, ServerCredentials.Insecure } }
+            };
+            metricsServer.Start();
+
+            if (options.TestDurationSecs >= 0)
+            {
+                finishedTokenSource.CancelAfter(TimeSpan.FromSeconds(options.TestDurationSecs));
+            }
+
+            var tasks = new List<Task>();
+            var channels = new List<Channel>();
+            foreach (var serverAddress in serverAddresses)
+            {
+                for (int i = 0; i < options.NumChannelsPerServer; i++)
+                {
+                    var channel = new Channel(serverAddress, ChannelCredentials.Insecure);
+                    channels.Add(channel);
+                    for (int j = 0; j < options.NumStubsPerChannel; j++)
+                    {
+                        var client = TestService.NewClient(channel);
+                        var task = Task.Factory.StartNew(() => RunBodyAsync(client).GetAwaiter().GetResult(),
+                            TaskCreationOptions.LongRunning);
+                        tasks.Add(task);  
+                    }
+                }
+            }
+            await Task.WhenAll(tasks);
+
+            foreach (var channel in channels)
+            {
+                await channel.ShutdownAsync();
+            }
+
+            await metricsServer.ShutdownAsync();
+        }
+
+        async Task RunBodyAsync(TestService.TestServiceClient client)
+        {
+            Logger.Info("Starting stress test client thread.");
+            while (!finishedTokenSource.Token.IsCancellationRequested)
+            {
+                var testCase = testCaseGenerator.GetNext();
+
+                var stopwatch = Stopwatch.StartNew();
+
+                await RunTestCaseAsync(client, testCase);
+
+                stopwatch.Stop();
+                histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+            }
+            Logger.Info("Stress test client thread finished.");
+        }
+
+        async Task RunTestCaseAsync(TestService.TestServiceClient client, string testCase)
+        {
+            switch (testCase)
+            {
+                case "empty_unary":
+                    InteropClient.RunEmptyUnary(client);
+                    break;
+                case "large_unary":
+                    InteropClient.RunLargeUnary(client);
+                    break;
+                case "client_streaming":
+                    await InteropClient.RunClientStreamingAsync(client);
+                    break;
+                case "server_streaming":
+                    await InteropClient.RunServerStreamingAsync(client);
+                    break;
+                case "ping_pong":
+                    await InteropClient.RunPingPongAsync(client);
+                    break;
+                case "empty_stream":
+                    await InteropClient.RunEmptyStreamAsync(client);
+                    break;
+                case "cancel_after_begin":
+                    await InteropClient.RunCancelAfterBeginAsync(client);
+                    break;
+                case "cancel_after_first_response":
+                    await InteropClient.RunCancelAfterFirstResponseAsync(client);
+                    break;
+                case "timeout_on_sleeping_server":
+                    await InteropClient.RunTimeoutOnSleepingServerAsync(client);
+                    break;
+                case "custom_metadata":
+                    await InteropClient.RunCustomMetadataAsync(client);
+                    break;
+                case "status_code_and_message":
+                    await InteropClient.RunStatusCodeAndMessageAsync(client);
+                    break;
+                default:
+                    throw new ArgumentException("Unsupported test case  " + testCase);
+            }
+        }
+
+        static Dictionary<string, int> ParseWeightedTestCases(string weightedTestCases)
+        {
+            var result = new Dictionary<string, int>();
+            foreach (var weightedTestCase in weightedTestCases.Split(','))
+            {
+                var parts = weightedTestCase.Split(new char[] {':'}, 2);
+                GrpcPreconditions.CheckArgument(parts.Length == 2, "Malformed test_cases option.");
+                result.Add(parts[0], int.Parse(parts[1]));
+            }
+            return result;
+        }
+
+        class WeightedRandomGenerator
+        {
+            readonly Random random = new Random();
+            readonly List<Tuple<int, string>> cumulativeSums;
+            readonly int weightSum;
+
+            public WeightedRandomGenerator(Dictionary<string, int> weightedItems)
+            {
+                cumulativeSums = new List<Tuple<int, string>>();
+                weightSum = 0;
+                foreach (var entry in weightedItems)
+                {
+                    weightSum += entry.Value;
+                    cumulativeSums.Add(Tuple.Create(weightSum, entry.Key));
+                }
+            }
+
+            public string GetNext()
+            {
+                int rand = random.Next(weightSum);
+                foreach (var entry in cumulativeSums)
+                {
+                    if (rand < entry.Item1)
+                    {
+                        return entry.Item2;
+                    }
+                }
+                throw new InvalidOperationException("GetNext() failed.");
+            }
+        }
+
+        class MetricsServiceImpl : MetricsService.MetricsServiceBase 
+        {
+            const string GaugeName = "csharp_overall_qps";
+
+            readonly Histogram histogram;
+            readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
+
+            public MetricsServiceImpl(Histogram histogram)
+            {
+                this.histogram = histogram;
+            }
+
+            public override Task<GaugeResponse> GetGauge(GaugeRequest request, ServerCallContext context)
+            {
+                if (request.Name == GaugeName)
+                {
+                    long qps = GetQpsAndReset();
+
+                    return Task.FromResult(new GaugeResponse
+                    {
+                        Name = GaugeName,
+                        LongValue = qps
+                    });
+                }
+                throw new RpcException(new Status(StatusCode.InvalidArgument, "Gauge does not exist"));
+            }
+
+            public override async Task GetAllGauges(EmptyMessage request, IServerStreamWriter<GaugeResponse> responseStream, ServerCallContext context)
+            {
+                long qps = GetQpsAndReset();
+
+                var response = new GaugeResponse
+                {
+                    Name = GaugeName,
+                    LongValue = qps
+                };
+                await responseStream.WriteAsync(response);
+            }
+
+            long GetQpsAndReset()
+            {
+                var snapshot = histogram.GetSnapshot(true);
+                var elapsedSnapshot = wallClockStopwatch.GetElapsedSnapshot(true);
+
+                return (long) (snapshot.Count / elapsedSnapshot.Seconds);
+            }
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Test.cs b/src/csharp/Grpc.IntegrationTesting/Test.cs
index 91e0a1e..363f644 100644
--- a/src/csharp/Grpc.IntegrationTesting/Test.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Test.cs
@@ -40,10 +40,10 @@
             "bWluZ091dHB1dENhbGxSZXF1ZXN0GikuZ3JwYy50ZXN0aW5nLlN0cmVhbWlu",
             "Z091dHB1dENhbGxSZXNwb25zZSgBMAEyVQoUVW5pbXBsZW1lbnRlZFNlcnZp",
             "Y2USPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRlc3RpbmcuRW1wdHka",
-            "Ey5ncnBjLnRlc3RpbmcuRW1wdHkyfwoQUmVjb25uZWN0U2VydmljZRIxCgVT",
-            "dGFydBITLmdycGMudGVzdGluZy5FbXB0eRoTLmdycGMudGVzdGluZy5FbXB0",
-            "eRI4CgRTdG9wEhMuZ3JwYy50ZXN0aW5nLkVtcHR5GhsuZ3JwYy50ZXN0aW5n",
-            "LlJlY29ubmVjdEluZm9iBnByb3RvMw=="));
+            "Ey5ncnBjLnRlc3RpbmcuRW1wdHkyiQEKEFJlY29ubmVjdFNlcnZpY2USOwoF",
+            "U3RhcnQSHS5ncnBjLnRlc3RpbmcuUmVjb25uZWN0UGFyYW1zGhMuZ3JwYy50",
+            "ZXN0aW5nLkVtcHR5EjgKBFN0b3ASEy5ncnBjLnRlc3RpbmcuRW1wdHkaGy5n",
+            "cnBjLnRlc3RpbmcuUmVjb25uZWN0SW5mb2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Grpc.Testing.EmptyReflection.Descriptor, global::Grpc.Testing.MessagesReflection.Descriptor, },
           new pbr::GeneratedCodeInfo(null, null));
diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
index ce108d8..774563d 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
@@ -35,6 +35,7 @@
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
+using System.Reflection;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using Grpc.Core;
@@ -50,9 +51,29 @@
     {
         public const string DefaultHostOverride = "foo.test.google.fr";
 
-        public const string ClientCertAuthorityPath = "data/ca.pem";
-        public const string ServerCertChainPath = "data/server1.pem";
-        public const string ServerPrivateKeyPath = "data/server1.key";
+        public static string ClientCertAuthorityPath
+        {
+            get
+            {
+                return GetPath("data/ca.pem");
+            }
+        }
+
+        public static string ServerCertChainPath
+        {
+            get
+            {
+                return GetPath("data/server1.pem");
+            }
+        }
+
+        public static string ServerPrivateKeyPath
+        {
+            get
+            {
+                return GetPath("data/server1.key");
+            }
+        }
 
         public static SslCredentials CreateSslCredentials()
         {
@@ -66,5 +87,11 @@
                 File.ReadAllText(ServerPrivateKeyPath));
             return new SslServerCredentials(new[] { keyCertPair });
         }
+
+        private static string GetPath(string relativePath)
+        {
+            var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+            return Path.Combine(assemblyDir, relativePath);
+        }
     }
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
index 2c46908..31746cb 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
@@ -69,6 +69,7 @@
     }
 
     // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface ITestServiceClient
     {
       global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@@ -90,6 +91,7 @@
     }
 
     // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface ITestService
     {
       Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context);
@@ -100,91 +102,126 @@
       Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context);
     }
 
+    // server-side abstract class
+    public abstract class TestServiceBase
+    {
+      public virtual Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
     // client stub
-    public class TestServiceClient : ClientBase, ITestServiceClient
+    public class TestServiceClient : ClientBase<TestServiceClient>, ITestServiceClient
     {
       public TestServiceClient(Channel channel) : base(channel)
       {
       }
-      public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public TestServiceClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected TestServiceClient() : base()
       {
-        var call = CreateCall(__Method_EmptyCall, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected TestServiceClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
+
+      public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_EmptyCall, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return EmptyCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
       {
-        var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
+        return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request);
       }
-      public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_UnaryCall, options);
-        return Calls.BlockingUnaryCall(call, request);
+        return EmptyCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
       {
-        var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
+        return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_UnaryCall, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
-        var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncServerStreamingCall(call, request);
+        return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
       }
-      public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
+      public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_StreamingOutputCall, options);
-        return Calls.AsyncServerStreamingCall(call, request);
+        return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
-        var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncClientStreamingCall(call);
+        return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
       }
-      public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
+      public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_StreamingInputCall, options);
-        return Calls.AsyncClientStreamingCall(call);
+        return StreamingOutputCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
       {
-        var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncDuplexStreamingCall(call);
+        return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request);
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
+      public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_FullDuplexCall, options);
-        return Calls.AsyncDuplexStreamingCall(call);
+        return StreamingInputCall(new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
       {
-        var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncDuplexStreamingCall(call);
+        return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options);
       }
-      public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_HalfDuplexCall, options);
-        return Calls.AsyncDuplexStreamingCall(call);
+        return FullDuplexCall(new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options);
+      }
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return HalfDuplexCall(new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options);
+      }
+      protected override TestServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new TestServiceClient(configuration);
       }
     }
 
@@ -200,6 +237,18 @@
           .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
     }
 
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(TestServiceBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
+          .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
+          .AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall)
+          .AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall)
+          .AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall)
+          .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
+    }
+
     // creates a new client
     public static TestServiceClient NewClient(Channel channel)
     {
@@ -227,6 +276,7 @@
     }
 
     // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IUnimplementedServiceClient
     {
       global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@@ -236,36 +286,59 @@
     }
 
     // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IUnimplementedService
     {
       Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context);
     }
 
+    // server-side abstract class
+    public abstract class UnimplementedServiceBase
+    {
+      public virtual Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
     // client stub
-    public class UnimplementedServiceClient : ClientBase, IUnimplementedServiceClient
+    public class UnimplementedServiceClient : ClientBase<UnimplementedServiceClient>, IUnimplementedServiceClient
     {
       public UnimplementedServiceClient(Channel channel) : base(channel)
       {
       }
-      public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public UnimplementedServiceClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected UnimplementedServiceClient() : base()
       {
-        var call = CreateCall(__Method_UnimplementedCall, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected UnimplementedServiceClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
+
+      public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_UnimplementedCall, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request);
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request);
+      }
+      protected override UnimplementedServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new UnimplementedServiceClient(configuration);
       }
     }
 
@@ -276,6 +349,13 @@
           .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
     }
 
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
+    }
+
     // creates a new client
     public static UnimplementedServiceClient NewClient(Channel channel)
     {
@@ -287,14 +367,15 @@
   {
     static readonly string __ServiceName = "grpc.testing.ReconnectService";
 
+    static readonly Marshaller<global::Grpc.Testing.ReconnectParams> __Marshaller_ReconnectParams = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ReconnectParams.Parser.ParseFrom);
     static readonly Marshaller<global::Grpc.Testing.Empty> __Marshaller_Empty = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Empty.Parser.ParseFrom);
     static readonly Marshaller<global::Grpc.Testing.ReconnectInfo> __Marshaller_ReconnectInfo = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ReconnectInfo.Parser.ParseFrom);
 
-    static readonly Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty> __Method_Start = new Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty>(
+    static readonly Method<global::Grpc.Testing.ReconnectParams, global::Grpc.Testing.Empty> __Method_Start = new Method<global::Grpc.Testing.ReconnectParams, global::Grpc.Testing.Empty>(
         MethodType.Unary,
         __ServiceName,
         "Start",
-        __Marshaller_Empty,
+        __Marshaller_ReconnectParams,
         __Marshaller_Empty);
 
     static readonly Method<global::Grpc.Testing.Empty, global::Grpc.Testing.ReconnectInfo> __Method_Stop = new Method<global::Grpc.Testing.Empty, global::Grpc.Testing.ReconnectInfo>(
@@ -311,12 +392,13 @@
     }
 
     // client interface
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IReconnectServiceClient
     {
-      global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
-      global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options);
-      AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
-      AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options);
+      global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, CallOptions options);
+      AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.ReconnectParams request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.ReconnectParams request, CallOptions options);
       global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
       global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options);
       AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@@ -324,57 +406,81 @@
     }
 
     // server-side interface
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IReconnectService
     {
-      Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.Empty request, ServerCallContext context);
+      Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context);
       Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context);
     }
 
+    // server-side abstract class
+    public abstract class ReconnectServiceBase
+    {
+      public virtual Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      public virtual Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
     // client stub
-    public class ReconnectServiceClient : ClientBase, IReconnectServiceClient
+    public class ReconnectServiceClient : ClientBase<ReconnectServiceClient>, IReconnectServiceClient
     {
       public ReconnectServiceClient(Channel channel) : base(channel)
       {
       }
-      public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public ReconnectServiceClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected ReconnectServiceClient() : base()
       {
-        var call = CreateCall(__Method_Start, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected ReconnectServiceClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options)
+
+      public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_Start, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return Start(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, CallOptions options)
       {
-        var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
+        return CallInvoker.BlockingUnaryCall(__Method_Start, null, options, request);
       }
-      public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options)
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.ReconnectParams request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_Stop, options);
-        return Calls.BlockingUnaryCall(call, request);
+        return StartAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.ReconnectParams request, CallOptions options)
       {
-        var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
+        return CallInvoker.AsyncUnaryCall(__Method_Start, null, options, request);
       }
-      public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options)
+      public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_Stop, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return Stop(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_Stop, null, options, request);
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return StopAsync(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_Stop, null, options, request);
+      }
+      protected override ReconnectServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new ReconnectServiceClient(configuration);
       }
     }
 
@@ -386,6 +492,14 @@
           .AddMethod(__Method_Stop, serviceImpl.Stop).Build();
     }
 
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_Start, serviceImpl.Start)
+          .AddMethod(__Method_Stop, serviceImpl.Stop).Build();
+    }
+
     // creates a new client
     public static ReconnectServiceClient NewClient(Channel channel)
     {
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
deleted file mode 100644
index 9f14dad..0000000
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
+++ /dev/null
@@ -1,204 +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.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using Grpc.Core;
-
-namespace grpc.testing
-{
-    /// <summary>
-    /// TestService (this is handwritten version of code that will normally be generated).
-    /// </summary>
-    public class TestServiceGrpc
-    {
-        static readonly string ServiceName = "/grpc.testing.TestService";
-
-        static readonly Marshaller<Empty> EmptyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
-        static readonly Marshaller<SimpleRequest> SimpleRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
-        static readonly Marshaller<SimpleResponse> SimpleResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
-        static readonly Marshaller<StreamingOutputCallRequest> StreamingOutputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom);
-        static readonly Marshaller<StreamingOutputCallResponse> StreamingOutputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom);
-        static readonly Marshaller<StreamingInputCallRequest> StreamingInputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom);
-        static readonly Marshaller<StreamingInputCallResponse> StreamingInputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom);
-
-        static readonly Method<Empty, Empty> EmptyCallMethod = new Method<Empty, Empty>(
-            MethodType.Unary,
-            "EmptyCall",
-            EmptyMarshaller,
-            EmptyMarshaller);
-
-        static readonly Method<SimpleRequest, SimpleResponse> UnaryCallMethod = new Method<SimpleRequest, SimpleResponse>(
-            MethodType.Unary,
-            "UnaryCall",
-            SimpleRequestMarshaller,
-            SimpleResponseMarshaller);
-
-        static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> StreamingOutputCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
-            MethodType.ServerStreaming,
-            "StreamingOutputCall",
-            StreamingOutputCallRequestMarshaller,
-            StreamingOutputCallResponseMarshaller);
-
-        static readonly Method<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCallMethod = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
-            MethodType.ClientStreaming,
-            "StreamingInputCall",
-            StreamingInputCallRequestMarshaller,
-            StreamingInputCallResponseMarshaller);
-
-        static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
-            MethodType.DuplexStreaming,
-            "FullDuplexCall",
-            StreamingOutputCallRequestMarshaller,
-            StreamingOutputCallResponseMarshaller);
-
-        static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
-            MethodType.DuplexStreaming,
-            "HalfDuplexCall",
-            StreamingOutputCallRequestMarshaller,
-            StreamingOutputCallResponseMarshaller);
-
-        public interface ITestServiceClient
-        {
-            Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken));
-
-            Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken));
-
-            SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken));
-
-            Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken));
-
-            AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken));
-
-            AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken));
-
-            AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken));
-
-            AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken));
-        }
-
-        public class TestServiceClientStub : AbstractStub<TestServiceClientStub, StubConfiguration>, ITestServiceClient
-        {
-            public TestServiceClientStub(Channel channel) : base(channel, StubConfiguration.Default)
-            {
-            }
-
-            public TestServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config)
-            {
-            }
-
-            public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, EmptyCallMethod);
-                return Calls.BlockingUnaryCall(call, request, token);
-            }
-
-            public Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, EmptyCallMethod);
-                return Calls.AsyncUnaryCall(call, request, token);
-            }
-
-            public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, UnaryCallMethod);
-                return Calls.BlockingUnaryCall(call, request, token);
-            }
-
-            public Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, UnaryCallMethod);
-                return Calls.AsyncUnaryCall(call, request, token);
-            }
-
-            public AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, StreamingOutputCallMethod);
-                return Calls.AsyncServerStreamingCall(call, request, token);
-            }
-
-            public AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, StreamingInputCallMethod);
-                return Calls.AsyncClientStreamingCall(call, token);
-            }
-
-            public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, FullDuplexCallMethod);
-                return Calls.AsyncDuplexStreamingCall(call, token);
-            }
-
-            public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken))
-            {
-                var call = CreateCall(ServiceName, HalfDuplexCallMethod);
-                return Calls.AsyncDuplexStreamingCall(call, token);
-            }
-        }
-
-        // server-side interface
-        public interface ITestService
-        {
-            Task<Empty> EmptyCall(ServerCallContext context, Empty request);
-
-            Task<SimpleResponse> UnaryCall(ServerCallContext context, SimpleRequest request);
-
-            Task StreamingOutputCall(ServerCallContext context, StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
-
-            Task<StreamingInputCallResponse> StreamingInputCall(ServerCallContext context, IAsyncStreamReader<StreamingInputCallRequest> requestStream);
-
-            Task FullDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
-
-            Task HalfDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
-        }
-
-        public static ServerServiceDefinition BindService(ITestService serviceImpl)
-        {
-            return ServerServiceDefinition.CreateBuilder(ServiceName)
-                .AddMethod(EmptyCallMethod, serviceImpl.EmptyCall)
-                .AddMethod(UnaryCallMethod, serviceImpl.UnaryCall)
-                .AddMethod(StreamingOutputCallMethod, serviceImpl.StreamingOutputCall)
-                .AddMethod(StreamingInputCallMethod, serviceImpl.StreamingInputCall)
-                .AddMethod(FullDuplexCallMethod, serviceImpl.FullDuplexCall)
-                .AddMethod(HalfDuplexCallMethod, serviceImpl.HalfDuplexCall)
-                .Build();
-        }
-
-        public static ITestServiceClient NewStub(Channel channel)
-        {
-            return new TestServiceClientStub(channel);
-        }
-    }
-}
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
index 5a1b4cf..354318e 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -45,14 +45,14 @@
     /// <summary>
     /// Implementation of TestService server
     /// </summary>
-    public class TestServiceImpl : TestService.ITestService
+    public class TestServiceImpl : TestService.TestServiceBase
     {
-        public Task<Empty> EmptyCall(Empty request, ServerCallContext context)
+        public override Task<Empty> EmptyCall(Empty request, ServerCallContext context)
         {
             return Task.FromResult(new Empty());
         }
 
-        public async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
+        public override async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
         {
             await EnsureEchoMetadataAsync(context);
             EnsureEchoStatus(request.ResponseStatus, context);
@@ -61,7 +61,7 @@
             return response;
         }
 
-        public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
+        public override async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
         {
             await EnsureEchoMetadataAsync(context);
             EnsureEchoStatus(request.ResponseStatus, context);
@@ -73,7 +73,7 @@
             }
         }
 
-        public async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
+        public override async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
         {
             await EnsureEchoMetadataAsync(context);
 
@@ -85,7 +85,7 @@
             return new StreamingInputCallResponse { AggregatedPayloadSize = sum };
         }
 
-        public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
+        public override async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
         {
             await EnsureEchoMetadataAsync(context);
 
@@ -100,7 +100,7 @@
             });
         }
 
-        public async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
+        public override async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
         {
             throw new NotImplementedException();
         }
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
index cab299a..80dad9f 100644
--- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,7 @@
     /// <summary>
     /// Implementation of WorkerService server
     /// </summary>
-    public class WorkerServiceImpl : WorkerService.IWorkerService
+    public class WorkerServiceImpl : WorkerService.WorkerServiceBase
     {
         readonly Action stopRequestHandler;
 
@@ -54,7 +54,7 @@
             this.stopRequestHandler = GrpcPreconditions.CheckNotNull(stopRequestHandler);
         }
         
-        public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
+        public override async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
         {
             GrpcPreconditions.CheckState(await requestStream.MoveNext());
             var serverConfig = requestStream.Current.Setup;
@@ -78,7 +78,7 @@
             await runner.StopAsync();
         }
 
-        public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
+        public override async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
         {
             GrpcPreconditions.CheckState(await requestStream.MoveNext());
             var clientConfig = requestStream.Current.Setup;
@@ -100,12 +100,12 @@
             await runner.StopAsync();
         }
 
-        public Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context)
+        public override Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context)
         {
             return Task.FromResult(new CoreResponse { Cores = Environment.ProcessorCount });
         }
 
-        public Task<Void> QuitWorker(Void request, ServerCallContext context)
+        public override Task<Void> QuitWorker(Void request, ServerCallContext context)
         {
             stopRequestHandler();
             return Task.FromResult(new Void());
diff --git a/src/csharp/Grpc.IntegrationTesting/app.config b/src/csharp/Grpc.IntegrationTesting/app.config
deleted file mode 100644
index 84d7534..0000000
--- a/src/csharp/Grpc.IntegrationTesting/app.config
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-</configuration>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 462dc9d..3fef67d 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -2,15 +2,12 @@
 <packages>
   <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
   <package id="CommandLineParser" version="1.9.71" targetFramework="net45" />
-  <package id="Google.Apis.Auth" version="1.10.0" targetFramework="net45" />
-  <package id="Google.Apis.Core" version="1.10.0" 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="Ix-Async" version="1.2.5" targetFramework="net45" />
-  <package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
-  <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
-  <package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
   <package id="Moq" version="4.2.1510.2205" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
-  <package id="NUnit" version="2.6.4" 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.sln b/src/csharp/Grpc.sln
index 8ff35e8..9be36c0 100644
--- a/src/csharp/Grpc.sln
+++ b/src/csharp/Grpc.sln
@@ -34,6 +34,8 @@
 EndProject

 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}"

 EndProject

+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.csproj", "{ADEBA147-80AE-4710-82E9-5B7F93690266}"

+EndProject

 Global

 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

 		Debug|Any CPU = Debug|Any CPU

@@ -83,6 +85,12 @@
 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.Build.0 = Release|Any CPU

 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{ADEBA147-80AE-4710-82E9-5B7F93690266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{ADEBA147-80AE-4710-82E9-5B7F93690266}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{ADEBA147-80AE-4710-82E9-5B7F93690266}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{ADEBA147-80AE-4710-82E9-5B7F93690266}.Release|Any CPU.Build.0 = Release|Any CPU

+		{ADEBA147-80AE-4710-82E9-5B7F93690266}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU

+		{ADEBA147-80AE-4710-82E9-5B7F93690266}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU

 		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

 		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU

 		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU

diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index 7c42a6d..9a60be2 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -12,12 +12,12 @@
 
 @rem Collect the artifacts built by the previous build step if running on Jenkins
 @rem TODO(jtattermusch): is there a better way to do this?
-xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x86\
-xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x64\
-xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x86\
-xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x64\
-xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x86\
-xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x64\
+xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x86\
+xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x64\
+xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x86\
+xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x64\
+xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x86\
+xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x64\
 
 @rem Collect protoc artifacts built by the previous build step
 xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86\
@@ -42,7 +42,6 @@
 
 endlocal
 
-%NUGET% pack grpc.native.csharp\grpc.native.csharp.nuspec -Version %VERSION% || goto :error
 %NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
 %NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
 %NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 1df74a0..aeef8a7 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/support/string.h"
+#include "src/core/lib/support/string.h"
 
 #include <grpc/byte_buffer_reader.h>
 #include <grpc/support/port_platform.h>
@@ -911,9 +911,12 @@
       key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
     }
   }
-  creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs,
-                                             num_key_cert_pairs,
-                                             force_client_auth, NULL);
+  creds = grpc_ssl_server_credentials_create_ex(
+      pem_root_certs, 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,
+      NULL);
   gpr_free(key_cert_pairs);
   return creds;
 }
diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh
index 23e0540..79488e0 100755
--- a/src/csharp/generate_proto_csharp.sh
+++ b/src/csharp/generate_proto_csharp.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -45,4 +45,4 @@
     -I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto
 
 $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-    -I . src/proto/grpc/testing/{control,empty,messages,payloads,services,stats,test}.proto 
+    -I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto 
diff --git a/src/csharp/grpc.native.csharp/README.md b/src/csharp/grpc.native.csharp/README.md
deleted file mode 100644
index 77f1cb9..0000000
--- a/src/csharp/grpc.native.csharp/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-gRPC Native Nuget package
-=========================
-
-Prerequisites
--------------
-
-NuGet binary
-
-Building the package
---------------------
-
-To build the native package, you need precompiled versions
-of grpc_csharp_ext library artifacts for Windows, Linux and Mac.
-In the normal gRPC release process, these are built by a Jenkins
-job and they are copied to the expected location before building
-the native nuget package is attempted.
-
-See tools/run_tests/build_artifacts.py for more details how
-precompiled artifacts are built.
-
-When building the native NuGet package, ignore the "Assembly outside lib folder"
-warnings (the DLLs are not assemblies, they are native libraries).
diff --git a/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec b/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec
index 6a1795b..cc688e2 100644
--- a/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec
+++ b/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec
@@ -10,7 +10,7 @@
     <requireLicenseAcceptance>false</requireLicenseAcceptance>
     <description>Native extension needed by gRPC C# library. This is not the package you are looking for, it is only meant to be used as a dependency.</description>
     <releaseNotes>Release of gRPC C core $version$ libraries.</releaseNotes>
-    <copyright>Copyright 2015-2016</copyright>
+    <copyright>Copyright 2015</copyright>
     <title>gRPC C# Native Extension</title>
     <summary>Native library required by gRPC C#</summary>
     <tags>gRPC native</tags>
diff --git a/src/csharp/tests.json b/src/csharp/tests.json
index 4aa9366..f733352 100644
--- a/src/csharp/tests.json
+++ b/src/csharp/tests.json
@@ -1,11 +1,5 @@
 {
-  "assemblies": [
-    "Grpc.Core.Tests",
-    "Grpc.Examples.Tests",
-    "Grpc.HealthCheck.Tests",
-    "Grpc.IntegrationTesting"
-  ],
-  "tests": [
+  "Grpc.Core.Tests": [
     "Grpc.Core.Internal.Tests.AsyncCallTest",
     "Grpc.Core.Internal.Tests.ChannelArgsSafeHandleTest",
     "Grpc.Core.Internal.Tests.CompletionQueueEventTest",
@@ -21,6 +15,7 @@
     "Grpc.Core.Tests.CompressionTest",
     "Grpc.Core.Tests.ContextPropagationTest",
     "Grpc.Core.Tests.GrpcEnvironmentTest",
+    "Grpc.Core.Tests.HalfcloseTest",
     "Grpc.Core.Tests.MarshallingErrorsTest",
     "Grpc.Core.Tests.MetadataTest",
     "Grpc.Core.Tests.NUnitVersionTest",
@@ -31,11 +26,18 @@
     "Grpc.Core.Tests.ServerTest",
     "Grpc.Core.Tests.ShutdownTest",
     "Grpc.Core.Tests.TimeoutsTest",
-    "Grpc.Core.Tests.UserAgentStringTest",
-    "Math.Tests.MathClientServerTest",
+    "Grpc.Core.Tests.UserAgentStringTest"
+  ],
+  "Grpc.Examples.Tests": [
+    "Math.Tests.MathClientServerTest"
+  ],
+  "Grpc.HealthCheck.Tests": [
     "Grpc.HealthCheck.Tests.HealthClientServerTest",
-    "Grpc.HealthCheck.Tests.HealthServiceImplTest",
-    "Grpc.IntegrationTesting.HeaderInterceptorTest",
+    "Grpc.HealthCheck.Tests.HealthServiceImplTest"
+  ],
+  "Grpc.IntegrationTesting": [
+    "Grpc.IntegrationTesting.GeneratedClientTest",
+    "Grpc.IntegrationTesting.GeneratedServiceBaseTest",
     "Grpc.IntegrationTesting.HistogramTest",
     "Grpc.IntegrationTesting.InteropClientServerTest",
     "Grpc.IntegrationTesting.MetadataCredentialsTest",
diff --git a/src/node/.gitignore b/src/node/.gitignore
deleted file mode 100644
index e3fbd98..0000000
--- a/src/node/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-build
-node_modules
diff --git a/src/node/.jshintignore b/src/node/.jshintignore
new file mode 100644
index 0000000..0a73e1e
--- /dev/null
+++ b/src/node/.jshintignore
@@ -0,0 +1 @@
+**/*_pb.js
\ No newline at end of file
diff --git a/src/node/.jshintrc b/src/node/.jshintrc
deleted file mode 100644
index 8237e0d..0000000
--- a/src/node/.jshintrc
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "bitwise": true,
-  "curly": true,
-  "eqeqeq": true,
-  "esnext": true,
-  "freeze": true,
-  "immed": true,
-  "indent": 2,
-  "latedef": "nofunc",
-  "maxlen": 80,
-  "newcap": true,
-  "node": true,
-  "noarg": true,
-  "quotmark": "single",
-  "strict": true,
-  "trailing": true,
-  "undef": true,
-  "unused": "vars",
-  "globals": {
-    /* Mocha-provided globals */
-    "describe": false,
-    "it": false,
-    "before": false,
-    "beforeEach": false,
-    "after": false,
-    "afterEach": false
-  }
-}
diff --git a/src/node/README.md b/src/node/README.md
index 3501b54..15d4c6d 100644
--- a/src/node/README.md
+++ b/src/node/README.md
@@ -7,6 +7,8 @@
 ## PREREQUISITES
 - `node`: This requires `node` to be installed, version `0.12` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
 
+- **Note:** If you installed `node` via a package manager and the version is still less than `0.12`, try directly installing it from [nodejs.org](https://nodejs.org).
+
 ## INSTALLATION
 
 Install the gRPC NPM package
@@ -17,7 +19,21 @@
 
 ## BUILD FROM SOURCE
  1. Clone [the grpc Git Repository](https://github.com/grpc/grpc).
- 3. Run `npm install`.
+ 2. Run `npm install` from the repository root.
+
+ - **Note:** On Windows, this might fail due to [nodejs issue #4932](https://github.com/nodejs/node/issues/4932) in which case, you will see something like the following in `npm install`'s output (towards the very beginning):
+
+    ```
+     ..
+     Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
+     WINDOWS_BUILD_WARNING
+      "..\IMPORTANT: Due to https:\github.com\nodejs\node\issues\4932, to build this library on Windows, you must first remove C:\Users\jenkins\.node-gyp\4.4.0\include\node\openssl"
+      ...
+      ..
+    ```
+
+    To fix this, you will have to delete the folder `C:\Users\<username>\.node-gyp\<node_version>\include\node\openssl` and retry `npm install`
+
 
 ## TESTING
 To run the test suite, simply run `npm test` in the install location.
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc
index 0f7edad..8e0b691 100644
--- a/src/node/ext/byte_buffer.cc
+++ b/src/node/ext/byte_buffer.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index da31288..9f023b5 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index bd2d146..3c8f0c5 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/ext/call_credentials.h b/src/node/ext/call_credentials.h
index 1f35595..04c852b 100644
--- a/src/node/ext/call_credentials.h
+++ b/src/node/ext/call_credentials.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc
index 0c71b2d..b988f29 100644
--- a/src/node/ext/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc
index 5285d53..cff821a 100644
--- a/src/node/ext/server_credentials.cc
+++ b/src/node/ext/server_credentials.cc
@@ -145,9 +145,13 @@
     return Nan::ThrowTypeError(
         "createSsl's second argument must be a list of objects");
   }
-  int force_client_auth = 0;
+
+  grpc_ssl_client_certificate_request_type client_certificate_request;
   if (info[2]->IsBoolean()) {
-    force_client_auth = (int)Nan::To<bool>(info[2]).FromJust();
+    client_certificate_request =
+        Nan::To<bool>(info[2]).FromJust()
+            ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+            : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
   } else if (!(info[2]->IsUndefined() || info[2]->IsNull())) {
     return Nan::ThrowTypeError(
         "createSsl's third argument must be a boolean if provided");
@@ -180,8 +184,9 @@
     key_cert_pairs[i].private_key = ::node::Buffer::Data(maybe_key);
     key_cert_pairs[i].cert_chain = ::node::Buffer::Data(maybe_cert);
   }
-  grpc_server_credentials *creds = grpc_ssl_server_credentials_create(
-      root_certs, key_cert_pairs, key_cert_pair_count, force_client_auth, NULL);
+  grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex(
+      root_certs, key_cert_pairs, key_cert_pair_count,
+      client_certificate_request, NULL);
   delete key_cert_pairs;
   if (creds == NULL) {
     info.GetReturnValue().SetNull();
diff --git a/src/node/ext/timeval.cc b/src/node/ext/timeval.cc
index c8f8534..9284db6 100644
--- a/src/node/ext/timeval.cc
+++ b/src/node/ext/timeval.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/health_check/health.js b/src/node/health_check/health.js
index 6ab4157..5236683 100644
--- a/src/node/health_check/health.js
+++ b/src/node/health_check/health.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/index.js b/src/node/index.js
index 1c19772..d345a51 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -87,6 +87,10 @@
  *   Buffers. Defaults to false
  * - longsAsStrings: deserialize long values as strings instead of objects.
  *   Defaults to true
+ * - deprecatedArgumentOrder: Use the beta method argument order for client
+ *   methods, with optional arguments after the callback. Defaults to false.
+ *   This option is only a temporary stopgap measure to smooth an API breakage.
+ *   It is deprecated, and new code should not use it.
  * @param {string|{root: string, file: string}} filename The file to load
  * @param {string=} format The file format to expect. Must be either 'proto' or
  *     'json'. Defaults to 'proto'
diff --git a/src/node/interop/async_delay_queue.js b/src/node/interop/async_delay_queue.js
index df57209..5df1e00 100644
--- a/src/node/interop/async_delay_queue.js
+++ b/src/node/interop/async_delay_queue.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index 5602011..e8f2d37 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -286,7 +286,7 @@
 function timeoutOnSleepingServer(client, done) {
   var deadline = new Date();
   deadline.setMilliseconds(deadline.getMilliseconds() + 1);
-  var call = client.fullDuplexCall(null, {deadline: deadline});
+  var call = client.fullDuplexCall({deadline: deadline});
   call.write({
     payload: {body: zeroBuffer(27182)}
   });
@@ -316,10 +316,10 @@
       body: zeroBuffer(271828)
     }
   };
-  var unary = client.unaryCall(arg, function(err, resp) {
+  var unary = client.unaryCall(arg, metadata, function(err, resp) {
     assert.ifError(err);
     done();
-  }, metadata);
+  });
   unary.on('metadata', function(metadata) {
     assert.deepEqual(metadata.get(ECHO_INITIAL_KEY),
                      ['test_initial_metadata_value']);
@@ -455,14 +455,14 @@
       credential = credential.createScoped(scope);
     }
     var creds = grpc.credentials.createFromGoogleCredential(credential);
-    client.unaryCall(arg, function(err, resp) {
+    client.unaryCall(arg, {credentials: creds}, function(err, resp) {
       assert.ifError(err);
       assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL);
       assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1);
       if (done) {
         done();
       }
-    }, null, {credentials: creds});
+    });
   });
 }
 
@@ -545,6 +545,8 @@
                   Client: testProto.TestService}
 };
 
+exports.test_cases = test_cases;
+
 /**
  * Execute a single test case.
  * @param {string} address The address of the server to connect to, in the
diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js
index c094817..7280762 100644
--- a/src/node/interop/interop_server.js
+++ b/src/node/interop/interop_server.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/performance/benchmark_client.js b/src/node/performance/benchmark_client.js
index 620aecd..262aa33 100644
--- a/src/node/performance/benchmark_client.js
+++ b/src/node/performance/benchmark_client.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,9 @@
 var _ = require('lodash');
 var PoissonProcess = require('poisson-process');
 var Histogram = require('./histogram');
+
+var genericService = require('./generic_service');
+
 var grpc = require('../../../');
 var serviceProto = grpc.load({
   root: __dirname + '/../../..',
@@ -104,10 +107,14 @@
   }
 
   this.clients = [];
+  var GenericClient = grpc.makeGenericClientConstructor(genericService);
+  this.genericClients = [];
 
   for (var i = 0; i < channels; i++) {
     this.clients[i] = new serviceProto.BenchmarkService(
         server_targets[i % server_targets.length], creds, options);
+    this.genericClients[i] = new GenericClient(
+        server_targets[i % server_targets.length], creds, options);
   }
 
   this.histogram = new Histogram(histogram_params.resolution,
@@ -130,9 +137,11 @@
  *     'STREAMING'
  * @param {number} req_size The size of the payload to send with each request
  * @param {number} resp_size The size of payload to request be sent in responses
+ * @param {boolean} generic Indicates that the generic (non-proto) clients
+ *     should be used
  */
 BenchmarkClient.prototype.startClosedLoop = function(
-    outstanding_rpcs_per_channel, rpc_type, req_size, resp_size) {
+    outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, generic) {
   var self = this;
 
   self.running = true;
@@ -141,12 +150,20 @@
 
   var makeCall;
 
-  var argument = {
-    response_size: resp_size,
-    payload: {
-      body: zeroBuffer(req_size)
-    }
-  };
+  var argument;
+  var client_list;
+  if (generic) {
+    argument = zeroBuffer(req_size);
+    client_list = self.genericClients;
+  } else {
+    argument = {
+      response_size: resp_size,
+      payload: {
+        body: zeroBuffer(req_size)
+      }
+    };
+    client_list = self.clients;
+  }
 
   if (rpc_type == 'UNARY') {
     makeCall = function(client) {
@@ -195,7 +212,7 @@
     };
   }
 
-  _.each(self.clients, function(client) {
+  _.each(client_list, function(client) {
     _.times(outstanding_rpcs_per_channel, function() {
       makeCall(client);
     });
@@ -213,9 +230,12 @@
  * @param {number} req_size The size of the payload to send with each request
  * @param {number} resp_size The size of payload to request be sent in responses
  * @param {number} offered_load The load parameter for the Poisson process
+ * @param {boolean} generic Indicates that the generic (non-proto) clients
+ *     should be used
  */
 BenchmarkClient.prototype.startPoisson = function(
-    outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, offered_load) {
+    outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, offered_load,
+    generic) {
   var self = this;
 
   self.running = true;
@@ -224,12 +244,20 @@
 
   var makeCall;
 
-  var argument = {
-    response_size: resp_size,
-    payload: {
-      body: zeroBuffer(req_size)
-    }
-  };
+  var argument;
+  var client_list;
+  if (generic) {
+    argument = zeroBuffer(req_size);
+    client_list = self.genericClients;
+  } else {
+    argument = {
+      response_size: resp_size,
+      payload: {
+        body: zeroBuffer(req_size)
+      }
+    };
+    client_list = self.clients;
+  }
 
   if (rpc_type == 'UNARY') {
     makeCall = function(client, poisson) {
@@ -282,7 +310,7 @@
 
   var averageIntervalMs = (1 / offered_load) * 1000;
 
-  _.each(self.clients, function(client) {
+  _.each(client_list, function(client) {
     _.times(outstanding_rpcs_per_channel, function() {
       var p = PoissonProcess.create(averageIntervalMs, function() {
         makeCall(client, p);
diff --git a/src/node/performance/benchmark_server.js b/src/node/performance/benchmark_server.js
index e48acd4..70cee99 100644
--- a/src/node/performance/benchmark_server.js
+++ b/src/node/performance/benchmark_server.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,8 @@
 var fs = require('fs');
 var path = require('path');
 
+var genericService = require('./generic_service');
+
 var grpc = require('../../../');
 var serviceProto = grpc.load({
   root: __dirname + '/../../..',
@@ -84,14 +86,28 @@
   });
 }
 
+function makeStreamingGenericCall(response_size) {
+  var response = zeroBuffer(response_size);
+  return function streamingGenericCall(call) {
+    call.on('data', function(value) {
+      call.write(response);
+    });
+    call.on('end', function() {
+      call.end();
+    });
+  };
+}
+
 /**
  * BenchmarkServer class. Constructed based on parameters from the driver and
  * stores statistics.
  * @param {string} host The host to serve on
  * @param {number} port The port to listen to
- * @param {tls} Indicates whether TLS should be used
+ * @param {boolean} tls Indicates whether TLS should be used
+ * @param {boolean} generic Indicates whether to use the generic service
+ * @param {number=} response_size The response size for the generic service
  */
-function BenchmarkServer(host, port, tls) {
+function BenchmarkServer(host, port, tls, generic, response_size) {
   var server_creds;
   var host_override;
   if (tls) {
@@ -109,10 +125,16 @@
 
   var server = new grpc.Server();
   this.port = server.bind(host + ':' + port, server_creds);
-  server.addProtoService(serviceProto.BenchmarkService.service, {
-    unaryCall: unaryCall,
-    streamingCall: streamingCall
-  });
+  if (generic) {
+    server.addService(genericService, {
+      streamingCall: makeStreamingGenericCall(response_size)
+    });
+  } else {
+    server.addProtoService(serviceProto.BenchmarkService.service, {
+      unaryCall: unaryCall,
+      streamingCall: streamingCall
+    });
+  }
   this.server = server;
 }
 
diff --git a/src/node/performance/generic_service.js b/src/node/performance/generic_service.js
new file mode 100644
index 0000000..ce09cc4
--- /dev/null
+++ b/src/node/performance/generic_service.js
@@ -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.
+ *
+ */
+
+var _ = require('lodash');
+
+module.exports = {
+  'streamingCall' : {
+    path: '/grpc.testing/BenchmarkService',
+    requestStream: true,
+    responseStream: true,
+    requestSerialize: _.identity,
+    requestDeserialize: _.identity,
+    responseSerialize: _.identity,
+    responseDeserialize: _.identity
+  }
+};
diff --git a/src/node/performance/worker.js b/src/node/performance/worker.js
index 7c8ab00..7ef9b84 100644
--- a/src/node/performance/worker.js
+++ b/src/node/performance/worker.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
 
 'use strict';
 
+var console = require('console');
 var worker_service_impl = require('./worker_service_impl');
 
 var grpc = require('../../../');
@@ -48,6 +49,7 @@
   var address = '0.0.0.0:' + port;
   server.bind(address, server_creds);
   server.start();
+  console.log('running QPS worker on %s', address);
   return server;
 }
 
diff --git a/src/node/performance/worker_service_impl.js b/src/node/performance/worker_service_impl.js
index 1439249..4b5cb8f 100644
--- a/src/node/performance/worker_service_impl.js
+++ b/src/node/performance/worker_service_impl.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
 'use strict';
 
 var os = require('os');
+var console = require('console');
 var BenchmarkClient = require('./benchmark_client');
 var BenchmarkServer = require('./benchmark_server');
 
@@ -49,6 +50,7 @@
     switch (request.argtype) {
       case 'setup':
       var setup = request.setup;
+      console.log('ClientConfig %j', setup);
       client = new BenchmarkClient(setup.server_targets,
                                    setup.client_channels,
                                    setup.histogram_params,
@@ -56,18 +58,31 @@
       client.on('error', function(error) {
         call.emit('error', error);
       });
+      var req_size, resp_size, generic;
+      switch (setup.payload_config.payload) {
+        case 'bytebuf_params':
+        req_size = setup.payload_config.bytebuf_params.req_size;
+        resp_size = setup.payload_config.bytebuf_params.resp_size;
+        generic = true;
+        break;
+        case 'simple_params':
+        req_size = setup.payload_config.simple_params.req_size;
+        resp_size = setup.payload_config.simple_params.resp_size;
+        generic = false;
+        break;
+        default:
+        call.emit('error', new Error('Unsupported PayloadConfig type' +
+            setup.payload_config.payload));
+      }
       switch (setup.load_params.load) {
         case 'closed_loop':
         client.startClosedLoop(setup.outstanding_rpcs_per_channel,
-                               setup.rpc_type,
-                               setup.payload_config.simple_params.req_size,
-                               setup.payload_config.simple_params.resp_size);
+                               setup.rpc_type, req_size, resp_size, generic);
         break;
         case 'poisson':
         client.startPoisson(setup.outstanding_rpcs_per_channel,
-                            setup.rpc_type, setup.payload_config.req_size,
-                            setup.payload_config.resp_size,
-                            setup.load_params.poisson.offered_load);
+                            setup.rpc_type, req_size, resp_size,
+                            setup.load_params.poisson.offered_load, generic);
         break;
         default:
         call.emit('error', new Error('Unsupported LoadParams type' +
@@ -105,6 +120,7 @@
     var stats;
     switch (request.argtype) {
       case 'setup':
+      console.log('ServerConfig %j', request.setup);
       server = new BenchmarkServer('[::]', request.setup.port,
                                    request.setup.security_params);
       server.start();
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 2459e28..5e07046 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,7 @@
 'use strict';
 
 var _ = require('lodash');
+var arguejs = require('arguejs');
 
 var grpc = require('./grpc_extension');
 
@@ -353,21 +354,23 @@
    * @this {Client} Client object. Must have a channel member.
    * @param {*} argument The argument to the call. Should be serializable with
    *     serialize
-   * @param {function(?Error, value=)} callback The callback to for when the
-   *     response is received
    * @param {Metadata=} metadata Metadata to add to the call
    * @param {Object=} options Options map
+   * @param {function(?Error, value=)} callback The callback to for when the
+   *     response is received
    * @return {EventEmitter} An event emitter for stream related events
    */
-  function makeUnaryRequest(argument, callback, metadata, options) {
+  function makeUnaryRequest(argument, metadata, options, callback) {
     /* jshint validthis: true */
+    /* While the arguments are listed in the function signature, those variables
+     * are not used directly. Instead, ArgueJS processes the arguments
+     * object. This allows for simple handling of optional arguments in the
+     * middle of the argument list, and also provides type checking. */
+    var args = arguejs({argument: null, metadata: [Metadata, new Metadata()],
+                        options: [Object], callback: Function}, arguments);
     var emitter = new EventEmitter();
-    var call = getCall(this.$channel, method, options);
-    if (metadata === null || metadata === undefined) {
-      metadata = new Metadata();
-    } else {
-      metadata = metadata.clone();
-    }
+    var call = getCall(this.$channel, method, args.options);
+    metadata = args.metadata.clone();
     emitter.cancel = function cancel() {
       call.cancel();
     };
@@ -375,9 +378,9 @@
       return call.getPeer();
     };
     var client_batch = {};
-    var message = serialize(argument);
-    if (options) {
-      message.grpcWriteFlags = options.flags;
+    var message = serialize(args.argument);
+    if (args.options) {
+      message.grpcWriteFlags = args.options.flags;
     }
     client_batch[grpc.opType.SEND_INITIAL_METADATA] =
         metadata._getCoreRepresentation();
@@ -395,7 +398,7 @@
       if (status.code === grpc.status.OK) {
         if (err) {
           // Got a batch error, but OK status. Something went wrong
-          callback(err);
+          args.callback(err);
           return;
         } else {
           try {
@@ -414,9 +417,9 @@
         error = new Error(status.details);
         error.code = status.code;
         error.metadata = status.metadata;
-        callback(error);
+        args.callback(error);
       } else {
-        callback(null, deserialized);
+        args.callback(null, deserialized);
       }
       emitter.emit('status', status);
       emitter.emit('metadata', Metadata._fromCoreRepresentation(
@@ -440,21 +443,23 @@
    * Make a client stream request with this method on the given channel with the
    * given callback, etc.
    * @this {Client} Client object. Must have a channel member.
-   * @param {function(?Error, value=)} callback The callback to for when the
-   *     response is received
    * @param {Metadata=} metadata Array of metadata key/value pairs to add to the
    *     call
    * @param {Object=} options Options map
+   * @param {function(?Error, value=)} callback The callback to for when the
+   *     response is received
    * @return {EventEmitter} An event emitter for stream related events
    */
-  function makeClientStreamRequest(callback, metadata, options) {
+  function makeClientStreamRequest(metadata, options, callback) {
     /* jshint validthis: true */
-    var call = getCall(this.$channel, method, options);
-    if (metadata === null || metadata === undefined) {
-      metadata = new Metadata();
-    } else {
-      metadata = metadata.clone();
-    }
+    /* While the arguments are listed in the function signature, those variables
+     * are not used directly. Instead, ArgueJS processes the arguments
+     * object. This allows for simple handling of optional arguments in the
+     * middle of the argument list, and also provides type checking. */
+    var args = arguejs({metadata: [Metadata, new Metadata()],
+                        options: [Object], callback: Function}, arguments);
+    var call = getCall(this.$channel, method, args.options);
+    metadata = args.metadata.clone();
     var stream = new ClientWritableStream(call, serialize);
     var metadata_batch = {};
     metadata_batch[grpc.opType.SEND_INITIAL_METADATA] =
@@ -481,7 +486,7 @@
       if (status.code === grpc.status.OK) {
         if (err) {
           // Got a batch error, but OK status. Something went wrong
-          callback(err);
+          args.callback(err);
           return;
         } else {
           try {
@@ -500,9 +505,9 @@
         error = new Error(response.status.details);
         error.code = status.code;
         error.metadata = status.metadata;
-        callback(error);
+        args.callback(error);
       } else {
-        callback(null, deserialized);
+        args.callback(null, deserialized);
       }
       stream.emit('status', status);
     });
@@ -533,17 +538,18 @@
    */
   function makeServerStreamRequest(argument, metadata, options) {
     /* jshint validthis: true */
-    var call = getCall(this.$channel, method, options);
-    if (metadata === null || metadata === undefined) {
-      metadata = new Metadata();
-    } else {
-      metadata = metadata.clone();
-    }
+    /* While the arguments are listed in the function signature, those variables
+     * are not used directly. Instead, ArgueJS processes the arguments
+     * object. */
+    var args = arguejs({argument: null, metadata: [Metadata, new Metadata()],
+                        options: [Object]}, arguments);
+    var call = getCall(this.$channel, method, args.options);
+    metadata = args.metadata.clone();
     var stream = new ClientReadableStream(call, deserialize);
     var start_batch = {};
-    var message = serialize(argument);
-    if (options) {
-      message.grpcWriteFlags = options.flags;
+    var message = serialize(args.argument);
+    if (args.options) {
+      message.grpcWriteFlags = args.options.flags;
     }
     start_batch[grpc.opType.SEND_INITIAL_METADATA] =
         metadata._getCoreRepresentation();
@@ -595,12 +601,13 @@
    */
   function makeBidiStreamRequest(metadata, options) {
     /* jshint validthis: true */
-    var call = getCall(this.$channel, method, options);
-    if (metadata === null || metadata === undefined) {
-      metadata = new Metadata();
-    } else {
-      metadata = metadata.clone();
-    }
+    /* While the arguments are listed in the function signature, those variables
+     * are not used directly. Instead, ArgueJS processes the arguments
+     * object. */
+    var args = arguejs({metadata: [Metadata, new Metadata()],
+                        options: [Object]}, arguments);
+    var call = getCall(this.$channel, method, args.options);
+    metadata = args.metadata.clone();
     var stream = new ClientDuplexStream(call, serialize, deserialize);
     var start_batch = {};
     start_batch[grpc.opType.SEND_INITIAL_METADATA] =
@@ -643,6 +650,40 @@
   bidi: makeBidiStreamRequestFunction
 };
 
+function getDefaultValues(metadata, options) {
+  var res = {};
+  res.metadata = metadata || new Metadata();
+  res.options = options || {};
+  return res;
+}
+
+/**
+ * Map with wrappers for each type of requester function to make it use the old
+ * argument order with optional arguments after the callback.
+ */
+var deprecated_request_wrap = {
+  unary: function(makeUnaryRequest) {
+    return function makeWrappedUnaryRequest(argument, callback,
+                                            metadata, options) {
+      /* jshint validthis: true */
+      var opt_args = getDefaultValues(metadata, metadata);
+      return makeUnaryRequest.call(this, argument, opt_args.metadata,
+                                   opt_args.options, callback);
+    };
+  },
+  client_stream: function(makeServerStreamRequest) {
+    return function makeWrappedClientStreamRequest(callback, metadata,
+                                                   options) {
+      /* jshint validthis: true */
+      var opt_args = getDefaultValues(metadata, options);
+      return makeServerStreamRequest.call(this, opt_args.metadata,
+                                          opt_args.options, callback);
+    };
+  },
+  server_stream: _.identity,
+  bidi: _.identity
+};
+
 /**
  * Creates a constructor for a client with the given methods. The methods object
  * maps method name to an object with the following keys:
@@ -654,9 +695,19 @@
  * responseDeserialize: function to deserialize response objects
  * @param {Object} methods An object mapping method names to method attributes
  * @param {string} serviceName The fully qualified name of the service
+ * @param {Object} class_options An options object. Currently only uses the key
+ *     deprecatedArgumentOrder, a boolean that Indicates that the old argument
+ *     order should be used for methods, with optional arguments at the end
+ *     instead of the callback at the end. Defaults to false. This option is
+ *     only a temporary stopgap measure to smooth an API breakage.
+ *     It is deprecated, and new code should not use it.
  * @return {function(string, Object)} New client constructor
  */
-exports.makeClientConstructor = function(methods, serviceName) {
+exports.makeClientConstructor = function(methods, serviceName,
+                                         class_options) {
+  if (!class_options) {
+    class_options = {};
+  }
   /**
    * Create a client with the given methods
    * @constructor
@@ -703,8 +754,13 @@
     }
     var serialize = attrs.requestSerialize;
     var deserialize = attrs.responseDeserialize;
-    Client.prototype[name] = requester_makers[method_type](
+    var method_func = requester_makers[method_type](
         attrs.path, serialize, deserialize);
+    if (class_options.deprecatedArgumentOrder) {
+      Client.prototype[name] = deprecated_request_wrap(method_func);
+    } else {
+      Client.prototype[name] = method_func;
+    }
     // Associate all provided attributes with the method
     _.assign(Client.prototype[name], attrs);
   });
@@ -761,8 +817,13 @@
 exports.makeProtobufClientConstructor =  function(service, options) {
   var method_attrs = common.getProtobufServiceAttrs(service, service.name,
                                                     options);
+  var deprecatedArgumentOrder = false;
+  if (options) {
+    deprecatedArgumentOrder = options.deprecatedArgumentOrder;
+  }
   var Client = exports.makeClientConstructor(
-      method_attrs, common.fullyQualifiedName(service));
+      method_attrs, common.fullyQualifiedName(service),
+      deprecatedArgumentOrder);
   Client.service = service;
   Client.service.grpc_options = options;
   return Client;
diff --git a/src/node/src/common.js b/src/node/src/common.js
index 7705a27..8cf43b7 100644
--- a/src/node/src/common.js
+++ b/src/node/src/common.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js
index 97c4bd7..a12eade 100644
--- a/src/node/src/credentials.js
+++ b/src/node/src/credentials.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js
index 33d7ea1..612361b 100644
--- a/src/node/src/metadata.js
+++ b/src/node/src/metadata.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 0cf7ba3..2212834 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -339,7 +339,7 @@
     try {
       deserialized = self.deserialize(data);
     } catch (e) {
-      e.code = grpc.status.INVALID_ARGUMENT;
+      e.code = grpc.status.INTERNAL;
       self.emit('error', e);
       return;
     }
@@ -475,7 +475,7 @@
     try {
       emitter.request = handler.deserialize(result.read);
     } catch (e) {
-      e.code = grpc.status.INVALID_ARGUMENT;
+      e.code = grpc.status.INTERNAL;
       handleError(call, e);
       return;
     }
@@ -516,7 +516,7 @@
     try {
       stream.request = handler.deserialize(result.read);
     } catch (e) {
-      e.code = grpc.status.INVALID_ARGUMENT;
+      e.code = grpc.status.INTERNAL;
       stream.emit('error', e);
       return;
     }
diff --git a/src/node/stress/metrics_client.js b/src/node/stress/metrics_client.js
new file mode 100644
index 0000000..dc8ef5e
--- /dev/null
+++ b/src/node/stress/metrics_client.js
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+var grpc = require('../../..');
+
+var proto = grpc.load(__dirname + '/../../proto/grpc/testing/metrics.proto');
+var metrics = proto.grpc.testing;
+
+function main() {
+  var parseArgs = require('minimist');
+  var argv = parseArgs(process.argv, {
+    string: 'metrics_server_address',
+    boolean: 'total_only'
+  });
+  var client = new metrics.MetricsService(argv.metrics_server_address,
+                                          grpc.credentials.createInsecure());
+  if (argv.total_only) {
+    client.getGauge({name: 'qps'}, function(err, data) {
+      console.log(data.name + ':', data.long_value);
+    });
+  } else {
+    var call = client.getAllGauges({});
+    call.on('data', function(data) {
+      console.log(data.name + ':', data.long_value);
+    });
+  }
+}
+
+main();
diff --git a/src/node/stress/metrics_server.js b/src/node/stress/metrics_server.js
new file mode 100644
index 0000000..3ab4b4c
--- /dev/null
+++ b/src/node/stress/metrics_server.js
@@ -0,0 +1,87 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+var _ = require('lodash');
+
+var grpc = require('../../..');
+
+var proto = grpc.load(__dirname + '/../../proto/grpc/testing/metrics.proto');
+var metrics = proto.grpc.testing;
+
+function getGauge(call, callback) {
+  /* jshint validthis: true */
+  // Should be bound to a MetricsServer object
+  var name = call.request.name;
+  if (this.gauges.hasOwnProperty(name)) {
+    callback(null, _.assign({name: name}, this.gauges[name]()));
+  } else {
+    callback({code: grpc.status.NOT_FOUND,
+              details: 'No such gauge: ' + name});
+  }
+}
+
+function getAllGauges(call) {
+  /* jshint validthis: true */
+  // Should be bound to a MetricsServer object
+  _.each(this.gauges, function(getter, name) {
+    call.write(_.assign({name: name}, getter()));
+  });
+  call.end();
+}
+
+function MetricsServer(port) {
+  var server = new grpc.Server();
+  server.addProtoService(metrics.MetricsService.service, {
+    getGauge: _.bind(getGauge, this),
+    getAllGauges: _.bind(getAllGauges, this)
+  });
+  server.bind('localhost:' + port, grpc.ServerCredentials.createInsecure());
+  this.server = server;
+  this.gauges = {};
+}
+
+MetricsServer.prototype.start = function() {
+  this.server.start();
+}
+
+MetricsServer.prototype.registerGauge = function(name, getter) {
+  this.gauges[name] = getter;
+};
+
+MetricsServer.prototype.shutdown = function() {
+  this.server.forceShutdown();
+};
+
+module.exports = MetricsServer;
diff --git a/src/node/stress/stress_client.js b/src/node/stress/stress_client.js
new file mode 100644
index 0000000..6054d3a
--- /dev/null
+++ b/src/node/stress/stress_client.js
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+var _ = require('lodash');
+
+var grpc = require('../../..');
+
+var interop_client = require('../interop/interop_client');
+var MetricsServer = require('./metrics_server');
+
+var running;
+
+var metrics_server;
+
+var start_time;
+var query_count;
+
+function makeCall(client, test_cases) {
+  if (!running) {
+    return;
+  }
+  var test_case = test_cases[_.random(test_cases.length - 1)];
+  interop_client.test_cases[test_case].run(client, function() {
+    query_count += 1;
+    makeCall(client, test_cases);
+  });
+}
+
+function makeCalls(client, test_cases, parallel_calls_per_channel) {
+  _.times(parallel_calls_per_channel, function() {
+    makeCall(client, test_cases);
+  });
+}
+
+function getQps() {
+  var diff = process.hrtime(start_time);
+  var seconds = diff[0] + diff[1] / 1e9;
+  return {long_value: query_count / seconds};
+}
+
+function start(server_addresses, test_cases, channels_per_server,
+               parallel_calls_per_channel, metrics_port) {
+  running = true;
+  /* Assuming that we are not calling unimplemented_method. The client class
+   * used by empty_unary is (currently) the client class used by every interop
+   * test except unimplemented_method */
+  var Client = interop_client.test_cases.empty_unary.Client;
+  /* Make channels_per_server clients connecting to each server address */
+  var channels = _.flatten(_.times(
+      channels_per_server, _.partial(_.map, server_addresses, function(address) {
+        return new Client(address, grpc.credentials.createInsecure());
+      })));
+  metrics_server = new MetricsServer(metrics_port);
+  metrics_server.registerGauge('qps', getQps);
+  start_time = process.hrtime();
+  query_count = 0;
+  _.each(channels, _.partial(makeCalls, _, test_cases,
+                             parallel_calls_per_channel));
+  metrics_server.start();
+}
+
+function stop() {
+  running = false;
+  metrics_server.shutdown();
+  console.log('QPS: ' + getQps().long_value);
+}
+
+function main() {
+  var parseArgs = require('minimist');
+  var argv = parseArgs(process.argv, {
+    string: ['server_addresses', 'test_cases', 'metrics_port'],
+    default: {'server_addresses': 'localhost:8080',
+              'test_duration_secs': -1,
+              'num_channels_per_server': 1,
+              'num_stubs_per_channel': 1,
+              'metrics_port': '8081'}
+  });
+  var server_addresses = argv.server_addresses.split(',');
+  /* Generate an array of test cases, where the number of instances of each name
+   * corresponds to the number given in the argument.
+   * e.g. 'empty_unary:1,large_unary:2' =>
+   * ['empty_unary', 'large_unary', 'large_unary'] */
+  var test_cases = _.flatten(_.map(argv.test_cases.split(','), function(value) {
+    var split = value.split(':');
+    return _.times(split[1], _.constant(split[0]));
+  }));
+  start(server_addresses, test_cases, argv.num_channels_per_server,
+        argv.num_stubs_per_channel, argv.metrics_port);
+  if (argv.test_duration_secs > -1) {
+    setTimeout(stop, argv.test_duration_secs * 1000);
+  }
+}
+
+main();
diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js
index 2300096..eb26860 100644
--- a/src/node/test/call_test.js
+++ b/src/node/test/call_test.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/channel_test.js b/src/node/test/channel_test.js
index c0ae2b7..0cdb633 100644
--- a/src/node/test/channel_test.js
+++ b/src/node/test/channel_test.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/common_test.js b/src/node/test/common_test.js
index 66a4205..c57b738 100644
--- a/src/node/test/common_test.js
+++ b/src/node/test/common_test.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/constant_test.js b/src/node/test/constant_test.js
index 712c707..414b1ac 100644
--- a/src/node/test/constant_test.js
+++ b/src/node/test/constant_test.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index 294600c..794215b 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -398,18 +398,20 @@
           metadataUpdater);
     });
     it('Should update metadata on a unary call', function(done) {
-      var call = client.unary({}, function(err, data) {
-        assert.ifError(err);
-      }, null, {credentials: updater_creds});
+      var call = client.unary({}, {credentials: updater_creds},
+                              function(err, data) {
+                                assert.ifError(err);
+                              });
       call.on('metadata', function(metadata) {
         assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
         done();
       });
     });
     it('should update metadata on a client streaming call', function(done) {
-      var call = client.clientStream(function(err, data) {
-        assert.ifError(err);
-      }, null, {credentials: updater_creds});
+      var call = client.clientStream({credentials: updater_creds},
+                                     function(err, data) {
+                                       assert.ifError(err);
+                                     });
       call.on('metadata', function(metadata) {
         assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
         done();
@@ -417,7 +419,7 @@
       call.end();
     });
     it('should update metadata on a server streaming call', function(done) {
-      var call = client.serverStream({}, null, {credentials: updater_creds});
+      var call = client.serverStream({}, {credentials: updater_creds});
       call.on('data', function() {});
       call.on('metadata', function(metadata) {
         assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
@@ -425,7 +427,7 @@
       });
     });
     it('should update metadata on a bidi streaming call', function(done) {
-      var call = client.bidiStream(null, {credentials: updater_creds});
+      var call = client.bidiStream({credentials: updater_creds});
       call.on('data', function() {});
       call.on('metadata', function(metadata) {
         assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
@@ -443,9 +445,10 @@
           altMetadataUpdater);
       var combined_updater = grpc.credentials.combineCallCredentials(
           updater_creds, alt_updater_creds);
-      var call = client.unary({}, function(err, data) {
-        assert.ifError(err);
-      }, null, {credentials: combined_updater});
+      var call = client.unary({}, {credentials: combined_updater},
+                              function(err, data) {
+                                assert.ifError(err);
+                              });
       call.on('metadata', function(metadata) {
         assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
         assert.deepEqual(metadata.get('other_plugin_key'),
diff --git a/src/node/test/echo_service.proto b/src/node/test/echo_service.proto
index 11b4f18..fc941a2 100644
--- a/src/node/test/echo_service.proto
+++ b/src/node/test/echo_service.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js
index 353c6c7..f127a41 100644
--- a/src/node/test/end_to_end_test.js
+++ b/src/node/test/end_to_end_test.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/math/math_grpc_pb.js b/src/node/test/math/math_grpc_pb.js
new file mode 100644
index 0000000..083ed66
--- /dev/null
+++ b/src/node/test/math/math_grpc_pb.js
@@ -0,0 +1,99 @@
+// GENERATED CODE -- DO NOT EDIT!
+
+'use strict';
+var grpc = require('grpc');
+var math_pb = require('./math_pb.js');
+
+function serialize_DivArgs(arg) {
+  if (!(arg instanceof math_pb.DivArgs)) {
+    throw new Error('Expected argument of type DivArgs');
+  }
+  return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_DivArgs(buffer_arg) {
+  return math_pb.DivArgs.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_DivReply(arg) {
+  if (!(arg instanceof math_pb.DivReply)) {
+    throw new Error('Expected argument of type DivReply');
+  }
+  return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_DivReply(buffer_arg) {
+  return math_pb.DivReply.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_FibArgs(arg) {
+  if (!(arg instanceof math_pb.FibArgs)) {
+    throw new Error('Expected argument of type FibArgs');
+  }
+  return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_FibArgs(buffer_arg) {
+  return math_pb.FibArgs.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_Num(arg) {
+  if (!(arg instanceof math_pb.Num)) {
+    throw new Error('Expected argument of type Num');
+  }
+  return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_Num(buffer_arg) {
+  return math_pb.Num.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+
+var MathService = exports.MathService = {
+  div: {
+    path: '/math.Math/Div',
+    requestStream: false,
+    responseStream: false,
+    requestType: math_pb.DivArgs,
+    responseType: math_pb.DivReply,
+    requestSerialize: serialize_DivArgs,
+    requestDeserialize: deserialize_DivArgs,
+    responseSerialize: serialize_DivReply,
+    responseDeserialize: deserialize_DivReply,
+  },
+  divMany: {
+    path: '/math.Math/DivMany',
+    requestStream: true,
+    responseStream: true,
+    requestType: math_pb.DivArgs,
+    responseType: math_pb.DivReply,
+    requestSerialize: serialize_DivArgs,
+    requestDeserialize: deserialize_DivArgs,
+    responseSerialize: serialize_DivReply,
+    responseDeserialize: deserialize_DivReply,
+  },
+  fib: {
+    path: '/math.Math/Fib',
+    requestStream: false,
+    responseStream: true,
+    requestType: math_pb.FibArgs,
+    responseType: math_pb.Num,
+    requestSerialize: serialize_FibArgs,
+    requestDeserialize: deserialize_FibArgs,
+    responseSerialize: serialize_Num,
+    responseDeserialize: deserialize_Num,
+  },
+  sum: {
+    path: '/math.Math/Sum',
+    requestStream: true,
+    responseStream: false,
+    requestType: math_pb.Num,
+    responseType: math_pb.Num,
+    requestSerialize: serialize_Num,
+    requestDeserialize: deserialize_Num,
+    responseSerialize: serialize_Num,
+    responseDeserialize: deserialize_Num,
+  },
+};
+
+exports.MathClient = grpc.makeGenericClientConstructor(MathService);
diff --git a/src/node/test/math/math_pb.js b/src/node/test/math/math_pb.js
new file mode 100644
index 0000000..3489143
--- /dev/null
+++ b/src/node/test/math/math_pb.js
@@ -0,0 +1,866 @@
+/**
+ * @fileoverview
+ * @enhanceable
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+goog.exportSymbol('proto.math.DivArgs', null, global);
+goog.exportSymbol('proto.math.DivReply', null, global);
+goog.exportSymbol('proto.math.FibArgs', null, global);
+goog.exportSymbol('proto.math.FibReply', null, global);
+goog.exportSymbol('proto.math.Num', null, global);
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.DivArgs = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.DivArgs, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  proto.math.DivArgs.displayName = 'proto.math.DivArgs';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.DivArgs.prototype.toObject = function(opt_includeInstance) {
+  return proto.math.DivArgs.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ *     instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.math.DivArgs} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.DivArgs.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    dividend: msg.getDividend(),
+    divisor: msg.getDivisor()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.DivArgs}
+ */
+proto.math.DivArgs.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.math.DivArgs;
+  return proto.math.DivArgs.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.DivArgs} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.DivArgs}
+ */
+proto.math.DivArgs.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt64());
+      msg.setDividend(value);
+      break;
+    case 2:
+      var value = /** @type {number} */ (reader.readInt64());
+      msg.setDivisor(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.DivArgs} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivArgs.serializeBinaryToWriter = function(message, writer) {
+  message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.DivArgs.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  this.serializeBinaryToWriter(writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivArgs.prototype.serializeBinaryToWriter = function (writer) {
+  var f = undefined;
+  f = this.getDividend();
+  if (f !== 0) {
+    writer.writeInt64(
+      1,
+      f
+    );
+  }
+  f = this.getDivisor();
+  if (f !== 0) {
+    writer.writeInt64(
+      2,
+      f
+    );
+  }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.DivArgs} The clone.
+ */
+proto.math.DivArgs.prototype.cloneMessage = function() {
+  return /** @type {!proto.math.DivArgs} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 dividend = 1;
+ * @return {number}
+ */
+proto.math.DivArgs.prototype.getDividend = function() {
+  return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value  */
+proto.math.DivArgs.prototype.setDividend = function(value) {
+  jspb.Message.setField(this, 1, value);
+};
+
+
+/**
+ * optional int64 divisor = 2;
+ * @return {number}
+ */
+proto.math.DivArgs.prototype.getDivisor = function() {
+  return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0));
+};
+
+
+/** @param {number} value  */
+proto.math.DivArgs.prototype.setDivisor = function(value) {
+  jspb.Message.setField(this, 2, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.DivReply = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.DivReply, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  proto.math.DivReply.displayName = 'proto.math.DivReply';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.DivReply.prototype.toObject = function(opt_includeInstance) {
+  return proto.math.DivReply.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ *     instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.math.DivReply} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.DivReply.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    quotient: msg.getQuotient(),
+    remainder: msg.getRemainder()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.DivReply}
+ */
+proto.math.DivReply.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.math.DivReply;
+  return proto.math.DivReply.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.DivReply} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.DivReply}
+ */
+proto.math.DivReply.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt64());
+      msg.setQuotient(value);
+      break;
+    case 2:
+      var value = /** @type {number} */ (reader.readInt64());
+      msg.setRemainder(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.DivReply} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivReply.serializeBinaryToWriter = function(message, writer) {
+  message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.DivReply.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  this.serializeBinaryToWriter(writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivReply.prototype.serializeBinaryToWriter = function (writer) {
+  var f = undefined;
+  f = this.getQuotient();
+  if (f !== 0) {
+    writer.writeInt64(
+      1,
+      f
+    );
+  }
+  f = this.getRemainder();
+  if (f !== 0) {
+    writer.writeInt64(
+      2,
+      f
+    );
+  }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.DivReply} The clone.
+ */
+proto.math.DivReply.prototype.cloneMessage = function() {
+  return /** @type {!proto.math.DivReply} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 quotient = 1;
+ * @return {number}
+ */
+proto.math.DivReply.prototype.getQuotient = function() {
+  return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value  */
+proto.math.DivReply.prototype.setQuotient = function(value) {
+  jspb.Message.setField(this, 1, value);
+};
+
+
+/**
+ * optional int64 remainder = 2;
+ * @return {number}
+ */
+proto.math.DivReply.prototype.getRemainder = function() {
+  return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0));
+};
+
+
+/** @param {number} value  */
+proto.math.DivReply.prototype.setRemainder = function(value) {
+  jspb.Message.setField(this, 2, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.FibArgs = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.FibArgs, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  proto.math.FibArgs.displayName = 'proto.math.FibArgs';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.FibArgs.prototype.toObject = function(opt_includeInstance) {
+  return proto.math.FibArgs.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ *     instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.math.FibArgs} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.FibArgs.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    limit: msg.getLimit()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.FibArgs}
+ */
+proto.math.FibArgs.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.math.FibArgs;
+  return proto.math.FibArgs.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.FibArgs} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.FibArgs}
+ */
+proto.math.FibArgs.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt64());
+      msg.setLimit(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.FibArgs} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibArgs.serializeBinaryToWriter = function(message, writer) {
+  message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.FibArgs.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  this.serializeBinaryToWriter(writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibArgs.prototype.serializeBinaryToWriter = function (writer) {
+  var f = undefined;
+  f = this.getLimit();
+  if (f !== 0) {
+    writer.writeInt64(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.FibArgs} The clone.
+ */
+proto.math.FibArgs.prototype.cloneMessage = function() {
+  return /** @type {!proto.math.FibArgs} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 limit = 1;
+ * @return {number}
+ */
+proto.math.FibArgs.prototype.getLimit = function() {
+  return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value  */
+proto.math.FibArgs.prototype.setLimit = function(value) {
+  jspb.Message.setField(this, 1, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.Num = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.Num, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  proto.math.Num.displayName = 'proto.math.Num';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.Num.prototype.toObject = function(opt_includeInstance) {
+  return proto.math.Num.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ *     instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.math.Num} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.Num.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    num: msg.getNum()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.Num}
+ */
+proto.math.Num.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.math.Num;
+  return proto.math.Num.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.Num} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.Num}
+ */
+proto.math.Num.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt64());
+      msg.setNum(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.Num} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.Num.serializeBinaryToWriter = function(message, writer) {
+  message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.Num.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  this.serializeBinaryToWriter(writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.Num.prototype.serializeBinaryToWriter = function (writer) {
+  var f = undefined;
+  f = this.getNum();
+  if (f !== 0) {
+    writer.writeInt64(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.Num} The clone.
+ */
+proto.math.Num.prototype.cloneMessage = function() {
+  return /** @type {!proto.math.Num} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 num = 1;
+ * @return {number}
+ */
+proto.math.Num.prototype.getNum = function() {
+  return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value  */
+proto.math.Num.prototype.setNum = function(value) {
+  jspb.Message.setField(this, 1, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.FibReply = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.FibReply, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  proto.math.FibReply.displayName = 'proto.math.FibReply';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.FibReply.prototype.toObject = function(opt_includeInstance) {
+  return proto.math.FibReply.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ *     instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.math.FibReply} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.FibReply.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    count: msg.getCount()
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.FibReply}
+ */
+proto.math.FibReply.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.math.FibReply;
+  return proto.math.FibReply.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.FibReply} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.FibReply}
+ */
+proto.math.FibReply.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt64());
+      msg.setCount(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.FibReply} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibReply.serializeBinaryToWriter = function(message, writer) {
+  message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.FibReply.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  this.serializeBinaryToWriter(writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibReply.prototype.serializeBinaryToWriter = function (writer) {
+  var f = undefined;
+  f = this.getCount();
+  if (f !== 0) {
+    writer.writeInt64(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.FibReply} The clone.
+ */
+proto.math.FibReply.prototype.cloneMessage = function() {
+  return /** @type {!proto.math.FibReply} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 count = 1;
+ * @return {number}
+ */
+proto.math.FibReply.prototype.getCount = function() {
+  return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value  */
+proto.math.FibReply.prototype.setCount = function(value) {
+  jspb.Message.setField(this, 1, value);
+};
+
+
+goog.object.extend(exports, proto.math);
diff --git a/src/node/test/math/math_server.js b/src/node/test/math/math_server.js
index 9f67c52..fa05ed0 100644
--- a/src/node/test/math/math_server.js
+++ b/src/node/test/math/math_server.js
@@ -34,8 +34,8 @@
 'use strict';
 
 var grpc = require('../..');
-var math = grpc.load(__dirname + '/../../../proto/math/math.proto').math;
-
+var grpcMath = require('./math_grpc_pb');
+var math = require('./math_pb');
 
 /**
  * Server function for division. Provides the /Math/DivMany and /Math/Div
@@ -46,14 +46,16 @@
  */
 function mathDiv(call, cb) {
   var req = call.request;
+  var divisor = req.getDivisor();
+  var dividend = req.getDividend();
   // Unary + is explicit coersion to integer
-  if (+req.divisor === 0) {
+  if (req.getDivisor() === 0) {
     cb(new Error('cannot divide by zero'));
   } else {
-    cb(null, {
-      quotient: req.dividend / req.divisor,
-      remainder: req.dividend % req.divisor
-    });
+    var response = new math.DivReply();
+    response.setQuotient(Math.floor(dividend / divisor));
+    response.setRemainder(dividend % divisor);
+    cb(null, response);
   }
 }
 
@@ -67,7 +69,9 @@
   // Here, call is a standard writable Node object Stream
   var previous = 0, current = 1;
   for (var i = 0; i < stream.request.limit; i++) {
-    stream.write({num: current});
+    var response = new math.Num();
+    response.setNum(current);
+    stream.write(response);
     var temp = current;
     current += previous;
     previous = temp;
@@ -85,22 +89,26 @@
   // Here, call is a standard readable Node object Stream
   var sum = 0;
   call.on('data', function(data) {
-    sum += (+data.num);
+    sum += data.getNum();
   });
   call.on('end', function() {
-    cb(null, {num: sum});
+    var response = new math.Num();
+    response.setNum(sum);
+    cb(null, response);
   });
 }
 
 function mathDivMany(stream) {
   stream.on('data', function(div_args) {
-    if (+div_args.divisor === 0) {
+    var divisor = div_args.getDivisor();
+    var dividend = div_args.getDividend();
+    if (divisor === 0) {
       stream.emit('error', new Error('cannot divide by zero'));
     } else {
-      stream.write({
-        quotient: div_args.dividend / div_args.divisor,
-        remainder: div_args.dividend % div_args.divisor
-      });
+      var response = new math.DivReply();
+      response.setQuotient(Math.floor(dividend / divisor));
+      response.setRemainder(dividend % divisor);
+      stream.write(response);
     }
   });
   stream.on('end', function() {
@@ -110,7 +118,7 @@
 
 function getMathServer() {
   var server = new grpc.Server();
-  server.addProtoService(math.Math.service, {
+  server.addService(grpcMath.MathService, {
     div: mathDiv,
     fib: mathFib,
     sum: mathSum,
diff --git a/src/node/test/math/node_modules/grpc.js b/src/node/test/math/node_modules/grpc.js
new file mode 100644
index 0000000..17c8fd9
--- /dev/null
+++ b/src/node/test/math/node_modules/grpc.js
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* This exists solely to allow the generated code to import the grpc module
+ * without using a relative path */
+
+module.exports = require('../../..');
diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js
index 3d44610..34c16e0 100644
--- a/src/node/test/math_client_test.js
+++ b/src/node/test/math_client_test.js
@@ -36,7 +36,8 @@
 var assert = require('assert');
 
 var grpc = require('..');
-var math = grpc.load(__dirname + '/../../proto/math/math.proto').math;
+var math = require('./math/math_pb');
+var MathClient = require('./math/math_grpc_pb').MathClient;
 
 /**
  * Client to use to make requests to a running server.
@@ -55,35 +56,41 @@
     var port_num = server.bind('0.0.0.0:0',
                                grpc.ServerCredentials.createInsecure());
     server.start();
-    math_client = new math.Math('localhost:' + port_num,
-                                grpc.credentials.createInsecure());
+    math_client = new MathClient('localhost:' + port_num,
+                                 grpc.credentials.createInsecure());
     done();
   });
   after(function() {
     server.forceShutdown();
   });
   it('should handle a single request', function(done) {
-    var arg = {dividend: 7, divisor: 4};
+    var arg = new math.DivArgs();
+    arg.setDividend(7);
+    arg.setDivisor(4);
     math_client.div(arg, function handleDivResult(err, value) {
       assert.ifError(err);
-      assert.equal(value.quotient, 1);
-      assert.equal(value.remainder, 3);
+      assert.equal(value.getQuotient(), 1);
+      assert.equal(value.getRemainder(), 3);
       done();
     });
   });
   it('should handle an error from a unary request', function(done) {
-    var arg = {dividend: 7, divisor: 0};
+    var arg = new math.DivArgs();
+    arg.setDividend(7);
+    arg.setDivisor(0);
     math_client.div(arg, function handleDivResult(err, value) {
       assert(err);
       done();
     });
   });
   it('should handle a server streaming request', function(done) {
-    var call = math_client.fib({limit: 7});
+    var arg = new math.FibArgs();
+    arg.setLimit(7);
+    var call = math_client.fib(arg);
     var expected_results = [1, 1, 2, 3, 5, 8, 13];
     var next_expected = 0;
     call.on('data', function checkResponse(value) {
-      assert.equal(value.num, expected_results[next_expected]);
+      assert.equal(value.getNum(), expected_results[next_expected]);
       next_expected += 1;
     });
     call.on('status', function checkStatus(status) {
@@ -94,10 +101,12 @@
   it('should handle a client streaming request', function(done) {
     var call = math_client.sum(function handleSumResult(err, value) {
       assert.ifError(err);
-      assert.equal(value.num, 21);
+      assert.equal(value.getNum(), 21);
     });
     for (var i = 0; i < 7; i++) {
-      call.write({'num': i});
+      var arg = new math.Num();
+      arg.setNum(i);
+      call.write(arg);
     }
     call.end();
     call.on('status', function checkStatus(status) {
@@ -107,8 +116,8 @@
   });
   it('should handle a bidirectional streaming request', function(done) {
     function checkResponse(index, value) {
-      assert.equal(value.quotient, index);
-      assert.equal(value.remainder, 1);
+      assert.equal(value.getQuotient(), index);
+      assert.equal(value.getRemainder(), 1);
     }
     var call = math_client.divMany();
     var response_index = 0;
@@ -117,7 +126,10 @@
       response_index += 1;
     });
     for (var i = 0; i < 7; i++) {
-      call.write({dividend: 2 * i + 1, divisor: 2});
+      var arg = new math.DivArgs();
+      arg.setDividend(2 * i + 1);
+      arg.setDivisor(2);
+      call.write(arg);
     }
     call.end();
     call.on('status', function checkStatus(status) {
@@ -131,7 +143,10 @@
       assert.fail(value, undefined, 'Unexpected data response on failing call',
                   '!=');
     });
-    call.write({dividend: 7, divisor: 0});
+    var arg = new math.DivArgs();
+    arg.setDividend(7);
+    arg.setDivisor(0);
+    call.write(arg);
     call.end();
     call.on('error', function checkStatus(status) {
       done();
diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js
index 71a9647..ed311c8 100644
--- a/src/node/test/server_test.js
+++ b/src/node/test/server_test.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 8a232d6..b96e8e4 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -404,18 +404,18 @@
     server.forceShutdown();
   });
   it('with unary call', function(done) {
-    var call = client.unary({}, function(err, data) {
+    var call = client.unary({}, metadata, function(err, data) {
       assert.ifError(err);
-    }, metadata);
+    });
     call.on('metadata', function(metadata) {
       assert.deepEqual(metadata.get('key'), ['value']);
       done();
     });
   });
   it('with client stream call', function(done) {
-    var call = client.clientStream(function(err, data) {
+    var call = client.clientStream(metadata, function(err, data) {
       assert.ifError(err);
-    }, metadata);
+    });
     call.on('metadata', function(metadata) {
       assert.deepEqual(metadata.get('key'), ['value']);
       done();
@@ -441,8 +441,8 @@
   });
   it('shows the correct user-agent string', function(done) {
     var version = require('../../../package.json').version;
-    var call = client.unary({}, function(err, data) { assert.ifError(err); },
-                            metadata);
+    var call = client.unary({}, metadata,
+                            function(err, data) { assert.ifError(err); });
     call.on('metadata', function(metadata) {
       assert(_.startsWith(metadata.get('user-agent')[0],
                           'grpc-node/' + version));
@@ -452,8 +452,8 @@
   it('properly handles duplicate values', function(done) {
     var dup_metadata = metadata.clone();
     dup_metadata.add('key', 'value2');
-    var call = client.unary({}, function(err, data) {assert.ifError(err); },
-                            dup_metadata);
+    var call = client.unary({}, dup_metadata,
+                            function(err, data) {assert.ifError(err); });
     call.on('metadata', function(resp_metadata) {
       // Two arrays are equal iff their symmetric difference is empty
       assert.deepEqual(_.xor(dup_metadata.get('key'), resp_metadata.get('key')),
@@ -709,14 +709,14 @@
     it('should respond correctly to a unary call', function(done) {
       misbehavingClient.unary(badArg, function(err, data) {
         assert(err);
-        assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
+        assert.strictEqual(err.code, grpc.status.INTERNAL);
         done();
       });
     });
     it('should respond correctly to a client stream', function(done) {
       var call = misbehavingClient.clientStream(function(err, data) {
         assert(err);
-        assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
+        assert.strictEqual(err.code, grpc.status.INTERNAL);
         done();
       });
       call.write(badArg);
@@ -729,7 +729,7 @@
         assert.fail(data, null, 'Unexpected data', '===');
       });
       call.on('error', function(err) {
-        assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
+        assert.strictEqual(err.code, grpc.status.INTERNAL);
         done();
       });
     });
@@ -739,7 +739,7 @@
         assert.fail(data, null, 'Unexpected data', '===');
       });
       call.on('error', function(err) {
-        assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
+        assert.strictEqual(err.code, grpc.status.INTERNAL);
         done();
       });
       call.write(badArg);
@@ -954,7 +954,7 @@
       done = multiDone(done, 2);
       var call;
       proxy_impl.unary = function(parent, callback) {
-        client.unary(parent.request, function(err, value) {
+        client.unary(parent.request, {parent: parent}, function(err, value) {
           try {
             assert(err);
             assert.strictEqual(err.code, grpc.status.CANCELLED);
@@ -962,7 +962,7 @@
             callback(err, value);
             done();
           }
-        }, null, {parent: parent});
+        });
         call.cancel();
       };
       proxy.addProtoService(test_service, proxy_impl);
@@ -976,7 +976,7 @@
       done = multiDone(done, 2);
       var call;
       proxy_impl.clientStream = function(parent, callback) {
-        client.clientStream(function(err, value) {
+        client.clientStream({parent: parent}, function(err, value) {
           try {
             assert(err);
             assert.strictEqual(err.code, grpc.status.CANCELLED);
@@ -984,7 +984,7 @@
             callback(err, value);
             done();
           }
-        }, null, {parent: parent});
+        });
         call.cancel();
       };
       proxy.addProtoService(test_service, proxy_impl);
@@ -998,8 +998,7 @@
       done = multiDone(done, 2);
       var call;
       proxy_impl.serverStream = function(parent) {
-        var child = client.serverStream(parent.request, null,
-                                        {parent: parent});
+        var child = client.serverStream(parent.request, {parent: parent});
         child.on('data', function() {});
         child.on('error', function(err) {
           assert(err);
@@ -1023,7 +1022,7 @@
       done = multiDone(done, 2);
       var call;
       proxy_impl.bidiStream = function(parent) {
-        var child = client.bidiStream(null, {parent: parent});
+        var child = client.bidiStream({parent: parent});
         child.on('data', function() {});
         child.on('error', function(err) {
           assert(err);
@@ -1051,7 +1050,8 @@
     it('With a client stream call', function(done) {
       done = multiDone(done, 2);
       proxy_impl.clientStream = function(parent, callback) {
-        client.clientStream(function(err, value) {
+        var options = {parent: parent, propagate_flags: deadline_flags};
+        client.clientStream(options, function(err, value) {
           try {
             assert(err);
             assert(err.code === grpc.status.DEADLINE_EXCEEDED ||
@@ -1060,7 +1060,7 @@
             callback(err, value);
             done();
           }
-        }, null, {parent: parent, propagate_flags: deadline_flags});
+        });
       };
       proxy.addProtoService(test_service, proxy_impl);
       var proxy_port = proxy.bind('localhost:0', server_insecure_creds);
@@ -1069,15 +1069,15 @@
                                     grpc.credentials.createInsecure());
       var deadline = new Date();
       deadline.setSeconds(deadline.getSeconds() + 1);
-      proxy_client.clientStream(function(err, value) {
+      proxy_client.clientStream({deadline: deadline}, function(err, value) {
         done();
-      }, null, {deadline: deadline});
+      });
     });
     it('With a bidi stream call', function(done) {
       done = multiDone(done, 2);
       proxy_impl.bidiStream = function(parent) {
         var child = client.bidiStream(
-            null, {parent: parent, propagate_flags: deadline_flags});
+            {parent: parent, propagate_flags: deadline_flags});
         child.on('data', function() {});
         child.on('error', function(err) {
           assert(err);
@@ -1093,7 +1093,7 @@
                                     grpc.credentials.createInsecure());
       var deadline = new Date();
       deadline.setSeconds(deadline.getSeconds() + 1);
-      var call = proxy_client.bidiStream(null, {deadline: deadline});
+      var call = proxy_client.bidiStream({deadline: deadline});
       call.on('data', function() {});
       call.on('error', function(err) {
         done();
diff --git a/src/node/test/test_messages.proto b/src/node/test/test_messages.proto
index 9b8cb87..a1a6a32 100644
--- a/src/node/test/test_messages.proto
+++ b/src/node/test/test_messages.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/node/test/test_service.proto b/src/node/test/test_service.proto
index 0ac2ae7..c86ce51 100644
--- a/src/node/test/test_service.proto
+++ b/src/node/test/test_service.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/node/tools/bin/protoc.js b/src/node/tools/bin/protoc.js
new file mode 100755
index 0000000..0c6d7ce
--- /dev/null
+++ b/src/node/tools/bin/protoc.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+/*
+ *
+ * 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 is required because package.json cannot reference a file that
+ * is not distributed with the package, and we use node-pre-gyp to distribute
+ * the protoc binary
+ */
+
+'use strict';
+
+var path = require('path');
+var execFile = require('child_process').execFile;
+
+var protoc = path.resolve(__dirname, 'protoc');
+
+execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
+  if (error) {
+    throw error;
+  }
+  console.log(stdout);
+  console.log(stderr);
+});
diff --git a/src/node/tools/index.js b/src/node/tools/index.js
new file mode 100644
index 0000000..2de3918
--- /dev/null
+++ b/src/node/tools/index.js
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+
+/**
+ * package.json requires this file to be present. In the future, this can
+ * export useful information about the included tools.
+ */
+
+module.exports = {};
diff --git a/src/node/tools/package.json b/src/node/tools/package.json
new file mode 100644
index 0000000..4b3499f
--- /dev/null
+++ b/src/node/tools/package.json
@@ -0,0 +1,38 @@
+{
+  "name": "grpc-tools",
+  "version": "0.14.0-dev",
+  "author": "Google Inc.",
+  "description": "Tools for developing with gRPC on Node.js",
+  "homepage": "http://www.grpc.io/",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/grpc/grpc.git"
+  },
+  "bugs": "https://github.com/grpc/grpc/issues",
+  "contributors": [
+    {
+      "name": "Michael Lumish",
+      "email": "mlumish@google.com"
+    }
+  ],
+  "bin": {
+    "grpc-tools-protoc": "./bin/protoc.js"
+  },
+  "scripts": {
+    "install": "./node_modules/.bin/node-pre-gyp install"
+  },
+  "bundledDependencies": ["node-pre-gyp"],
+  "binary": {
+    "module_name": "grpc_tools",
+    "host": "https://storage.googleapis.com/",
+    "remote_path": "grpc-precompiled-binaries/node/{name}/v{version}",
+    "package_name": "{platform}-{arch}.tar.gz",
+    "module_path": "bin"
+  },
+  "files": [
+    "index.js",
+    "bin/protoc.js",
+    "LICENSE"
+  ],
+  "main": "index.js"
+}
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index 2d45818..1847d60 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -308,37 +308,30 @@
 }
 
 - (void)invokeCall {
-  __weak GRPCCall *weakSelf = self;
   [self invokeCallWithHeadersHandler:^(NSDictionary *headers) {
     // Response headers received.
-    GRPCCall *strongSelf = weakSelf;
-    if (strongSelf) {
-      strongSelf.responseHeaders = headers;
-      [strongSelf startNextRead];
-    }
+    self.responseHeaders = headers;
+    [self startNextRead];
   } completionHandler:^(NSError *error, NSDictionary *trailers) {
-    GRPCCall *strongSelf = weakSelf;
-    if (strongSelf) {
-      strongSelf.responseTrailers = trailers;
+    self.responseTrailers = trailers;
 
-      if (error) {
-        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
-        if (error.userInfo) {
-          [userInfo addEntriesFromDictionary:error.userInfo];
-        }
-        userInfo[kGRPCTrailersKey] = strongSelf.responseTrailers;
-        // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be
-        // called before this one, so an error might end up with trailers but no headers. We
-        // shouldn't call finishWithError until ater both blocks are called. It is also when this is
-        // done that we can provide a merged view of response headers and trailers in a thread-safe
-        // way.
-        if (strongSelf.responseHeaders) {
-          userInfo[kGRPCHeadersKey] = strongSelf.responseHeaders;
-        }
-        error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
+    if (error) {
+      NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+      if (error.userInfo) {
+        [userInfo addEntriesFromDictionary:error.userInfo];
       }
-      [strongSelf finishWithError:error];
+      userInfo[kGRPCTrailersKey] = self.responseTrailers;
+      // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be
+      // called before this one, so an error might end up with trailers but no headers. We
+      // shouldn't call finishWithError until ater both blocks are called. It is also when this is
+      // done that we can provide a merged view of response headers and trailers in a thread-safe
+      // way.
+      if (self.responseHeaders) {
+        userInfo[kGRPCHeadersKey] = self.responseHeaders;
+      }
+      error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
     }
+    [self finishWithError:error];
   }];
   // Now that the RPC has been initiated, request writes can start.
   @synchronized(_requestWriter) {
@@ -377,7 +370,6 @@
       [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
                                                       code:GRPCErrorCodeUnavailable
                                                   userInfo:@{NSLocalizedDescriptionKey: @"Connectivity lost."}]];
-      [[GRPCHost hostWithAddress:strongSelf->_host] disconnect];
     }
   }];
 }
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h
index e49a6ac..73bf8d9 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.h
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
index d7de025..926f550 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
index a52095d..fe3b8f3 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,8 +36,6 @@
 
 typedef void(^GRPCQueueCompletionHandler)(bool success);
 
-extern const int64_t kGRPCCompletionQueueDefaultTimeoutSecs;
-
 /**
  * This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the
  * |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for
@@ -51,11 +49,6 @@
  */
 @interface GRPCCompletionQueue : NSObject
 @property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue;
-@property(nonatomic, readonly) int64_t timeoutSecs;
 
 + (instancetype)completionQueue;
-
-- (instancetype)init;
-- (instancetype)initWithTimeout:(int64_t)timeoutSecs NS_DESIGNATED_INITIALIZER;
-
 @end
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
index be214d4..539b5ab 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,6 @@
 
 #import <grpc/grpc.h>
 
-
-const int64_t kGRPCCompletionQueueDefaultTimeoutSecs = 60;
-
 @implementation GRPCCompletionQueue
 
 + (instancetype)completionQueue {
@@ -50,13 +47,8 @@
 }
 
 - (instancetype)init {
-  return [self initWithTimeout:kGRPCCompletionQueueDefaultTimeoutSecs];
-}
-
-- (instancetype)initWithTimeout:(int64_t)timeoutSecs {
   if ((self = [super init])) {
     _unmanagedQueue = grpc_completion_queue_create(NULL);
-    _timeoutSecs = timeoutSecs;
 
     // This is for the following block to capture the pointer by value (instead
     // of retaining self and doing self->_unmanagedQueue). This is essential
@@ -74,28 +66,22 @@
       gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     });
     dispatch_async(gDefaultConcurrentQueue, ^{
-      // Using a non-infinite deadline to re-enter grpc_completion_queue_next()
-      // alleviates https://github.com/grpc/grpc/issues/5593
-      gpr_timespec deadline = (timeoutSecs < 0)
-          ? gpr_inf_future(GPR_CLOCK_REALTIME)
-          : gpr_time_from_seconds(timeoutSecs, GPR_CLOCK_REALTIME);
       while (YES) {
-        // The following call blocks until an event is available or the deadline elapses.
-        grpc_event event = grpc_completion_queue_next(unmanagedQueue, deadline, NULL);
+        // The following call blocks until an event is available.
+        grpc_event event = grpc_completion_queue_next(unmanagedQueue,
+                                                      gpr_inf_future(GPR_CLOCK_REALTIME),
+                                                      NULL);
         GRPCQueueCompletionHandler handler;
         switch (event.type) {
           case GRPC_OP_COMPLETE:
             handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag;
             handler(event.success);
             break;
-          case GRPC_QUEUE_TIMEOUT:
-            // Nothing to do here
-            break;
           case GRPC_QUEUE_SHUTDOWN:
             grpc_completion_queue_destroy(unmanagedQueue);
             return;
           default:
-            [NSException raise:@"Unrecognized completion type" format:@"type=%d", event.type];
+            [NSException raise:@"Unrecognized completion type" format:@""];
         }
       };
     });
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h
index 987d3e9..e58bb7a 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.h
+++ b/src/objective-c/GRPCClient/private/GRPCHost.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index 508cb20..739d808 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h b/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
index 02871d5..4b92504 100644
--- a/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
+++ b/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
@@ -54,7 +54,9 @@
        GRPC_XMACRO_ITEM.
 #endif
 
+#if TARGET_OS_IPHONE
 GRPC_XMACRO_ITEM(isCell, IsWWAN)
+#endif
 GRPC_XMACRO_ITEM(reachable, Reachable)
 GRPC_XMACRO_ITEM(transientConnection, TransientConnection)
 GRPC_XMACRO_ITEM(connectionRequired, ConnectionRequired)
diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
index fe3d51d..16e5bff 100644
--- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
+++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
@@ -54,7 +54,9 @@
 
 - (void)finish {
   if (_handler) {
-    _handler();
+    void(^handler)() = _handler;
+    _handler = nil;
+    handler();
   }
 }
 @end
diff --git a/src/objective-c/ProtoRPC/ProtoMethod.m b/src/objective-c/ProtoRPC/ProtoMethod.m
index 75e5efc..4b7ed63 100644
--- a/src/objective-c/ProtoRPC/ProtoMethod.m
+++ b/src/objective-c/ProtoRPC/ProtoMethod.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/RxLibrary/GRXWriteable.m b/src/objective-c/RxLibrary/GRXWriteable.m
index 028ba9b..c15ccb1 100644
--- a/src/objective-c/RxLibrary/GRXWriteable.m
+++ b/src/objective-c/RxLibrary/GRXWriteable.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m
index a2bb3ee..433a8a2 100644
--- a/src/objective-c/examples/Sample/Sample/ViewController.m
+++ b/src/objective-c/examples/Sample/Sample/ViewController.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index 7dd6873..9a8d425 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m
index 155e334..f0f4b1d 100644
--- a/src/objective-c/tests/InteropTestsLocalSSL.m
+++ b/src/objective-c/tests/InteropTestsLocalSSL.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m
index 00eadc2..758cc93 100644
--- a/src/objective-c/tests/InteropTestsRemote.m
+++ b/src/objective-c/tests/InteropTestsRemote.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/tests/RxLibraryUnitTests.m b/src/objective-c/tests/RxLibraryUnitTests.m
index ae9465f..62fbdfc 100644
--- a/src/objective-c/tests/RxLibraryUnitTests.m
+++ b/src/objective-c/tests/RxLibraryUnitTests.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/php/ext/grpc/LICENSE b/src/php/ext/grpc/LICENSE
index a8c47a2..0c651a0 100644
--- a/src/php/ext/grpc/LICENSE
+++ b/src/php/ext/grpc/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2015-2016, Google Inc.
+Copyright 2015, Google Inc.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/src/php/ext/grpc/byte_buffer.c b/src/php/ext/grpc/byte_buffer.c
index 8be0a20..7a726de 100644
--- a/src/php/ext/grpc/byte_buffer.c
+++ b/src/php/ext/grpc/byte_buffer.c
@@ -72,6 +72,7 @@
   while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
     memcpy(string + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
     offset += GPR_SLICE_LENGTH(next);
+    gpr_slice_unref(next);
   }
   *out_string = string;
   *out_length = length;
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 4f48d6f..a0f3d16 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -492,6 +492,14 @@
   if (status_details != NULL) {
     gpr_free(status_details);
   }
+  for (int i = 0; i < op_num; i++) {
+    if (ops[i].op == GRPC_OP_SEND_MESSAGE) {
+      grpc_byte_buffer_destroy(ops[i].data.send_message);
+    }
+    if (ops[i].op == GRPC_OP_RECV_MESSAGE) {
+      grpc_byte_buffer_destroy(message);
+    }
+  }
   RETURN_DESTROY_ZVAL(result);
 }
 
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index b7e7c26..eba2c81 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 7918824..f3951b3 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -115,10 +115,11 @@
                          "createSsl expects 3 strings", 1 TSRMLS_CC);
     return;
   }
-  /* TODO: add a force_client_auth field in ServerCredentials and pass it as
-   * the last parameter. */
-  grpc_server_credentials *creds = grpc_ssl_server_credentials_create(
-      pem_root_certs, &pem_key_cert_pair, 1, 0, NULL);
+  /* TODO: add a client_certificate_request field in ServerCredentials and pass
+   * it as the last parameter. */
+  grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex(
+      pem_root_certs, &pem_key_cert_pair, 1,
+      GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL);
   zval *creds_object = grpc_php_wrap_server_credentials(creds);
   RETURN_DESTROY_ZVAL(creds_object);
 }
diff --git a/src/php/tests/bootstrap.php b/src/php/tests/bootstrap.php
index b61f2c4..8b3d434 100644
--- a/src/php/tests/bootstrap.php
+++ b/src/php/tests/bootstrap.php
@@ -17,5 +17,5 @@
  */
 
 error_reporting(E_ALL | E_STRICT);
-require dirname(__DIR__) . '/vendor/autoload.php';
+require dirname(__DIR__).'/vendor/autoload.php';
 date_default_timezone_set('UTC');
diff --git a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
index f70525e..75922d4 100644
--- a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
+++ b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php b/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
index 6bb1955..6b70b8a 100644
--- a/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
+++ b/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
@@ -46,7 +46,8 @@
                                 $a_copy['foo'] = ['bar'];
 
                                 return $a_copy;
-                              }]);
+                              },
+         ]);
     }
 
     public function tearDown()
diff --git a/src/php/tests/generated_code/math_client.php b/src/php/tests/generated_code/math_client.php
index 2085560..6ee92bc 100644
--- a/src/php/tests/generated_code/math_client.php
+++ b/src/php/tests/generated_code/math_client.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,13 +38,13 @@
 
 function p($line)
 {
-    print("$line<br/>\n");
+    echo "$line<br/>\n";
 }
 
 $host = 'localhost:50051';
 p("Connecting to host: $host");
 $client = new math\MathClient($host, [
-    'credentials' => Grpc\ChannelCredentials::createInsecure()
+    'credentials' => Grpc\ChannelCredentials::createInsecure(),
 ]);
 p('Client class: '.get_class($client));
 p('');
diff --git a/src/php/tests/unit_tests/CallCredentials2Test.php b/src/php/tests/unit_tests/CallCredentials2Test.php
index 1282db6..a57e2b9 100644
--- a/src/php/tests/unit_tests/CallCredentials2Test.php
+++ b/src/php/tests/unit_tests/CallCredentials2Test.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/php/tests/unit_tests/CallCredentials3Test.php b/src/php/tests/unit_tests/CallCredentials3Test.php
index a458f1d..8f5e109 100644
--- a/src/php/tests/unit_tests/CallCredentials3Test.php
+++ b/src/php/tests/unit_tests/CallCredentials3Test.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -132,5 +132,4 @@
         unset($call);
         unset($server_call);
     }
-
 }
diff --git a/src/php/tests/unit_tests/CallCredentialsTest.php b/src/php/tests/unit_tests/CallCredentialsTest.php
index 2870248..5fec06c 100644
--- a/src/php/tests/unit_tests/CallCredentialsTest.php
+++ b/src/php/tests/unit_tests/CallCredentialsTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php
index a2522fb..fa026f0 100755
--- a/src/php/tests/unit_tests/CallTest.php
+++ b/src/php/tests/unit_tests/CallTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -94,7 +94,7 @@
 
     public function testCancel()
     {
-      $this->assertNull($this->call->cancel());
+        $this->assertNull($this->call->cancel());
     }
 
     /**
@@ -118,5 +118,4 @@
         ];
         $result = $this->call->startBatch($batch);
     }
-
 }
diff --git a/src/php/tests/unit_tests/ChannelCredentialsTest.php b/src/php/tests/unit_tests/ChannelCredentialsTest.php
index 6d472dc..56c1d8f 100644
--- a/src/php/tests/unit_tests/ChannelCredentialsTest.php
+++ b/src/php/tests/unit_tests/ChannelCredentialsTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -70,4 +70,4 @@
         $channel_credentials = Grpc\ChannelCredentials::createInsecure();
         $this->assertNull($channel_credentials);
     }
-}
\ No newline at end of file
+}
diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php
index acb8a0a..a1f9053 100644
--- a/src/php/tests/unit_tests/ChannelTest.php
+++ b/src/php/tests/unit_tests/ChannelTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -78,5 +78,4 @@
             ]
         );
     }
-
-}
\ No newline at end of file
+}
diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php
index 45f6708..2b09f9d 100755
--- a/src/php/tests/unit_tests/EndToEndTest.php
+++ b/src/php/tests/unit_tests/EndToEndTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -261,7 +261,8 @@
             Grpc\OP_SEND_INITIAL_METADATA => [],
             Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
             Grpc\OP_SEND_MESSAGE => ['message' => 'abc',
-                                     'flags' => 'invalid'],
+                                     'flags' => 'invalid',
+                                     ],
         ]);
     }
 
@@ -574,7 +575,7 @@
     public function testGetConnectivityStateInvalidParam()
     {
         $this->assertTrue($this->channel->getConnectivityState(
-            new Grpc\Timeval));
+            new Grpc\Timeval()));
     }
 
     /**
@@ -591,12 +592,11 @@
      */
     public function testChannelConstructorInvalidParam()
     {
-        $this->channel = new Grpc\Channel('localhost:'.$this->port, NULL);
+        $this->channel = new Grpc\Channel('localhost:'.$this->port, null);
     }
 
     public function testClose()
     {
         $this->assertNull($this->channel->close());
     }
-
 }
diff --git a/src/php/tests/unit_tests/ServerTest.php b/src/php/tests/unit_tests/ServerTest.php
index cde6a9a..76aaa06 100644
--- a/src/php/tests/unit_tests/ServerTest.php
+++ b/src/php/tests/unit_tests/ServerTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -67,5 +67,4 @@
         $this->server = new Grpc\Server([]);
         $this->port = $this->server->addSecureHttp2Port(['0.0.0.0:0']);
     }
-
-}
\ No newline at end of file
+}
diff --git a/src/php/tests/unit_tests/TimevalTest.php b/src/php/tests/unit_tests/TimevalTest.php
index 9e4bc29..a3dbce0 100755
--- a/src/php/tests/unit_tests/TimevalTest.php
+++ b/src/php/tests/unit_tests/TimevalTest.php
@@ -1,7 +1,7 @@
 <?php
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -94,13 +94,13 @@
 
     public function testSimilar()
     {
-      $a = Grpc\Timeval::now();
-      $delta = new Grpc\Timeval(1000);
-      $b = $a->add($delta);
-      $thresh = new Grpc\Timeval(1100);
-      $this->assertTrue(Grpc\Timeval::similar($a, $b, $thresh));
-      $thresh = new Grpc\Timeval(900);
-      $this->assertFalse(Grpc\Timeval::similar($a, $b, $thresh));
+        $a = Grpc\Timeval::now();
+        $delta = new Grpc\Timeval(1000);
+        $b = $a->add($delta);
+        $thresh = new Grpc\Timeval(1100);
+        $this->assertTrue(Grpc\Timeval::similar($a, $b, $thresh));
+        $thresh = new Grpc\Timeval(900);
+        $this->assertFalse(Grpc\Timeval::similar($a, $b, $thresh));
     }
 
     public function testSleepUntil()
@@ -155,5 +155,4 @@
     {
         $a = Grpc\Timeval::similar(1000, 1100, 1200);
     }
-
 }
diff --git a/src/proto/gen_build_yaml.py b/src/proto/gen_build_yaml.py
index e243d0d..2a8d9fa 100755
--- a/src/proto/gen_build_yaml.py
+++ b/src/proto/gen_build_yaml.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@
 import re
 import sys
 
-def update_deps(key, proto_filename, deps, is_trans, visited):
+def update_deps(key, proto_filename, deps, deps_external, is_trans, visited):
   if not proto_filename in visited:
     visited.append(proto_filename)
     with open(proto_filename) as inp:
@@ -44,10 +44,17 @@
         imp = re.search(r'import "([^"]*)"', line)
         if not imp: continue
         imp_proto = imp.group(1)
+        # This indicates an external dependency, which we should handle
+        # differently and not traverse recursively
+        if imp_proto.startswith('google/'):
+          if key not in deps_external:
+            deps_external[key] = []
+          deps_external[key].append(imp_proto[:-6])
+          continue
         if key not in deps: deps[key] = []
         deps[key].append(imp_proto[:-6])
         if is_trans:
-          update_deps(key, imp_proto, deps, is_trans, visited)
+          update_deps(key, imp_proto, deps, deps_external, is_trans, visited)
 
 def main():
   proto_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
@@ -55,17 +62,23 @@
 
   deps = {}
   deps_trans = {}
+  deps_external = {}
+  deps_external_trans = {}
   for root, dirs, files in os.walk('src/proto'):
     for f in files:
       if f[-6:] != '.proto': continue
       look_at = os.path.join(root, f)
       deps_for = look_at[:-6]
-      update_deps(deps_for, look_at, deps, False, [])      # First level deps
-      update_deps(deps_for, look_at, deps_trans, True, []) # Transitive deps
+      # First level deps
+      update_deps(deps_for, look_at, deps, deps_external, False, [])
+      # Transitive deps
+      update_deps(deps_for, look_at, deps_trans, deps_external_trans, True, [])
 
   json = {
     'proto_deps': deps,
-    'proto_transitive_deps': deps_trans
+    'proto_transitive_deps': deps_trans,
+    'proto_external_deps': deps_external,
+    'proto_transitive_external_deps': deps_external_trans
   }
 
   print yaml.dump(json)
diff --git a/src/proto/grpc/binary_log/v1alpha/log.proto b/src/proto/grpc/binary_log/v1alpha/log.proto
new file mode 100644
index 0000000..83166cd
--- /dev/null
+++ b/src/proto/grpc/binary_log/v1alpha/log.proto
@@ -0,0 +1,108 @@
+// 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.
+
+syntax = "proto3";
+
+import "google/protobuf/timestamp.proto"
+
+package grpc.binary_log.v1alpha;
+
+enum Direction {
+  SERVER_SEND;
+  SERVER_RECV;
+  CLIENT_SEND;
+  CLIENT_RECV;
+}
+
+message KeyValuePair {
+  string key;
+  string value;
+}
+
+// Any sort of metadata that may be sent in either direction during a call
+message Metadata {
+  // Cryptographically unique identifier, generated on the client and sent
+  // to the server.
+  uint64 rpc_id = 1;
+  // Timestamp of logging the metadata
+  google.protobuf.Timestamp timestamp = 2;
+  Direction direction = 3;
+  // The actual metadata that is being sent
+  repeated KeyValuePair metadata = 4;
+
+  // Initial metadata sent by the client to initiate a request
+  message ClientInitialMetadata {
+    // The full method name that is being called
+    string method_name = 1;
+    // The call's deadline
+    google.protobuf.Timestamp deadline = 2;
+    // The address of the connected peer
+    string peer = 3;
+  }
+
+  // Arbitrary key/value pairs specified by the user that are not sent over
+  // the network but are nonetheless useful to log
+  message UserData {
+  }
+
+  // Initial metadata response sent by the server after accepting the request
+  message ServerInitialMetadata {
+  }
+
+  // Status sent by the server when closing the call on the server side
+  message ServerStatus {
+    // The status code
+    uint32 code = 1;
+    // The status details
+    string details = 2;
+  }
+
+  oneof kind {
+    ClientInitialMetadata client_initial_metadata = 5;
+    UserData user_data = 6;
+    ServerInitialMetadata server_initial_metadata = 7;
+    ServerStatus server_status = 8;
+  }
+}
+
+// A message that is sent during a call
+message Message {
+  // Cryptographically unique identifier, generated on the client and sent
+  // to the server.
+  uint64 rpc_id = 1;
+  // The sequence number of the message. Messages sent by the client and by the
+  // server should have independently incrementing sequence numbers.
+  uint32 sequence_number = 2;
+  Direction direction = 3;
+  // The length of the complete message.
+  uint32 length = 4;
+  // The contents of the message. May be a prefix instead of the complete
+  // message.
+  bytes data = 5;
+}
diff --git a/src/proto/grpc/health/v1/health.proto b/src/proto/grpc/health/v1/health.proto
index 6e27606..4ab30a0 100644
--- a/src/proto/grpc/health/v1/health.proto
+++ b/src/proto/grpc/health/v1/health.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto
index cc365ca..20496a8 100644
--- a/src/proto/grpc/testing/control.proto
+++ b/src/proto/grpc/testing/control.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -35,14 +35,18 @@
 package grpc.testing;
 
 enum ClientType {
+  // Many languages support a basic distinction between using
+  // sync or async client, and this allows the specification
   SYNC_CLIENT = 0;
   ASYNC_CLIENT = 1;
+  OTHER_CLIENT = 2; // used for some language-specific variants
 }
 
 enum ServerType {
   SYNC_SERVER = 0;
   ASYNC_SERVER = 1;
   ASYNC_GENERIC_SERVER = 2;
+  OTHER_SERVER = 3; // used for some language-specific variants
 }
 
 enum RpcType {
@@ -57,18 +61,6 @@
   double offered_load = 1;
 }
 
-message UniformParams {
-  double interarrival_lo = 1;
-  double interarrival_hi = 2;
-}
-
-message DeterministicParams { double offered_load = 1; }
-
-message ParetoParams {
-  double interarrival_base = 1;
-  double alpha = 2;
-}
-
 // Once an RPC finishes, immediately start a new one.
 // No configuration parameters needed.
 message ClosedLoopParams {}
@@ -77,9 +69,6 @@
   oneof load {
     ClosedLoopParams closed_loop = 1;
     PoissonParams poisson = 2;
-    UniformParams uniform = 3;
-    DeterministicParams determ = 4;
-    ParetoParams pareto = 5;
   };
 }
 
@@ -111,6 +100,9 @@
   // Specify the cores we should run the client on, if desired
   repeated int32 core_list = 13;
   int32 core_limit = 14;
+
+  // If we use an OTHER_CLIENT client_type, this string gives more detail
+  string other_client_api = 15;
 }
 
 message ClientStatus { ClientStats stats = 1; }
@@ -142,6 +134,9 @@
 
   // Specify the cores we should run the server on, if desired
   repeated int32 core_list = 10;
+
+  // If we use an OTHER_SERVER client_type, this string gives more detail
+  string other_server_api = 11;
 }
 
 message ServerArgs {
@@ -169,3 +164,69 @@
 
 message Void {
 }
+
+// A single performance scenario: input to qps_json_driver
+message Scenario {
+  // Human readable name for this scenario
+  string name = 1;
+  // Client configuration
+  ClientConfig client_config = 2;
+  // Number of clients to start for the test
+  int32 num_clients = 3;
+  // Server configuration
+  ServerConfig server_config = 4;
+  // Number of servers to start for the test
+  int32 num_servers = 5;
+  // Warmup period, in seconds
+  int32 warmup_seconds = 6;
+  // Benchmark time, in seconds
+  int32 benchmark_seconds = 7;
+  // Number of workers to spawn locally (usually zero)
+  int32 spawn_local_worker_count = 8;
+}
+
+// A set of scenarios to be run with qps_json_driver
+message Scenarios {
+  repeated Scenario scenarios = 1;
+}
+
+// Basic summary that can be computed from ClientStats and ServerStats
+// once the scenario has finished.
+message ScenarioResultSummary
+{
+  // Total number of operations per second over all clients.
+  double qps = 1;
+  // QPS per one server core.
+  double qps_per_server_core = 2;
+  // server load based on system_time (0.85 => 85%)
+  double server_system_time = 3;
+  // server load based on user_time (0.85 => 85%)
+  double server_user_time = 4;
+  // client load based on system_time (0.85 => 85%)
+  double client_system_time = 5;
+  // client load based on user_time (0.85 => 85%)
+  double client_user_time = 6;
+
+  // X% latency percentiles (in nanoseconds)
+  double latency_50 = 7;
+  double latency_90 = 8;
+  double latency_95 = 9;
+  double latency_99 = 10;
+  double latency_999 = 11;
+}
+
+// Results of a single benchmark scenario.
+message ScenarioResult {
+  // Inputs used to run the scenario.
+  Scenario scenario = 1;
+  // Histograms from all clients merged into one histogram.
+  HistogramData latencies = 2;
+  // Client stats for each client
+  repeated ClientStats client_stats = 3;
+  // Server stats for each server
+  repeated ServerStats server_stats = 4;
+  // Number of cores available to each server
+  repeated int32 server_cores = 5;
+  // An after-the-fact computed summary
+  ScenarioResultSummary summary = 6;
+}
diff --git a/src/proto/grpc/testing/duplicate/echo_duplicate.proto b/src/proto/grpc/testing/duplicate/echo_duplicate.proto
index 9d84de1..94130ea 100644
--- a/src/proto/grpc/testing/duplicate/echo_duplicate.proto
+++ b/src/proto/grpc/testing/duplicate/echo_duplicate.proto
@@ -1,5 +1,5 @@
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/proto/grpc/testing/echo.proto b/src/proto/grpc/testing/echo.proto
index 06c3baf..0eef53a 100644
--- a/src/proto/grpc/testing/echo.proto
+++ b/src/proto/grpc/testing/echo.proto
@@ -1,5 +1,5 @@
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/proto/grpc/testing/echo_messages.proto b/src/proto/grpc/testing/echo_messages.proto
index 5ce0a1f..1be1966 100644
--- a/src/proto/grpc/testing/echo_messages.proto
+++ b/src/proto/grpc/testing/echo_messages.proto
@@ -1,5 +1,5 @@
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/proto/grpc/testing/messages.proto b/src/proto/grpc/testing/messages.proto
index 193b6c4..a063b47 100644
--- a/src/proto/grpc/testing/messages.proto
+++ b/src/proto/grpc/testing/messages.proto
@@ -1,5 +1,5 @@
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -159,6 +159,12 @@
 }
 
 // For reconnect interop test only.
+// Client tells server what reconnection parameters it used.
+message ReconnectParams {
+  int32 max_reconnect_backoff_ms = 1;
+}
+
+// For reconnect interop test only.
 // Server tells client whether its reconnects are following the spec and the
 // reconnect backoffs it saw.
 message ReconnectInfo {
diff --git a/src/proto/grpc/testing/metrics.proto b/src/proto/grpc/testing/metrics.proto
index 4485d3a..1202b20 100644
--- a/src/proto/grpc/testing/metrics.proto
+++ b/src/proto/grpc/testing/metrics.proto
@@ -1,5 +1,4 @@
-
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -28,26 +27,38 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// An integration test service that covers all the method signature permutations
-// of unary/streaming requests/responses.
+// Contains the definitions for a metrics service and the type of metrics
+// exposed by the service.
+//
+// Currently, 'Gauge' (i.e a metric that represents the measured value of
+// something at an instant of time) is the only metric type supported by the
+// service.
 syntax = "proto3";
 
 package grpc.testing;
 
+// Reponse message containing the gauge name and value
 message GaugeResponse {
   string name = 1;
   oneof value {
     int64 long_value = 2;
-    double double_vale = 3;
+    double double_value = 3;
     string string_value = 4;
   }
 }
 
-message GaugeRequest { string name = 1; }
+// Request message containing the gauge name
+message GaugeRequest {
+  string name = 1;
+}
 
 message EmptyMessage {}
 
 service MetricsService {
+  // Returns the values of all the gauges that are currently being maintained by
+  // the service
   rpc GetAllGauges(EmptyMessage) returns (stream GaugeResponse);
+
+  // Returns the value of one gauge
   rpc GetGauge(GaugeRequest) returns (GaugeResponse);
 }
diff --git a/src/proto/grpc/testing/services.proto b/src/proto/grpc/testing/services.proto
index a2c5fda..f71dae3 100644
--- a/src/proto/grpc/testing/services.proto
+++ b/src/proto/grpc/testing/services.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/proto/grpc/testing/test.proto b/src/proto/grpc/testing/test.proto
index 9faba29..84369db 100644
--- a/src/proto/grpc/testing/test.proto
+++ b/src/proto/grpc/testing/test.proto
@@ -1,5 +1,5 @@
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,6 @@
 
 // A service used to control reconnect server.
 service ReconnectService {
-  rpc Start(grpc.testing.Empty) returns (grpc.testing.Empty);
+  rpc Start(grpc.testing.ReconnectParams) returns (grpc.testing.Empty);
   rpc Stop(grpc.testing.Empty) returns (grpc.testing.ReconnectInfo);
 }
diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py
index 1d43547..9e74570 100644
--- a/src/python/grpcio/commands.py
+++ b/src/python/grpcio/commands.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py
index 62fd52a..b13d8dd 100644
--- a/src/python/grpcio/grpc/_adapter/_low.py
+++ b/src/python/grpcio/grpc/_adapter/_low.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_adapter/_types.py b/src/python/grpcio/grpc/_adapter/_types.py
index f9e18f0..8ca7ff4 100644
--- a/src/python/grpcio/grpc/_adapter/_types.py
+++ b/src/python/grpcio/grpc/_adapter/_types.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
index d1b9c98..1bfe634 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index d612c90..c26bc08 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
index 305475c..a67c963 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index 09e47d4..cdae39d 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
index 1d7adca..94d13b5 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -302,6 +302,8 @@
         (<SslPemKeyCertPair>pem_key_cert_pairs[i]).c_pair)
   credentials.c_credentials = grpc_ssl_server_credentials_create(
       c_pem_root_certs, credentials.c_ssl_pem_key_cert_pairs,
-      credentials.c_ssl_pem_key_cert_pairs_count, force_client_auth, NULL)
+      credentials.c_ssl_pem_key_cert_pairs_count,
+      GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY if force_client_auth else GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
+      NULL)
   return credentials
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 61165cb..3d158a7 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -105,6 +105,13 @@
     GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY
     GRPC_SSL_ROOTS_OVERRIDE_FAILED
 
+  ctypedef enum grpc_ssl_client_certificate_request_type:
+    GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
+    GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
+    GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY
+    GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY
+    GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+
   struct grpc_byte_buffer_reader:
     # We don't care about the internals
     pass
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
index 851389a..c2202bd 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -254,7 +254,7 @@
     if self.c_byte_buffer != NULL:
       with nogil:
         grpc_byte_buffer_reader_init(&reader, self.c_byte_buffer)
-      result = b""
+      result = bytearray()
       with nogil:
         while grpc_byte_buffer_reader_next(&reader, &data_slice):
           data_slice_pointer = gpr_slice_start_ptr(data_slice)
@@ -263,7 +263,7 @@
             result += (<char *>data_slice_pointer)[:data_slice_length]
       with nogil:
         grpc_byte_buffer_reader_destroy(&reader)
-      return result
+      return bytes(result)
     else:
       return None
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi
index a344230..a35eb5e 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
index a098f11..8419a59 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pxd b/src/python/grpcio/grpc/_cython/cygrpc.pxd
index 61b0fa7..9779534 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pxd
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pxd
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index 8a0f171..8823ea5 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c
index 8bd6ae6..9ab0696 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/python/grpcio/grpc/_cython/imports.generated.c
@@ -152,6 +152,7 @@
 grpc_secure_channel_create_type grpc_secure_channel_create_import;
 grpc_server_credentials_release_type grpc_server_credentials_release_import;
 grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import;
+grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import;
 grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import;
 grpc_call_set_credentials_type grpc_call_set_credentials_import;
 grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import;
@@ -174,6 +175,8 @@
 grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import;
 gpr_log_type gpr_log_import;
 gpr_log_message_type gpr_log_message_import;
+gpr_set_log_verbosity_type gpr_set_log_verbosity_import;
+gpr_log_verbosity_init_type gpr_log_verbosity_init_import;
 gpr_set_log_function_type gpr_set_log_function_import;
 gpr_slice_ref_type gpr_slice_ref_import;
 gpr_slice_unref_type gpr_slice_unref_import;
@@ -418,6 +421,7 @@
   grpc_secure_channel_create_import = (grpc_secure_channel_create_type) GetProcAddress(library, "grpc_secure_channel_create");
   grpc_server_credentials_release_import = (grpc_server_credentials_release_type) GetProcAddress(library, "grpc_server_credentials_release");
   grpc_ssl_server_credentials_create_import = (grpc_ssl_server_credentials_create_type) GetProcAddress(library, "grpc_ssl_server_credentials_create");
+  grpc_ssl_server_credentials_create_ex_import = (grpc_ssl_server_credentials_create_ex_type) GetProcAddress(library, "grpc_ssl_server_credentials_create_ex");
   grpc_server_add_secure_http2_port_import = (grpc_server_add_secure_http2_port_type) GetProcAddress(library, "grpc_server_add_secure_http2_port");
   grpc_call_set_credentials_import = (grpc_call_set_credentials_type) GetProcAddress(library, "grpc_call_set_credentials");
   grpc_server_credentials_set_auth_metadata_processor_import = (grpc_server_credentials_set_auth_metadata_processor_type) GetProcAddress(library, "grpc_server_credentials_set_auth_metadata_processor");
@@ -440,6 +444,8 @@
   grpc_raw_byte_buffer_from_reader_import = (grpc_raw_byte_buffer_from_reader_type) GetProcAddress(library, "grpc_raw_byte_buffer_from_reader");
   gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log");
   gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message");
+  gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity");
+  gpr_log_verbosity_init_import = (gpr_log_verbosity_init_type) GetProcAddress(library, "gpr_log_verbosity_init");
   gpr_set_log_function_import = (gpr_set_log_function_type) GetProcAddress(library, "gpr_set_log_function");
   gpr_slice_ref_import = (gpr_slice_ref_type) GetProcAddress(library, "gpr_slice_ref");
   gpr_slice_unref_import = (gpr_slice_unref_type) GetProcAddress(library, "gpr_slice_unref");
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h
index 4d18369..e50051d 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/python/grpcio/grpc/_cython/imports.generated.h
@@ -283,7 +283,7 @@
 typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
 extern grpc_server_request_call_type grpc_server_request_call_import;
 #define grpc_server_request_call grpc_server_request_call_import
-typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host);
+typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags);
 extern grpc_server_register_method_type grpc_server_register_method_import;
 #define grpc_server_register_method grpc_server_register_method_import
 typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
@@ -406,6 +406,9 @@
 typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_type)(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);
 extern grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import;
 #define grpc_ssl_server_credentials_create grpc_ssl_server_credentials_create_import
+typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_ex_type)(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);
+extern grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import;
+#define grpc_ssl_server_credentials_create_ex grpc_ssl_server_credentials_create_ex_import
 typedef int(*grpc_server_add_secure_http2_port_type)(grpc_server *server, const char *addr, grpc_server_credentials *creds);
 extern grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import;
 #define grpc_server_add_secure_http2_port grpc_server_add_secure_http2_port_import
@@ -472,6 +475,12 @@
 typedef void(*gpr_log_message_type)(const char *file, int line, gpr_log_severity severity, const char *message);
 extern gpr_log_message_type gpr_log_message_import;
 #define gpr_log_message gpr_log_message_import
+typedef void(*gpr_set_log_verbosity_type)(gpr_log_severity min_severity_to_print);
+extern gpr_set_log_verbosity_type gpr_set_log_verbosity_import;
+#define gpr_set_log_verbosity gpr_set_log_verbosity_import
+typedef void(*gpr_log_verbosity_init_type)();
+extern gpr_log_verbosity_init_type gpr_log_verbosity_init_import;
+#define gpr_log_verbosity_init gpr_log_verbosity_init_import
 typedef void(*gpr_set_log_function_type)(gpr_log_func func);
 extern gpr_set_log_function_type gpr_set_log_function_import;
 #define gpr_set_log_function gpr_set_log_function_import
diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py
index 672e3e4..003653e 100644
--- a/src/python/grpcio/grpc/_links/invocation.py
+++ b/src/python/grpcio/grpc/_links/invocation.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py
index 01edee6..11310e2 100644
--- a/src/python/grpcio/grpc/_links/service.py
+++ b/src/python/grpcio/grpc/_links/service.py
@@ -177,7 +177,7 @@
     call = service_acceptance.call
     call.accept(self._completion_queue, call)
     try:
-      group, method = service_acceptance.method.split('/')[1:3]
+      group, method = service_acceptance.method.split(b'/')[1:3]
     except ValueError:
       logging.info('Illegal path "%s"!', service_acceptance.method)
       return
diff --git a/src/python/grpcio/grpc/beta/_server.py b/src/python/grpcio/grpc/beta/_server.py
index 2b520cc..eb0aadb 100644
--- a/src/python/grpcio/grpc/beta/_server.py
+++ b/src/python/grpcio/grpc/beta/_server.py
@@ -62,7 +62,7 @@
       if e.code is None and e.details is None:
         raise base.NoSuchMethodError(
             interfaces.StatusCode.UNIMPLEMENTED,
-            b'Method "%s" of service "%s" not implemented!' % (method, group))
+            'Method "%s" of service "%s" not implemented!' % (method, group))
       else:
         raise
 
diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py
index a0ca330..742e94d 100644
--- a/src/python/grpcio/grpc/beta/implementations.py
+++ b/src/python/grpcio/grpc/beta/implementations.py
@@ -61,15 +61,16 @@
     self._low_credentials = low_credentials
 
 
-def ssl_channel_credentials(root_certificates, private_key, certificate_chain):
+def ssl_channel_credentials(root_certificates=None, private_key=None,
+                            certificate_chain=None):
   """Creates a ChannelCredentials for use with an SSL-enabled Channel.
 
   Args:
-    root_certificates: The PEM-encoded root certificates or None to ask for
+    root_certificates: The PEM-encoded root certificates or unset to ask for
       them to be retrieved from a default location.
-    private_key: The PEM-encoded private key to use or None if no private key
+    private_key: The PEM-encoded private key to use or unset if no private key
       should be used.
-    certificate_chain: The PEM-encoded certificate chain to use or None if no
+    certificate_chain: The PEM-encoded certificate chain to use or unset if no
       certificate chain should be used.
 
   Returns:
diff --git a/src/python/grpcio/grpc/beta/interfaces.py b/src/python/grpcio/grpc/beta/interfaces.py
index e29a5b3..33ca45a 100644
--- a/src/python/grpcio/grpc/beta/interfaces.py
+++ b/src/python/grpcio/grpc/beta/interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/alpha/_face_utilities.py b/src/python/grpcio/grpc/framework/alpha/_face_utilities.py
index b5e4133..15c47d5 100644
--- a/src/python/grpcio/grpc/framework/alpha/_face_utilities.py
+++ b/src/python/grpcio/grpc/framework/alpha/_face_utilities.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/alpha/_reexport.py b/src/python/grpcio/grpc/framework/alpha/_reexport.py
index 4ea0e94..e027077 100644
--- a/src/python/grpcio/grpc/framework/alpha/_reexport.py
+++ b/src/python/grpcio/grpc/framework/alpha/_reexport.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/alpha/exceptions.py b/src/python/grpcio/grpc/framework/alpha/exceptions.py
index 8ec2604..09359c5 100644
--- a/src/python/grpcio/grpc/framework/alpha/exceptions.py
+++ b/src/python/grpcio/grpc/framework/alpha/exceptions.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/alpha/interfaces.py b/src/python/grpcio/grpc/framework/alpha/interfaces.py
index cb6d58b..48f144f 100644
--- a/src/python/grpcio/grpc/framework/alpha/interfaces.py
+++ b/src/python/grpcio/grpc/framework/alpha/interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/base/_ingestion.py b/src/python/grpcio/grpc/framework/base/_ingestion.py
index 090cb15..c9b10ac 100644
--- a/src/python/grpcio/grpc/framework/base/_ingestion.py
+++ b/src/python/grpcio/grpc/framework/base/_ingestion.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/base/_interfaces.py b/src/python/grpcio/grpc/framework/base/_interfaces.py
index c0cc866..6bb9837 100644
--- a/src/python/grpcio/grpc/framework/base/_interfaces.py
+++ b/src/python/grpcio/grpc/framework/base/_interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/base/_reception.py b/src/python/grpcio/grpc/framework/base/_reception.py
index 2bee394..a59c516 100644
--- a/src/python/grpcio/grpc/framework/base/_reception.py
+++ b/src/python/grpcio/grpc/framework/base/_reception.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/base/_transmission.py b/src/python/grpcio/grpc/framework/base/_transmission.py
index 398faaf..e2a2562 100644
--- a/src/python/grpcio/grpc/framework/base/_transmission.py
+++ b/src/python/grpcio/grpc/framework/base/_transmission.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/base/interfaces.py b/src/python/grpcio/grpc/framework/base/interfaces.py
index 7c58a23..995b51c 100644
--- a/src/python/grpcio/grpc/framework/base/interfaces.py
+++ b/src/python/grpcio/grpc/framework/base/interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/core/_end.py b/src/python/grpcio/grpc/framework/core/_end.py
index dc2f485..009d27c 100644
--- a/src/python/grpcio/grpc/framework/core/_end.py
+++ b/src/python/grpcio/grpc/framework/core/_end.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/core/_ingestion.py b/src/python/grpcio/grpc/framework/core/_ingestion.py
index 1e1fd73..f2767c9 100644
--- a/src/python/grpcio/grpc/framework/core/_ingestion.py
+++ b/src/python/grpcio/grpc/framework/core/_ingestion.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/core/_interfaces.py b/src/python/grpcio/grpc/framework/core/_interfaces.py
index 985e5e8..63ac82f 100644
--- a/src/python/grpcio/grpc/framework/core/_interfaces.py
+++ b/src/python/grpcio/grpc/framework/core/_interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/core/_termination.py b/src/python/grpcio/grpc/framework/core/_termination.py
index e8c4ec6..fff3a3f 100644
--- a/src/python/grpcio/grpc/framework/core/_termination.py
+++ b/src/python/grpcio/grpc/framework/core/_termination.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/crust/_control.py b/src/python/grpcio/grpc/framework/crust/_control.py
index c27fc91..9b4167b 100644
--- a/src/python/grpcio/grpc/framework/crust/_control.py
+++ b/src/python/grpcio/grpc/framework/crust/_control.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/crust/implementations.py b/src/python/grpcio/grpc/framework/crust/implementations.py
index d0ecafc..2d3ab73 100644
--- a/src/python/grpcio/grpc/framework/crust/implementations.py
+++ b/src/python/grpcio/grpc/framework/crust/implementations.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/face/_control.py b/src/python/grpcio/grpc/framework/face/_control.py
index ec43203..539615e 100644
--- a/src/python/grpcio/grpc/framework/face/_control.py
+++ b/src/python/grpcio/grpc/framework/face/_control.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/face/exceptions.py b/src/python/grpcio/grpc/framework/face/exceptions.py
index c272ac7..f954556 100644
--- a/src/python/grpcio/grpc/framework/face/exceptions.py
+++ b/src/python/grpcio/grpc/framework/face/exceptions.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/face/implementations.py b/src/python/grpcio/grpc/framework/face/implementations.py
index 9c75a5f..96055b4 100644
--- a/src/python/grpcio/grpc/framework/face/implementations.py
+++ b/src/python/grpcio/grpc/framework/face/implementations.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/face/interfaces.py b/src/python/grpcio/grpc/framework/face/interfaces.py
index 9fc18d7..e9a25c1 100644
--- a/src/python/grpcio/grpc/framework/face/interfaces.py
+++ b/src/python/grpcio/grpc/framework/face/interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/foundation/activated.py b/src/python/grpcio/grpc/framework/foundation/activated.py
index 9b49b63..8b8e4f4 100644
--- a/src/python/grpcio/grpc/framework/foundation/activated.py
+++ b/src/python/grpcio/grpc/framework/foundation/activated.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/foundation/callable_util.py b/src/python/grpcio/grpc/framework/foundation/callable_util.py
index e0a4cab..4f029f9 100644
--- a/src/python/grpcio/grpc/framework/foundation/callable_util.py
+++ b/src/python/grpcio/grpc/framework/foundation/callable_util.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/foundation/future.py b/src/python/grpcio/grpc/framework/foundation/future.py
index bb8ee3a..9210616 100644
--- a/src/python/grpcio/grpc/framework/foundation/future.py
+++ b/src/python/grpcio/grpc/framework/foundation/future.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/foundation/logging_pool.py b/src/python/grpcio/grpc/framework/foundation/logging_pool.py
index f82c7f7..9b469a1 100644
--- a/src/python/grpcio/grpc/framework/foundation/logging_pool.py
+++ b/src/python/grpcio/grpc/framework/foundation/logging_pool.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/foundation/relay.py b/src/python/grpcio/grpc/framework/foundation/relay.py
index ff4e227..20f41b2 100644
--- a/src/python/grpcio/grpc/framework/foundation/relay.py
+++ b/src/python/grpcio/grpc/framework/foundation/relay.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/foundation/stream.py b/src/python/grpcio/grpc/framework/foundation/stream.py
index 32a2e52..ddd6cc4 100644
--- a/src/python/grpcio/grpc/framework/foundation/stream.py
+++ b/src/python/grpcio/grpc/framework/foundation/stream.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/foundation/stream_util.py b/src/python/grpcio/grpc/framework/foundation/stream_util.py
index 7d5977f..a6f234f 100644
--- a/src/python/grpcio/grpc/framework/foundation/stream_util.py
+++ b/src/python/grpcio/grpc/framework/foundation/stream_util.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/interfaces/base/base.py b/src/python/grpcio/grpc/framework/interfaces/base/base.py
index 69be37e..a2ddd9c 100644
--- a/src/python/grpcio/grpc/framework/interfaces/base/base.py
+++ b/src/python/grpcio/grpc/framework/interfaces/base/base.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/interfaces/face/face.py b/src/python/grpcio/grpc/framework/interfaces/face/face.py
index b994ace..4826e7f 100644
--- a/src/python/grpcio/grpc/framework/interfaces/face/face.py
+++ b/src/python/grpcio/grpc/framework/interfaces/face/face.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc/framework/interfaces/links/links.py b/src/python/grpcio/grpc/framework/interfaces/links/links.py
index 8081679..9631b19 100644
--- a/src/python/grpcio/grpc/framework/interfaces/links/links.py
+++ b/src/python/grpcio/grpc/framework/interfaces/links/links.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index b9e7d8c..c5a0a39 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -30,213 +30,215 @@
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_core_dependencies.py.template`!!!
 
 CORE_SOURCE_FILES = [
-  'src/core/profiling/basic_timers.c',
-  'src/core/profiling/stap_timers.c',
-  'src/core/support/alloc.c',
-  'src/core/support/avl.c',
-  'src/core/support/backoff.c',
-  'src/core/support/cmdline.c',
-  'src/core/support/cpu_iphone.c',
-  'src/core/support/cpu_linux.c',
-  'src/core/support/cpu_posix.c',
-  'src/core/support/cpu_windows.c',
-  'src/core/support/env_linux.c',
-  'src/core/support/env_posix.c',
-  'src/core/support/env_win32.c',
-  'src/core/support/histogram.c',
-  'src/core/support/host_port.c',
-  'src/core/support/load_file.c',
-  'src/core/support/log.c',
-  'src/core/support/log_android.c',
-  'src/core/support/log_linux.c',
-  'src/core/support/log_posix.c',
-  'src/core/support/log_win32.c',
-  'src/core/support/murmur_hash.c',
-  'src/core/support/slice.c',
-  'src/core/support/slice_buffer.c',
-  'src/core/support/stack_lockfree.c',
-  'src/core/support/string.c',
-  'src/core/support/string_posix.c',
-  'src/core/support/string_win32.c',
-  'src/core/support/subprocess_posix.c',
-  'src/core/support/subprocess_windows.c',
-  'src/core/support/sync.c',
-  'src/core/support/sync_posix.c',
-  'src/core/support/sync_win32.c',
-  'src/core/support/thd.c',
-  'src/core/support/thd_posix.c',
-  'src/core/support/thd_win32.c',
-  'src/core/support/time.c',
-  'src/core/support/time_posix.c',
-  'src/core/support/time_precise.c',
-  'src/core/support/time_win32.c',
-  'src/core/support/tls_pthread.c',
-  'src/core/support/tmpfile_posix.c',
-  'src/core/support/tmpfile_win32.c',
-  'src/core/support/wrap_memcpy.c',
-  'src/core/census/grpc_context.c',
-  'src/core/census/grpc_filter.c',
-  'src/core/census/grpc_plugin.c',
-  'src/core/channel/channel_args.c',
-  'src/core/channel/channel_stack.c',
-  'src/core/channel/channel_stack_builder.c',
-  'src/core/channel/client_channel.c',
-  'src/core/channel/client_uchannel.c',
-  'src/core/channel/compress_filter.c',
-  'src/core/channel/connected_channel.c',
-  'src/core/channel/http_client_filter.c',
-  'src/core/channel/http_server_filter.c',
-  'src/core/channel/subchannel_call_holder.c',
-  'src/core/client_config/client_config.c',
-  'src/core/client_config/connector.c',
-  'src/core/client_config/default_initial_connect_string.c',
-  'src/core/client_config/initial_connect_string.c',
-  'src/core/client_config/lb_policies/load_balancer_api.c',
-  'src/core/client_config/lb_policies/pick_first.c',
-  'src/core/client_config/lb_policies/round_robin.c',
-  'src/core/client_config/lb_policy.c',
-  'src/core/client_config/lb_policy_factory.c',
-  'src/core/client_config/lb_policy_registry.c',
-  'src/core/client_config/resolver.c',
-  'src/core/client_config/resolver_factory.c',
-  'src/core/client_config/resolver_registry.c',
-  'src/core/client_config/resolvers/dns_resolver.c',
-  'src/core/client_config/resolvers/sockaddr_resolver.c',
-  'src/core/client_config/subchannel.c',
-  'src/core/client_config/subchannel_factory.c',
-  'src/core/client_config/subchannel_index.c',
-  'src/core/client_config/uri_parser.c',
-  'src/core/compression/compression_algorithm.c',
-  'src/core/compression/message_compress.c',
-  'src/core/debug/trace.c',
-  'src/core/httpcli/format_request.c',
-  'src/core/httpcli/httpcli.c',
-  'src/core/httpcli/parser.c',
-  'src/core/iomgr/closure.c',
-  'src/core/iomgr/endpoint.c',
-  'src/core/iomgr/endpoint_pair_posix.c',
-  'src/core/iomgr/endpoint_pair_windows.c',
-  'src/core/iomgr/exec_ctx.c',
-  'src/core/iomgr/executor.c',
-  'src/core/iomgr/fd_posix.c',
-  'src/core/iomgr/iocp_windows.c',
-  'src/core/iomgr/iomgr.c',
-  'src/core/iomgr/iomgr_posix.c',
-  'src/core/iomgr/iomgr_windows.c',
-  'src/core/iomgr/pollset_multipoller_with_epoll.c',
-  'src/core/iomgr/pollset_multipoller_with_poll_posix.c',
-  'src/core/iomgr/pollset_posix.c',
-  'src/core/iomgr/pollset_set_posix.c',
-  'src/core/iomgr/pollset_set_windows.c',
-  'src/core/iomgr/pollset_windows.c',
-  'src/core/iomgr/resolve_address_posix.c',
-  'src/core/iomgr/resolve_address_windows.c',
-  'src/core/iomgr/sockaddr_utils.c',
-  'src/core/iomgr/socket_utils_common_posix.c',
-  'src/core/iomgr/socket_utils_linux.c',
-  'src/core/iomgr/socket_utils_posix.c',
-  'src/core/iomgr/socket_windows.c',
-  'src/core/iomgr/tcp_client_posix.c',
-  'src/core/iomgr/tcp_client_windows.c',
-  'src/core/iomgr/tcp_posix.c',
-  'src/core/iomgr/tcp_server_posix.c',
-  'src/core/iomgr/tcp_server_windows.c',
-  'src/core/iomgr/tcp_windows.c',
-  'src/core/iomgr/time_averaged_stats.c',
-  'src/core/iomgr/timer.c',
-  'src/core/iomgr/timer_heap.c',
-  'src/core/iomgr/udp_server.c',
-  'src/core/iomgr/wakeup_fd_eventfd.c',
-  'src/core/iomgr/wakeup_fd_nospecial.c',
-  'src/core/iomgr/wakeup_fd_pipe.c',
-  'src/core/iomgr/wakeup_fd_posix.c',
-  'src/core/iomgr/workqueue_posix.c',
-  'src/core/iomgr/workqueue_windows.c',
-  'src/core/json/json.c',
-  'src/core/json/json_reader.c',
-  'src/core/json/json_string.c',
-  'src/core/json/json_writer.c',
-  'src/core/proto/grpc/lb/v0/load_balancer.pb.c',
-  'src/core/surface/alarm.c',
-  'src/core/surface/api_trace.c',
-  'src/core/surface/byte_buffer.c',
-  'src/core/surface/byte_buffer_reader.c',
-  'src/core/surface/call.c',
-  'src/core/surface/call_details.c',
-  'src/core/surface/call_log_batch.c',
-  'src/core/surface/channel.c',
-  'src/core/surface/channel_connectivity.c',
-  'src/core/surface/channel_create.c',
-  'src/core/surface/channel_init.c',
-  'src/core/surface/channel_ping.c',
-  'src/core/surface/channel_stack_type.c',
-  'src/core/surface/completion_queue.c',
-  'src/core/surface/event_string.c',
-  'src/core/surface/init.c',
-  'src/core/surface/lame_client.c',
-  'src/core/surface/metadata_array.c',
-  'src/core/surface/server.c',
-  'src/core/surface/server_chttp2.c',
-  'src/core/surface/validate_metadata.c',
-  'src/core/surface/version.c',
-  'src/core/transport/byte_stream.c',
-  'src/core/transport/chttp2/alpn.c',
-  'src/core/transport/chttp2/bin_encoder.c',
-  'src/core/transport/chttp2/frame_data.c',
-  'src/core/transport/chttp2/frame_goaway.c',
-  'src/core/transport/chttp2/frame_ping.c',
-  'src/core/transport/chttp2/frame_rst_stream.c',
-  'src/core/transport/chttp2/frame_settings.c',
-  'src/core/transport/chttp2/frame_window_update.c',
-  'src/core/transport/chttp2/hpack_encoder.c',
-  'src/core/transport/chttp2/hpack_parser.c',
-  'src/core/transport/chttp2/hpack_table.c',
-  'src/core/transport/chttp2/huffsyms.c',
-  'src/core/transport/chttp2/incoming_metadata.c',
-  'src/core/transport/chttp2/parsing.c',
-  'src/core/transport/chttp2/status_conversion.c',
-  'src/core/transport/chttp2/stream_lists.c',
-  'src/core/transport/chttp2/stream_map.c',
-  'src/core/transport/chttp2/timeout_encoding.c',
-  'src/core/transport/chttp2/varint.c',
-  'src/core/transport/chttp2/writing.c',
-  'src/core/transport/chttp2_transport.c',
-  'src/core/transport/connectivity_state.c',
-  'src/core/transport/metadata.c',
-  'src/core/transport/metadata_batch.c',
-  'src/core/transport/static_metadata.c',
-  'src/core/transport/transport.c',
-  'src/core/transport/transport_op_string.c',
-  'src/core/httpcli/httpcli_security_connector.c',
-  'src/core/security/b64.c',
-  'src/core/security/client_auth_filter.c',
-  'src/core/security/credentials.c',
-  'src/core/security/credentials_metadata.c',
-  'src/core/security/credentials_posix.c',
-  'src/core/security/credentials_win32.c',
-  'src/core/security/google_default_credentials.c',
-  'src/core/security/handshake.c',
-  'src/core/security/json_token.c',
-  'src/core/security/jwt_verifier.c',
-  'src/core/security/secure_endpoint.c',
-  'src/core/security/security_connector.c',
-  'src/core/security/security_context.c',
-  'src/core/security/server_auth_filter.c',
-  'src/core/security/server_secure_chttp2.c',
-  'src/core/surface/init_secure.c',
-  'src/core/surface/secure_channel_create.c',
-  'src/core/tsi/fake_transport_security.c',
-  'src/core/tsi/ssl_transport_security.c',
-  'src/core/tsi/transport_security.c',
-  'src/core/census/context.c',
-  'src/core/census/initialize.c',
-  'src/core/census/mlog.c',
-  'src/core/census/operation.c',
-  'src/core/census/placeholders.c',
-  'src/core/census/tracing.c',
+  'src/core/lib/profiling/basic_timers.c',
+  'src/core/lib/profiling/stap_timers.c',
+  'src/core/lib/support/alloc.c',
+  'src/core/lib/support/avl.c',
+  'src/core/lib/support/backoff.c',
+  'src/core/lib/support/cmdline.c',
+  'src/core/lib/support/cpu_iphone.c',
+  'src/core/lib/support/cpu_linux.c',
+  'src/core/lib/support/cpu_posix.c',
+  'src/core/lib/support/cpu_windows.c',
+  'src/core/lib/support/env_linux.c',
+  'src/core/lib/support/env_posix.c',
+  'src/core/lib/support/env_win32.c',
+  'src/core/lib/support/histogram.c',
+  'src/core/lib/support/host_port.c',
+  'src/core/lib/support/load_file.c',
+  'src/core/lib/support/log.c',
+  'src/core/lib/support/log_android.c',
+  'src/core/lib/support/log_linux.c',
+  'src/core/lib/support/log_posix.c',
+  'src/core/lib/support/log_win32.c',
+  'src/core/lib/support/murmur_hash.c',
+  'src/core/lib/support/slice.c',
+  'src/core/lib/support/slice_buffer.c',
+  'src/core/lib/support/stack_lockfree.c',
+  'src/core/lib/support/string.c',
+  'src/core/lib/support/string_posix.c',
+  'src/core/lib/support/string_win32.c',
+  'src/core/lib/support/subprocess_posix.c',
+  'src/core/lib/support/subprocess_windows.c',
+  'src/core/lib/support/sync.c',
+  'src/core/lib/support/sync_posix.c',
+  'src/core/lib/support/sync_win32.c',
+  'src/core/lib/support/thd.c',
+  'src/core/lib/support/thd_posix.c',
+  'src/core/lib/support/thd_win32.c',
+  'src/core/lib/support/time.c',
+  'src/core/lib/support/time_posix.c',
+  'src/core/lib/support/time_precise.c',
+  'src/core/lib/support/time_win32.c',
+  'src/core/lib/support/tls_pthread.c',
+  'src/core/lib/support/tmpfile_posix.c',
+  'src/core/lib/support/tmpfile_win32.c',
+  'src/core/lib/support/wrap_memcpy.c',
+  'src/core/lib/surface/init.c',
+  'src/core/lib/channel/channel_args.c',
+  'src/core/lib/channel/channel_stack.c',
+  'src/core/lib/channel/channel_stack_builder.c',
+  'src/core/lib/channel/compress_filter.c',
+  'src/core/lib/channel/connected_channel.c',
+  'src/core/lib/channel/http_client_filter.c',
+  'src/core/lib/channel/http_server_filter.c',
+  'src/core/lib/compression/compression_algorithm.c',
+  'src/core/lib/compression/message_compress.c',
+  'src/core/lib/debug/trace.c',
+  'src/core/lib/http/format_request.c',
+  'src/core/lib/http/httpcli.c',
+  'src/core/lib/http/parser.c',
+  'src/core/lib/iomgr/closure.c',
+  'src/core/lib/iomgr/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_posix.c',
+  'src/core/lib/iomgr/exec_ctx.c',
+  'src/core/lib/iomgr/executor.c',
+  'src/core/lib/iomgr/iocp_windows.c',
+  'src/core/lib/iomgr/iomgr.c',
+  'src/core/lib/iomgr/iomgr_posix.c',
+  'src/core/lib/iomgr/iomgr_windows.c',
+  'src/core/lib/iomgr/pollset_set_windows.c',
+  'src/core/lib/iomgr/pollset_windows.c',
+  'src/core/lib/iomgr/resolve_address_posix.c',
+  'src/core/lib/iomgr/resolve_address_windows.c',
+  'src/core/lib/iomgr/sockaddr_utils.c',
+  'src/core/lib/iomgr/socket_utils_common_posix.c',
+  'src/core/lib/iomgr/socket_utils_linux.c',
+  'src/core/lib/iomgr/socket_utils_posix.c',
+  'src/core/lib/iomgr/socket_windows.c',
+  'src/core/lib/iomgr/tcp_client_posix.c',
+  'src/core/lib/iomgr/tcp_client_windows.c',
+  'src/core/lib/iomgr/tcp_posix.c',
+  'src/core/lib/iomgr/tcp_server_posix.c',
+  'src/core/lib/iomgr/tcp_server_windows.c',
+  'src/core/lib/iomgr/tcp_windows.c',
+  'src/core/lib/iomgr/time_averaged_stats.c',
+  'src/core/lib/iomgr/timer.c',
+  'src/core/lib/iomgr/timer_heap.c',
+  'src/core/lib/iomgr/udp_server.c',
+  'src/core/lib/iomgr/unix_sockets_posix.c',
+  'src/core/lib/iomgr/unix_sockets_posix_noop.c',
+  'src/core/lib/iomgr/wakeup_fd_eventfd.c',
+  'src/core/lib/iomgr/wakeup_fd_nospecial.c',
+  'src/core/lib/iomgr/wakeup_fd_pipe.c',
+  'src/core/lib/iomgr/wakeup_fd_posix.c',
+  'src/core/lib/iomgr/workqueue_posix.c',
+  'src/core/lib/iomgr/workqueue_windows.c',
+  'src/core/lib/json/json.c',
+  'src/core/lib/json/json_reader.c',
+  'src/core/lib/json/json_string.c',
+  'src/core/lib/json/json_writer.c',
+  'src/core/lib/surface/alarm.c',
+  'src/core/lib/surface/api_trace.c',
+  'src/core/lib/surface/byte_buffer.c',
+  'src/core/lib/surface/byte_buffer_reader.c',
+  'src/core/lib/surface/call.c',
+  'src/core/lib/surface/call_details.c',
+  'src/core/lib/surface/call_log_batch.c',
+  'src/core/lib/surface/channel.c',
+  'src/core/lib/surface/channel_init.c',
+  'src/core/lib/surface/channel_ping.c',
+  'src/core/lib/surface/channel_stack_type.c',
+  'src/core/lib/surface/completion_queue.c',
+  'src/core/lib/surface/event_string.c',
+  'src/core/lib/surface/lame_client.c',
+  'src/core/lib/surface/metadata_array.c',
+  'src/core/lib/surface/server.c',
+  'src/core/lib/surface/validate_metadata.c',
+  'src/core/lib/surface/version.c',
+  'src/core/lib/transport/byte_stream.c',
+  'src/core/lib/transport/connectivity_state.c',
+  'src/core/lib/transport/metadata.c',
+  'src/core/lib/transport/metadata_batch.c',
+  'src/core/lib/transport/static_metadata.c',
+  'src/core/lib/transport/transport.c',
+  'src/core/lib/transport/transport_op_string.c',
+  'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c',
+  'src/core/ext/transport/chttp2/transport/bin_encoder.c',
+  'src/core/ext/transport/chttp2/transport/chttp2_plugin.c',
+  'src/core/ext/transport/chttp2/transport/chttp2_transport.c',
+  'src/core/ext/transport/chttp2/transport/frame_data.c',
+  'src/core/ext/transport/chttp2/transport/frame_goaway.c',
+  'src/core/ext/transport/chttp2/transport/frame_ping.c',
+  'src/core/ext/transport/chttp2/transport/frame_rst_stream.c',
+  'src/core/ext/transport/chttp2/transport/frame_settings.c',
+  'src/core/ext/transport/chttp2/transport/frame_window_update.c',
+  'src/core/ext/transport/chttp2/transport/hpack_encoder.c',
+  'src/core/ext/transport/chttp2/transport/hpack_parser.c',
+  'src/core/ext/transport/chttp2/transport/hpack_table.c',
+  'src/core/ext/transport/chttp2/transport/huffsyms.c',
+  'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
+  'src/core/ext/transport/chttp2/transport/parsing.c',
+  'src/core/ext/transport/chttp2/transport/status_conversion.c',
+  'src/core/ext/transport/chttp2/transport/stream_lists.c',
+  'src/core/ext/transport/chttp2/transport/stream_map.c',
+  'src/core/ext/transport/chttp2/transport/timeout_encoding.c',
+  'src/core/ext/transport/chttp2/transport/varint.c',
+  'src/core/ext/transport/chttp2/transport/writing.c',
+  'src/core/ext/transport/chttp2/alpn/alpn.c',
+  'src/core/lib/http/httpcli_security_connector.c',
+  'src/core/lib/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/surface/init_secure.c',
+  'src/core/lib/tsi/fake_transport_security.c',
+  'src/core/lib/tsi/ssl_transport_security.c',
+  'src/core/lib/tsi/transport_security.c',
+  'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c',
+  'src/core/ext/client_config/channel_connectivity.c',
+  'src/core/ext/client_config/client_channel.c',
+  'src/core/ext/client_config/client_channel_factory.c',
+  'src/core/ext/client_config/client_config.c',
+  'src/core/ext/client_config/client_config_plugin.c',
+  'src/core/ext/client_config/connector.c',
+  'src/core/ext/client_config/default_initial_connect_string.c',
+  'src/core/ext/client_config/initial_connect_string.c',
+  'src/core/ext/client_config/lb_policy.c',
+  'src/core/ext/client_config/lb_policy_factory.c',
+  'src/core/ext/client_config/lb_policy_registry.c',
+  'src/core/ext/client_config/parse_address.c',
+  'src/core/ext/client_config/resolver.c',
+  'src/core/ext/client_config/resolver_factory.c',
+  'src/core/ext/client_config/resolver_registry.c',
+  'src/core/ext/client_config/subchannel.c',
+  'src/core/ext/client_config/subchannel_call_holder.c',
+  'src/core/ext/client_config/subchannel_index.c',
+  'src/core/ext/client_config/uri_parser.c',
+  'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c',
+  'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
+  'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
+  'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c',
   'third_party/nanopb/pb_common.c',
   'third_party/nanopb/pb_decode.c',
   'third_party/nanopb/pb_encode.c',
+  'src/core/ext/lb_policy/pick_first/pick_first.c',
+  'src/core/ext/lb_policy/round_robin/round_robin.c',
+  'src/core/ext/resolver/dns/native/dns_resolver.c',
+  'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
+  'src/core/ext/census/context.c',
+  'src/core/ext/census/grpc_context.c',
+  'src/core/ext/census/grpc_filter.c',
+  'src/core/ext/census/grpc_plugin.c',
+  'src/core/ext/census/initialize.c',
+  'src/core/ext/census/mlog.c',
+  'src/core/ext/census/operation.c',
+  'src/core/ext/census/placeholders.c',
+  'src/core/ext/census/tracing.c',
+  'src/core/plugin_registry/grpc_plugin_registry.c',
   'src/boringssl/err_data.c',
   'third_party/boringssl/crypto/aes/aes.c',
   'third_party/boringssl/crypto/aes/mode_wrappers.c',
@@ -309,6 +311,7 @@
   'third_party/boringssl/crypto/bn/shift.c',
   'third_party/boringssl/crypto/bn/sqrt.c',
   'third_party/boringssl/crypto/buf/buf.c',
+  'third_party/boringssl/crypto/bytestring/asn1_compat.c',
   'third_party/boringssl/crypto/bytestring/ber.c',
   'third_party/boringssl/crypto/bytestring/cbb.c',
   'third_party/boringssl/crypto/bytestring/cbs.c',
@@ -332,6 +335,7 @@
   'third_party/boringssl/crypto/cpu-intel.c',
   'third_party/boringssl/crypto/crypto.c',
   'third_party/boringssl/crypto/curve25519/curve25519.c',
+  'third_party/boringssl/crypto/curve25519/x25519-x86_64.c',
   'third_party/boringssl/crypto/des/des.c',
   'third_party/boringssl/crypto/dh/check.c',
   'third_party/boringssl/crypto/dh/dh.c',
@@ -523,6 +527,7 @@
   'third_party/boringssl/ssl/ssl_buffer.c',
   'third_party/boringssl/ssl/ssl_cert.c',
   'third_party/boringssl/ssl/ssl_cipher.c',
+  'third_party/boringssl/ssl/ssl_ecdh.c',
   'third_party/boringssl/ssl/ssl_file.c',
   'third_party/boringssl/ssl/ssl_lib.c',
   'third_party/boringssl/ssl/ssl_rsa.c',
diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py
index 75b88cf..873b4e2 100644
--- a/src/python/grpcio/grpc_version.py
+++ b/src/python/grpcio/grpc_version.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/precompiled.py b/src/python/grpcio/precompiled.py
index d34250b..b6aa7fc 100644
--- a/src/python/grpcio/precompiled.py
+++ b/src/python/grpcio/precompiled.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -91,6 +91,9 @@
 
 
 def update_setup_arguments(setup_arguments):
+  if not USE_PRECOMPILED_BINARIES:
+    sys.stderr.write('not using precompiled extension')
+    return
   url = '{}/{}.so'.format(BINARIES_REPOSITORY, _tagged_ext_name('cygrpc'))
   target_path = os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so')
   try:
diff --git a/src/python/grpcio/tests/__init__.py b/src/python/grpcio/tests/__init__.py
index b76b398..a70a1b1 100644
--- a/src/python/grpcio/tests/__init__.py
+++ b/src/python/grpcio/tests/__init__.py
@@ -27,6 +27,8 @@
 # (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 __future__ import absolute_import
+
 from tests import _loader
 from tests import _runner
 
diff --git a/src/python/grpcio/tests/_loader.py b/src/python/grpcio/tests/_loader.py
index 6992029..c2f097f 100644
--- a/src/python/grpcio/tests/_loader.py
+++ b/src/python/grpcio/tests/_loader.py
@@ -27,6 +27,8 @@
 # (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 __future__ import absolute_import
+
 import importlib
 import pkgutil
 import re
diff --git a/src/python/grpcio/tests/_result.py b/src/python/grpcio/tests/_result.py
index 0670be9..1acec6a 100644
--- a/src/python/grpcio/tests/_result.py
+++ b/src/python/grpcio/tests/_result.py
@@ -27,7 +27,8 @@
 # (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 cStringIO as StringIO
+from __future__ import absolute_import
+
 import collections
 import itertools
 import traceback
@@ -35,6 +36,7 @@
 from xml.etree import ElementTree
 
 import coverage
+from six import moves
 
 from tests import _loader
 
@@ -202,7 +204,7 @@
     """
     case_id = self.id_map(test)
     self.cases[case_id] = self.cases[case_id].updated(
-        stdout=stdout, stderr=stderr)
+        stdout=stdout.decode(), stderr=stderr.decode())
 
   def augmented_results(self, filter):
     """Convenience method to retrieve filtered case results.
@@ -356,7 +358,7 @@
   Returns:
     str: Formatted exception descriptive string.
   """
-  buffer = StringIO.StringIO()
+  buffer = moves.cStringIO()
   traceback.print_exception(type, value, trace, file=buffer)
   return buffer.getvalue()
 
diff --git a/src/python/grpcio/tests/_runner.py b/src/python/grpcio/tests/_runner.py
index 3b5ca03..f071857 100644
--- a/src/python/grpcio/tests/_runner.py
+++ b/src/python/grpcio/tests/_runner.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,8 @@
 # (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 cStringIO as StringIO
+from __future__ import absolute_import
+
 import collections
 import fcntl
 import multiprocessing
@@ -41,6 +42,9 @@
 import unittest
 import uuid
 
+import six
+from six import moves
+
 from tests import _loader
 from tests import _result
 
@@ -92,6 +96,8 @@
     Arguments:
       value (str): What to write to the original file.
     """
+    if six.PY3 and not isinstance(value, six.binary_type):
+      value = bytes(value, 'ascii')
     if self._saved_fd is None:
       os.write(self._redirect_fd, value)
     else:
@@ -143,7 +149,7 @@
                        for case in filtered_cases]
     case_id_by_case = dict((augmented_case.case, augmented_case.id)
                            for augmented_case in augmented_cases)
-    result_out = StringIO.StringIO()
+    result_out = moves.cStringIO()
     result = _result.TerminalResult(
         result_out, id_map=lambda case: case_id_by_case[case])
     stdout_pipe = CaptureFile(sys.stdout.fileno())
@@ -168,9 +174,9 @@
         result.stopTestRun()
         stdout_pipe.write_bypass(result_out.getvalue())
         stdout_pipe.write_bypass(
-            '\ninterrupted stdout:\n{}\n'.format(stdout_pipe.output()))
+            '\ninterrupted stdout:\n{}\n'.format(stdout_pipe.output().decode()))
         stderr_pipe.write_bypass(
-            '\ninterrupted stderr:\n{}\n'.format(stderr_pipe.output()))
+            '\ninterrupted stderr:\n{}\n'.format(stderr_pipe.output().decode()))
         os._exit(1)
     signal.signal(signal.SIGINT, sigint_handler)
     signal.signal(signal.SIGSEGV, fault_handler)
@@ -213,7 +219,7 @@
     sys.stdout.write(result_out.getvalue())
     sys.stdout.flush()
     signal.signal(signal.SIGINT, signal.SIG_DFL)
-    with open('report.xml', 'w') as report_xml_file:
+    with open('report.xml', 'wb') as report_xml_file:
       _result.jenkins_junit_xml(result).write(report_xml_file)
     return result
 
diff --git a/src/python/grpcio/tests/interop/_secure_interop_test.py b/src/python/grpcio/tests/interop/_secure_interop_test.py
index 7e30611..86d7e43 100644
--- a/src/python/grpcio/tests/interop/_secure_interop_test.py
+++ b/src/python/grpcio/tests/interop/_secure_interop_test.py
@@ -56,7 +56,7 @@
     self.stub = test_pb2.beta_create_TestService_stub(
         test_utilities.not_really_secure_channel(
             '[::]', port, implementations.ssl_channel_credentials(
-                resources.test_root_certificates(), None, None),
+                resources.test_root_certificates()),
                 _SERVER_HOST_OVERRIDE))
 
   def tearDown(self):
diff --git a/src/python/grpcio/tests/interop/client.py b/src/python/grpcio/tests/interop/client.py
index 573ec2b..1d10d7e 100644
--- a/src/python/grpcio/tests/interop/client.py
+++ b/src/python/grpcio/tests/interop/client.py
@@ -94,7 +94,7 @@
 
     channel = test_utilities.not_really_secure_channel(
         args.server_host, args.server_port,
-        implementations.ssl_channel_credentials(root_certificates, None, None),
+        implementations.ssl_channel_credentials(root_certificates),
         args.server_host_override)
     stub = test_pb2.beta_create_TestService_stub(
         channel, metadata_transformer=metadata_transformer)
diff --git a/src/python/grpcio/tests/interop/methods.py b/src/python/grpcio/tests/interop/methods.py
index 1f5561c..0381033 100644
--- a/src/python/grpcio/tests/interop/methods.py
+++ b/src/python/grpcio/tests/interop/methods.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,8 @@
 
 """Implementations of interoperability test methods."""
 
+from __future__ import print_function
+
 import enum
 import json
 import os
@@ -208,7 +210,7 @@
 
   with stub, _Pipe() as pipe:
     response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
-    print 'Starting ping-pong with response iterator %s' % response_iterator
+    print('Starting ping-pong with response iterator %s' % response_iterator)
     for response_size, payload_size in zip(
         request_response_sizes, request_payload_sizes):
       request = messages_pb2.StreamingOutputCallRequest(
diff --git a/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py
index ba5b219..6fba3d4 100644
--- a/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py
+++ b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py
@@ -42,6 +42,8 @@
 import time
 import unittest
 
+from six import moves
+
 from grpc.beta import implementations
 from grpc.framework.foundation import future
 from grpc.framework.interfaces.face import face
@@ -250,7 +252,7 @@
   def testImportAttributes(self):
     # check that we can access the generated module and its members.
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None))
     self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None))
     self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None))
@@ -258,13 +260,13 @@
 
   def testUpDown(self):
     import protoc_plugin_test_pb2 as test_pb2
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (servicer, stub):
       request = test_pb2.SimpleRequest(response_size=13)
 
   def testUnaryCall(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       request = test_pb2.SimpleRequest(response_size=13)
       response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT)
@@ -273,7 +275,7 @@
 
   def testUnaryCallFuture(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request = test_pb2.SimpleRequest(response_size=13)
     with _CreateService(test_pb2) as (methods, stub):
       # Check that the call does not block waiting for the server to respond.
@@ -286,7 +288,7 @@
 
   def testUnaryCallFutureExpired(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       request = test_pb2.SimpleRequest(response_size=13)
       with methods.pause():
@@ -297,7 +299,7 @@
 
   def testUnaryCallFutureCancelled(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request = test_pb2.SimpleRequest(response_size=13)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.pause():
@@ -307,7 +309,7 @@
 
   def testUnaryCallFutureFailed(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request = test_pb2.SimpleRequest(response_size=13)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.fail():
@@ -317,20 +319,20 @@
 
   def testStreamingOutputCall(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request = _streaming_output_request(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       responses = stub.StreamingOutputCall(
           request, test_constants.LONG_TIMEOUT)
       expected_responses = methods.StreamingOutputCall(
           request, 'not a real RpcContext!')
-      for expected_response, response in itertools.izip_longest(
+      for expected_response, response in moves.zip_longest(
           expected_responses, responses):
         self.assertEqual(expected_response, response)
 
   def testStreamingOutputCallExpired(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request = _streaming_output_request(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.pause():
@@ -341,7 +343,7 @@
 
   def testStreamingOutputCallCancelled(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request = _streaming_output_request(test_pb2)
     with _CreateService(test_pb2) as (unused_methods, stub):
       responses = stub.StreamingOutputCall(
@@ -353,7 +355,7 @@
 
   def testStreamingOutputCallFailed(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request = _streaming_output_request(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.fail():
@@ -364,7 +366,7 @@
 
   def testStreamingInputCall(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       response = stub.StreamingInputCall(
           _streaming_input_request_iterator(test_pb2),
@@ -375,7 +377,7 @@
 
   def testStreamingInputCallFuture(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.pause():
         response_future = stub.StreamingInputCall.future(
@@ -388,7 +390,7 @@
 
   def testStreamingInputCallFutureExpired(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.pause():
         response_future = stub.StreamingInputCall.future(
@@ -401,7 +403,7 @@
 
   def testStreamingInputCallFutureCancelled(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.pause():
         response_future = stub.StreamingInputCall.future(
@@ -414,7 +416,7 @@
 
   def testStreamingInputCallFutureFailed(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.fail():
         response_future = stub.StreamingInputCall.future(
@@ -424,19 +426,19 @@
 
   def testFullDuplexCall(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       responses = stub.FullDuplexCall(
           _full_duplex_request_iterator(test_pb2), test_constants.LONG_TIMEOUT)
       expected_responses = methods.FullDuplexCall(
           _full_duplex_request_iterator(test_pb2), 'not a real RpcContext!')
-      for expected_response, response in itertools.izip_longest(
+      for expected_response, response in moves.zip_longest(
           expected_responses, responses):
         self.assertEqual(expected_response, response)
 
   def testFullDuplexCallExpired(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request_iterator = _full_duplex_request_iterator(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.pause():
@@ -447,7 +449,7 @@
 
   def testFullDuplexCallCancelled(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       request_iterator = _full_duplex_request_iterator(test_pb2)
       responses = stub.FullDuplexCall(
@@ -459,7 +461,7 @@
 
   def testFullDuplexCallFailed(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     request_iterator = _full_duplex_request_iterator(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       with methods.fail():
@@ -471,7 +473,7 @@
 
   def testHalfDuplexCall(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     with _CreateService(test_pb2) as (methods, stub):
       def half_duplex_request_iterator():
         request = test_pb2.StreamingOutputCallRequest()
@@ -485,13 +487,13 @@
           half_duplex_request_iterator(), test_constants.LONG_TIMEOUT)
       expected_responses = methods.HalfDuplexCall(
           half_duplex_request_iterator(), 'not a real RpcContext!')
-      for check in itertools.izip_longest(expected_responses, responses):
+      for check in moves.zip_longest(expected_responses, responses):
         expected_response, response = check
         self.assertEqual(expected_response, response)
 
   def testHalfDuplexCallWedged(self):
     import protoc_plugin_test_pb2 as test_pb2  # pylint: disable=g-import-not-at-top
-    reload(test_pb2)
+    moves.reload_module(test_pb2)
     condition = threading.Condition()
     wait_cell = [False]
     @contextlib.contextmanager
diff --git a/src/python/grpcio/tests/unit/_adapter/_intermediary_low_test.py b/src/python/grpcio/tests/unit/_adapter/_intermediary_low_test.py
index a6fd823..22d4b01 100644
--- a/src/python/grpcio/tests/unit/_adapter/_intermediary_low_test.py
+++ b/src/python/grpcio/tests/unit/_adapter/_intermediary_low_test.py
@@ -29,11 +29,13 @@
 
 """Tests for the old '_low'."""
 
-import Queue
 import threading
 import time
 import unittest
 
+import six
+from six.moves import queue
+
 from grpc._adapter import _intermediary_low as _low
 
 _STREAM_LENGTH = 300
@@ -67,7 +69,7 @@
     second_event = completion_queue.get(after_deadline)
     self.assertIsNotNone(second_event)
     kinds = [event.kind for event in (first_event, second_event)]
-    self.assertItemsEqual(
+    six.assertCountEqual(self,
         (_low.Event.Kind.METADATA_ACCEPTED, _low.Event.Kind.FINISH),
         kinds)
 
@@ -99,7 +101,7 @@
     self.server = _low.Server(self.server_completion_queue)
     port = self.server.add_http2_addr('[::]:0')
     self.server.start()
-    self.server_events = Queue.Queue()
+    self.server_events = queue.Queue()
     self.server_completion_queue_thread = threading.Thread(
         target=_drive_completion_queue,
         args=(self.server_completion_queue, self.server_events))
@@ -107,7 +109,7 @@
 
     self.client_completion_queue = _low.CompletionQueue()
     self.channel = _low.Channel('%s:%d' % (self.host, port), None)
-    self.client_events = Queue.Queue()
+    self.client_events = queue.Queue()
     self.client_completion_queue_thread = threading.Thread(
         target=_drive_completion_queue,
         args=(self.client_completion_queue, self.client_events))
@@ -315,7 +317,7 @@
     self.server = _low.Server(self.server_completion_queue)
     port = self.server.add_http2_addr('[::]:0')
     self.server.start()
-    self.server_events = Queue.Queue()
+    self.server_events = queue.Queue()
     self.server_completion_queue_thread = threading.Thread(
         target=_drive_completion_queue,
         args=(self.server_completion_queue, self.server_events))
@@ -323,7 +325,7 @@
 
     self.client_completion_queue = _low.CompletionQueue()
     self.channel = _low.Channel('%s:%d' % (self.host, port), None)
-    self.client_events = Queue.Queue()
+    self.client_events = queue.Queue()
     self.client_completion_queue_thread = threading.Thread(
         target=_drive_completion_queue,
         args=(self.client_completion_queue, self.client_events))
diff --git a/src/python/grpcio/tests/unit/_adapter/_proto_scenarios.py b/src/python/grpcio/tests/unit/_adapter/_proto_scenarios.py
index c9f3663..7a90eac 100644
--- a/src/python/grpcio/tests/unit/_adapter/_proto_scenarios.py
+++ b/src/python/grpcio/tests/unit/_adapter/_proto_scenarios.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/_core_over_links_base_interface_test.py b/src/python/grpcio/tests/unit/_core_over_links_base_interface_test.py
index 8816337..2b8981c 100644
--- a/src/python/grpcio/tests/unit/_core_over_links_base_interface_test.py
+++ b/src/python/grpcio/tests/unit/_core_over_links_base_interface_test.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/_crust_over_core_over_links_face_interface_test.py b/src/python/grpcio/tests/unit/_crust_over_core_over_links_face_interface_test.py
index 3be3b05..50b9a5a 100644
--- a/src/python/grpcio/tests/unit/_crust_over_core_over_links_face_interface_test.py
+++ b/src/python/grpcio/tests/unit/_crust_over_core_over_links_face_interface_test.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/_links/_proto_scenarios.py b/src/python/grpcio/tests/unit/_links/_proto_scenarios.py
index acd4891..5066108 100644
--- a/src/python/grpcio/tests/unit/_links/_proto_scenarios.py
+++ b/src/python/grpcio/tests/unit/_links/_proto_scenarios.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/beta/_beta_features_test.py b/src/python/grpcio/tests/unit/beta/_beta_features_test.py
index ebdedcc..bb2893a 100644
--- a/src/python/grpcio/tests/unit/beta/_beta_features_test.py
+++ b/src/python/grpcio/tests/unit/beta/_beta_features_test.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -183,7 +183,7 @@
     port = self._server.add_secure_port('[::]:0', server_credentials)
     self._server.start()
     self._channel_credentials = implementations.ssl_channel_credentials(
-        resources.test_root_certificates(), None, None)
+        resources.test_root_certificates())
     self._call_credentials = implementations.metadata_call_credentials(
         _metadata_plugin)
     channel = test_utilities.not_really_secure_channel(
@@ -296,7 +296,7 @@
     self._server_credentials = implementations.ssl_server_credentials(
         [(resources.private_key(), resources.certificate_chain(),),])
     self._channel_credentials = implementations.ssl_channel_credentials(
-        resources.test_root_certificates(), None, None)
+        resources.test_root_certificates())
     self._stub_options = implementations.stub_options(
         thread_pool_size=test_constants.POOL_SIZE)
 
diff --git a/src/python/grpcio/tests/unit/beta/_face_interface_test.py b/src/python/grpcio/tests/unit/beta/_face_interface_test.py
index cb302bb..3a67516 100644
--- a/src/python/grpcio/tests/unit/beta/_face_interface_test.py
+++ b/src/python/grpcio/tests/unit/beta/_face_interface_test.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -94,7 +94,7 @@
     port = server.add_secure_port('[::]:0', server_credentials)
     server.start()
     channel_credentials = implementations.ssl_channel_credentials(
-        resources.test_root_certificates(), None, None)
+        resources.test_root_certificates())
     channel = test_utilities.not_really_secure_channel(
         'localhost', port, channel_credentials, _SERVER_HOST_OVERRIDE)
     stub_options = implementations.stub_options(
diff --git a/src/python/grpcio/tests/unit/beta/_implementations_test.py b/src/python/grpcio/tests/unit/beta/_implementations_test.py
index 6b32305..26be670 100644
--- a/src/python/grpcio/tests/unit/beta/_implementations_test.py
+++ b/src/python/grpcio/tests/unit/beta/_implementations_test.py
@@ -38,14 +38,13 @@
 class ChannelCredentialsTest(unittest.TestCase):
 
   def test_runtime_provided_root_certificates(self):
-    channel_credentials = implementations.ssl_channel_credentials(
-        None, None, None)
+    channel_credentials = implementations.ssl_channel_credentials()
     self.assertIsInstance(
         channel_credentials, implementations.ChannelCredentials)
   
   def test_application_provided_root_certificates(self):
     channel_credentials = implementations.ssl_channel_credentials(
-        resources.test_root_certificates(), None, None)
+        resources.test_root_certificates())
     self.assertIsInstance(
         channel_credentials, implementations.ChannelCredentials)
 
diff --git a/src/python/grpcio/tests/unit/framework/_crust_over_core_face_interface_test.py b/src/python/grpcio/tests/unit/framework/_crust_over_core_face_interface_test.py
index fd2d429..43457be 100644
--- a/src/python/grpcio/tests/unit/framework/_crust_over_core_face_interface_test.py
+++ b/src/python/grpcio/tests/unit/framework/_crust_over_core_face_interface_test.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/common/test_constants.py b/src/python/grpcio/tests/unit/framework/common/test_constants.py
index 9f1fb84..8d89101 100644
--- a/src/python/grpcio/tests/unit/framework/common/test_constants.py
+++ b/src/python/grpcio/tests/unit/framework/common/test_constants.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/common/test_control.py b/src/python/grpcio/tests/unit/framework/common/test_control.py
index 0387668..ca5ba3a 100644
--- a/src/python/grpcio/tests/unit/framework/common/test_control.py
+++ b/src/python/grpcio/tests/unit/framework/common/test_control.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/common/test_coverage.py b/src/python/grpcio/tests/unit/framework/common/test_coverage.py
index 184621f..ea2d281 100644
--- a/src/python/grpcio/tests/unit/framework/common/test_coverage.py
+++ b/src/python/grpcio/tests/unit/framework/common/test_coverage.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/base_util.py b/src/python/grpcio/tests/unit/framework/face/testing/base_util.py
index 60ab5bc..59652b3 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/base_util.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/base_util.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py
index b0b00bf..2ebe1a3 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/control.py b/src/python/grpcio/tests/unit/framework/face/testing/control.py
index 0d40331..8425aff 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/control.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/control.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/coverage.py b/src/python/grpcio/tests/unit/framework/face/testing/coverage.py
index 9f53810..3c88b78 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/coverage.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/coverage.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/digest.py b/src/python/grpcio/tests/unit/framework/face/testing/digest.py
index 100067c..2b45ade 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/digest.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/digest.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
index db901cf..98b61e4 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
index d8706aa..cae791a 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py b/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py
index 87be836..8a25f89 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/service.py b/src/python/grpcio/tests/unit/framework/face/testing/service.py
index dc0f204..3e4228c 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/service.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/service.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/test_case.py
index 5be9330..f29d400 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/test_case.py
+++ b/src/python/grpcio/tests/unit/framework/face/testing/test_case.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/foundation/_logging_pool_test.py b/src/python/grpcio/tests/unit/framework/foundation/_logging_pool_test.py
index 0521e1c..330e445 100644
--- a/src/python/grpcio/tests/unit/framework/foundation/_logging_pool_test.py
+++ b/src/python/grpcio/tests/unit/framework/foundation/_logging_pool_test.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/base/_control.py b/src/python/grpcio/tests/unit/framework/interfaces/base/_control.py
index fe69e63..0eb38ab 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/base/_control.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/base/_control.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,8 @@
 
 """Part of the tests of the base interface of RPC Framework."""
 
+from __future__ import division
+
 import abc
 import collections
 import enum
@@ -47,8 +49,8 @@
 _GROUP = 'base test cases test group'
 _METHOD = 'base test cases test method'
 
-_PAYLOAD_RANDOM_SECTION_MAXIMUM_SIZE = test_constants.PAYLOAD_SIZE / 20
-_MINIMUM_PAYLOAD_SIZE = test_constants.PAYLOAD_SIZE / 600
+_PAYLOAD_RANDOM_SECTION_MAXIMUM_SIZE = test_constants.PAYLOAD_SIZE // 20
+_MINIMUM_PAYLOAD_SIZE = test_constants.PAYLOAD_SIZE // 600
 
 
 def _create_payload(randomness):
@@ -59,7 +61,7 @@
   random_section = bytes(
       bytearray(
           randomness.getrandbits(8) for _ in range(random_section_length)))
-  sevens_section = '\x07' * (length - random_section_length)
+  sevens_section = b'\x07' * (length - random_section_length)
   return b''.join(randomness.sample((random_section, sevens_section), 2))
 
 
@@ -385,13 +387,13 @@
     return request + request
 
   def deserialize_request(self, serialized_request):
-    return serialized_request[:len(serialized_request) / 2]
+    return serialized_request[:len(serialized_request) // 2]
 
   def serialize_response(self, response):
     return response * 3
 
   def deserialize_response(self, serialized_response):
-    return serialized_response[2 * len(serialized_response) / 3:]
+    return serialized_response[2 * len(serialized_response) // 3:]
 
   def invocation(self):
     with self._condition:
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/base/test_interfaces.py b/src/python/grpcio/tests/unit/framework/interfaces/base/test_interfaces.py
index 0594cfe..5eba475 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/base/test_interfaces.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/base/test_interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py
index 530ba4f..6498924 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,8 @@
 
 """Test code for the Face layer of RPC Framework."""
 
+from __future__ import division
+
 import abc
 import itertools
 import unittest
@@ -182,7 +184,7 @@
 
         some_completed_response_futures_iterator = itertools.islice(
             futures.as_completed(response_futures_to_indices),
-            test_constants.PARALLELISM / 2)
+            test_constants.PARALLELISM // 2)
         for response_future in some_completed_response_futures_iterator:
           index = response_futures_to_indices[response_future]
           test_messages.verify(requests[index], response_future.result(), self)
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_digest.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_digest.py
index 40c03f9..f0befb0 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/_digest.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_digest.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py
index 89f344c..c3813d5 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,8 @@
 
 """Test code for the Face layer of RPC Framework."""
 
+from __future__ import division
+
 import abc
 import contextlib
 import itertools
@@ -277,7 +279,7 @@
 
         some_completed_response_futures_iterator = itertools.islice(
             futures.as_completed(response_futures_to_indices),
-            test_constants.PARALLELISM / 2)
+            test_constants.PARALLELISM // 2)
         for response_future in some_completed_response_futures_iterator:
           index = response_futures_to_indices[response_future]
           test_messages.verify(requests[index], response_future.result(), self)
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_invocation.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_invocation.py
index ff38dc2..ac487be 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/_invocation.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_invocation.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_receiver.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_receiver.py
index 42a7f4e..48f31fc 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/_receiver.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_receiver.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_service.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_service.py
index bec8d51..f13dff0 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/_service.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_service.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/test_cases.py b/src/python/grpcio/tests/unit/framework/interfaces/face/test_cases.py
index 06b9d77..71de9d8 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/test_cases.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/test_cases.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/test_interfaces.py b/src/python/grpcio/tests/unit/framework/interfaces/face/test_interfaces.py
index a5e28b7..40f38e6 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/face/test_interfaces.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/face/test_interfaces.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/framework/interfaces/links/test_cases.py b/src/python/grpcio/tests/unit/framework/interfaces/links/test_cases.py
index 2283e79..608e641 100644
--- a/src/python/grpcio/tests/unit/framework/interfaces/links/test_cases.py
+++ b/src/python/grpcio/tests/unit/framework/interfaces/links/test_cases.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/test_common.py b/src/python/grpcio/tests/unit/test_common.py
index 824f1cb..7b4d20d 100644
--- a/src/python/grpcio/tests/unit/test_common.py
+++ b/src/python/grpcio/tests/unit/test_common.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio_health_checking/grpc/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py
index 13aac79..7086519 100644
--- a/src/python/grpcio_health_checking/grpc/health/v1/__init__.py
+++ b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio_health_checking/grpc/health/v1/health.proto b/src/python/grpcio_health_checking/grpc/health/v1/health.proto
index de10719..b0bac54 100644
--- a/src/python/grpcio_health_checking/grpc/health/v1/health.proto
+++ b/src/python/grpcio_health_checking/grpc/health/v1/health.proto
@@ -1,4 +1,4 @@
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio_health_checking/grpc/health/v1/health.py b/src/python/grpcio_health_checking/grpc/health/v1/health.py
index 60cbd644..4b5af15 100644
--- a/src/python/grpcio_health_checking/grpc/health/v1/health.py
+++ b/src/python/grpcio_health_checking/grpc/health/v1/health.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/bin/grpc_ruby_interop_client b/src/ruby/bin/grpc_ruby_interop_client
deleted file mode 100755
index e79fd33..0000000
--- a/src/ruby/bin/grpc_ruby_interop_client
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env ruby
-
-# 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.
-
-# Provides a gem binary entry point for the interop client.
-require 'test/client'
diff --git a/src/ruby/bin/grpc_ruby_interop_server b/src/ruby/bin/grpc_ruby_interop_server
deleted file mode 100755
index 656a5f7..0000000
--- a/src/ruby/bin/grpc_ruby_interop_server
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env ruby
-
-# 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.
-
-# Provides a gem binary entry point for the interop server
-require 'test/server'
diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb
deleted file mode 100755
index 239083f..0000000
--- a/src/ruby/bin/interop/interop_client.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env ruby
-
-# 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.
-
-# #######################################################################
-# DEPRECATED: The behaviour in this file has been moved to pb/test/client.rb
-#
-# This file remains to support existing tools and scripts that use it.
-# ######################################################################
-#
-# interop_client is a testing tool that accesses a gRPC interop testing
-# server and runs a test on it.
-#
-# Helps validate interoperation b/w different gRPC implementations.
-#
-# Usage: $ path/to/interop_client.rb --server_host=<hostname> \
-#                                    --server_port=<port> \
-#                                    --test_case=<testcase_name>
-
-this_dir = File.expand_path(File.dirname(__FILE__))
-pb_dir = File.join(File.dirname(File.dirname(this_dir)), 'pb')
-$LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
-
-require 'test/client'
diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb
deleted file mode 100755
index c6b0d00..0000000
--- a/src/ruby/bin/interop/interop_server.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env ruby
-
-# 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.
-
-# #######################################################################
-# DEPRECATED: The behaviour in this file has been moved to pb/test/server.rb
-#
-# This file remains to support existing tools and scripts that use it.
-# ######################################################################
-#
-# interop_server is a Testing app that runs a gRPC interop testing server.
-#
-# It helps validate interoperation b/w gRPC in different environments
-#
-# Helps validate interoperation b/w different gRPC implementations.
-#
-# Usage: $ path/to/interop_server.rb --port
-
-this_dir = File.expand_path(File.dirname(__FILE__))
-pb_dir = File.join(File.dirname(File.dirname(this_dir)), 'pb')
-$LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
-
-require 'test/server'
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index 6b7001a..82b6d31 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_byte_buffer.c b/src/ruby/ext/grpc/rb_byte_buffer.c
index db7cac3..cba910d 100644
--- a/src/ruby/ext/grpc/rb_byte_buffer.c
+++ b/src/ruby/ext/grpc/rb_byte_buffer.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,21 +50,18 @@
 }
 
 VALUE grpc_rb_byte_buffer_to_s(grpc_byte_buffer *buffer) {
-  size_t length = 0;
-  char *string = NULL;
-  size_t offset = 0;
+  VALUE rb_string;
   grpc_byte_buffer_reader reader;
   gpr_slice next;
   if (buffer == NULL) {
     return Qnil;
-
   }
-  length = grpc_byte_buffer_length(buffer);
-  string = xmalloc(length + 1);
+  rb_string = rb_str_buf_new(grpc_byte_buffer_length(buffer));
   grpc_byte_buffer_reader_init(&reader, buffer);
   while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
-    memcpy(string + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
-    offset += GPR_SLICE_LENGTH(next);
+    rb_str_cat(rb_string, (const char *) GPR_SLICE_START_PTR(next),
+               GPR_SLICE_LENGTH(next));
+    gpr_slice_unref(next);
   }
-  return rb_str_new(string, length);
+  return rb_string;
 }
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index cd0aa6a..f5fdbb2 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -359,7 +359,7 @@
       md_ary->metadata[md_ary->count].value_length = value_len;
       md_ary->count += 1;
     }
-  } else {
+  } else if (TYPE(val) == T_STRING) {
     value_str = RSTRING_PTR(val);
     value_len = RSTRING_LEN(val);
     if (!grpc_is_binary_header(key_str, key_len) &&
@@ -373,6 +373,10 @@
     md_ary->metadata[md_ary->count].value = value_str;
     md_ary->metadata[md_ary->count].value_length = value_len;
     md_ary->count += 1;
+  } else {
+    rb_raise(rb_eArgError,
+               "Header values must be of type string or array");
+    return ST_STOP;
   }
 
   return ST_CONTINUE;
@@ -551,13 +555,26 @@
 /* grpc_run_batch_stack_cleanup ensures the run_batch_stack is properly
  * cleaned up */
 static void grpc_run_batch_stack_cleanup(run_batch_stack *st) {
+  size_t i = 0;
+
   grpc_metadata_array_destroy(&st->send_metadata);
   grpc_metadata_array_destroy(&st->send_trailing_metadata);
   grpc_metadata_array_destroy(&st->recv_metadata);
   grpc_metadata_array_destroy(&st->recv_trailing_metadata);
+
   if (st->recv_status_details != NULL) {
     gpr_free(st->recv_status_details);
   }
+
+  if (st->recv_message != NULL) {
+    grpc_byte_buffer_destroy(st->recv_message);
+  }
+
+  for (i = 0; i < st->op_num; i++) {
+    if (st->ops[i].op == GRPC_OP_SEND_MESSAGE) {
+      grpc_byte_buffer_destroy(st->ops[i].data.send_message);
+    }
+  }
 }
 
 /* grpc_run_batch_stack_fill_ops fills the run_batch_stack ops array from
@@ -643,7 +660,6 @@
         break;
       case GRPC_OP_SEND_MESSAGE:
         rb_struct_aset(result, sym_send_message, Qtrue);
-        grpc_byte_buffer_destroy(st->ops[i].data.send_message);
         break;
       case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
         rb_struct_aset(result, sym_send_close, Qtrue);
diff --git a/src/ruby/ext/grpc/rb_call_credentials.c b/src/ruby/ext/grpc/rb_call_credentials.c
index 2b978fc..38bf1f7 100644
--- a/src/ruby/ext/grpc/rb_call_credentials.c
+++ b/src/ruby/ext/grpc/rb_call_credentials.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index e1aaa53..984afad 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_channel_args.c b/src/ruby/ext/grpc/rb_channel_args.c
index 69827ce..2ffb8f4 100644
--- a/src/ruby/ext/grpc/rb_channel_args.c
+++ b/src/ruby/ext/grpc/rb_channel_args.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c
index f649084..10391bc 100644
--- a/src/ruby/ext/grpc/rb_channel_credentials.c
+++ b/src/ruby/ext/grpc/rb_channel_credentials.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c
index 1eb5a28..2a2eee1 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.c
+++ b/src/ruby/ext/grpc/rb_completion_queue.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index 0f9b18f..acb47b0 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 56db4ec..e2068d7 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -152,6 +152,7 @@
 grpc_secure_channel_create_type grpc_secure_channel_create_import;
 grpc_server_credentials_release_type grpc_server_credentials_release_import;
 grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import;
+grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import;
 grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import;
 grpc_call_set_credentials_type grpc_call_set_credentials_import;
 grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import;
@@ -174,6 +175,8 @@
 grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import;
 gpr_log_type gpr_log_import;
 gpr_log_message_type gpr_log_message_import;
+gpr_set_log_verbosity_type gpr_set_log_verbosity_import;
+gpr_log_verbosity_init_type gpr_log_verbosity_init_import;
 gpr_set_log_function_type gpr_set_log_function_import;
 gpr_slice_ref_type gpr_slice_ref_import;
 gpr_slice_unref_type gpr_slice_unref_import;
@@ -414,6 +417,7 @@
   grpc_secure_channel_create_import = (grpc_secure_channel_create_type) GetProcAddress(library, "grpc_secure_channel_create");
   grpc_server_credentials_release_import = (grpc_server_credentials_release_type) GetProcAddress(library, "grpc_server_credentials_release");
   grpc_ssl_server_credentials_create_import = (grpc_ssl_server_credentials_create_type) GetProcAddress(library, "grpc_ssl_server_credentials_create");
+  grpc_ssl_server_credentials_create_ex_import = (grpc_ssl_server_credentials_create_ex_type) GetProcAddress(library, "grpc_ssl_server_credentials_create_ex");
   grpc_server_add_secure_http2_port_import = (grpc_server_add_secure_http2_port_type) GetProcAddress(library, "grpc_server_add_secure_http2_port");
   grpc_call_set_credentials_import = (grpc_call_set_credentials_type) GetProcAddress(library, "grpc_call_set_credentials");
   grpc_server_credentials_set_auth_metadata_processor_import = (grpc_server_credentials_set_auth_metadata_processor_type) GetProcAddress(library, "grpc_server_credentials_set_auth_metadata_processor");
@@ -436,6 +440,8 @@
   grpc_raw_byte_buffer_from_reader_import = (grpc_raw_byte_buffer_from_reader_type) GetProcAddress(library, "grpc_raw_byte_buffer_from_reader");
   gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log");
   gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message");
+  gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity");
+  gpr_log_verbosity_init_import = (gpr_log_verbosity_init_type) GetProcAddress(library, "gpr_log_verbosity_init");
   gpr_set_log_function_import = (gpr_set_log_function_type) GetProcAddress(library, "gpr_set_log_function");
   gpr_slice_ref_import = (gpr_slice_ref_type) GetProcAddress(library, "gpr_slice_ref");
   gpr_slice_unref_import = (gpr_slice_unref_type) GetProcAddress(library, "gpr_slice_unref");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 3bf81af..c8d2133 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -283,7 +283,7 @@
 typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
 extern grpc_server_request_call_type grpc_server_request_call_import;
 #define grpc_server_request_call grpc_server_request_call_import
-typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host);
+typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags);
 extern grpc_server_register_method_type grpc_server_register_method_import;
 #define grpc_server_register_method grpc_server_register_method_import
 typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
@@ -406,6 +406,9 @@
 typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_type)(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);
 extern grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import;
 #define grpc_ssl_server_credentials_create grpc_ssl_server_credentials_create_import
+typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_ex_type)(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);
+extern grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import;
+#define grpc_ssl_server_credentials_create_ex grpc_ssl_server_credentials_create_ex_import
 typedef int(*grpc_server_add_secure_http2_port_type)(grpc_server *server, const char *addr, grpc_server_credentials *creds);
 extern grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import;
 #define grpc_server_add_secure_http2_port grpc_server_add_secure_http2_port_import
@@ -472,6 +475,12 @@
 typedef void(*gpr_log_message_type)(const char *file, int line, gpr_log_severity severity, const char *message);
 extern gpr_log_message_type gpr_log_message_import;
 #define gpr_log_message gpr_log_message_import
+typedef void(*gpr_set_log_verbosity_type)(gpr_log_severity min_severity_to_print);
+extern gpr_set_log_verbosity_type gpr_set_log_verbosity_import;
+#define gpr_set_log_verbosity gpr_set_log_verbosity_import
+typedef void(*gpr_log_verbosity_init_type)();
+extern gpr_log_verbosity_init_type gpr_log_verbosity_init_import;
+#define gpr_log_verbosity_init gpr_log_verbosity_init_import
 typedef void(*gpr_set_log_function_type)(gpr_log_func func);
 extern gpr_set_log_function_type gpr_set_log_function_import;
 #define gpr_set_log_function gpr_set_log_function_import
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index 37cc55a..96e60c6 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c
index 4ea59b6..b2d7280 100644
--- a/src/ruby/ext/grpc/rb_server_credentials.c
+++ b/src/ruby/ext/grpc/rb_server_credentials.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -90,9 +90,12 @@
 
 static const rb_data_type_t grpc_rb_server_credentials_data_type = {
     "grpc_server_credentials",
-    {grpc_rb_server_credentials_mark, grpc_rb_server_credentials_free,
-     GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
-    NULL, NULL,
+    {grpc_rb_server_credentials_mark,
+     grpc_rb_server_credentials_free,
+     GRPC_RB_MEMSIZE_UNAVAILABLE,
+     {NULL, NULL}},
+    NULL,
+    NULL,
 #ifdef RUBY_TYPED_FREE_IMMEDIATELY
     RUBY_TYPED_FREE_IMMEDIATELY
 #endif
@@ -219,7 +222,9 @@
     }
   }
 
-  auth_client = TYPE(force_client_auth) == T_TRUE;
+  auth_client = TYPE(force_client_auth) == T_TRUE
+                    ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+                    : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
   key_cert_pairs = ALLOC_N(grpc_ssl_pem_key_cert_pair, num_key_certs);
   for (i = 0; i < num_key_certs; i++) {
     key_cert = rb_ary_entry(pem_key_certs, i);
@@ -233,13 +238,12 @@
                        &grpc_rb_server_credentials_data_type, wrapper);
 
   if (pem_root_certs == Qnil) {
-    creds = grpc_ssl_server_credentials_create(NULL, key_cert_pairs,
-                                               num_key_certs,
-                                               auth_client, NULL);
+    creds = grpc_ssl_server_credentials_create_ex(
+        NULL, key_cert_pairs, num_key_certs, auth_client, NULL);
   } else {
-    creds = grpc_ssl_server_credentials_create(RSTRING_PTR(pem_root_certs),
-                                               key_cert_pairs, num_key_certs,
-                                               auth_client, NULL);
+    creds = grpc_ssl_server_credentials_create_ex(RSTRING_PTR(pem_root_certs),
+                                                  key_cert_pairs, num_key_certs,
+                                                  auth_client, NULL);
   }
   xfree(key_cert_pairs);
   if (creds == NULL) {
diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb
index 1671ba3..a56c49f 100644
--- a/src/ruby/lib/grpc.rb
+++ b/src/ruby/lib/grpc.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -32,13 +32,13 @@
   ENV['GRPC_DEFAULT_SSL_ROOTS_FILE_PATH'] = ssl_roots_path
 end
 
-require 'grpc/errors'
-require 'grpc/grpc'
-require 'grpc/logconfig'
-require 'grpc/notifier'
-require 'grpc/version'
-require 'grpc/core/time_consts'
-require 'grpc/generic/active_call'
-require 'grpc/generic/client_stub'
-require 'grpc/generic/service'
-require 'grpc/generic/rpc_server'
+require_relative 'grpc/errors'
+require_relative 'grpc/grpc'
+require_relative 'grpc/logconfig'
+require_relative 'grpc/notifier'
+require_relative 'grpc/version'
+require_relative 'grpc/core/time_consts'
+require_relative 'grpc/generic/active_call'
+require_relative 'grpc/generic/client_stub'
+require_relative 'grpc/generic/service'
+require_relative 'grpc/generic/rpc_server'
diff --git a/src/ruby/lib/grpc/core/time_consts.rb b/src/ruby/lib/grpc/core/time_consts.rb
index c8eae78..5be7ed2 100644
--- a/src/ruby/lib/grpc/core/time_consts.rb
+++ b/src/ruby/lib/grpc/core/time_consts.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -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.
 
-require 'grpc/grpc'
+require_relative '../grpc'
 
 # GRPC contains the General RPC module.
 module GRPC
diff --git a/src/ruby/lib/grpc/errors.rb b/src/ruby/lib/grpc/errors.rb
index 2227ee1..a1dd1e3 100644
--- a/src/ruby/lib/grpc/errors.rb
+++ b/src/ruby/lib/grpc/errors.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -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.
 
-require 'grpc/grpc'
+require_relative './grpc'
 
 # GRPC contains the General RPC module.
 module GRPC
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index e80d24e..24cab95 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -28,7 +28,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 require 'forwardable'
-require 'grpc/generic/bidi_call'
+require_relative 'bidi_call'
 
 class Struct
   # BatchResult is the struct returned by calls to call#start_batch.
diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb
index 213176b..1f6d5f3 100644
--- a/src/ruby/lib/grpc/generic/bidi_call.rb
+++ b/src/ruby/lib/grpc/generic/bidi_call.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 require 'forwardable'
-require 'grpc/grpc'
+require_relative '../grpc'
 
 # GRPC contains the General RPC module.
 module GRPC
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index 4da9ff0..68e167a 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -27,8 +27,8 @@
 # (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 'grpc/generic/active_call'
-require 'grpc/version'
+require_relative 'active_call'
+require_relative '../version'
 
 # GRPC contains the General RPC module.
 module GRPC
@@ -85,7 +85,8 @@
     # when present, this is the default timeout used for calls
     #
     # @param host [String] the host the stub connects to
-    # @param q [Core::CompletionQueue] used to wait for events
+    # @param q [Core::CompletionQueue] used to wait for events - now deprecated
+    #        since each new active call gets its own separately
     # @param creds [Core::ChannelCredentials|Symbol] the channel credentials, or
     #     :this_channel_is_insecure
     # @param channel_override [Core::Channel] a pre-created channel
@@ -97,7 +98,6 @@
                    propagate_mask: nil,
                    **kw)
       fail(TypeError, '!CompletionQueue') unless q.is_a?(Core::CompletionQueue)
-      @queue = q
       @ch = ClientStub.setup_channel(channel_override, host, creds, **kw)
       alt_host = kw[Core::Channel::SSL_TARGET]
       @host = alt_host.nil? ? host : alt_host
@@ -458,14 +458,17 @@
       if deadline.nil?
         deadline = from_relative_time(timeout.nil? ? @timeout : timeout)
       end
-      call = @ch.create_call(@queue,
+      # Provide each new client call with its own completion queue
+      call_queue = Core::CompletionQueue.new
+      call = @ch.create_call(call_queue,
                              parent, # parent call
                              @propagate_mask, # propagation options
                              method,
                              nil, # host use nil,
                              deadline)
       call.set_credentials! credentials unless credentials.nil?
-      ActiveCall.new(call, @queue, marshal, unmarshal, deadline, started: false)
+      ActiveCall.new(call, call_queue, marshal, unmarshal, deadline,
+                     started: false)
     end
   end
 end
diff --git a/src/ruby/lib/grpc/generic/rpc_desc.rb b/src/ruby/lib/grpc/generic/rpc_desc.rb
index 526b2ba..cc21ffd 100644
--- a/src/ruby/lib/grpc/generic/rpc_desc.rb
+++ b/src/ruby/lib/grpc/generic/rpc_desc.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -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.
 
-require 'grpc/grpc'
+require_relative '../grpc'
 
 # GRPC contains the General RPC module.
 module GRPC
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index b30d19d..7f3a38a 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -27,9 +27,9 @@
 # (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 'grpc/grpc'
-require 'grpc/generic/active_call'
-require 'grpc/generic/service'
+require_relative '../grpc'
+require_relative 'active_call'
+require_relative 'service'
 require 'thread'
 
 # A global that contains signals the gRPC servers should respond to.
@@ -332,10 +332,15 @@
     # the current thread to terminate it.
     def run_till_terminated
       GRPC.trap_signals
-      t = Thread.new { run }
+      stopped = false
+      t = Thread.new do
+        run
+        stopped = true
+      end
       wait_till_running
       loop do
         sleep SIGNAL_CHECK_PERIOD
+        break if stopped
         break unless GRPC.handle_signals
       end
       stop
@@ -403,7 +408,7 @@
       loop_handle_server_calls
     end
 
-    # Sends UNAVAILABLE if there are too many unprocessed jobs
+    # Sends RESOURCE_EXHAUSTED if there are too many unprocessed jobs
     def available?(an_rpc)
       jobs_count, max = @pool.jobs_waiting, @max_waiting_requests
       GRPC.logger.info("waiting: #{jobs_count}, max: #{max}")
@@ -411,7 +416,7 @@
       GRPC.logger.warn("NOT AVAILABLE: too many jobs_waiting: #{an_rpc}")
       noop = proc { |x| x }
       c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline)
-      c.send_status(StatusCodes::UNAVAILABLE, '')
+      c.send_status(StatusCodes::RESOURCE_EXHAUSTED, '')
       nil
     end
 
@@ -434,7 +439,6 @@
         begin
           an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE)
           break if (!an_rpc.nil?) && an_rpc.call.nil?
-
           active_call = new_active_server_call(an_rpc)
           unless active_call.nil?
             @pool.schedule(active_call) do |ac|
diff --git a/src/ruby/lib/grpc/generic/service.rb b/src/ruby/lib/grpc/generic/service.rb
index 410e1ad..8e940b5 100644
--- a/src/ruby/lib/grpc/generic/service.rb
+++ b/src/ruby/lib/grpc/generic/service.rb
@@ -27,8 +27,8 @@
 # (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 'grpc/generic/client_stub'
-require 'grpc/generic/rpc_desc'
+require_relative 'client_stub'
+require_relative 'rpc_desc'
 
 # GRPC contains the General RPC module.
 module GRPC
diff --git a/src/ruby/lib/grpc/grpc.rb b/src/ruby/lib/grpc/grpc.rb
index d8a4947..b60a828 100644
--- a/src/ruby/lib/grpc/grpc.rb
+++ b/src/ruby/lib/grpc/grpc.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 begin
-  require "grpc/#{RUBY_VERSION.sub(/\.\d$/, '')}/grpc_c"
+  require_relative "#{RUBY_VERSION.sub(/\.\d$/, '')}/grpc_c"
 rescue LoadError
-  require 'grpc/grpc_c'
+  require_relative 'grpc_c'
 end
diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb
index ef08761..67c6a5d 100644
--- a/src/ruby/lib/grpc/version.rb
+++ b/src/ruby/lib/grpc/version.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/pb/generate_proto_ruby.sh b/src/ruby/pb/generate_proto_ruby.sh
index 86c0820..82dad18 100755
--- a/src/ruby/pb/generate_proto_ruby.sh
+++ b/src/ruby/pb/generate_proto_ruby.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -40,11 +40,18 @@
     --ruby_out=src/ruby/pb \
     --plugin=$PLUGIN
 
-$PROTOC -I . test/proto/{messages,test,empty}.proto \
+$PROTOC -I . \
+    src/proto/grpc/testing/{messages,test,empty}.proto \
     --grpc_out=src/ruby/pb \
     --ruby_out=src/ruby/pb \
     --plugin=$PLUGIN
 
+$PROTOC -I . \
+    src/proto/grpc/testing/{messages,payloads,stats,services,control}.proto \
+    --grpc_out=src/ruby/qps \
+    --ruby_out=src/ruby/qps \
+    --plugin=$PLUGIN
+
 $PROTOC -I src/proto/math src/proto/math/math.proto \
     --grpc_out=src/ruby/bin \
     --ruby_out=src/ruby/bin \
diff --git a/src/ruby/pb/grpc/health/checker.rb b/src/ruby/pb/grpc/health/checker.rb
index 9f1ee65..f7310d9 100644
--- a/src/ruby/pb/grpc/health/checker.rb
+++ b/src/ruby/pb/grpc/health/checker.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb b/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb
new file mode 100644
index 0000000..9f6e7e0
--- /dev/null
+++ b/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb
@@ -0,0 +1,28 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# Source: src/proto/grpc/testing/duplicate/echo_duplicate.proto for package 'grpc.testing.duplicate'
+
+require 'grpc'
+require 'src/proto/grpc/testing/duplicate/echo_duplicate'
+
+module Grpc
+  module Testing
+    module Duplicate
+      module EchoTestService
+
+        # TODO: add proto service documentation here
+        class Service
+
+          include GRPC::GenericService
+
+          self.marshal_class_method = :encode
+          self.unmarshal_class_method = :decode
+          self.service_name = 'grpc.testing.duplicate.EchoTestService'
+
+          rpc :Echo, Grpc::Testing::EchoRequest, Grpc::Testing::EchoResponse
+        end
+
+        Stub = Service.rpc_stub_class
+      end
+    end
+  end
+end
diff --git a/src/ruby/pb/grpc/testing/metrics.rb b/src/ruby/pb/grpc/testing/metrics.rb
new file mode 100644
index 0000000..3b3c8cd
--- /dev/null
+++ b/src/ruby/pb/grpc/testing/metrics.rb
@@ -0,0 +1,28 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: grpc/testing/metrics.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "grpc.testing.GaugeResponse" do
+    optional :name, :string, 1
+    oneof :value do
+      optional :long_value, :int64, 2
+      optional :double_value, :double, 3
+      optional :string_value, :string, 4
+    end
+  end
+  add_message "grpc.testing.GaugeRequest" do
+    optional :name, :string, 1
+  end
+  add_message "grpc.testing.EmptyMessage" do
+  end
+end
+
+module Grpc
+  module Testing
+    GaugeResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.GaugeResponse").msgclass
+    GaugeRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.GaugeRequest").msgclass
+    EmptyMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.EmptyMessage").msgclass
+  end
+end
diff --git a/src/ruby/pb/grpc/testing/metrics_services.rb b/src/ruby/pb/grpc/testing/metrics_services.rb
new file mode 100644
index 0000000..f5778bb
--- /dev/null
+++ b/src/ruby/pb/grpc/testing/metrics_services.rb
@@ -0,0 +1,27 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# Source: grpc/testing/metrics.proto for package 'grpc.testing'
+
+require 'grpc'
+require 'grpc/testing/metrics'
+
+module Grpc
+  module Testing
+    module MetricsService
+
+      # TODO: add proto service documentation here
+      class Service
+
+        include GRPC::GenericService
+
+        self.marshal_class_method = :encode
+        self.unmarshal_class_method = :decode
+        self.service_name = 'grpc.testing.MetricsService'
+
+        rpc :GetAllGauges, EmptyMessage, stream(GaugeResponse)
+        rpc :GetGauge, GaugeRequest, GaugeResponse
+      end
+
+      Stub = Service.rpc_stub_class
+    end
+  end
+end
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index 684ee80..95b059a 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -1,6 +1,6 @@
 #!/usr/bin/env ruby
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -38,23 +38,23 @@
 #                            --server_port=<port> \
 #                            --test_case=<testcase_name>
 
+# These lines are required for the generated files to load grpc
 this_dir = File.expand_path(File.dirname(__FILE__))
 lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
-pb_dir = File.dirname(File.dirname(this_dir))
+pb_dir = File.dirname(this_dir)
 $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
 $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
-$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
 
 require 'optparse'
 require 'logger'
 
-require 'grpc'
+require_relative '../../lib/grpc'
 require 'googleauth'
 require 'google/protobuf'
 
-require 'test/proto/empty'
-require 'test/proto/messages'
-require 'test/proto/test_services'
+require_relative 'proto/empty'
+require_relative 'proto/messages'
+require_relative 'proto/test_services'
 
 AUTH_ENV = Google::Auth::CredentialsLoader::ENV_VAR
 
@@ -208,12 +208,10 @@
   def empty_unary
     resp = @stub.empty_call(Empty.new)
     assert('empty_unary: invalid response') { resp.is_a?(Empty) }
-    p 'OK: empty_unary'
   end
 
   def large_unary
     perform_large_unary
-    p 'OK: large_unary'
   end
 
   def service_account_creds
@@ -230,7 +228,6 @@
     assert("#{__callee__}: bad oauth scope") do
       @args.oauth_scope.include?(resp.oauth_scope)
     end
-    p "OK: #{__callee__}"
   end
 
   def jwt_token_creds
@@ -238,7 +235,6 @@
     wanted_email = MultiJson.load(json_key)['client_email']
     resp = perform_large_unary(fill_username: true)
     assert("#{__callee__}: bad username") { wanted_email == resp.username }
-    p "OK: #{__callee__}"
   end
 
   def compute_engine_creds
@@ -247,7 +243,6 @@
     assert("#{__callee__}: bad username") do
       @args.default_service_account == resp.username
     end
-    p "OK: #{__callee__}"
   end
 
   def oauth2_auth_token
@@ -259,7 +254,6 @@
     assert("#{__callee__}: bad oauth scope") do
       @args.oauth_scope.include?(resp.oauth_scope)
     end
-    p "OK: #{__callee__}"
   end
 
   def per_rpc_creds
@@ -279,7 +273,6 @@
     assert("#{__callee__}: bad oauth scope") do
       @args.oauth_scope.include?(resp.oauth_scope)
     end
-    p "OK: #{__callee__}"
   end
 
   def client_streaming
@@ -293,7 +286,6 @@
     assert("#{__callee__}: aggregate payload size is incorrect") do
       wanted_aggregate_size == resp.aggregated_payload_size
     end
-    p "OK: #{__callee__}"
   end
 
   def server_streaming
@@ -311,7 +303,6 @@
         :COMPRESSABLE == r.payload.type
       end
     end
-    p "OK: #{__callee__}"
   end
 
   def ping_pong
@@ -319,7 +310,6 @@
     ppp = PingPongPlayer.new(msg_sizes)
     resps = @stub.full_duplex_call(ppp.each_item)
     resps.each { |r| ppp.queue.push(r) }
-    p "OK: #{__callee__}"
   end
 
   def timeout_on_sleeping_server
@@ -332,7 +322,6 @@
     assert("#{__callee__}: status was wrong") do
       e.code == GRPC::Core::StatusCodes::DEADLINE_EXCEEDED
     end
-    p "OK: #{__callee__}"
   end
 
   def empty_stream
@@ -346,7 +335,6 @@
     assert("#{__callee__}: too many responses expected 0") do
       count == 0
     end
-    p "OK: #{__callee__}"
   end
 
   def cancel_after_begin
@@ -361,7 +349,6 @@
     fail 'Should have raised GRPC:Cancelled'
   rescue GRPC::Cancelled
     assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled }
-    p "OK: #{__callee__}"
   end
 
   def cancel_after_first_response
@@ -374,7 +361,6 @@
   rescue GRPC::Cancelled
     assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled }
     op.wait
-    p "OK: #{__callee__}"
   end
 
   def all
@@ -442,7 +428,7 @@
     opts.on('--use_tls USE_TLS', ['false', 'true'],
             'require a secure connection?') do |v|
       args['secure'] = v == 'true'
-    end
+p    end
     opts.on('--use_test_ca USE_TEST_CA', ['false', 'true'],
             'if secure, use the test certificate?') do |v|
       args['use_test_ca'] = v == 'true'
@@ -464,6 +450,9 @@
   opts = parse_args
   stub = create_stub(opts)
   NamedTests.new(stub, opts).method(opts['test_case']).call
+  p "OK: #{opts['test_case']}"
 end
 
-main
+if __FILE__ == $0
+  main
+end
diff --git a/src/ruby/pb/test/server.rb b/src/ruby/pb/test/server.rb
index 851e815..914c7cc 100755
--- a/src/ruby/pb/test/server.rb
+++ b/src/ruby/pb/test/server.rb
@@ -39,7 +39,7 @@
 
 this_dir = File.expand_path(File.dirname(__FILE__))
 lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
-pb_dir = File.dirname(File.dirname(this_dir))
+pb_dir = File.dirname(this_dir)
 $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
 $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
 $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
diff --git a/src/ruby/qps/client.rb b/src/ruby/qps/client.rb
new file mode 100644
index 0000000..d04f707
--- /dev/null
+++ b/src/ruby/qps/client.rb
@@ -0,0 +1,164 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+# Worker and worker service implementation
+
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(this_dir), 'lib')
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
+
+require 'grpc'
+require 'histogram'
+require 'src/proto/grpc/testing/services_services'
+
+class Poisson
+  def interarrival
+    @lambda_recip * (-Math.log(1.0-rand))
+  end
+  def advance
+    t = @next_time
+    @next_time += interarrival
+    t
+  end
+  def initialize(lambda)
+    @lambda_recip = 1.0/lambda
+    @next_time = Time.now + interarrival
+  end
+end
+
+class BenchmarkClient
+  def initialize(config)
+    opts = {}
+    if config.security_params
+      if config.security_params.use_test_ca
+        certs = load_test_certs
+        cred = GRPC::Core::ChannelCredentials.new(certs[0])
+      else
+        cred = GRPC::Core::ChannelCredentials.new()
+      end
+      if config.security_params.server_host_override
+        opts[GRPC::Core::Channel::SSL_TARGET] =
+          config.security_params.server_host_override
+      end
+    else
+      cred = :this_channel_is_insecure
+    end
+    @histres = config.histogram_params.resolution
+    @histmax = config.histogram_params.max_possible
+    @start_time = Time.now
+    @histogram = Histogram.new(@histres, @histmax)
+    @done = false
+
+    gtsr = Grpc::Testing::SimpleRequest
+    gtpt = Grpc::Testing::PayloadType
+    gtp = Grpc::Testing::Payload
+    simple_params = config.payload_config.simple_params
+    req = gtsr.new(response_type: gtpt::COMPRESSABLE,
+                   response_size: simple_params.resp_size,
+                   payload: gtp.new(type: gtpt::COMPRESSABLE,
+                                    body: nulls(simple_params.req_size)))
+
+    (0..config.client_channels-1).each do |chan|
+      gtbss = Grpc::Testing::BenchmarkService::Stub
+      st = config.server_targets
+      stub = gtbss.new(st[chan % st.length], cred, **opts)
+      (0..config.outstanding_rpcs_per_channel-1).each do |r|
+        Thread.new {
+          case config.load_params.load.to_s
+          when 'closed_loop'
+            waiter = nil
+          when 'poisson'
+            waiter = Poisson.new(config.load_params.poisson.offered_load /
+                                 (config.client_channels *
+                                  config.outstanding_rpcs_per_channel))
+          end
+          case config.rpc_type
+          when :UNARY
+            unary_ping_ponger(req,stub,config,waiter)
+          when :STREAMING
+            streaming_ping_ponger(req,stub,config,waiter)
+          end
+        }
+      end
+    end
+  end
+  def wait_to_issue(waiter)
+    if waiter
+      delay = waiter.advance-Time.now
+      sleep delay if delay > 0
+    end
+  end
+  def unary_ping_ponger(req, stub, config,waiter)
+    while !@done
+      wait_to_issue(waiter)
+      start = Time.now
+      resp = stub.unary_call(req)
+      @histogram.add((Time.now-start)*1e9)
+    end
+  end
+  def streaming_ping_ponger(req, stub, config, waiter)
+    q = EnumeratorQueue.new(self)
+    resp = stub.streaming_call(q.each_item)
+    start = Time.now
+    q.push(req)
+    resp.each do |r|
+      @histogram.add((Time.now-start)*1e9)
+      if !@done
+        wait_to_issue(waiter)
+        start = Time.now
+        q.push(req)
+      else
+        q.push(self)
+        break
+      end
+    end
+  end
+  def mark(reset)
+    lat = Grpc::Testing::HistogramData.new(
+      bucket: @histogram.contents,
+      min_seen: @histogram.minimum,
+      max_seen: @histogram.maximum,
+      sum: @histogram.sum,
+      sum_of_squares: @histogram.sum_of_squares,
+      count: @histogram.count
+    )
+    elapsed = Time.now-@start_time
+    if reset
+      @start_time = Time.now
+      @histogram = Histogram.new(@histres, @histmax)
+    end
+    Grpc::Testing::ClientStats.new(latencies: lat, time_elapsed: elapsed)
+  end
+  def shutdown
+    @done = true
+  end
+end
diff --git a/src/ruby/qps/histogram.rb b/src/ruby/qps/histogram.rb
new file mode 100644
index 0000000..bf7a89a
--- /dev/null
+++ b/src/ruby/qps/histogram.rb
@@ -0,0 +1,88 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+# Histogram class for use in performance testing and measurement
+
+class Histogram
+  # Determine the bucket index for a given value
+  # @param {number} value The value to check
+  # @return {number} The bucket index
+  def bucket_for(value)
+    (Math.log(value)/Math.log(@multiplier)).to_i
+  end
+  # Initialize an empty histogram
+  # @param {number} resolution The resolution of the histogram
+  # @param {number} max_possible The maximum value for the histogram
+  def initialize(resolution, max_possible)
+    @resolution=resolution
+    @max_possible=max_possible
+    @sum=0
+    @sum_of_squares=0
+    @multiplier=1+resolution
+    @count=0
+    @min_seen=max_possible
+    @max_seen=0
+    @buckets=Array.new(bucket_for(max_possible)+1, 0)
+  end
+  # Add a value to the histogram. This updates all statistics with the new
+  # value. Those statistics should not be modified except with this function
+  # @param {number} value The value to add
+  def add(value)
+    @sum += value
+    @sum_of_squares += value * value
+    @count += 1
+    if value < @min_seen
+      @min_seen = value
+    end
+    if value > @max_seen
+      @max_seen = value
+    end
+    @buckets[bucket_for(value)] += 1
+  end
+  def minimum
+    @min_seen
+  end
+  def maximum
+    @max_seen
+  end
+  def sum
+    @sum
+  end
+  def sum_of_squares
+    @sum_of_squares
+  end
+  def count
+    @count
+  end
+  def contents
+    @buckets
+  end
+end
diff --git a/src/ruby/qps/qps-common.rb b/src/ruby/qps/qps-common.rb
new file mode 100644
index 0000000..4119d60
--- /dev/null
+++ b/src/ruby/qps/qps-common.rb
@@ -0,0 +1,76 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+# Worker and worker service implementation
+
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(this_dir), 'lib')
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
+
+require 'grpc'
+
+# produces a string of null chars (\0 aka pack 'x') of length l.
+def nulls(l)
+  fail 'requires #{l} to be +ve' if l < 0
+  [].pack('x' * l).force_encoding('ascii-8bit')
+end
+
+# load the test-only certificates
+def load_test_certs
+  this_dir = File.expand_path(File.dirname(__FILE__))
+  data_dir = File.join(File.dirname(this_dir), 'spec/testdata')
+  files = ['ca.pem', 'server1.key', 'server1.pem']
+  files.map { |f| File.open(File.join(data_dir, f)).read }
+end
+
+# A EnumeratorQueue wraps a Queue yielding the items added to it via each_item.
+class EnumeratorQueue
+  extend Forwardable
+  def_delegators :@q, :push
+
+  def initialize(sentinel)
+    @q = Queue.new
+    @sentinel = sentinel
+  end
+
+  def each_item
+    return enum_for(:each_item) unless block_given?
+    loop do
+      r = @q.pop
+      break if r.equal?(@sentinel)
+      fail r if r.is_a? Exception
+      yield r
+    end
+  end
+end
+
+
diff --git a/src/ruby/qps/server.rb b/src/ruby/qps/server.rb
new file mode 100644
index 0000000..f05fbbd
--- /dev/null
+++ b/src/ruby/qps/server.rb
@@ -0,0 +1,94 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+# Worker and worker service implementation
+
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(this_dir), 'lib')
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
+
+require 'grpc'
+require 'qps-common'
+require 'src/proto/grpc/testing/messages'
+require 'src/proto/grpc/testing/services_services'
+require 'src/proto/grpc/testing/stats'
+
+class BenchmarkServiceImpl < Grpc::Testing::BenchmarkService::Service
+  def unary_call(req, _call)
+    sr = Grpc::Testing::SimpleResponse
+    pl = Grpc::Testing::Payload
+    sr.new(payload: pl.new(body: nulls(req.response_size)))
+  end
+  def streaming_call(reqs)
+    q = EnumeratorQueue.new(self)
+    Thread.new {
+      sr = Grpc::Testing::SimpleResponse
+      pl = Grpc::Testing::Payload
+      reqs.each do |req|
+        q.push(sr.new(payload: pl.new(body: nulls(req.response_size))))
+      end
+      q.push(self)
+    }
+    q.each_item
+  end
+end
+
+class BenchmarkServer
+  def initialize(config, port)
+    if config.security_params
+      certs = load_test_certs
+      cred = GRPC::Core::ServerCredentials.new(
+        nil, [{private_key: certs[1], cert_chain: certs[2]}], false)
+    else
+      cred = :this_port_is_insecure
+    end
+    @server = GRPC::RpcServer.new
+    @port = @server.add_http2_port("0.0.0.0:" + port.to_s, cred)
+    @server.handle(BenchmarkServiceImpl.new)
+    @start_time = Time.now
+    Thread.new {
+      @server.run
+    }
+  end
+  def mark(reset)
+    s = Grpc::Testing::ServerStats.new(time_elapsed:
+                                         (Time.now-@start_time).to_f)
+    @start_time = Time.now if reset
+    s
+  end
+  def get_port
+    @port
+  end
+  def stop
+    @server.stop
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/control.rb b/src/ruby/qps/src/proto/grpc/testing/control.rb
new file mode 100644
index 0000000..958fca3
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/control.rb
@@ -0,0 +1,154 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+require 'google/protobuf'
+
+require 'src/proto/grpc/testing/payloads'
+require 'src/proto/grpc/testing/stats'
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "grpc.testing.PoissonParams" do
+    optional :offered_load, :double, 1
+  end
+  add_message "grpc.testing.ClosedLoopParams" do
+  end
+  add_message "grpc.testing.LoadParams" do
+    oneof :load do
+      optional :closed_loop, :message, 1, "grpc.testing.ClosedLoopParams"
+      optional :poisson, :message, 2, "grpc.testing.PoissonParams"
+    end
+  end
+  add_message "grpc.testing.SecurityParams" do
+    optional :use_test_ca, :bool, 1
+    optional :server_host_override, :string, 2
+  end
+  add_message "grpc.testing.ClientConfig" do
+    repeated :server_targets, :string, 1
+    optional :client_type, :enum, 2, "grpc.testing.ClientType"
+    optional :security_params, :message, 3, "grpc.testing.SecurityParams"
+    optional :outstanding_rpcs_per_channel, :int32, 4
+    optional :client_channels, :int32, 5
+    optional :async_client_threads, :int32, 7
+    optional :rpc_type, :enum, 8, "grpc.testing.RpcType"
+    optional :load_params, :message, 10, "grpc.testing.LoadParams"
+    optional :payload_config, :message, 11, "grpc.testing.PayloadConfig"
+    optional :histogram_params, :message, 12, "grpc.testing.HistogramParams"
+    repeated :core_list, :int32, 13
+    optional :core_limit, :int32, 14
+    optional :other_client_api, :string, 15
+  end
+  add_message "grpc.testing.ClientStatus" do
+    optional :stats, :message, 1, "grpc.testing.ClientStats"
+  end
+  add_message "grpc.testing.Mark" do
+    optional :reset, :bool, 1
+  end
+  add_message "grpc.testing.ClientArgs" do
+    oneof :argtype do
+      optional :setup, :message, 1, "grpc.testing.ClientConfig"
+      optional :mark, :message, 2, "grpc.testing.Mark"
+    end
+  end
+  add_message "grpc.testing.ServerConfig" do
+    optional :server_type, :enum, 1, "grpc.testing.ServerType"
+    optional :security_params, :message, 2, "grpc.testing.SecurityParams"
+    optional :port, :int32, 4
+    optional :async_server_threads, :int32, 7
+    optional :core_limit, :int32, 8
+    optional :payload_config, :message, 9, "grpc.testing.PayloadConfig"
+    repeated :core_list, :int32, 10
+    optional :other_server_api, :string, 11
+  end
+  add_message "grpc.testing.ServerArgs" do
+    oneof :argtype do
+      optional :setup, :message, 1, "grpc.testing.ServerConfig"
+      optional :mark, :message, 2, "grpc.testing.Mark"
+    end
+  end
+  add_message "grpc.testing.ServerStatus" do
+    optional :stats, :message, 1, "grpc.testing.ServerStats"
+    optional :port, :int32, 2
+    optional :cores, :int32, 3
+  end
+  add_message "grpc.testing.CoreRequest" do
+  end
+  add_message "grpc.testing.CoreResponse" do
+    optional :cores, :int32, 1
+  end
+  add_message "grpc.testing.Void" do
+  end
+  add_message "grpc.testing.Scenario" do
+    optional :name, :string, 1
+    optional :client_config, :message, 2, "grpc.testing.ClientConfig"
+    optional :num_clients, :int32, 3
+    optional :server_config, :message, 4, "grpc.testing.ServerConfig"
+    optional :num_servers, :int32, 5
+    optional :warmup_seconds, :int32, 6
+    optional :benchmark_seconds, :int32, 7
+    optional :spawn_local_worker_count, :int32, 8
+  end
+  add_message "grpc.testing.Scenarios" do
+    repeated :scenarios, :message, 1, "grpc.testing.Scenario"
+  end
+  add_message "grpc.testing.ScenarioResultSummary" do
+    optional :qps, :double, 1
+    optional :qps_per_server_core, :double, 2
+    optional :server_system_time, :double, 3
+    optional :server_user_time, :double, 4
+    optional :client_system_time, :double, 5
+    optional :client_user_time, :double, 6
+    optional :latency_50, :double, 7
+    optional :latency_90, :double, 8
+    optional :latency_95, :double, 9
+    optional :latency_99, :double, 10
+    optional :latency_999, :double, 11
+  end
+  add_message "grpc.testing.ScenarioResult" do
+    optional :scenario, :message, 1, "grpc.testing.Scenario"
+    optional :latencies, :message, 2, "grpc.testing.HistogramData"
+    repeated :client_stats, :message, 3, "grpc.testing.ClientStats"
+    repeated :server_stats, :message, 4, "grpc.testing.ServerStats"
+    repeated :server_cores, :int32, 5
+    optional :summary, :message, 6, "grpc.testing.ScenarioResultSummary"
+  end
+  add_enum "grpc.testing.ClientType" do
+    value :SYNC_CLIENT, 0
+    value :ASYNC_CLIENT, 1
+    value :OTHER_CLIENT, 2
+  end
+  add_enum "grpc.testing.ServerType" do
+    value :SYNC_SERVER, 0
+    value :ASYNC_SERVER, 1
+    value :ASYNC_GENERIC_SERVER, 2
+    value :OTHER_SERVER, 3
+  end
+  add_enum "grpc.testing.RpcType" do
+    value :UNARY, 0
+    value :STREAMING, 1
+  end
+end
+
+module Grpc
+  module Testing
+    PoissonParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.PoissonParams").msgclass
+    ClosedLoopParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClosedLoopParams").msgclass
+    LoadParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.LoadParams").msgclass
+    SecurityParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SecurityParams").msgclass
+    ClientConfig = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientConfig").msgclass
+    ClientStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientStatus").msgclass
+    Mark = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Mark").msgclass
+    ClientArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientArgs").msgclass
+    ServerConfig = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ServerConfig").msgclass
+    ServerArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ServerArgs").msgclass
+    ServerStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ServerStatus").msgclass
+    CoreRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.CoreRequest").msgclass
+    CoreResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.CoreResponse").msgclass
+    Void = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Void").msgclass
+    Scenario = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Scenario").msgclass
+    Scenarios = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Scenarios").msgclass
+    ScenarioResultSummary = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ScenarioResultSummary").msgclass
+    ScenarioResult = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ScenarioResult").msgclass
+    ClientType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientType").enummodule
+    ServerType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ServerType").enummodule
+    RpcType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.RpcType").enummodule
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/messages.rb b/src/ruby/qps/src/proto/grpc/testing/messages.rb
new file mode 100644
index 0000000..2bdfe0e
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/messages.rb
@@ -0,0 +1,84 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "grpc.testing.Payload" do
+    optional :type, :enum, 1, "grpc.testing.PayloadType"
+    optional :body, :bytes, 2
+  end
+  add_message "grpc.testing.EchoStatus" do
+    optional :code, :int32, 1
+    optional :message, :string, 2
+  end
+  add_message "grpc.testing.SimpleRequest" do
+    optional :response_type, :enum, 1, "grpc.testing.PayloadType"
+    optional :response_size, :int32, 2
+    optional :payload, :message, 3, "grpc.testing.Payload"
+    optional :fill_username, :bool, 4
+    optional :fill_oauth_scope, :bool, 5
+    optional :response_compression, :enum, 6, "grpc.testing.CompressionType"
+    optional :response_status, :message, 7, "grpc.testing.EchoStatus"
+  end
+  add_message "grpc.testing.SimpleResponse" do
+    optional :payload, :message, 1, "grpc.testing.Payload"
+    optional :username, :string, 2
+    optional :oauth_scope, :string, 3
+  end
+  add_message "grpc.testing.StreamingInputCallRequest" do
+    optional :payload, :message, 1, "grpc.testing.Payload"
+  end
+  add_message "grpc.testing.StreamingInputCallResponse" do
+    optional :aggregated_payload_size, :int32, 1
+  end
+  add_message "grpc.testing.ResponseParameters" do
+    optional :size, :int32, 1
+    optional :interval_us, :int32, 2
+  end
+  add_message "grpc.testing.StreamingOutputCallRequest" do
+    optional :response_type, :enum, 1, "grpc.testing.PayloadType"
+    repeated :response_parameters, :message, 2, "grpc.testing.ResponseParameters"
+    optional :payload, :message, 3, "grpc.testing.Payload"
+    optional :response_compression, :enum, 6, "grpc.testing.CompressionType"
+    optional :response_status, :message, 7, "grpc.testing.EchoStatus"
+  end
+  add_message "grpc.testing.StreamingOutputCallResponse" do
+    optional :payload, :message, 1, "grpc.testing.Payload"
+  end
+  add_message "grpc.testing.ReconnectParams" do
+    optional :max_reconnect_backoff_ms, :int32, 1
+  end
+  add_message "grpc.testing.ReconnectInfo" do
+    optional :passed, :bool, 1
+    repeated :backoff_ms, :int32, 2
+  end
+  add_enum "grpc.testing.PayloadType" do
+    value :COMPRESSABLE, 0
+    value :UNCOMPRESSABLE, 1
+    value :RANDOM, 2
+  end
+  add_enum "grpc.testing.CompressionType" do
+    value :NONE, 0
+    value :GZIP, 1
+    value :DEFLATE, 2
+  end
+end
+
+module Grpc
+  module Testing
+    Payload = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Payload").msgclass
+    EchoStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.EchoStatus").msgclass
+    SimpleRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleRequest").msgclass
+    SimpleResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleResponse").msgclass
+    StreamingInputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallRequest").msgclass
+    StreamingInputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallResponse").msgclass
+    ResponseParameters = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ResponseParameters").msgclass
+    StreamingOutputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallRequest").msgclass
+    StreamingOutputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallResponse").msgclass
+    ReconnectParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ReconnectParams").msgclass
+    ReconnectInfo = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ReconnectInfo").msgclass
+    PayloadType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.PayloadType").enummodule
+    CompressionType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.CompressionType").enummodule
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/payloads.rb b/src/ruby/qps/src/proto/grpc/testing/payloads.rb
new file mode 100644
index 0000000..ae8855f
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/payloads.rb
@@ -0,0 +1,33 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/payloads.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "grpc.testing.ByteBufferParams" do
+    optional :req_size, :int32, 1
+    optional :resp_size, :int32, 2
+  end
+  add_message "grpc.testing.SimpleProtoParams" do
+    optional :req_size, :int32, 1
+    optional :resp_size, :int32, 2
+  end
+  add_message "grpc.testing.ComplexProtoParams" do
+  end
+  add_message "grpc.testing.PayloadConfig" do
+    oneof :payload do
+      optional :bytebuf_params, :message, 1, "grpc.testing.ByteBufferParams"
+      optional :simple_params, :message, 2, "grpc.testing.SimpleProtoParams"
+      optional :complex_params, :message, 3, "grpc.testing.ComplexProtoParams"
+    end
+  end
+end
+
+module Grpc
+  module Testing
+    ByteBufferParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ByteBufferParams").msgclass
+    SimpleProtoParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleProtoParams").msgclass
+    ComplexProtoParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ComplexProtoParams").msgclass
+    PayloadConfig = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.PayloadConfig").msgclass
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/services.rb b/src/ruby/qps/src/proto/grpc/testing/services.rb
new file mode 100644
index 0000000..b2675c2
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/services.rb
@@ -0,0 +1,14 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/services.proto
+
+require 'google/protobuf'
+
+require 'src/proto/grpc/testing/messages'
+require 'src/proto/grpc/testing/control'
+Google::Protobuf::DescriptorPool.generated_pool.build do
+end
+
+module Grpc
+  module Testing
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/services_services.rb b/src/ruby/qps/src/proto/grpc/testing/services_services.rb
new file mode 100644
index 0000000..3fd9f20
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/services_services.rb
@@ -0,0 +1,46 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# Source: src/proto/grpc/testing/services.proto for package 'grpc.testing'
+
+require 'grpc'
+require 'src/proto/grpc/testing/services'
+
+module Grpc
+  module Testing
+    module BenchmarkService
+
+      # TODO: add proto service documentation here
+      class Service
+
+        include GRPC::GenericService
+
+        self.marshal_class_method = :encode
+        self.unmarshal_class_method = :decode
+        self.service_name = 'grpc.testing.BenchmarkService'
+
+        rpc :UnaryCall, SimpleRequest, SimpleResponse
+        rpc :StreamingCall, stream(SimpleRequest), stream(SimpleResponse)
+      end
+
+      Stub = Service.rpc_stub_class
+    end
+    module WorkerService
+
+      # TODO: add proto service documentation here
+      class Service
+
+        include GRPC::GenericService
+
+        self.marshal_class_method = :encode
+        self.unmarshal_class_method = :decode
+        self.service_name = 'grpc.testing.WorkerService'
+
+        rpc :RunServer, stream(ServerArgs), stream(ServerStatus)
+        rpc :RunClient, stream(ClientArgs), stream(ClientStatus)
+        rpc :CoreCount, CoreRequest, CoreResponse
+        rpc :QuitWorker, Void, Void
+      end
+
+      Stub = Service.rpc_stub_class
+    end
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/stats.rb b/src/ruby/qps/src/proto/grpc/testing/stats.rb
new file mode 100644
index 0000000..41f75be
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/stats.rb
@@ -0,0 +1,39 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/stats.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "grpc.testing.ServerStats" do
+    optional :time_elapsed, :double, 1
+    optional :time_user, :double, 2
+    optional :time_system, :double, 3
+  end
+  add_message "grpc.testing.HistogramParams" do
+    optional :resolution, :double, 1
+    optional :max_possible, :double, 2
+  end
+  add_message "grpc.testing.HistogramData" do
+    repeated :bucket, :uint32, 1
+    optional :min_seen, :double, 2
+    optional :max_seen, :double, 3
+    optional :sum, :double, 4
+    optional :sum_of_squares, :double, 5
+    optional :count, :double, 6
+  end
+  add_message "grpc.testing.ClientStats" do
+    optional :latencies, :message, 1, "grpc.testing.HistogramData"
+    optional :time_elapsed, :double, 2
+    optional :time_user, :double, 3
+    optional :time_system, :double, 4
+  end
+end
+
+module Grpc
+  module Testing
+    ServerStats = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ServerStats").msgclass
+    HistogramParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.HistogramParams").msgclass
+    HistogramData = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.HistogramData").msgclass
+    ClientStats = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientStats").msgclass
+  end
+end
diff --git a/src/ruby/qps/worker.rb b/src/ruby/qps/worker.rb
new file mode 100755
index 0000000..665fb86
--- /dev/null
+++ b/src/ruby/qps/worker.rb
@@ -0,0 +1,128 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+# Worker and worker service implementation
+
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(this_dir), 'lib')
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
+
+require 'grpc'
+require 'optparse'
+require 'histogram'
+require 'etc'
+require 'facter'
+require 'client'
+require 'qps-common'
+require 'server'
+require 'src/proto/grpc/testing/services_services'
+
+class WorkerServiceImpl < Grpc::Testing::WorkerService::Service
+  def cpu_cores
+    Facter.value('processors')['count']
+  end
+  def run_server(reqs)
+    q = EnumeratorQueue.new(self)
+    Thread.new {
+      bms = ''
+      gtss = Grpc::Testing::ServerStatus
+      reqs.each do |req|
+        case req.argtype.to_s
+        when 'setup'
+          bms = BenchmarkServer.new(req.setup, @server_port)
+          q.push(gtss.new(stats: bms.mark(false), port: bms.get_port))
+        when 'mark'
+          q.push(gtss.new(stats: bms.mark(req.mark.reset), cores: cpu_cores))
+        end
+      end
+      q.push(self)
+      bms.stop
+    }
+    q.each_item
+  end
+  def run_client(reqs)
+    q = EnumeratorQueue.new(self)
+    Thread.new {
+      client = ''
+      reqs.each do |req|
+        case req.argtype.to_s
+        when 'setup'
+          client = BenchmarkClient.new(req.setup)
+          q.push(Grpc::Testing::ClientStatus.new(stats: client.mark(false)))
+        when 'mark'
+          q.push(Grpc::Testing::ClientStatus.new(stats:
+                                                   client.mark(req.mark.reset)))
+        end
+      end
+      q.push(self)
+      client.shutdown
+    }
+    q.each_item
+  end
+  def core_count(_args, _call)
+    Grpc::Testing::CoreResponse.new(cores: cpu_cores)
+  end
+  def quit_worker(_args, _call)
+    Thread.new {
+      sleep 3
+      @server.stop
+    }
+    Grpc::Testing::Void.new
+  end
+  def initialize(s, sp)
+    @server = s
+    @server_port = sp
+  end
+end
+
+def main
+  options = {
+    'driver_port' => 0,
+    'server_port' => 0
+  }
+  OptionParser.new do |opts|
+    opts.banner = 'Usage: [--driver_port <port>] [--server_port <port>]'
+    opts.on('--driver_port PORT', '<port>') do |v|
+      options['driver_port'] = v
+    end
+    opts.on('--server_port PORT', '<port>') do |v|
+      options['server_port'] = v
+    end
+  end.parse!
+  s = GRPC::RpcServer.new
+  s.add_http2_port("0.0.0.0:" + options['driver_port'].to_s,
+                   :this_port_is_insecure)
+  s.handle(WorkerServiceImpl.new(s, options['server_port'].to_i))
+  s.run
+end
+
+main
diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb
index 7ef5345..aedeca2 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index 5e13c25..dd8e2e9 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -193,44 +193,45 @@
   describe '#client_streamer' do
     shared_examples 'client streaming' do
       before(:each) do
+        server_port = create_test_server
+        host = "localhost:#{server_port}"
+        @stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
+        @options = { k1: 'v1', k2: 'v2' }
         @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
         @resp = 'a_reply'
       end
 
       it 'should send requests to/receive a reply from a server' do
-        server_port = create_test_server
-        host = "localhost:#{server_port}"
         th = run_client_streamer(@sent_msgs, @resp, @pass)
-        stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
-        expect(get_response(stub)).to eq(@resp)
+        expect(get_response(@stub)).to eq(@resp)
         th.join
       end
 
       it 'should send metadata to the server ok' do
-        server_port = create_test_server
-        host = "localhost:#{server_port}"
-        th = run_client_streamer(@sent_msgs, @resp, @pass,
-                                 k1: 'v1', k2: 'v2')
-        stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
-        expect(get_response(stub)).to eq(@resp)
+        th = run_client_streamer(@sent_msgs, @resp, @pass, @options)
+        expect(get_response(@stub)).to eq(@resp)
         th.join
       end
 
       it 'should raise an error if the status is not ok' do
-        server_port = create_test_server
-        host = "localhost:#{server_port}"
         th = run_client_streamer(@sent_msgs, @resp, @fail)
-        stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
-        blk = proc { get_response(stub) }
+        blk = proc { get_response(@stub) }
         expect(&blk).to raise_error(GRPC::BadStatus)
         th.join
       end
+
+      it 'should raise ArgumentError if metadata contains invalid values' do
+        @options.merge!(k3: 3)
+        expect do
+          get_response(@stub)
+        end.to raise_error(ArgumentError,
+                           /Header values must be of type string or array/)
+      end
     end
 
     describe 'without a call operation' do
       def get_response(stub)
-        stub.client_streamer(@method, @sent_msgs, noop, noop,
-                             k1: 'v1', k2: 'v2')
+        stub.client_streamer(@method, @sent_msgs, noop, noop, @options)
       end
 
       it_behaves_like 'client streaming'
@@ -239,7 +240,7 @@
     describe 'via a call operation' do
       def get_response(stub)
         op = stub.client_streamer(@method, @sent_msgs, noop, noop,
-                                  return_op: true, k1: 'v1', k2: 'v2')
+                                  @options.merge(return_op: true))
         expect(op).to be_a(GRPC::ActiveCall::Operation)
         op.execute
       end
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index dfaec6d..e688057 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -426,7 +426,7 @@
         threads.each(&:join)
       end
 
-      it 'should return UNAVAILABLE on too many jobs', server: true do
+      it 'should return RESOURCE_EXHAUSTED on too many jobs', server: true do
         opts = {
           a_channel_arg: 'an_arg',
           server_override: @server,
@@ -449,7 +449,8 @@
             begin
               stub.an_rpc(req)
             rescue GRPC::BadStatus => e
-              one_failed_as_unavailable = e.code == StatusCodes::UNAVAILABLE
+              one_failed_as_unavailable =
+                e.code == StatusCodes::RESOURCE_EXHAUSTED
             end
           end
         end
diff --git a/src/ruby/spec/pb/duplicate/codegen_spec.rb b/src/ruby/spec/pb/duplicate/codegen_spec.rb
new file mode 100644
index 0000000..54c136c
--- /dev/null
+++ b/src/ruby/spec/pb/duplicate/codegen_spec.rb
@@ -0,0 +1,71 @@
+# 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 'open3'
+require 'tmpdir'
+
+def can_run_codegen_check
+  system('which grpc_ruby_plugin') && system('which protoc')
+end
+
+describe 'Ping protobuf code generation' do
+  if !can_run_codegen_check
+    skip 'protoc || grpc_ruby_plugin missing, cannot verify ping code-gen'
+  else
+    it 'should have the same content as created by code generation' do
+      root_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..')
+
+      # Get the current content
+      service_path = File.join(root_dir, 'src', 'ruby', 'pb', 'grpc',
+                               'testing', 'duplicate',
+                               'echo_duplicate_services.rb')
+      want = nil
+      File.open(service_path) { |f| want = f.read }
+
+      # Regenerate it
+      plugin, = Open3.capture2('which', 'grpc_ruby_plugin')
+      plugin = plugin.strip
+      got = nil
+      Dir.mktmpdir do |tmp_dir|
+        gen_out = File.join(tmp_dir, 'src', 'proto', 'grpc', 'testing',
+                            'duplicate', 'echo_duplicate_services.rb')
+        pid = spawn(
+          'protoc',
+          '-I.',
+          'src/proto/grpc/testing/duplicate/echo_duplicate.proto',
+          "--grpc_out=#{tmp_dir}",
+          "--plugin=protoc-gen-grpc=#{plugin}",
+          chdir: root_dir)
+        Process.wait(pid)
+        File.open(gen_out) { |f| got = f.read }
+      end
+      expect(got).to eq(want)
+    end
+  end
+end
diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb
index 9bb79bb..5523347 100644
--- a/src/ruby/spec/pb/health/checker_spec.rb
+++ b/src/ruby/spec/pb/health/checker_spec.rb
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/ruby/stress/metrics_server.rb b/src/ruby/stress/metrics_server.rb
new file mode 100644
index 0000000..13638c4
--- /dev/null
+++ b/src/ruby/stress/metrics_server.rb
@@ -0,0 +1,83 @@
+# 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_relative '../pb/grpc/testing/metrics.rb'
+require_relative '../pb/grpc/testing/metrics_services.rb'
+
+class Gauge
+  def get_name
+    raise NoMethodError.new
+  end
+
+  def get_type
+    raise NoMethodError.new
+  end
+
+  def get_value
+    raise NoMethodError.new
+  end
+end
+
+class MetricsServiceImpl < Grpc::Testing::MetricsService::Service
+  include Grpc::Testing
+  @gauges
+
+  def initialize
+    @gauges = {}
+  end
+
+  def register_gauge(gauge)
+    @gauges[gauge.get_name] = gauge
+  end
+
+  def make_gauge_response(gauge)
+    response = GaugeResponse.new(:name => gauge.get_name)
+    value = gauge.get_value
+    case gauge.get_type
+    when 'long'
+      response.long_value = value
+    when 'double'
+      response.double_value = value
+    when 'string'
+      response.string_value = value
+    end
+    response
+  end
+
+  def get_all_gauges(_empty, _call)
+    @gauges.values.map do |gauge|
+      make_gauge_response gauge
+    end
+  end
+
+  def get_gauge(gauge_req, _call)
+    gauge = @gauges[gauge_req.name]
+    make_gauge_response gauge
+  end
+end
diff --git a/src/ruby/stress/stress_client.rb b/src/ruby/stress/stress_client.rb
new file mode 100755
index 0000000..698f9f1
--- /dev/null
+++ b/src/ruby/stress/stress_client.rb
@@ -0,0 +1,155 @@
+#!/usr/bin/env ruby
+
+# 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 'optparse'
+require 'thread'
+require_relative '../pb/test/client'
+require_relative './metrics_server'
+require_relative '../lib/grpc'
+
+class QpsGauge < Gauge
+  @query_count
+  @query_mutex
+  @start_time
+
+  def initialize
+    @query_count = 0
+    @query_mutex = Mutex.new
+    @start_time = Time.now
+  end
+
+  def increment_queries
+    @query_mutex.synchronize { @query_count += 1}
+  end
+
+  def get_name
+    'qps'
+  end
+
+  def get_type
+    'long'
+  end
+
+  def get_value
+    (@query_mutex.synchronize { @query_count / (Time.now - @start_time) }).to_i
+  end
+end
+
+def start_metrics_server(port)
+  host = "0.0.0.0:#{port}"
+  server = GRPC::RpcServer.new
+  server.add_http2_port(host, :this_port_is_insecure)
+  service = MetricsServiceImpl.new
+  server.handle(service)
+  server_thread = Thread.new { server.run_till_terminated }
+  [server, service, server_thread]
+end
+
+StressArgs = Struct.new(:server_addresses, :test_cases, :duration,
+                        :channels_per_server, :concurrent_calls, :metrics_port)
+
+def start(stress_args)
+  running = true
+  threads = []
+  qps_gauge = QpsGauge.new
+  metrics_server, metrics_service, metrics_thread =
+    start_metrics_server(stress_args.metrics_port)
+  metrics_service.register_gauge(qps_gauge)
+  stress_args.server_addresses.each do |address|
+    stress_args.channels_per_server.times do
+      client_args = Args.new
+      client_args.host, client_args.port = address.split(':')
+      client_args.secure = false
+      client_args.test_case = ''
+      stub = create_stub(client_args)
+      named_tests = NamedTests.new(stub, client_args)
+      stress_args.concurrent_calls.times do
+        threads << Thread.new do
+          while running
+            named_tests.method(stress_args.test_cases.sample).call
+            qps_gauge.increment_queries
+          end
+        end
+      end
+    end
+  end
+  if stress_args.duration >= 0
+    sleep stress_args.duration
+    running = false
+    metrics_server.stop
+    p "QPS: #{qps_gauge.get_value}"
+    threads.each { |thd| thd.join; }
+  end
+  metrics_thread.join
+end
+
+def parse_stress_args
+  stress_args = StressArgs.new
+  stress_args.server_addresses = ['localhost:8080']
+  stress_args.test_cases = []
+  stress_args.duration = -1
+  stress_args.channels_per_server = 1
+  stress_args.concurrent_calls = 1
+  stress_args.metrics_port = '8081'
+  OptionParser.new do |opts|
+    opts.on('--server_addresses [LIST]', Array) do |addrs|
+      stress_args.server_addresses = addrs
+    end
+    opts.on('--test_cases cases', Array) do |cases|
+      stress_args.test_cases = (cases.map do |item|
+                                  split = item.split(':')
+                                  [split[0]] * split[1].to_i
+                                end).reduce([], :+)
+    end
+    opts.on('--test_duration_secs [INT]', OptionParser::DecimalInteger) do |time|
+      stress_args.duration = time
+    end
+    opts.on('--num_channels_per_server [INT]', OptionParser::DecimalInteger) do |channels|
+      stress_args.channels_per_server = channels
+    end
+    opts.on('--num_stubs_per_channel [INT]', OptionParser::DecimalInteger) do |stubs|
+      stress_args.concurrent_calls = stubs
+    end
+    opts.on('--metrics_port [port]') do |port|
+      stress_args.metrics_port = port
+    end
+  end.parse!
+  stress_args
+end
+
+def main
+  opts = parse_stress_args
+  start(opts)
+end
+
+if __FILE__ == $0
+  main
+end
diff --git a/src/zlib/gen_build_yaml.py b/src/zlib/gen_build_yaml.py
index 4bd5573..0692edb 100755
--- a/src/zlib/gen_build_yaml.py
+++ b/src/zlib/gen_build_yaml.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2.7
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/summerofcode/ideas.md b/summerofcode/ideas.md
index 83f2cec..d87cf1b 100644
--- a/summerofcode/ideas.md
+++ b/summerofcode/ideas.md
@@ -36,7 +36,7 @@
  * **Required skills:** Python programming language, PyPy Python interpreter.
  * **Likely mentors:** [Nathaniel Manista](https://github.com/nathanielmanistaatgoogle), [Masood Malekghassemi](https://github.com/soltanmm).
 1. Develop and test Python 3.5 Support for gRPC. Make necessary changes to port gRPC and package it for supported platforms.
- * **Required skills:** Python programming language, PyPy Python interpreter.
+ * **Required skills:** Python programming language, Python 3.5 interpreter.
  * **Likely mentors:** [Nathaniel Manista](https://github.com/nathanielmanistaatgoogle), [Masood Malekghassemi](https://github.com/soltanmm).
  
 gRPC Ruby/Java:
diff --git a/templates/BUILD.template b/templates/BUILD.template
index 54dc697..23a656c 100644
--- a/templates/BUILD.template
+++ b/templates/BUILD.template
@@ -49,7 +49,9 @@
       ]
     if target_dict.get('build', None) == 'protoc':
       deps.append("//external:protobuf_compiler")
-    if target_dict['name'] == 'grpc++_unsecure' or target_dict['name'] == 'grpc++':
+    if (target_dict['name'] == 'grpc++_unsecure' or
+        target_dict['name'] == 'grpc++' or
+        target_dict['name'] == 'grpc++_codegen_lib'):
       deps.append("//external:protobuf_clib")
     elif target_dict['name'] == 'grpc':
       deps.append("//external:zlib")
@@ -60,7 +62,7 @@
         deps.append(':%s' % (d))
     return deps
   %>
-  
+
   % for lib in libs:
   % if lib.build in ("all", "protoc"):
   ${cc_library(lib)}
@@ -80,13 +82,19 @@
   % endfor
   
   <%def name="cc_library(lib)">
+  <%
+    lib_hdrs = lib.get("headers", [])
+    hdrs = [h for h in lib_hdrs if not h.startswith('third_party/nanopb')]
+    srcs = [s for s in lib.src if not s.startswith('third_party/nanopb')]
+    uses_nanopb = len(lib_hdrs) != len(hdrs) or len(srcs) != len(lib.src)
+  %>
   cc_library(
     name = "${lib.name}",
     srcs = [
-  % for hdr in lib.get("headers", []):
+  % for hdr in hdrs:
       "${hdr}",
   % endfor
-  % for src in lib.src:
+  % for src in srcs:
       "${src}",
   % endfor
     ],
@@ -103,6 +111,9 @@
   % for dep in get_deps(lib):
       "${dep}",
   % endfor
+  % if uses_nanopb:
+      "//external:nanopb",
+  % endif
     ],
   % if lib.name in ("grpc", "grpc_unsecure"):
     copts = [
@@ -113,10 +124,16 @@
   </%def>
   
   <%def name="objc_library(lib)">
+  <%
+    lib_hdrs = lib.get("headers", [])
+    hdrs = [h for h in lib_hdrs if not h.startswith('third_party/nanopb')]
+    srcs = [s for s in lib.src if not s.startswith('third_party/nanopb')]
+    uses_nanopb = len(lib_hdrs) != len(hdrs) or len(srcs) != len(lib.src)
+  %>
   objc_library(
     name = "${lib.name}_objc",
     srcs = [
-  % for src in lib.src:
+  % for src in srcs:
       "${src}",
   % endfor
     ],
@@ -124,7 +141,7 @@
   % for hdr in lib.get("public_headers", []):
       "${hdr}",
   % endfor
-  % for hdr in lib.get("headers", []):
+  % for hdr in hdrs:
       "${hdr}",
   % endfor
     ],
@@ -139,6 +156,9 @@
   % if lib.get('secure', False):
       "//external:libssl_objc",
   % endif
+  % if uses_nanopb:
+      "//external:nanopb",
+  % endif
     ],
   % if lib.get("baselib", false):
     sdk_dylibs = ["libz"],
diff --git a/templates/Makefile.template b/templates/Makefile.template
index c54c146..e84ceeb 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -7,7 +7,7 @@
   # This file can be regenerated from the template by running
   # tools/buildgen/generate_projects.sh
 
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
@@ -1737,7 +1737,7 @@
    $(LIBDIR)/$(CONFIG)/lib${dep}.a\
   % endfor
 
-  % if tgt.language == "c++" or tgt.boringssl:
+  % if tgt.language == "c++" or tgt.boringssl or tgt.build == 'fuzzer':
   ## C++ targets specificies.
   % if tgt.build == 'protoc':
   	$(E) "[HOSTLD]  Linking $@"
@@ -1791,6 +1791,9 @@
   % elif tgt.language == 'c++' and tgt.build == 'benchmark':
    $(GTEST_LIB)\
   % endif
+  % if tgt.build == 'fuzzer':
+   -lFuzzer\
+  % endif
    -o $(BINDIR)/$(CONFIG)/${tgt.name}
   % if tgt.build == 'protoc' or tgt.language == 'c++':
 
diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template
index 3ffbc06..40d430f 100644
--- a/templates/binding.gyp.template
+++ b/templates/binding.gyp.template
@@ -7,7 +7,7 @@
   # This file can be regenerated from the template by running
   # tools/buildgen/generate_projects.sh
 
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/composer.json.template b/templates/composer.json.template
new file mode 100644
index 0000000..275b465
--- /dev/null
+++ b/templates/composer.json.template
@@ -0,0 +1,27 @@
+%YAML 1.2
+--- |
+  {
+    "name": "grpc/grpc",
+    "type": "library",
+    "description": "gRPC library for PHP",
+    "version": "${settings.php_version.php()}",
+    "keywords": ["rpc"],
+    "homepage": "http://grpc.io",
+    "license": "BSD-3-Clause",
+    "repositories": [
+      {
+        "type": "vcs",
+        "url": "https://github.com/stanley-cheung/Protobuf-PHP"
+      }
+    ],
+    "require": {
+      "php": ">=5.5.0",
+      "datto/protobuf-php": "dev-master",
+      "google/auth": "v0.7"
+    },
+    "autoload": {
+      "psr-4": {
+        "Grpc\\": "src/php/lib/Grpc/"
+      }
+    }
+  }
diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template
index 701e1c7..ce775ff 100644
--- a/templates/grpc.gemspec.template
+++ b/templates/grpc.gemspec.template
@@ -26,10 +26,6 @@
     s.files += Dir.glob('include/grpc/**/*')
     s.test_files = Dir.glob('src/ruby/spec/**/*')
     s.bindir = 'src/ruby/bin'
-    ${'%'}w(math noproto).each do |b|
-      s.executables += ["#{b}_client.rb", "#{b}_server.rb"]
-    end
-    s.executables += %w(grpc_ruby_interop_client grpc_ruby_interop_server)
     s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
     s.platform      = Gem::Platform::RUBY
 
@@ -37,6 +33,7 @@
     s.add_dependency 'googleauth',      '~> 0.5.1'
 
     s.add_development_dependency 'bundler',            '~> 1.9'
+    s.add_development_dependency 'facter',             '~> 2.4'
     s.add_development_dependency 'logging',            '~> 2.0'
     s.add_development_dependency 'simplecov',          '~> 0.9'
     s.add_development_dependency 'rake',               '~> 10.4'
diff --git a/templates/package.json.template b/templates/package.json.template
index 99e8287..11718b1 100644
--- a/templates/package.json.template
+++ b/templates/package.json.template
@@ -21,7 +21,7 @@
       "lib": "src/node/src"
     },
     "scripts": {
-      "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js",
+      "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js --exclude-path=src/node/.jshintignore",
       "test": "./node_modules/.bin/mocha src/node/test && npm run-script lint",
       "gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json",
       "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test",
@@ -29,6 +29,7 @@
     },
     "bundledDependencies": ["node-pre-gyp"],
     "dependencies": {
+      "arguejs": "^0.2.3",
       "lodash": "^3.9.3",
       "nan": "^2.0.0",
       "protobufjs": "^4.0.0"
@@ -36,6 +37,7 @@
     "devDependencies": {
       "async": "^1.5.0",
       "google-auth-library": "^0.9.2",
+      "google-protobuf": "^3.0.0-alpha.5",
       "istanbul": "^0.3.21",
       "jsdoc": "^3.3.2",
       "jshint": "^2.5.0",
@@ -62,22 +64,36 @@
       "src/node/health_check",
       "src/proto",
       "etc",
-      % for module in node_modules:
-      % for file in module.headers + module.src + module.js:
-      "${file}",
-      % endfor
-      % for dep in module.transitive_deps:
-      % for lib in libs:
-      % if lib.name == dep:
-      % for file in lib.get('public_headers', []) + lib.headers + lib.src:
-      "${file}",
-      % endfor
-      % endif
-      % endfor
-      % endfor
-      % endfor
+      "src/node/index.js",
+      "src/node/src",
+      "src/node/ext",
+      "include/grpc",
+      "src/core",
+      "third_party/nanopb",
+      "third_party/zlib",
+      "third_party/boringssl",
       "binding.gyp"
     ],
     "main": "src/node/index.js",
-    "license": "BSD-3-Clause"
+    "license": "BSD-3-Clause",
+    "jshintConfig" : {
+      "bitwise": true,
+      "curly": true,
+      "eqeqeq": true,
+      "esnext": true,
+      "freeze": true,
+      "immed": true,
+      "indent": 2,
+      "latedef": "nofunc",
+      "maxlen": 80,
+      "mocha": true,
+      "newcap": true,
+      "node": true,
+      "noarg": true,
+      "quotmark": "single",
+      "strict": true,
+      "trailing": true,
+      "undef": true,
+      "unused": "vars"
+    }
   }
diff --git a/templates/package.xml.template b/templates/package.xml.template
index 8f75740..2f498c02 100644
--- a/templates/package.xml.template
+++ b/templates/package.xml.template
@@ -15,8 +15,8 @@
    <date>2016-03-01</date>
    <time>16:06:07</time>
    <version>
-    <release>0.14.0</release>
-    <api>0.14.0</api>
+    <release>${settings.php_version.php()}</release>
+    <api>${settings.php_version.php()}</api>
    </version>
    <stability>
     <release>beta</release>
@@ -157,8 +157,8 @@
     </release>
     <release>
      <version>
-      <release>0.14.0</release>
-      <api>0.14.0</api>
+      <release>${settings.php_version.php()}</release>
+      <api>${settings.php_version.php()}</api>
      </version>
      <stability>
       <release>beta</release>
diff --git a/templates/src/core/lib/surface/version.c.template b/templates/src/core/lib/surface/version.c.template
new file mode 100644
index 0000000..5f0273e
--- /dev/null
+++ b/templates/src/core/lib/surface/version.c.template
@@ -0,0 +1,41 @@
+%YAML 1.2
+--- |
+  /*
+   *
+   * 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 is autogenerated from:
+     templates/src/core/surface/version.c.template */
+  
+  #include <grpc/grpc.h>
+  
+  const char *grpc_version_string(void) { return "${settings.core_version}"; }
diff --git a/templates/src/core/plugin_registry.template b/templates/src/core/plugin_registry.template
new file mode 100644
index 0000000..352682c
--- /dev/null
+++ b/templates/src/core/plugin_registry.template
@@ -0,0 +1,52 @@
+%YAML 1.2
+---
+foreach: libs
+cond: selected.get('generate_plugin_registry', False)
+output_name: ${selected.name}_plugin_registry.c
+template: |
+  /*
+   *
+   * 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 <grpc/grpc.h>
+
+  %for plugin in selected.plugins:
+  extern void ${plugin}_init(void);
+  extern void ${plugin}_shutdown(void);
+  %endfor
+
+  void grpc_register_built_in_plugins(void) {
+  %for plugin in selected.plugins:
+    grpc_register_plugin(${plugin}_init,
+                         ${plugin}_shutdown);
+  %endfor
+  }
diff --git a/templates/src/core/surface/version.c.template b/templates/src/core/surface/version.c.template
deleted file mode 100644
index f2b3cfd..0000000
--- a/templates/src/core/surface/version.c.template
+++ /dev/null
@@ -1,41 +0,0 @@
-%YAML 1.2
---- |
-  /*
-   *
-   * 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.
-   *
-   */
-  
-  /* This file is autogenerated from:
-     templates/src/core/surface/version.c.template */
-  
-  #include <grpc/grpc.h>
-  
-  const char *grpc_version_string(void) { return "${settings.core_version}"; }
diff --git a/templates/src/csharp/Grpc.Core/VersionInfo.cs.template b/templates/src/csharp/Grpc.Core/VersionInfo.cs.template
index 59864fa..3ca111e 100644
--- a/templates/src/csharp/Grpc.Core/VersionInfo.cs.template
+++ b/templates/src/csharp/Grpc.Core/VersionInfo.cs.template
@@ -2,7 +2,7 @@
 --- |
   #region Copyright notice and license
   
-  // Copyright 2015-2016, Google Inc.
+  // Copyright 2015, Google Inc.
   // All rights reserved.
   //
   // Redistribution and use in source and binary forms, with or without
diff --git a/templates/src/csharp/build_packages.bat.template b/templates/src/csharp/build_packages.bat.template
index 3245568..3b445a8 100644
--- a/templates/src/csharp/build_packages.bat.template
+++ b/templates/src/csharp/build_packages.bat.template
@@ -14,12 +14,12 @@
   
   @rem Collect the artifacts built by the previous build step if running on Jenkins
   @rem TODO(jtattermusch): is there a better way to do this?
-  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x64${"\\"}
-  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x64${"\\"}
-  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x64${"\\"}
+  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x86${"\\"}
+  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x64${"\\"}
+  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x86${"\\"}
+  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x64${"\\"}
+  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x86${"\\"}
+  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x64${"\\"}
   
   @rem Collect protoc artifacts built by the previous build step
   xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86${"\\"}
@@ -44,7 +44,6 @@
   
   endlocal
   
-  %%NUGET% pack grpc.native.csharp\grpc.native.csharp.nuspec -Version %VERSION% || goto :error
   %%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
   %%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
   %%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
diff --git a/templates/src/node/tools/package.json.template b/templates/src/node/tools/package.json.template
new file mode 100644
index 0000000..c69de7c
--- /dev/null
+++ b/templates/src/node/tools/package.json.template
@@ -0,0 +1,40 @@
+%YAML 1.2
+--- |
+  {
+    "name": "grpc-tools",
+    "version": "${settings.node_version}",
+    "author": "Google Inc.",
+    "description": "Tools for developing with gRPC on Node.js",
+    "homepage": "http://www.grpc.io/",
+    "repository": {
+      "type": "git",
+      "url": "https://github.com/grpc/grpc.git"
+    },
+    "bugs": "https://github.com/grpc/grpc/issues",
+    "contributors": [
+      {
+        "name": "Michael Lumish",
+        "email": "mlumish@google.com"
+      }
+    ],
+    "bin": {
+      "grpc-tools-protoc": "./bin/protoc.js"
+    },
+    "scripts": {
+      "install": "./node_modules/.bin/node-pre-gyp install"
+    },
+    "bundledDependencies": ["node-pre-gyp"],
+    "binary": {
+      "module_name": "grpc_tools",
+      "host": "https://storage.googleapis.com/",
+      "remote_path": "grpc-precompiled-binaries/node/{name}/v{version}",
+      "package_name": "{platform}-{arch}.tar.gz",
+      "module_path": "bin"
+    },
+    "files": [
+      "index.js",
+      "bin/protoc.js",
+      "LICENSE"
+    ],
+    "main": "index.js"
+  }
diff --git a/templates/src/python/grpcio/grpc_core_dependencies.py.template b/templates/src/python/grpcio/grpc_core_dependencies.py.template
index 2fc7a03..01770a9 100644
--- a/templates/src/python/grpcio/grpc_core_dependencies.py.template
+++ b/templates/src/python/grpcio/grpc_core_dependencies.py.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/src/python/grpcio/grpc_version.py.template b/templates/src/python/grpcio/grpc_version.py.template
index aaacab1..39a6932 100644
--- a/templates/src/python/grpcio/grpc_version.py.template
+++ b/templates/src/python/grpcio/grpc_version.py.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/src/ruby/lib/grpc/version.rb.template b/templates/src/ruby/lib/grpc/version.rb.template
index 6488614..9c7bc13 100644
--- a/templates/src/ruby/lib/grpc/version.rb.template
+++ b/templates/src/ruby/lib/grpc/version.rb.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/test/core/end2end/end2end_defs.include b/templates/test/core/end2end/end2end_defs.include
index 929827e..b828f84 100644
--- a/templates/test/core/end2end/end2end_defs.include
+++ b/templates/test/core/end2end/end2end_defs.include
@@ -1,7 +1,7 @@
 <%def name="end2end_selector(tests)">
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,17 +36,33 @@
 /* This file is auto-generated */
 
 #include "test/core/end2end/end2end_tests.h"
+
+#include <stdbool.h>
 #include <string.h>
+
 #include <grpc/support/log.h>
 
+static bool g_pre_init_called = false;
+
 % for test in tests:
 extern void ${test}(grpc_end2end_test_config config);
+extern void ${test}_pre_init(void);
 % endfor
 
+void grpc_end2end_tests_pre_init(void) {
+  GPR_ASSERT(!g_pre_init_called);
+  g_pre_init_called = true;
+% for test in tests:
+  ${test}_pre_init();
+% endfor
+}
+
 void grpc_end2end_tests(int argc, char **argv,
                         grpc_end2end_test_config config) {
   int i;
 
+  GPR_ASSERT(g_pre_init_called);
+
   if (argc <= 1) {
 % for test in tests:
     ${test}(config);
@@ -64,4 +80,4 @@
     gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]);
     abort();
   }
-}</%def>
\ No newline at end of file
+}</%def>
diff --git a/templates/tools/dockerfile/clang_update.include b/templates/tools/dockerfile/clang_update.include
index 83ab3e0..4f827c8 100644
--- a/templates/tools/dockerfile/clang_update.include
+++ b/templates/tools/dockerfile/clang_update.include
@@ -1,5 +1,5 @@
 #=================
-# Update clang to a version with improved tsan
+# Update clang to a version with improved tsan and fuzzing capabilities
 
 RUN apt-get update && apt-get -y install python cmake && apt-get clean
 
@@ -29,4 +29,4 @@
   -DCMAKE_INSTALL_PREFIX:STRING=/usr ${'\\'}
   -DLLVM_TARGETS_TO_BUILD:STRING=X86 ${'\\'}
   ../llvm
-RUN make -C llvm-build && make -C llvm-build install && rm -rf llvm-build
+RUN make -C llvm-build -j 12 && make -C llvm-build install && rm -rf llvm-build
diff --git a/templates/tools/dockerfile/gcp_api_libraries.include b/templates/tools/dockerfile/gcp_api_libraries.include
new file mode 100644
index 0000000..669b0f8
--- /dev/null
+++ b/templates/tools/dockerfile/gcp_api_libraries.include
@@ -0,0 +1,4 @@
+# Google Cloud platform API libraries
+RUN apt-get update && apt-get install -y python-pip && apt-get clean
+RUN pip install --upgrade google-api-python-client
+
diff --git a/templates/tools/dockerfile/go_path.include b/templates/tools/dockerfile/go_path.include
new file mode 100644
index 0000000..a41cc49
--- /dev/null
+++ b/templates/tools/dockerfile/go_path.include
@@ -0,0 +1,2 @@
+# Using login shell removes Go from path, so we add it.
+RUN ln -s /usr/local/go/bin/go /usr/local/bin
diff --git a/templates/tools/dockerfile/java_deps.include b/templates/tools/dockerfile/java_deps.include
new file mode 100644
index 0000000..40d70e0
--- /dev/null
+++ b/templates/tools/dockerfile/java_deps.include
@@ -0,0 +1,17 @@
+# Install JDK 8 and Git
+#
+RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && ${'\\'}
+  echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'}
+  echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'}
+  apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
+
+RUN apt-get update && apt-get -y install ${'\\'}
+      git ${'\\'}
+      libapr1 ${'\\'}
+      oracle-java8-installer ${'\\'}
+      && ${'\\'}
+    apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
+
+ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
+ENV PATH $PATH:$JAVA_HOME/bin
+
diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile.template
new file mode 100644
index 0000000..ac087c5
--- /dev/null
+++ b/templates/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile.template
@@ -0,0 +1,40 @@
+%YAML 1.2
+--- |
+  # 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.
+  
+  FROM debian:jessie
+  
+  <%include file="../../apt_get_basic.include"/>
+  <%include file="../../ccache_setup.include"/>
+  <%include file="../../cxx_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../clang_update.include"/>
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile.template
new file mode 100644
index 0000000..3ed3d65
--- /dev/null
+++ b/templates/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile.template
@@ -0,0 +1,37 @@
+%YAML 1.2
+--- |
+  # 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.
+  
+  FROM golang:1.5
+  
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../go_path.include"/>
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile.template
new file mode 100644
index 0000000..17ed99f
--- /dev/null
+++ b/templates/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile.template
@@ -0,0 +1,40 @@
+%YAML 1.2
+--- |
+  # 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.
+  
+  FROM debian:jessie
+  
+  <%include file="../../apt_get_basic.include"/>
+  <%include file="../../ccache_setup.include"/>
+  <%include file="../../cxx_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../java_deps.include"/>
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile.template
new file mode 100644
index 0000000..c50d38d
--- /dev/null
+++ b/templates/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile.template
@@ -0,0 +1,39 @@
+%YAML 1.2
+--- |
+  # 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.
+  
+  FROM debian:jessie
+  
+  <%include file="../../apt_get_basic.include"/>
+  <%include file="../../node_deps.include"/>
+  <%include file="../../gcp_api_libraries.include"/>
+  <%include file="../../run_tests_addons.include"/>
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template
index 1c01dea..4cb8d3b 100644
--- a/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template
index eb11ce3..04abf9f 100644
--- a/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template b/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template
index 4e95cdd..7f43e75 100644
--- a/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template
+++ b/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template
index d824220..fbed539 100644
--- a/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template
index 6b30274..c11cefd 100644
--- a/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/fuzzer/Dockerfile.template b/templates/tools/dockerfile/test/fuzzer/Dockerfile.template
new file mode 100644
index 0000000..33df275
--- /dev/null
+++ b/templates/tools/dockerfile/test/fuzzer/Dockerfile.template
@@ -0,0 +1,43 @@
+%YAML 1.2
+--- |
+  # 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.
+
+  FROM debian:jessie
+
+  <%include file="../../apt_get_basic.include"/>
+  <%include file="../../cxx_deps.include"/>
+  <%include file="../../clang_update.include"/>
+  <%include file="../../run_tests_addons.include"/>
+  RUN clang++ -c -g -O2 -std=c++11 llvm/lib/Fuzzer/*.cpp -IFuzzer
+  RUN ar ruv libFuzzer.a Fuzzer*.o
+  RUN mv libFuzzer.a /usr/lib
+  RUN rm -f Fuzzer*.o
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template
index 10551a5..5a62333 100644
--- a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template
index d717239..fffac89 100644
--- a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template
index 9e68b3e..46fb84b 100644
--- a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template
index db777be..70baddf 100644
--- a/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template
index 8265c09..8d6f52d 100644
--- a/templates/tools/dockerfile/test/sanity/Dockerfile.template
+++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template
@@ -1,6 +1,6 @@
 %YAML 1.2
 --- |
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,8 @@
         automake ${"\\"}
         libtool ${"\\"}
         curl ${"\\"}
-        python-virtualenv
+        python-virtualenv ${"\\"}
+        python-lxml
   RUN pip install simplejson mako
 
   #===================
diff --git a/templates/tools/fuzzer/runners.template b/templates/tools/fuzzer/runners.template
new file mode 100644
index 0000000..e84a89a
--- /dev/null
+++ b/templates/tools/fuzzer/runners.template
@@ -0,0 +1,54 @@
+%YAML 1.2
+---
+foreach: targets
+cond: selected.build == 'fuzzer'
+output_name: ${selected.name}.sh
+template: |
+  #!/bin/bash
+  # 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.
+  #
+
+  flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=${selected.maxlen} -timeout=120"
+  
+  %if selected.get('dict'):
+  flags="$flags -dict=${selected.dict}"
+  %endif
+
+  if [ "$jobs" != "1" ]
+  then
+    flags="-jobs=$jobs -workers=$jobs $flags"
+  fi
+
+  if [ "$config" == "asan-trace-cmp" ]
+  then
+    flags="-use_traces=1 $flags"
+  fi
+
+  bins/$config/${selected.name} $flags fuzzer_output ${' '.join(selected.corpus_dirs)}
diff --git a/templates/tools/openssl/use_openssl.sh.template b/templates/tools/openssl/use_openssl.sh.template
index 5fb3771..237a92b 100644
--- a/templates/tools/openssl/use_openssl.sh.template
+++ b/templates/tools/openssl/use_openssl.sh.template
@@ -2,7 +2,7 @@
 --- |
   #!/bin/bash
 
-  # Copyright 2015-2016, Google Inc.
+  # Copyright 2015, Google Inc.
   # All rights reserved.
   #
   # Redistribution and use in source and binary forms, with or without
diff --git a/templates/tools/run_tests/sources_and_headers.json.template b/templates/tools/run_tests/sources_and_headers.json.template
index 18b9bc2..0755982 100644
--- a/templates/tools/run_tests/sources_and_headers.json.template
+++ b/templates/tools/run_tests/sources_and_headers.json.template
@@ -12,11 +12,13 @@
         out.extend(fmt % name for fmt in ['%s.grpc.pb.h', '%s.pb.h'])
     return out
 
-  def all_targets(targets, libs):
+  def all_targets(targets, libs, filegroups):
     for tgt in targets:
       yield ('target', tgt)
     for tgt in libs:
       yield ('lib', tgt)
+    for tgt in filegroups:
+      yield ('filegroup', tgt)
 
   def no_protos_filter(src):
   	return os.path.splitext(src)[1] != '.proto'
@@ -38,13 +40,15 @@
                  "language": tgt.language,
                  "third_party": tgt.boringssl or tgt.zlib,
                  "src": sorted(
-                     filter_srcs(tgt.src, (no_protos_filter, no_third_party_filter)) +
-                     filter_srcs(tgt.get('public_headers', []), (no_protos_filter, no_third_party_filter)) +
-                     filter_srcs(tgt.get('headers', []), (no_third_party_filter,))),
+                     filter_srcs(tgt.own_src, (no_protos_filter, no_third_party_filter)) +
+                     filter_srcs(tgt.own_public_headers, (no_protos_filter, no_third_party_filter)) +
+                     filter_srcs(tgt.own_headers, (no_third_party_filter,))),
                  "headers": sorted(
-                     tgt.get('public_headers', []) +
-                     tgt.get('headers', []) +
-                     proto_headers(tgt.src)),
-                 "deps": sorted(tgt.get('deps', []))}
-                for typ, tgt in all_targets(targets, libs)],
+                     tgt.own_public_headers +
+                     tgt.own_headers +
+                     proto_headers(tgt.own_src)),
+                 "deps": sorted(tgt.get('deps', []) +
+                                tgt.get('uses', []) +
+                                tgt.get('filegroups', []))}
+                for typ, tgt in all_targets(targets, libs, filegroups)],
                sort_keys=True, indent=2)}
diff --git a/templates/vsprojects/buildtests_c.sln.template b/templates/vsprojects/buildtests_c.sln.template
index a985fea..21312ab 100644
--- a/templates/vsprojects/buildtests_c.sln.template
+++ b/templates/vsprojects/buildtests_c.sln.template
@@ -2,6 +2,6 @@
 --- |
   <%namespace file="sln_defs.include" import="gen_solution"/>\
   <%
-  solution_projects = [p for p in vsprojects if p.build != 'protoc' and p.language == 'c' and not p.boringssl and not p.zlib]
+  solution_projects = [p for p in vsprojects if p.build not in ['protoc', 'fuzzer'] and p.language == 'c' and not p.boringssl and not p.zlib]
   %>\
   ${gen_solution(solution_projects, use_dlls='yes')}
diff --git a/templates/vsprojects/grpc.sln.template b/templates/vsprojects/grpc.sln.template
index dbbb2c2..ded9838 100644
--- a/templates/vsprojects/grpc.sln.template
+++ b/templates/vsprojects/grpc.sln.template
@@ -2,6 +2,6 @@
 --- |
   <%namespace file="sln_defs.include" import="gen_solution"/>\
   <%
-  solution_projects = [p for p in vsprojects if p.build not in ['protoc', 'test'] and p.language in ['c', 'c++'] and p.vs_proj_dir == '.' and not (p.build == 'private' and p.language == 'c++')]
+  solution_projects = [p for p in vsprojects if p.build not in ['protoc', 'test', 'fuzzer'] and p.language in ['c', 'c++'] and p.vs_proj_dir == '.' and not (p.build == 'private' and p.language == 'c++')]
   %>\
   ${gen_solution(solution_projects, use_dlls='yes')}
diff --git a/templates/vsprojects/vcxproj.template b/templates/vsprojects/vcxproj.template
index ecf113b..0bb208f 100644
--- a/templates/vsprojects/vcxproj.template
+++ b/templates/vsprojects/vcxproj.template
@@ -2,12 +2,14 @@
 ---
 foreach: vsprojects
 output_name: ${selected.vs_proj_dir}/${selected.name}/${selected.name}.vcxproj
+cond: selected.build not in ['fuzzer']
 template: |
   <%namespace file="vcxproj_defs.include" import="gen_project"/>\
   ${gen_project(selected.name, vsprojects)}
 ---
 foreach: vsprojects
 output_name: ${selected.vs_proj_dir}/${selected.name}/${selected.name}.vcxproj.filters
+cond: selected.build not in ['fuzzer']
 template: |
   <%namespace file="vcxproj.filters_defs.include" import="gen_filters"/>\
   ${gen_filters(selected.name, vsprojects)}
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index ba19013..cd5b541 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,17 +33,19 @@
 
 #include "test/core/bad_client/bad_client.h"
 
-#include "src/core/channel/channel_stack.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/surface/completion_queue.h"
-#include "src/core/surface/server.h"
-#include "src/core/support/string.h"
-#include "src/core/transport/chttp2_transport.h"
-
 #include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
+#include <stdio.h>
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/iomgr/endpoint_pair.h"
+#include "src/core/lib/support/murmur_hash.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/server.h"
 
 typedef struct {
   grpc_server *server;
@@ -110,7 +112,8 @@
   grpc_server_register_completion_queue(a.server, a.cq, NULL);
   a.registered_method =
       grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD,
-                                  GRPC_BAD_CLIENT_REGISTERED_HOST);
+                                  GRPC_BAD_CLIENT_REGISTERED_HOST,
+                                  GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0);
   grpc_server_start(a.server);
   transport = grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, 0);
   server_setup_transport(&a, transport);
@@ -155,9 +158,9 @@
     grpc_exec_ctx_finish(&exec_ctx);
   }
   grpc_server_shutdown_and_notify(a.server, a.cq, NULL);
-  GPR_ASSERT(grpc_completion_queue_pluck(a.cq, NULL,
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 a.cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(a.server);
   grpc_completion_queue_destroy(a.cq);
   gpr_slice_buffer_destroy(&outgoing);
diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py
index c538bff..d49858e 100755
--- a/test/core/bad_client/gen_build_yaml.py
+++ b/test/core/bad_client/gen_build_yaml.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -44,6 +44,7 @@
     'connection_prefix': default_test_options._replace(cpu_cost=0.2),
     'headers': default_test_options._replace(cpu_cost=0.2),
     'initial_settings_frame': default_test_options._replace(cpu_cost=0.2),
+    'head_of_line_blocking': default_test_options,
     'server_registered_method': default_test_options,
     'simple_request': default_test_options,
     'window_overflow': default_test_options,
diff --git a/test/core/bad_client/tests/badreq.c b/test/core/bad_client/tests/badreq.c
index 6d59d25..b17e3b3 100644
--- a/test/core/bad_client/tests/badreq.c
+++ b/test/core/bad_client/tests/badreq.c
@@ -35,8 +35,8 @@
 
 #include <string.h>
 
+#include "src/core/lib/surface/server.h"
 #include "test/core/end2end/cq_verifier.h"
-#include "src/core/surface/server.h"
 
 #define PFX_STR                      \
   "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
@@ -45,9 +45,9 @@
 static void verifier(grpc_server *server, grpc_completion_queue *cq,
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
-    GPR_ASSERT(grpc_completion_queue_next(cq,
-                                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
-                                          NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   .type == GRPC_QUEUE_TIMEOUT);
   }
 }
 
diff --git a/test/core/bad_client/tests/connection_prefix.c b/test/core/bad_client/tests/connection_prefix.c
index 66ff8c2..9a30aad 100644
--- a/test/core/bad_client/tests/connection_prefix.c
+++ b/test/core/bad_client/tests/connection_prefix.c
@@ -31,15 +31,15 @@
  *
  */
 
+#include "src/core/lib/surface/server.h"
 #include "test/core/bad_client/bad_client.h"
-#include "src/core/surface/server.h"
 
 static void verifier(grpc_server *server, grpc_completion_queue *cq,
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
-    GPR_ASSERT(grpc_completion_queue_next(cq,
-                                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
-                                          NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   .type == GRPC_QUEUE_TIMEOUT);
   }
 }
 
diff --git a/test/core/bad_client/tests/head_of_line_blocking.c b/test/core/bad_client/tests/head_of_line_blocking.c
new file mode 100644
index 0000000..53cd453
--- /dev/null
+++ b/test/core/bad_client/tests/head_of_line_blocking.c
@@ -0,0 +1,151 @@
+/*
+ *
+ * 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 "test/core/bad_client/bad_client.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/lib/surface/server.h"
+#include "test/core/end2end/cq_verifier.h"
+
+static const char prefix[] =
+    "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+    // settings frame
+    "\x00\x00\x00\x04\x00\x00\x00\x00\x00"
+    // stream 1 headers: generated from server_registered_method.headers in this
+    // directory
+    "\x00\x00\xd0\x01\x04\x00\x00\x00\x01"
+    "\x10\x05:path\x0f/registered/bar"
+    "\x10\x07:scheme\x04http"
+    "\x10\x07:method\x04POST"
+    "\x10\x0a:authority\x09localhost"
+    "\x10\x0c"
+    "content-type\x10"
+    "application/grpc"
+    "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"
+    "\x10\x02te\x08trailers"
+    "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
+    // data frame for stream 1: advertise a 10000 byte payload (that we won't
+    // fulfill)
+    "\x00\x00\x05\x00\x00\x00\x00\x00\x01"
+    "\x01\x00\x00\x27\x10"
+    // stream 3 headers: generated from server_registered_method.headers in this
+    // directory
+    "\x00\x00\xd0\x01\x04\x00\x00\x00\x03"
+    "\x10\x05:path\x0f/registered/bar"
+    "\x10\x07:scheme\x04http"
+    "\x10\x07:method\x04POST"
+    "\x10\x0a:authority\x09localhost"
+    "\x10\x0c"
+    "content-type\x10"
+    "application/grpc"
+    "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"
+    "\x10\x02te\x08trailers"
+    "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
+    // data frame for stream 3: advertise a 10000 byte payload (that we will
+    // fulfill)
+    "\x00\x00\x05\x00\x00\x00\x00\x00\x03"
+    "\x01\x00\x00\x27\x10"
+    "";
+
+static void *tag(intptr_t t) { return (void *)t; }
+
+static void verifier(grpc_server *server, grpc_completion_queue *cq,
+                     void *registered_method) {
+  grpc_call_error error;
+  grpc_call *s;
+  cq_verifier *cqv = cq_verifier_create(cq);
+  grpc_metadata_array request_metadata_recv;
+  gpr_timespec deadline;
+  grpc_byte_buffer *payload = NULL;
+
+  grpc_metadata_array_init(&request_metadata_recv);
+
+  error = grpc_server_request_registered_call(server, registered_method, &s,
+                                              &deadline, &request_metadata_recv,
+                                              &payload, cq, cq, tag(101));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  cq_expect_completion(cqv, tag(101), 1);
+  cq_verify(cqv);
+
+  GPR_ASSERT(payload != NULL);
+
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_destroy(s);
+  grpc_byte_buffer_destroy(payload);
+  cq_verifier_destroy(cqv);
+}
+
+char *g_buffer;
+size_t g_cap = 0;
+size_t g_count = 0;
+
+static void addbuf(const void *data, size_t len) {
+  if (g_count + len > g_cap) {
+    g_cap = GPR_MAX(g_count + len, g_cap * 2);
+    g_buffer = gpr_realloc(g_buffer, g_cap);
+  }
+  memcpy(g_buffer + g_count, data, len);
+  g_count += len;
+}
+
+int main(int argc, char **argv) {
+  int i;
+  grpc_test_init(argc, argv);
+
+#define NUM_FRAMES 10
+#define FRAME_SIZE 1000
+
+  addbuf(prefix, sizeof(prefix) - 1);
+  for (i = 0; i < NUM_FRAMES; i++) {
+    uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16),
+                      (uint8_t)(FRAME_SIZE >> 8),
+                      (uint8_t)FRAME_SIZE,
+                      0,
+                      0,
+                      0,
+                      0,
+                      0,
+                      3};
+    uint8_t msg[FRAME_SIZE];
+    memset(msg, 'a', sizeof(msg));
+    addbuf(hdr, sizeof(hdr));
+    addbuf(msg, FRAME_SIZE);
+  }
+  grpc_run_bad_client_test(verifier, g_buffer, g_count, 0);
+  gpr_free(g_buffer);
+
+  return 0;
+}
diff --git a/test/core/bad_client/tests/headers.c b/test/core/bad_client/tests/headers.c
index 2186a4f..4c1a767 100644
--- a/test/core/bad_client/tests/headers.c
+++ b/test/core/bad_client/tests/headers.c
@@ -31,8 +31,8 @@
  *
  */
 
+#include "src/core/lib/surface/server.h"
 #include "test/core/bad_client/bad_client.h"
-#include "src/core/surface/server.h"
 
 #define PFX_STR                      \
   "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
@@ -41,9 +41,9 @@
 static void verifier(grpc_server *server, grpc_completion_queue *cq,
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
-    GPR_ASSERT(grpc_completion_queue_next(cq,
-                                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
-                                          NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   .type == GRPC_QUEUE_TIMEOUT);
   }
 }
 
diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c
index fb6149c..63a770d 100644
--- a/test/core/bad_client/tests/initial_settings_frame.c
+++ b/test/core/bad_client/tests/initial_settings_frame.c
@@ -31,8 +31,8 @@
  *
  */
 
+#include "src/core/lib/surface/server.h"
 #include "test/core/bad_client/bad_client.h"
-#include "src/core/surface/server.h"
 
 #define PFX_STR "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
 #define ONE_SETTING_HDR "\x00\x00\x06\x04\x00\x00\x00\x00\x00"
@@ -40,9 +40,9 @@
 static void verifier(grpc_server *server, grpc_completion_queue *cq,
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
-    GPR_ASSERT(grpc_completion_queue_next(cq,
-                                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
-                                          NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   .type == GRPC_QUEUE_TIMEOUT);
   }
 }
 
diff --git a/test/core/bad_client/tests/server_registered_method.c b/test/core/bad_client/tests/server_registered_method.c
index dc6ecc5..60d3b89 100644
--- a/test/core/bad_client/tests/server_registered_method.c
+++ b/test/core/bad_client/tests/server_registered_method.c
@@ -35,8 +35,8 @@
 
 #include <string.h>
 
+#include "src/core/lib/surface/server.h"
 #include "test/core/end2end/cq_verifier.h"
-#include "src/core/surface/server.h"
 
 #define PFX_STR                                               \
   "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"                          \
diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c
index c04319e..ac0fdde 100644
--- a/test/core/bad_client/tests/simple_request.c
+++ b/test/core/bad_client/tests/simple_request.c
@@ -35,8 +35,8 @@
 
 #include <string.h>
 
+#include "src/core/lib/surface/server.h"
 #include "test/core/end2end/cq_verifier.h"
-#include "src/core/surface/server.h"
 
 #define PFX_STR                                                            \
   "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"                                       \
@@ -108,9 +108,9 @@
 static void failure_verifier(grpc_server *server, grpc_completion_queue *cq,
                              void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
-    GPR_ASSERT(grpc_completion_queue_next(cq,
-                                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
-                                          NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   .type == GRPC_QUEUE_TIMEOUT);
   }
 }
 
diff --git a/test/core/bad_client/tests/unknown_frame.c b/test/core/bad_client/tests/unknown_frame.c
index 2ef340e..f3870a1 100644
--- a/test/core/bad_client/tests/unknown_frame.c
+++ b/test/core/bad_client/tests/unknown_frame.c
@@ -31,8 +31,8 @@
  *
  */
 
+#include "src/core/lib/surface/server.h"
 #include "test/core/bad_client/bad_client.h"
-#include "src/core/surface/server.h"
 
 #define PFX_STR                      \
   "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
@@ -41,9 +41,9 @@
 static void verifier(grpc_server *server, grpc_completion_queue *cq,
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
-    GPR_ASSERT(grpc_completion_queue_next(cq,
-                                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
-                                          NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   .type == GRPC_QUEUE_TIMEOUT);
   }
 }
 
diff --git a/test/core/bad_client/tests/window_overflow.c b/test/core/bad_client/tests/window_overflow.c
index 646d5c5..16f11e7 100644
--- a/test/core/bad_client/tests/window_overflow.c
+++ b/test/core/bad_client/tests/window_overflow.c
@@ -37,7 +37,7 @@
 
 #include <grpc/support/alloc.h>
 
-#include "src/core/surface/server.h"
+#include "src/core/lib/surface/server.h"
 
 #define PFX_STR                                                            \
   "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"                                       \
@@ -60,9 +60,9 @@
 static void verifier(grpc_server *server, grpc_completion_queue *cq,
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
-    GPR_ASSERT(grpc_completion_queue_next(cq,
-                                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
-                                          NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   .type == GRPC_QUEUE_TIMEOUT);
   }
 }
 
@@ -90,8 +90,15 @@
 
   addbuf(PFX_STR, sizeof(PFX_STR) - 1);
   for (i = 0; i < NUM_FRAMES; i++) {
-    uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16), (uint8_t)(FRAME_SIZE >> 8),
-                      (uint8_t)FRAME_SIZE, 0, 0, 0, 0, 0, 1};
+    uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16),
+                      (uint8_t)(FRAME_SIZE >> 8),
+                      (uint8_t)FRAME_SIZE,
+                      0,
+                      0,
+                      0,
+                      0,
+                      0,
+                      1};
     addbuf(hdr, sizeof(hdr));
     for (j = 0; j < MESSAGES_PER_FRAME; j++) {
       uint8_t message[5] = {0, 0, 0, 0, 0};
diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c
index a78a079..c4ae212 100644
--- a/test/core/bad_ssl/bad_ssl_test.c
+++ b/test/core/bad_ssl/bad_ssl_test.c
@@ -31,8 +31,8 @@
  *
  */
 
-#include <string.h>
 #include <stdio.h>
+#include <string.h>
 
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
@@ -41,9 +41,10 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/subprocess.h>
-#include "src/core/support/string.h"
-#include "test/core/util/port.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
+#include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
 static void *tag(intptr_t t) { return (void *)t; }
@@ -86,7 +87,7 @@
   op = ops;
   op->op = GRPC_OP_SEND_INITIAL_METADATA;
   op->data.send_initial_metadata.count = 0;
-  op->flags = 0;
+  op->flags = GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY;
   op->reserved = NULL;
   op++;
   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
@@ -144,6 +145,9 @@
   } else {
     strcpy(root, ".");
   }
+  if (argc == 2) {
+    gpr_setenv("GRPC_DEFAULT_SSL_ROOTS_FILE_PATH", argv[1]);
+  }
   /* figure out our test name */
   tmp = lunder - 1;
   while (*tmp != '_') tmp--;
diff --git a/test/core/bad_ssl/gen_build_yaml.py b/test/core/bad_ssl/gen_build_yaml.py
index e2a3feb..69f9219 100755
--- a/test/core/bad_ssl/gen_build_yaml.py
+++ b/test/core/bad_ssl/gen_build_yaml.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/test/core/bad_ssl/server_common.c b/test/core/bad_ssl/server_common.c
index cde844a..14b1892 100644
--- a/test/core/bad_ssl/server_common.c
+++ b/test/core/bad_ssl/server_common.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/bad_ssl/server_common.h b/test/core/bad_ssl/server_common.h
index 2566c25..8ec7755 100644
--- a/test/core/bad_ssl/server_common.h
+++ b/test/core/bad_ssl/server_common.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/bad_ssl/servers/alpn.c b/test/core/bad_ssl/servers/alpn.c
index c8cc83b..007fa25 100644
--- a/test/core/bad_ssl/servers/alpn.c
+++ b/test/core/bad_ssl/servers/alpn.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/transport/chttp2/alpn.h"
+#include "src/core/ext/transport/chttp2/alpn/alpn.h"
 #include "test/core/bad_ssl/server_common.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 
diff --git a/test/core/bad_ssl/servers/cert.c b/test/core/bad_ssl/servers/cert.c
index 4edef50..bd11efd 100644
--- a/test/core/bad_ssl/servers/cert.c
+++ b/test/core/bad_ssl/servers/cert.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/support/load_file.h"
+#include "src/core/lib/support/load_file.h"
 
 #include "test/core/bad_ssl/server_common.h"
 #include "test/core/end2end/data/ssl_test_data.h"
@@ -56,9 +56,11 @@
 
   grpc_init();
 
-  cert_slice = gpr_load_file("src/core/tsi/test_creds/badserver.pem", 1, &ok);
+  cert_slice =
+      gpr_load_file("src/core/lib/tsi/test_creds/badserver.pem", 1, &ok);
   GPR_ASSERT(ok);
-  key_slice = gpr_load_file("src/core/tsi/test_creds/badserver.key", 1, &ok);
+  key_slice =
+      gpr_load_file("src/core/lib/tsi/test_creds/badserver.key", 1, &ok);
   GPR_ASSERT(ok);
   pem_key_cert_pair.private_key = (const char *)GPR_SLICE_START_PTR(key_slice);
   pem_key_cert_pair.cert_chain = (const char *)GPR_SLICE_START_PTR(cert_slice);
diff --git a/test/core/census/context_test.c b/test/core/census/context_test.c
index ad4c337..e7a6538 100644
--- a/test/core/census/context_test.c
+++ b/test/core/census/context_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/census/mlog_test.c b/test/core/census/mlog_test.c
index 000ac73..36e8a49 100644
--- a/test/core/census/mlog_test.c
+++ b/test/core/census/mlog_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/census/mlog.h"
+#include "src/core/ext/census/mlog.h"
 #include <grpc/support/cpu.h>
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
diff --git a/test/core/channel/channel_args_test.c b/test/core/channel/channel_args_test.c
index 0b74dee..c7fc259 100644
--- a/test/core/channel/channel_args_test.c
+++ b/test/core/channel/channel_args_test.c
@@ -36,7 +36,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/channel/channel_args.h"
+#include "src/core/lib/channel/channel_args.h"
 
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c
index e19e9a5..81e3927 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/channel/channel_stack.h"
+#include "src/core/lib/channel/channel_stack.h"
 
 #include <string.h>
 
@@ -92,10 +92,17 @@
 }
 
 static void test_create_channel_stack(void) {
-  const grpc_channel_filter filter = {
-      call_func, channel_func, sizeof(int), call_init_func,
-      grpc_call_stack_ignore_set_pollset, call_destroy_func, sizeof(int),
-      channel_init_func, channel_destroy_func, get_peer, "some_test_filter"};
+  const grpc_channel_filter filter = {call_func,
+                                      channel_func,
+                                      sizeof(int),
+                                      call_init_func,
+                                      grpc_call_stack_ignore_set_pollset,
+                                      call_destroy_func,
+                                      sizeof(int),
+                                      channel_init_func,
+                                      channel_destroy_func,
+                                      get_peer,
+                                      "some_test_filter"};
   const grpc_channel_filter *filters = &filter;
   grpc_channel_stack *channel_stack;
   grpc_call_stack *call_stack;
diff --git a/test/core/client_config/lb_policies_test.c b/test/core/client_config/lb_policies_test.c
index 1ea0c42..e766672 100644
--- a/test/core/client_config/lb_policies_test.c
+++ b/test/core/client_config/lb_policies_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,13 +41,12 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 
-#include "src/core/channel/channel_stack.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/client_config/lb_policies/round_robin.h"
-#include "src/core/client_config/lb_policy_registry.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -139,8 +138,9 @@
   gpr_log(GPR_INFO, "KILLING SERVER %d", i);
   GPR_ASSERT(f->servers[i] != NULL);
   grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(
+      grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000), NULL)
+          .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->servers[i]);
   f->servers[i] = NULL;
 }
@@ -206,8 +206,8 @@
     if (f->servers[i] == NULL) continue;
     grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
     GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000),
-                                           n_millis_time(5000),
-                                           NULL).type == GRPC_OP_COMPLETE);
+                                           n_millis_time(5000), NULL)
+                   .type == GRPC_OP_COMPLETE);
     grpc_server_destroy(f->servers[i]);
   }
   grpc_completion_queue_shutdown(f->cq);
@@ -304,9 +304,10 @@
                grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL));
 
     s_idx = -1;
-    while ((ev = grpc_completion_queue_next(
-                f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10 * RETRY_TIMEOUT),
-                NULL)).type != GRPC_QUEUE_TIMEOUT) {
+    while (
+        (ev = grpc_completion_queue_next(
+             f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10 * RETRY_TIMEOUT), NULL))
+            .type != GRPC_QUEUE_TIMEOUT) {
       GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
       read_tag = ((int)(intptr_t)ev.tag);
       gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d",
@@ -378,9 +379,10 @@
       }
     }
 
-    GPR_ASSERT(grpc_completion_queue_next(
-                   f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(2 * RETRY_TIMEOUT),
-                   NULL).type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(
+        grpc_completion_queue_next(
+            f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(2 * RETRY_TIMEOUT), NULL)
+            .type == GRPC_QUEUE_TIMEOUT);
 
     grpc_metadata_array_destroy(&rdata->initial_metadata_recv);
     grpc_metadata_array_destroy(&rdata->trailing_metadata_recv);
@@ -870,6 +872,7 @@
 }
 
 int main(int argc, char **argv) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   test_spec *spec;
   size_t i;
   const size_t NUM_ITERS = 10;
@@ -877,11 +880,11 @@
 
   grpc_test_init(argc, argv);
   grpc_init();
-  grpc_lb_round_robin_trace = 1;
+  grpc_tracer_set_enabled("round_robin", 1);
 
-  GPR_ASSERT(grpc_lb_policy_create("this-lb-policy-does-not-exist", NULL) ==
-             NULL);
-  GPR_ASSERT(grpc_lb_policy_create(NULL, NULL) == NULL);
+  GPR_ASSERT(grpc_lb_policy_create(&exec_ctx, "this-lb-policy-does-not-exist",
+                                   NULL) == NULL);
+  GPR_ASSERT(grpc_lb_policy_create(&exec_ctx, NULL, NULL) == NULL);
 
   spec = test_spec_create(NUM_ITERS, NUM_SERVERS);
   /* everything is fine, all servers stay up the whole time and life's peachy */
@@ -933,6 +936,7 @@
   test_pending_calls(4);
   test_ping();
 
+  grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
   return 0;
 }
diff --git a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
index 75d1eb6..2322aa6 100644
--- a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,31 +31,38 @@
  *
  */
 
-#include "src/core/client_config/resolvers/dns_resolver.h"
-
 #include <string.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/timer.h"
+#include "src/core/ext/client_config/resolver_registry.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/timer.h"
 #include "test/core/util/test_config.h"
 
-static void subchannel_factory_ref(grpc_subchannel_factory *scv) {}
-static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_factory *scv) {}
-static grpc_subchannel *subchannel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
+static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
+static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
+                                         grpc_client_channel_factory *scv) {}
+static grpc_subchannel *client_channel_factory_create_subchannel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
     grpc_subchannel_args *args) {
   return NULL;
 }
 
-static const grpc_subchannel_factory_vtable sc_vtable = {
-    subchannel_factory_ref, subchannel_factory_unref,
-    subchannel_factory_create_subchannel};
+static grpc_channel *client_channel_factory_create_channel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
+    const char *target, grpc_client_channel_type type,
+    grpc_channel_args *args) {
+  GPR_UNREACHABLE_CODE(return NULL);
+}
 
-static grpc_subchannel_factory sc_factory = {&sc_vtable};
+static const grpc_client_channel_factory_vtable sc_vtable = {
+    client_channel_factory_ref, client_channel_factory_unref,
+    client_channel_factory_create_subchannel,
+    client_channel_factory_create_channel};
+
+static grpc_client_channel_factory cc_factory = {&sc_vtable};
 
 static gpr_mu g_mu;
 static bool g_fail_resolution = true;
@@ -79,13 +86,13 @@
 }
 
 static grpc_resolver *create_resolver(const char *name) {
-  grpc_resolver_factory *factory = grpc_dns_resolver_factory_create();
+  grpc_resolver_factory *factory = grpc_resolver_factory_lookup("dns");
   grpc_uri *uri = grpc_uri_parse(name, 0);
   GPR_ASSERT(uri);
   grpc_resolver_args args;
   memset(&args, 0, sizeof(args));
   args.uri = uri;
-  args.subchannel_factory = &sc_factory;
+  args.client_channel_factory = &cc_factory;
   grpc_resolver *resolver =
       grpc_resolver_factory_create_resolver(factory, &args);
   grpc_resolver_factory_unref(factory);
diff --git a/test/core/client_config/resolvers/dns_resolver_test.c b/test/core/client_config/resolvers/dns_resolver_test.c
index 38e76d5..21dc99c 100644
--- a/test/core/client_config/resolvers/dns_resolver_test.c
+++ b/test/core/client_config/resolvers/dns_resolver_test.c
@@ -31,29 +31,35 @@
  *
  */
 
-#include "src/core/client_config/resolvers/dns_resolver.h"
-
 #include <string.h>
 
 #include <grpc/support/log.h>
 
-#include "src/core/client_config/resolver.h"
+#include "src/core/ext/client_config/resolver_registry.h"
 #include "test/core/util/test_config.h"
 
-static void subchannel_factory_ref(grpc_subchannel_factory *scv) {}
-static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_factory *scv) {}
-static grpc_subchannel *subchannel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
+static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
+static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
+                                         grpc_client_channel_factory *scv) {}
+static grpc_subchannel *client_channel_factory_create_subchannel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
     grpc_subchannel_args *args) {
   GPR_UNREACHABLE_CODE(return NULL);
 }
 
-static const grpc_subchannel_factory_vtable sc_vtable = {
-    subchannel_factory_ref, subchannel_factory_unref,
-    subchannel_factory_create_subchannel};
+static grpc_channel *client_channel_factory_create_channel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
+    const char *target, grpc_client_channel_type type,
+    grpc_channel_args *args) {
+  GPR_UNREACHABLE_CODE(return NULL);
+}
 
-static grpc_subchannel_factory sc_factory = {&sc_vtable};
+static const grpc_client_channel_factory_vtable sc_vtable = {
+    client_channel_factory_ref, client_channel_factory_unref,
+    client_channel_factory_create_subchannel,
+    client_channel_factory_create_channel};
+
+static grpc_client_channel_factory cc_factory = {&sc_vtable};
 
 static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -65,7 +71,7 @@
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
-  args.subchannel_factory = &sc_factory;
+  args.client_channel_factory = &cc_factory;
   resolver = grpc_resolver_factory_create_resolver(factory, &args);
   GPR_ASSERT(resolver != NULL);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
@@ -92,8 +98,9 @@
 int main(int argc, char **argv) {
   grpc_resolver_factory *dns;
   grpc_test_init(argc, argv);
+  grpc_init();
 
-  dns = grpc_dns_resolver_factory_create();
+  dns = grpc_resolver_factory_lookup("dns");
 
   test_succeeds(dns, "dns:10.2.1.1");
   test_succeeds(dns, "dns:10.2.1.1:1234");
@@ -101,6 +108,7 @@
   test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
 
   grpc_resolver_factory_unref(dns);
+  grpc_shutdown();
 
   return 0;
 }
diff --git a/test/core/client_config/resolvers/sockaddr_resolver_test.c b/test/core/client_config/resolvers/sockaddr_resolver_test.c
index 8856c85..b11546b 100644
--- a/test/core/client_config/resolvers/sockaddr_resolver_test.c
+++ b/test/core/client_config/resolvers/sockaddr_resolver_test.c
@@ -31,29 +31,35 @@
  *
  */
 
-#include "src/core/client_config/resolvers/sockaddr_resolver.h"
-
 #include <string.h>
 
 #include <grpc/support/log.h>
 
-#include "src/core/client_config/resolver.h"
+#include "src/core/ext/client_config/resolver_registry.h"
 #include "test/core/util/test_config.h"
 
-static void subchannel_factory_ref(grpc_subchannel_factory *scv) {}
-static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_factory *scv) {}
-static grpc_subchannel *subchannel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
+static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
+static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
+                                         grpc_client_channel_factory *scv) {}
+static grpc_subchannel *client_channel_factory_create_subchannel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
     grpc_subchannel_args *args) {
   GPR_UNREACHABLE_CODE(return NULL);
 }
 
-static const grpc_subchannel_factory_vtable sc_vtable = {
-    subchannel_factory_ref, subchannel_factory_unref,
-    subchannel_factory_create_subchannel};
+static grpc_channel *client_channel_factory_create_channel(
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
+    const char *target, grpc_client_channel_type type,
+    grpc_channel_args *args) {
+  GPR_UNREACHABLE_CODE(return NULL);
+}
 
-static grpc_subchannel_factory sc_factory = {&sc_vtable};
+static const grpc_client_channel_factory_vtable sc_vtable = {
+    client_channel_factory_ref, client_channel_factory_unref,
+    client_channel_factory_create_subchannel,
+    client_channel_factory_create_channel};
+
+static grpc_client_channel_factory cc_factory = {&sc_vtable};
 
 static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -65,7 +71,7 @@
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
-  args.subchannel_factory = &sc_factory;
+  args.client_channel_factory = &cc_factory;
   resolver = grpc_resolver_factory_create_resolver(factory, &args);
   GPR_ASSERT(resolver != NULL);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
@@ -92,12 +98,14 @@
 int main(int argc, char **argv) {
   grpc_resolver_factory *ipv4, *ipv6;
   grpc_test_init(argc, argv);
+  grpc_init();
 
-  ipv4 = grpc_ipv4_resolver_factory_create();
-  ipv6 = grpc_ipv6_resolver_factory_create();
+  ipv4 = grpc_resolver_factory_lookup("ipv4");
+  ipv6 = grpc_resolver_factory_lookup("ipv6");
 
   test_fails(ipv4, "ipv4:10.2.1.1");
   test_succeeds(ipv4, "ipv4:10.2.1.1:1234");
+  test_succeeds(ipv4, "ipv4:10.2.1.1:1234,127.0.0.1:4321");
   test_fails(ipv4, "ipv4:10.2.1.1:123456");
   test_fails(ipv4, "ipv4:www.google.com");
   test_fails(ipv4, "ipv4:[");
@@ -111,6 +119,7 @@
 
   grpc_resolver_factory_unref(ipv4);
   grpc_resolver_factory_unref(ipv6);
+  grpc_shutdown();
 
   return 0;
 }
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 3cf267f..83058d9 100644
--- a/test/core/client_config/set_initial_connect_string_test.c
+++ b/test/core/client_config/set_initial_connect_string_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,10 +38,10 @@
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
 
-#include "src/core/client_config/initial_connect_string.h"
-#include "src/core/iomgr/sockaddr.h"
-#include "src/core/security/credentials.h"
-#include "src/core/support/string.h"
+#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/support/string.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_tcp_server.h"
diff --git a/test/core/client_config/uri_corpus/02d156dc5e6f2c11c90c2e06fcee04adf036a342 b/test/core/client_config/uri_corpus/02d156dc5e6f2c11c90c2e06fcee04adf036a342
new file mode 100644
index 0000000..a85e7a8
--- /dev/null
+++ b/test/core/client_config/uri_corpus/02d156dc5e6f2c11c90c2e06fcee04adf036a342
@@ -0,0 +1,2 @@
+::nix::ii///ii/\a‡?=n;iI_!';&b.cii??nn!%i!*%
+*;
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/042dc4512fa3d391c5170cf3aa61e6a638f84342 b/test/core/client_config/uri_corpus/042dc4512fa3d391c5170cf3aa61e6a638f84342
new file mode 100644
index 0000000..597a6db
--- /dev/null
+++ b/test/core/client_config/uri_corpus/042dc4512fa3d391c5170cf3aa61e6a638f84342
@@ -0,0 +1 @@
+i
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/0e9bbe975f2027e8c39c89f85f667530368e7d11 b/test/core/client_config/uri_corpus/0e9bbe975f2027e8c39c89f85f667530368e7d11
new file mode 100644
index 0000000..d56b8fc
--- /dev/null
+++ b/test/core/client_config/uri_corpus/0e9bbe975f2027e8c39c89f85f667530368e7d11
@@ -0,0 +1 @@
+:iiiÐ?+n!ij
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/1155aa6ea7ef262a81a63692513ea395f84dad6f b/test/core/client_config/uri_corpus/1155aa6ea7ef262a81a63692513ea395f84dad6f
new file mode 100644
index 0000000..5b913f1
--- /dev/null
+++ b/test/core/client_config/uri_corpus/1155aa6ea7ef262a81a63692513ea395f84dad6f
@@ -0,0 +1,2 @@
+:ipip~6:‡i:::1
+v:miP/ii:::/iu?n?n)i!=
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/13856a5569ffd085a4d5c07af5f8e9310835a118 b/test/core/client_config/uri_corpus/13856a5569ffd085a4d5c07af5f8e9310835a118
new file mode 100644
index 0000000..76f157c
--- /dev/null
+++ b/test/core/client_config/uri_corpus/13856a5569ffd085a4d5c07af5f8e9310835a118
@@ -0,0 +1 @@
+i:i:‡ii:i?nip~??ni=niI&6.u/n_!'p~
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/14b57bcbf1e17b1db1de491ef2ba3768f704b7dc b/test/core/client_config/uri_corpus/14b57bcbf1e17b1db1de491ef2ba3768f704b7dc
new file mode 100644
index 0000000..3936e89
--- /dev/null
+++ b/test/core/client_config/uri_corpus/14b57bcbf1e17b1db1de491ef2ba3768f704b7dc
@@ -0,0 +1 @@
+:‡i?=niI_!';ñ
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/1794310671a060eead6e5ee66ac978a18ec7e84f b/test/core/client_config/uri_corpus/1794310671a060eead6e5ee66ac978a18ec7e84f
new file mode 100644
index 0000000..a94c4cf
--- /dev/null
+++ b/test/core/client_config/uri_corpus/1794310671a060eead6e5ee66ac978a18ec7e84f
@@ -0,0 +1,2 @@
+~ipip~6::1
+v:Ð:1
diff --git a/test/core/client_config/uri_corpus/1d30b2a79afbaf2828ff42b9a9647e942ba1ab80 b/test/core/client_config/uri_corpus/1d30b2a79afbaf2828ff42b9a9647e942ba1ab80
new file mode 100644
index 0000000..875ac2a
--- /dev/null
+++ b/test/core/client_config/uri_corpus/1d30b2a79afbaf2828ff42b9a9647e942ba1ab80
@@ -0,0 +1 @@
+:il0P/8?n!$i:
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/1fcf5d9c333b70596cf5ba04d1f7affdf445b971 b/test/core/client_config/uri_corpus/1fcf5d9c333b70596cf5ba04d1f7affdf445b971
new file mode 100644
index 0000000..59469af
--- /dev/null
+++ b/test/core/client_config/uri_corpus/1fcf5d9c333b70596cf5ba04d1f7affdf445b971
@@ -0,0 +1,3 @@
+iiP*v:::pip~6:::0
+v:::11
+
diff --git a/test/core/client_config/uri_corpus/23162c8a8936e20b195404c21337ee734d02a6bc b/test/core/client_config/uri_corpus/23162c8a8936e20b195404c21337ee734d02a6bc
new file mode 100644
index 0000000..2f90235
--- /dev/null
+++ b/test/core/client_config/uri_corpus/23162c8a8936e20b195404c21337ee734d02a6bc
@@ -0,0 +1 @@
+:ii/i?n!%i*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/23f3198b815ca60bdadcaae682b9f965dda387f1 b/test/core/client_config/uri_corpus/23f3198b815ca60bdadcaae682b9f965dda387f1
new file mode 100644
index 0000000..4bdc3f6
--- /dev/null
+++ b/test/core/client_config/uri_corpus/23f3198b815ca60bdadcaae682b9f965dda387f1
@@ -0,0 +1 @@
+uni::.i?n(!ipR6/
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/2ef3893b43f1f60b77b59ce06a6bce9815d78eaf b/test/core/client_config/uri_corpus/2ef3893b43f1f60b77b59ce06a6bce9815d78eaf
new file mode 100644
index 0000000..fb7665d
--- /dev/null
+++ b/test/core/client_config/uri_corpus/2ef3893b43f1f60b77b59ce06a6bce9815d78eaf
@@ -0,0 +1,2 @@
+:/i?n!ipv6:./::abc.*
+
diff --git a/test/core/client_config/uri_corpus/356c3c129e203b5c74550b4209764d74b9caefce b/test/core/client_config/uri_corpus/356c3c129e203b5c74550b4209764d74b9caefce
new file mode 100644
index 0000000..6c1e22f
--- /dev/null
+++ b/test/core/client_config/uri_corpus/356c3c129e203b5c74550b4209764d74b9caefce
@@ -0,0 +1 @@
+unix://ii:#v6i?n!
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/396568fc41c8ccb31ec925b4a862e4d29ead1327 b/test/core/client_config/uri_corpus/396568fc41c8ccb31ec925b4a862e4d29ead1327
new file mode 100644
index 0000000..694d51d
--- /dev/null
+++ b/test/core/client_config/uri_corpus/396568fc41c8ccb31ec925b4a862e4d29ead1327
@@ -0,0 +1 @@
+uni:/i:i:‡i:i:‡i??ni=niIi??ni=niI__!!i?n!i'p'pR2p~~
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/3b1e7526a99918006b87e499d2beb6c4ac9c3c0c b/test/core/client_config/uri_corpus/3b1e7526a99918006b87e499d2beb6c4ac9c3c0c
new file mode 100644
index 0000000..af80f07
--- /dev/null
+++ b/test/core/client_config/uri_corpus/3b1e7526a99918006b87e499d2beb6c4ac9c3c0c
@@ -0,0 +1 @@
+i:i:‡i??ni=niI_!'p~
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/3b58860f3451d3e7aad99690a8d39782ca5116fc b/test/core/client_config/uri_corpus/3b58860f3451d3e7aad99690a8d39782ca5116fc
new file mode 100644
index 0000000..725b208
--- /dev/null
+++ b/test/core/client_config/uri_corpus/3b58860f3451d3e7aad99690a8d39782ca5116fc
@@ -0,0 +1,4 @@
+i:i?nip~&2./:::abipip~6c.*
+
+::1
+v:Ð:1
diff --git a/test/core/client_config/uri_corpus/41963cc10752f70c3af7e3d85868efb097a0ea9c b/test/core/client_config/uri_corpus/41963cc10752f70c3af7e3d85868efb097a0ea9c
new file mode 100644
index 0000000..7f0f2ea
--- /dev/null
+++ b/test/core/client_config/uri_corpus/41963cc10752f70c3af7e3d85868efb097a0ea9c
@@ -0,0 +1 @@
+:‡i?=niI_!';;
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/47b5228404451fc9d4071fa69192514bb4ce33c1 b/test/core/client_config/uri_corpus/47b5228404451fc9d4071fa69192514bb4ce33c1
new file mode 100644
index 0000000..23d52e1
--- /dev/null
+++ b/test/core/client_config/uri_corpus/47b5228404451fc9d4071fa69192514bb4ce33c1
@@ -0,0 +1 @@
+:iiP/i?n!'i*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/56a2da4b2e6fb795243901023ed8d0aa083d1aab b/test/core/client_config/uri_corpus/56a2da4b2e6fb795243901023ed8d0aa083d1aab
new file mode 100644
index 0000000..f975f97
--- /dev/null
+++ b/test/core/client_config/uri_corpus/56a2da4b2e6fb795243901023ed8d0aa083d1aab
@@ -0,0 +1 @@
+i:i?nip~&6.u/n
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/574c2f13858a9a6d724654bd913ede9ae3abf822 b/test/core/client_config/uri_corpus/574c2f13858a9a6d724654bd913ede9ae3abf822
new file mode 100644
index 0000000..d5fb7ba
--- /dev/null
+++ b/test/core/client_config/uri_corpus/574c2f13858a9a6d724654bd913ede9ae3abf822
@@ -0,0 +1,2 @@
+:unix://ii//a.b.ci?n!%
+*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/582f789c19033a152094cbf8565f14154a778ddb b/test/core/client_config/uri_corpus/582f789c19033a152094cbf8565f14154a778ddb
new file mode 100644
index 0000000..1860e1c
--- /dev/null
+++ b/test/core/client_config/uri_corpus/582f789c19033a152094cbf8565f14154a778ddb
@@ -0,0 +1 @@
+:‡i?P=niIii-i?%n'!%*i=
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/636c5606fc23713a1bae88c8899c0541cfad4fd8 b/test/core/client_config/uri_corpus/636c5606fc23713a1bae88c8899c0541cfad4fd8
new file mode 100644
index 0000000..1dc4931
--- /dev/null
+++ b/test/core/client_config/uri_corpus/636c5606fc23713a1bae88c8899c0541cfad4fd8
@@ -0,0 +1,4 @@
+:i?n!ip~f2:./::abipip~6c.*
+
+::1
+v:Ð:1
diff --git a/test/core/client_config/uri_corpus/63fe493b270b17426d77a27cbf3abac5b2c2794a b/test/core/client_config/uri_corpus/63fe493b270b17426d77a27cbf3abac5b2c2794a
new file mode 100644
index 0000000..7b95329
--- /dev/null
+++ b/test/core/client_config/uri_corpus/63fe493b270b17426d77a27cbf3abac5b2c2794a
@@ -0,0 +1 @@
+:‡i?=niI!';ñ
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/655300a902b62662296a8e46bfb04fbcb07182cb b/test/core/client_config/uri_corpus/655300a902b62662296a8e46bfb04fbcb07182cb
new file mode 100644
index 0000000..4eaca39
--- /dev/null
+++ b/test/core/client_config/uri_corpus/655300a902b62662296a8e46bfb04fbcb07182cb
@@ -0,0 +1 @@
+unix://ii:pv6i?n!
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/6ae3acd9d8507b61bf235748026080a4138dba58 b/test/core/client_config/uri_corpus/6ae3acd9d8507b61bf235748026080a4138dba58
new file mode 100644
index 0000000..fe908d2
--- /dev/null
+++ b/test/core/client_config/uri_corpus/6ae3acd9d8507b61bf235748026080a4138dba58
@@ -0,0 +1 @@
+uni::.ilP:%:%i:i‡i:‡i?=nii?n(!ipRI_&/.i;;!?=ii/?n#lniiI_!*Kii!/?ni*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/6b70979a70a038ff6607d6cf85485ee95baf58e6 b/test/core/client_config/uri_corpus/6b70979a70a038ff6607d6cf85485ee95baf58e6
new file mode 100644
index 0000000..57cbd72
--- /dev/null
+++ b/test/core/client_config/uri_corpus/6b70979a70a038ff6607d6cf85485ee95baf58e6
@@ -0,0 +1 @@
+uni::/i?n!ipR6/
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/7314ab3545a7535a26e0e8aad67caea5534d68b1 b/test/core/client_config/uri_corpus/7314ab3545a7535a26e0e8aad67caea5534d68b1
new file mode 100644
index 0000000..e13cf5a
--- /dev/null
+++ b/test/core/client_config/uri_corpus/7314ab3545a7535a26e0e8aad67caea5534d68b1
@@ -0,0 +1,2 @@
+ipip~6:::1
+v:::1
diff --git a/test/core/client_config/uri_corpus/7ff4d8b8d1ffd0d42c48bbb91e5856a9ec31aecb b/test/core/client_config/uri_corpus/7ff4d8b8d1ffd0d42c48bbb91e5856a9ec31aecb
new file mode 100644
index 0000000..0e7f44c
--- /dev/null
+++ b/test/core/client_config/uri_corpus/7ff4d8b8d1ffd0d42c48bbb91e5856a9ec31aecb
@@ -0,0 +1 @@
+i:i:‡i:i:‡i??ni=niIi??ni=niI__!!'p'p~~
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/87daa131e0973b77a232a870ed749ef29cf58e6d b/test/core/client_config/uri_corpus/87daa131e0973b77a232a870ed749ef29cf58e6d
new file mode 100644
index 0000000..679f13e
--- /dev/null
+++ b/test/core/client_config/uri_corpus/87daa131e0973b77a232a870ed749ef29cf58e6d
@@ -0,0 +1,2 @@
+unix:///a/:.:ii/i?nc!%
+i*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/884dcaee2908ffe5f12b65b8eba81016099c4266 b/test/core/client_config/uri_corpus/884dcaee2908ffe5f12b65b8eba81016099c4266
new file mode 100644
index 0000000..58ecc7e
--- /dev/null
+++ b/test/core/client_config/uri_corpus/884dcaee2908ffe5f12b65b8eba81016099c4266
@@ -0,0 +1 @@
+ip*v:::1
diff --git a/test/core/client_config/uri_corpus/8d7e944fd5d0ede94097fcc98b47b09a3f9c76cb b/test/core/client_config/uri_corpus/8d7e944fd5d0ede94097fcc98b47b09a3f9c76cb
new file mode 100644
index 0000000..ffd807b
--- /dev/null
+++ b/test/core/client_config/uri_corpus/8d7e944fd5d0ede94097fcc98b47b09a3f9c76cb
@@ -0,0 +1 @@
+ilP:%i:‡i?=niI_.i;;!ii/?nni*!
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/9671149af0b444f59bbdf71340d3441dadd8a7b4 b/test/core/client_config/uri_corpus/9671149af0b444f59bbdf71340d3441dadd8a7b4
new file mode 100644
index 0000000..8ad79f9
--- /dev/null
+++ b/test/core/client_config/uri_corpus/9671149af0b444f59bbdf71340d3441dadd8a7b4
@@ -0,0 +1 @@
+:‡i?P-niI%'i=
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/96c8d266b7dc037288ef305c996608270f72e7fb b/test/core/client_config/uri_corpus/96c8d266b7dc037288ef305c996608270f72e7fb
new file mode 100644
index 0000000..efb392b
--- /dev/null
+++ b/test/core/client_config/uri_corpus/96c8d266b7dc037288ef305c996608270f72e7fb
@@ -0,0 +1,2 @@
+:/i/n!ipv6:::/a.b.c1
+
diff --git a/test/core/client_config/uri_corpus/975536c71ade4800415a7e9c2f1b45c35a6d5ea8 b/test/core/client_config/uri_corpus/975536c71ade4800415a7e9c2f1b45c35a6d5ea8
new file mode 100644
index 0000000..7155222
--- /dev/null
+++ b/test/core/client_config/uri_corpus/975536c71ade4800415a7e9c2f1b45c35a6d5ea8
@@ -0,0 +1 @@
+ilP.i;?n!#i!;
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/99750aa67d30beaea8af565c829d4999aa8cb91b b/test/core/client_config/uri_corpus/99750aa67d30beaea8af565c829d4999aa8cb91b
new file mode 100644
index 0000000..4061e02
--- /dev/null
+++ b/test/core/client_config/uri_corpus/99750aa67d30beaea8af565c829d4999aa8cb91b
@@ -0,0 +1 @@
+unix::/i?n!ipv6/
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/a1140f3f8b5cffc1010221b9a4084a25fb75c1f6 b/test/core/client_config/uri_corpus/a1140f3f8b5cffc1010221b9a4084a25fb75c1f6
new file mode 100644
index 0000000..facb11c
--- /dev/null
+++ b/test/core/client_config/uri_corpus/a1140f3f8b5cffc1010221b9a4084a25fb75c1f6
@@ -0,0 +1 @@
+:%i:‡i?=niI_!ii/?ni*!
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/a1f0f9b75bb354eb063d7cba4fcfa2d0b88d63de b/test/core/client_config/uri_corpus/a1f0f9b75bb354eb063d7cba4fcfa2d0b88d63de
new file mode 100644
index 0000000..736e63e
--- /dev/null
+++ b/test/core/client_config/uri_corpus/a1f0f9b75bb354eb063d7cba4fcfa2d0b88d63de
@@ -0,0 +1 @@
+:¢ilP/i;n!#i:
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/a296eb3d1d436ed7df7195b10aa3c4de3896f98d b/test/core/client_config/uri_corpus/a296eb3d1d436ed7df7195b10aa3c4de3896f98d
new file mode 100644
index 0000000..dff2f89
--- /dev/null
+++ b/test/core/client_config/uri_corpus/a296eb3d1d436ed7df7195b10aa3c4de3896f98d
@@ -0,0 +1 @@
+u+ni::/i?n!ipR3/
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/a8b8e66050b424f1b8c07d46f868199fb7f60e38 b/test/core/client_config/uri_corpus/a8b8e66050b424f1b8c07d46f868199fb7f60e38
new file mode 100644
index 0000000..13a1154
--- /dev/null
+++ b/test/core/client_config/uri_corpus/a8b8e66050b424f1b8c07d46f868199fb7f60e38
@@ -0,0 +1 @@
+uni::pi:miP/?ni.!(Ri?)8/n!'i*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/aba1472880406a318ce207ee79815b7acf087757 b/test/core/client_config/uri_corpus/aba1472880406a318ce207ee79815b7acf087757
new file mode 100644
index 0000000..b7e7e97
--- /dev/null
+++ b/test/core/client_config/uri_corpus/aba1472880406a318ce207ee79815b7acf087757
@@ -0,0 +1 @@
+:iI/i?n!%š*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/af55baf8c8855e563befdf1eefbcbd46c5ddb8d2 b/test/core/client_config/uri_corpus/af55baf8c8855e563befdf1eefbcbd46c5ddb8d2
new file mode 100644
index 0000000..fe019fc
--- /dev/null
+++ b/test/core/client_config/uri_corpus/af55baf8c8855e563befdf1eefbcbd46c5ddb8d2
@@ -0,0 +1 @@
+uni::.i!in:/i/n!ipv6ž:?(pR;::/a.2b
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/b3c0bf66c2bf5d24ef1daf4cc5a9d6d5bd0e8bfd b/test/core/client_config/uri_corpus/b3c0bf66c2bf5d24ef1daf4cc5a9d6d5bd0e8bfd
new file mode 100644
index 0000000..6e12167
--- /dev/null
+++ b/test/core/client_config/uri_corpus/b3c0bf66c2bf5d24ef1daf4cc5a9d6d5bd0e8bfd
@@ -0,0 +1 @@
+:ii/iilP.i;?n?n!#i!;!%*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/c28a47409cf5d95bb372238d01e73d8b831408e4 b/test/core/client_config/uri_corpus/c28a47409cf5d95bb372238d01e73d8b831408e4
new file mode 100644
index 0000000..119b080
--- /dev/null
+++ b/test/core/client_config/uri_corpus/c28a47409cf5d95bb372238d01e73d8b831408e4
@@ -0,0 +1 @@
+:%i:i‡?=#liI_!Kii/?ni*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/c3ef1d41888063a08700c3add1e4465aabcf8807 b/test/core/client_config/uri_corpus/c3ef1d41888063a08700c3add1e4465aabcf8807
new file mode 100644
index 0000000..01db5d8
--- /dev/null
+++ b/test/core/client_config/uri_corpus/c3ef1d41888063a08700c3add1e4465aabcf8807
@@ -0,0 +1,2 @@
+::unix://ii//a‡?=niI_!';.b.ci?n!%
+*;
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/c550a76af21f9b9cc92a386d5c8998b26f8f2e4d b/test/core/client_config/uri_corpus/c550a76af21f9b9cc92a386d5c8998b26f8f2e4d
new file mode 100644
index 0000000..2ccb535
--- /dev/null
+++ b/test/core/client_config/uri_corpus/c550a76af21f9b9cc92a386d5c8998b26f8f2e4d
@@ -0,0 +1 @@
+uni::.i?n(!ipR&/
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/c79721406d0ab80495f186fd88e37fba98637ae9 b/test/core/client_config/uri_corpus/c79721406d0ab80495f186fd88e37fba98637ae9
new file mode 100644
index 0000000..f3c0404
--- /dev/null
+++ b/test/core/client_config/uri_corpus/c79721406d0ab80495f186fd88e37fba98637ae9
@@ -0,0 +1 @@
+::nix::ii///ii/\a:‡?=n;iI_!';&b.ciii
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/ceb4e2264ba7a8d5be47d276b37ec09489e00245 b/test/core/client_config/uri_corpus/ceb4e2264ba7a8d5be47d276b37ec09489e00245
new file mode 100644
index 0000000..b565522
--- /dev/null
+++ b/test/core/client_config/uri_corpus/ceb4e2264ba7a8d5be47d276b37ec09489e00245
@@ -0,0 +1 @@
+:‡i?P-niI!'iñ
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/cf4395958f5bfb46fd6f535a39657d016c75114c b/test/core/client_config/uri_corpus/cf4395958f5bfb46fd6f535a39657d016c75114c
new file mode 100644
index 0000000..a765672
--- /dev/null
+++ b/test/core/client_config/uri_corpus/cf4395958f5bfb46fd6f535a39657d016c75114c
@@ -0,0 +1 @@
+unix://ipv6:::
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/d46668372b7e20154a89409a7430a28e642afdca b/test/core/client_config/uri_corpus/d46668372b7e20154a89409a7430a28e642afdca
new file mode 100644
index 0000000..d658fb8
--- /dev/null
+++ b/test/core/client_config/uri_corpus/d46668372b7e20154a89409a7430a28e642afdca
@@ -0,0 +1 @@
+:ilP/i?n!#i:
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/d6fe7412a0a1d1c733160246f3fa425f4f97682a b/test/core/client_config/uri_corpus/d6fe7412a0a1d1c733160246f3fa425f4f97682a
new file mode 100644
index 0000000..6d37b5f
--- /dev/null
+++ b/test/core/client_config/uri_corpus/d6fe7412a0a1d1c733160246f3fa425f4f97682a
@@ -0,0 +1 @@
+:ilP/i?n,!#i:
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/dns.txt b/test/core/client_config/uri_corpus/dns.txt
new file mode 100644
index 0000000..577e105
--- /dev/null
+++ b/test/core/client_config/uri_corpus/dns.txt
@@ -0,0 +1 @@
+dns:10.2.1.1
diff --git a/test/core/client_config/uri_corpus/e241f29957b0e30ec11aaaf91b2339f7015fa5fd b/test/core/client_config/uri_corpus/e241f29957b0e30ec11aaaf91b2339f7015fa5fd
new file mode 100644
index 0000000..497bfd3
--- /dev/null
+++ b/test/core/client_config/uri_corpus/e241f29957b0e30ec11aaaf91b2339f7015fa5fd
@@ -0,0 +1 @@
+ilP:%:%i:i‡i:‡i?=niI_.i;;!?=ii/?n#lniiI_!*Kii!/?ni*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/ea02d9fea9bad5b89cf353a0169238f584177e71 b/test/core/client_config/uri_corpus/ea02d9fea9bad5b89cf353a0169238f584177e71
new file mode 100644
index 0000000..52f5a23
--- /dev/null
+++ b/test/core/client_config/uri_corpus/ea02d9fea9bad5b89cf353a0169238f584177e71
@@ -0,0 +1,4 @@
+i:i?n!ip~f2.:/::abipip~6c.*
+
+::1
+v:Ð:1
diff --git a/test/core/client_config/uri_corpus/ec4731dddf94ed3ea92ae4d5a71f145ab6e3f6ee b/test/core/client_config/uri_corpus/ec4731dddf94ed3ea92ae4d5a71f145ab6e3f6ee
new file mode 100644
index 0000000..c3c93fe
--- /dev/null
+++ b/test/core/client_config/uri_corpus/ec4731dddf94ed3ea92ae4d5a71f145ab6e3f6ee
@@ -0,0 +1 @@
+ii-i?n!%*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/ed2f78646f19fc47dd85ff0877c232b71913ece2 b/test/core/client_config/uri_corpus/ed2f78646f19fc47dd85ff0877c232b71913ece2
new file mode 100644
index 0000000..45065e2
--- /dev/null
+++ b/test/core/client_config/uri_corpus/ed2f78646f19fc47dd85ff0877c232b71913ece2
@@ -0,0 +1 @@
+:ii/i?n!%*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/f6889f4a6350fea1596a3adea5cdac02bd5d1ff3 b/test/core/client_config/uri_corpus/f6889f4a6350fea1596a3adea5cdac02bd5d1ff3
new file mode 100644
index 0000000..02151c8
--- /dev/null
+++ b/test/core/client_config/uri_corpus/f6889f4a6350fea1596a3adea5cdac02bd5d1ff3
@@ -0,0 +1,2 @@
+:ipip~6:::1
+vii/:::iunix:?n/1/ipv6!%
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/f6f3bd030f0d321efe7c51ca3f057de23509af67 b/test/core/client_config/uri_corpus/f6f3bd030f0d321efe7c51ca3f057de23509af67
new file mode 100644
index 0000000..8034e13
--- /dev/null
+++ b/test/core/client_config/uri_corpus/f6f3bd030f0d321efe7c51ca3f057de23509af67
@@ -0,0 +1 @@
+:iiP/i?n!i*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/f97598cff03306af3c70400608fec47268b5075d b/test/core/client_config/uri_corpus/f97598cff03306af3c70400608fec47268b5075d
new file mode 100644
index 0000000..240946d
--- /dev/null
+++ b/test/core/client_config/uri_corpus/f97598cff03306af3c70400608fec47268b5075d
@@ -0,0 +1,2 @@
+unix://ipv6:::/a.b.c1
+
diff --git a/test/core/client_config/uri_corpus/f9e1ec1fc642b575bc9955618b7065747f56b101 b/test/core/client_config/uri_corpus/f9e1ec1fc642b575bc9955618b7065747f56b101
new file mode 100644
index 0000000..d089a59
--- /dev/null
+++ b/test/core/client_config/uri_corpus/f9e1ec1fc642b575bc9955618b7065747f56b101
@@ -0,0 +1 @@
+:ilP.i;?n!#i;
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/fe0630a3aeed2ec6f474f362e4c839478290d5c4 b/test/core/client_config/uri_corpus/fe0630a3aeed2ec6f474f362e4c839478290d5c4
new file mode 100644
index 0000000..66eefbc
--- /dev/null
+++ b/test/core/client_config/uri_corpus/fe0630a3aeed2ec6f474f362e4c839478290d5c4
@@ -0,0 +1 @@
+:miP/i?)n!'i*
\ No newline at end of file
diff --git a/test/core/client_config/uri_corpus/ipv4.txt b/test/core/client_config/uri_corpus/ipv4.txt
new file mode 100644
index 0000000..fe29486
--- /dev/null
+++ b/test/core/client_config/uri_corpus/ipv4.txt
@@ -0,0 +1 @@
+ipv4:10.2.1.1
diff --git a/test/core/client_config/uri_corpus/ipv6.txt b/test/core/client_config/uri_corpus/ipv6.txt
new file mode 100644
index 0000000..7b6932b
--- /dev/null
+++ b/test/core/client_config/uri_corpus/ipv6.txt
@@ -0,0 +1 @@
+ipv6:::1
diff --git a/test/core/client_config/uri_corpus/unix.txt b/test/core/client_config/uri_corpus/unix.txt
new file mode 100644
index 0000000..7a0997e
--- /dev/null
+++ b/test/core/client_config/uri_corpus/unix.txt
@@ -0,0 +1 @@
+unix:///a.b.c
diff --git a/test/core/client_config/uri_fuzzer_test.c b/test/core/client_config/uri_fuzzer_test.c
new file mode 100644
index 0000000..eb976fc
--- /dev/null
+++ b/test/core/client_config/uri_fuzzer_test.c
@@ -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.
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/ext/client_config/uri_parser.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  char *s = gpr_malloc(size + 1);
+  memcpy(s, data, size);
+  s[size] = 0;
+
+  grpc_uri *x;
+  if ((x = grpc_uri_parse(s, 1))) {
+    grpc_uri_destroy(x);
+  }
+  gpr_free(s);
+  return 0;
+}
diff --git a/test/core/client_config/uri_parser_test.c b/test/core/client_config/uri_parser_test.c
index df12d6b..323e8b6 100644
--- a/test/core/client_config/uri_parser_test.c
+++ b/test/core/client_config/uri_parser_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/client_config/uri_parser.h"
+#include "src/core/ext/client_config/uri_parser.h"
 
 #include <string.h>
 
@@ -56,6 +56,73 @@
   GPR_ASSERT(NULL == grpc_uri_parse(uri_text, 0));
 }
 
+static void test_query_parts() {
+  {
+    const char *uri_text = "http://foo/path?a&b=B&c=&#frag";
+    grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+    GPR_ASSERT(uri);
+
+    GPR_ASSERT(0 == strcmp("http", uri->scheme));
+    GPR_ASSERT(0 == strcmp("foo", uri->authority));
+    GPR_ASSERT(0 == strcmp("/path", uri->path));
+    GPR_ASSERT(0 == strcmp("a&b=B&c=&", uri->query));
+    GPR_ASSERT(4 == uri->num_query_parts);
+
+    GPR_ASSERT(0 == strcmp("a", uri->query_parts[0]));
+    GPR_ASSERT(NULL == uri->query_parts_values[0]);
+
+    GPR_ASSERT(0 == strcmp("b", uri->query_parts[1]));
+    GPR_ASSERT(0 == strcmp("B", uri->query_parts_values[1]));
+
+    GPR_ASSERT(0 == strcmp("c", uri->query_parts[2]));
+    GPR_ASSERT(0 == strcmp("", uri->query_parts_values[2]));
+
+    GPR_ASSERT(0 == strcmp("", uri->query_parts[3]));
+    GPR_ASSERT(NULL == uri->query_parts_values[3]);
+
+    GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, "a"));
+    GPR_ASSERT(0 == strcmp("B", grpc_uri_get_query_arg(uri, "b")));
+    GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "c")));
+    GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, ""));
+
+    GPR_ASSERT(0 == strcmp("frag", uri->fragment));
+    grpc_uri_destroy(uri);
+  }
+  {
+    /* test the current behavior of multiple query part values */
+    const char *uri_text = "http://auth/path?foo=bar=baz&foobar==";
+    grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+    GPR_ASSERT(uri);
+
+    GPR_ASSERT(0 == strcmp("http", uri->scheme));
+    GPR_ASSERT(0 == strcmp("auth", uri->authority));
+    GPR_ASSERT(0 == strcmp("/path", uri->path));
+    GPR_ASSERT(0 == strcmp("foo=bar=baz&foobar==", uri->query));
+    GPR_ASSERT(2 == uri->num_query_parts);
+
+    GPR_ASSERT(0 == strcmp("bar", grpc_uri_get_query_arg(uri, "foo")));
+    GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "foobar")));
+
+    grpc_uri_destroy(uri);
+  }
+  {
+    /* empty query */
+    const char *uri_text = "http://foo/path";
+    grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+    GPR_ASSERT(uri);
+
+    GPR_ASSERT(0 == strcmp("http", uri->scheme));
+    GPR_ASSERT(0 == strcmp("foo", uri->authority));
+    GPR_ASSERT(0 == strcmp("/path", uri->path));
+    GPR_ASSERT(0 == strcmp("", uri->query));
+    GPR_ASSERT(0 == uri->num_query_parts);
+    GPR_ASSERT(NULL == uri->query_parts);
+    GPR_ASSERT(NULL == uri->query_parts_values);
+    GPR_ASSERT(0 == strcmp("", uri->fragment));
+    grpc_uri_destroy(uri);
+  }
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_succeeds("http://www.google.com", "http", "www.google.com", "", "", "");
@@ -82,5 +149,6 @@
   test_fails("http://foo?x[bar]");
   test_fails("http://foo?bar#lol#");
 
+  test_query_parts();
   return 0;
 }
diff --git a/test/core/compression/algorithm_test.c b/test/core/compression/algorithm_test.c
index 7de7e11..bdee748 100644
--- a/test/core/compression/algorithm_test.c
+++ b/test/core/compression/algorithm_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/compression/algorithm_metadata.h"
+#include "src/core/lib/compression/algorithm_metadata.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -40,7 +40,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/transport/static_metadata.h"
+#include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
 static void test_algorithm_mesh(void) {
diff --git a/test/core/compression/compression_test.c b/test/core/compression/compression_test.c
index 5d8231f..4c43746 100644
--- a/test/core/compression/compression_test.c
+++ b/test/core/compression/compression_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/compression/message_compress_test.c b/test/core/compression/message_compress_test.c
index 6d3d161..1a93903 100644
--- a/test/core/compression/message_compress_test.c
+++ b/test/core/compression/message_compress_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/compression/message_compress.h"
+#include "src/core/lib/compression/message_compress.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -40,7 +40,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/support/murmur_hash.h"
+#include "src/core/lib/support/murmur_hash.h"
 #include "test/core/util/slice_splitter.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c
index 724d419..77afe58 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -37,8 +37,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/surface/event_string.h"
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/byte_buffer_reader.h>
 #include <grpc/support/alloc.h>
@@ -46,6 +44,8 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/event_string.h"
 
 #define ROOT_EXPECTATION 1000
 
diff --git a/test/core/end2end/data/client_certs.c b/test/core/end2end/data/client_certs.c
new file mode 100644
index 0000000..9cdb704
--- /dev/null
+++ b/test/core/end2end/data/client_certs.c
@@ -0,0 +1,343 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+const char test_self_signed_client_cert[] = {
+    0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
+    0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
+    0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6f, 0x44, 0x43, 0x43,
+    0x41, 0x67, 0x6d, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4a,
+    0x41, 0x4e, 0x49, 0x7a, 0x32, 0x2f, 0x7a, 0x6f, 0x52, 0x69, 0x61, 0x70,
+    0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33,
+    0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4d, 0x47, 0x6b, 0x78,
+    0x43, 0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x59,
+    0x54, 0x41, 0x6b, 0x46, 0x56, 0x4d, 0x52, 0x4d, 0x77, 0x45, 0x51, 0x59,
+    0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x70, 0x54, 0x62, 0x32, 0x31,
+    0x6c, 0x4c, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x53, 0x45,
+    0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x42, 0x68,
+    0x4a, 0x62, 0x6e, 0x52, 0x6c, 0x63, 0x6d, 0x35, 0x6c, 0x64, 0x43, 0x42,
+    0x58, 0x0a, 0x61, 0x57, 0x52, 0x6e, 0x61, 0x58, 0x52, 0x7a, 0x49, 0x46,
+    0x42, 0x30, 0x65, 0x53, 0x42, 0x4d, 0x64, 0x47, 0x51, 0x78, 0x49, 0x6a,
+    0x41, 0x67, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x4d, 0x4d, 0x47, 0x57,
+    0x4a, 0x68, 0x5a, 0x47, 0x4e, 0x73, 0x61, 0x57, 0x56, 0x75, 0x64, 0x43,
+    0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, 0x76, 0x62, 0x32,
+    0x64, 0x73, 0x5a, 0x53, 0x35, 0x6a, 0x0a, 0x62, 0x32, 0x30, 0x77, 0x48,
+    0x68, 0x63, 0x4e, 0x4d, 0x54, 0x51, 0x77, 0x4e, 0x7a, 0x49, 0x34, 0x4d,
+    0x6a, 0x41, 0x77, 0x4f, 0x44, 0x49, 0x31, 0x57, 0x68, 0x63, 0x4e, 0x4d,
+    0x6a, 0x51, 0x77, 0x4e, 0x7a, 0x49, 0x31, 0x4d, 0x6a, 0x41, 0x77, 0x4f,
+    0x44, 0x49, 0x31, 0x57, 0x6a, 0x42, 0x70, 0x4d, 0x51, 0x73, 0x77, 0x43,
+    0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x42, 0x0a,
+    0x56, 0x54, 0x45, 0x54, 0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45,
+    0x43, 0x41, 0x77, 0x4b, 0x55, 0x32, 0x39, 0x74, 0x5a, 0x53, 0x31, 0x54,
+    0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45, 0x68, 0x4d, 0x42, 0x38, 0x47,
+    0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x59, 0x53, 0x57, 0x35, 0x30,
+    0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51, 0x67, 0x56, 0x32, 0x6c, 0x6b,
+    0x5a, 0x32, 0x6c, 0x30, 0x0a, 0x63, 0x79, 0x42, 0x51, 0x64, 0x48, 0x6b,
+    0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59,
+    0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x6c, 0x69, 0x59, 0x57, 0x52,
+    0x6a, 0x62, 0x47, 0x6c, 0x6c, 0x62, 0x6e, 0x51, 0x75, 0x64, 0x47, 0x56,
+    0x7a, 0x64, 0x43, 0x35, 0x6e, 0x62, 0x32, 0x39, 0x6e, 0x62, 0x47, 0x55,
+    0x75, 0x59, 0x32, 0x39, 0x74, 0x4d, 0x49, 0x47, 0x66, 0x0a, 0x4d, 0x41,
+    0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51,
+    0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x47, 0x4e, 0x41, 0x44,
+    0x43, 0x42, 0x69, 0x51, 0x4b, 0x42, 0x67, 0x51, 0x43, 0x79, 0x58, 0x32,
+    0x4a, 0x78, 0x5a, 0x2b, 0x4a, 0x35, 0x49, 0x2b, 0x64, 0x6c, 0x68, 0x52,
+    0x4f, 0x56, 0x74, 0x71, 0x6c, 0x4d, 0x51, 0x6e, 0x34, 0x37, 0x42, 0x42,
+    0x63, 0x72, 0x0a, 0x6c, 0x32, 0x47, 0x43, 0x6b, 0x76, 0x39, 0x4f, 0x31,
+    0x44, 0x31, 0x72, 0x4c, 0x39, 0x34, 0x4b, 0x57, 0x59, 0x62, 0x59, 0x31,
+    0x34, 0x48, 0x58, 0x68, 0x69, 0x2f, 0x6e, 0x61, 0x63, 0x42, 0x41, 0x51,
+    0x74, 0x43, 0x45, 0x51, 0x77, 0x58, 0x78, 0x70, 0x35, 0x44, 0x4b, 0x65,
+    0x6d, 0x47, 0x4f, 0x55, 0x6a, 0x75, 0x36, 0x35, 0x78, 0x4d, 0x39, 0x46,
+    0x39, 0x36, 0x2f, 0x33, 0x37, 0x34, 0x47, 0x0a, 0x4d, 0x76, 0x6e, 0x52,
+    0x4a, 0x64, 0x6f, 0x35, 0x32, 0x67, 0x4f, 0x73, 0x34, 0x48, 0x4f, 0x30,
+    0x63, 0x7a, 0x42, 0x70, 0x66, 0x56, 0x4e, 0x64, 0x58, 0x65, 0x65, 0x6f,
+    0x44, 0x2f, 0x52, 0x59, 0x67, 0x77, 0x74, 0x74, 0x66, 0x64, 0x4a, 0x72,
+    0x7a, 0x2f, 0x34, 0x61, 0x61, 0x74, 0x73, 0x53, 0x32, 0x51, 0x6b, 0x32,
+    0x79, 0x4d, 0x59, 0x70, 0x71, 0x5a, 0x6d, 0x71, 0x45, 0x4d, 0x73, 0x62,
+    0x0a, 0x72, 0x68, 0x39, 0x57, 0x32, 0x32, 0x4c, 0x70, 0x33, 0x72, 0x43,
+    0x42, 0x76, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6f, 0x31, 0x41,
+    0x77, 0x54, 0x6a, 0x41, 0x64, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x51, 0x34,
+    0x45, 0x46, 0x67, 0x51, 0x55, 0x35, 0x32, 0x33, 0x41, 0x4a, 0x4d, 0x52,
+    0x38, 0x44, 0x73, 0x39, 0x56, 0x38, 0x66, 0x68, 0x66, 0x37, 0x67, 0x75,
+    0x31, 0x69, 0x30, 0x4d, 0x4d, 0x0a, 0x55, 0x71, 0x41, 0x77, 0x48, 0x77,
+    0x59, 0x44, 0x56, 0x52, 0x30, 0x6a, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6f,
+    0x41, 0x55, 0x35, 0x32, 0x33, 0x41, 0x4a, 0x4d, 0x52, 0x38, 0x44, 0x73,
+    0x39, 0x56, 0x38, 0x66, 0x68, 0x66, 0x37, 0x67, 0x75, 0x31, 0x69, 0x30,
+    0x4d, 0x4d, 0x55, 0x71, 0x41, 0x77, 0x44, 0x41, 0x59, 0x44, 0x56, 0x52,
+    0x30, 0x54, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0a, 0x2f,
+    0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39,
+    0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4f, 0x42, 0x67,
+    0x51, 0x43, 0x49, 0x2f, 0x74, 0x76, 0x53, 0x42, 0x59, 0x48, 0x31, 0x69,
+    0x79, 0x66, 0x4c, 0x61, 0x43, 0x54, 0x42, 0x4b, 0x77, 0x70, 0x64, 0x6a,
+    0x33, 0x36, 0x2b, 0x4d, 0x6b, 0x52, 0x39, 0x45, 0x65, 0x4a, 0x4a, 0x6d,
+    0x49, 0x6d, 0x78, 0x0a, 0x58, 0x2b, 0x62, 0x6a, 0x68, 0x4b, 0x57, 0x58,
+    0x77, 0x73, 0x42, 0x58, 0x34, 0x50, 0x44, 0x4d, 0x57, 0x76, 0x64, 0x75,
+    0x73, 0x72, 0x2b, 0x2b, 0x51, 0x47, 0x55, 0x59, 0x74, 0x79, 0x6f, 0x79,
+    0x61, 0x2b, 0x68, 0x66, 0x59, 0x4d, 0x58, 0x52, 0x68, 0x58, 0x75, 0x61,
+    0x33, 0x39, 0x6d, 0x44, 0x35, 0x34, 0x78, 0x67, 0x6c, 0x6f, 0x51, 0x4e,
+    0x75, 0x75, 0x39, 0x52, 0x45, 0x44, 0x77, 0x58, 0x0a, 0x46, 0x66, 0x74,
+    0x6f, 0x2b, 0x61, 0x4f, 0x77, 0x33, 0x42, 0x63, 0x59, 0x64, 0x75, 0x63,
+    0x7a, 0x36, 0x6f, 0x66, 0x78, 0x69, 0x63, 0x46, 0x4b, 0x2f, 0x59, 0x32,
+    0x56, 0x65, 0x58, 0x44, 0x75, 0x72, 0x53, 0x4d, 0x70, 0x52, 0x76, 0x35,
+    0x54, 0x66, 0x47, 0x66, 0x32, 0x51, 0x72, 0x36, 0x65, 0x4f, 0x4f, 0x64,
+    0x61, 0x52, 0x68, 0x6a, 0x36, 0x65, 0x64, 0x37, 0x42, 0x69, 0x62, 0x48,
+    0x6b, 0x0a, 0x58, 0x31, 0x56, 0x47, 0x5a, 0x41, 0x3d, 0x3d, 0x0a, 0x2d,
+    0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54,
+    0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
+    0x0a, 0x00};
+
+const char test_self_signed_client_key[] = {
+    0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50,
+    0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d,
+    0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x64, 0x77, 0x49, 0x42,
+    0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47,
+    0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43,
+    0x41, 0x6d, 0x45, 0x77, 0x67, 0x67, 0x4a, 0x64, 0x41, 0x67, 0x45, 0x41,
+    0x41, 0x6f, 0x47, 0x42, 0x41, 0x4c, 0x4a, 0x66, 0x59, 0x6e, 0x46, 0x6e,
+    0x34, 0x6e, 0x6b, 0x6a, 0x35, 0x32, 0x57, 0x46, 0x0a, 0x45, 0x35, 0x57,
+    0x32, 0x71, 0x55, 0x78, 0x43, 0x66, 0x6a, 0x73, 0x45, 0x46, 0x79, 0x75,
+    0x58, 0x59, 0x59, 0x4b, 0x53, 0x2f, 0x30, 0x37, 0x55, 0x50, 0x57, 0x73,
+    0x76, 0x33, 0x67, 0x70, 0x5a, 0x68, 0x74, 0x6a, 0x58, 0x67, 0x64, 0x65,
+    0x47, 0x4c, 0x2b, 0x64, 0x70, 0x77, 0x45, 0x42, 0x43, 0x30, 0x49, 0x52,
+    0x44, 0x42, 0x66, 0x47, 0x6e, 0x6b, 0x4d, 0x70, 0x36, 0x59, 0x59, 0x35,
+    0x53, 0x0a, 0x4f, 0x37, 0x72, 0x6e, 0x45, 0x7a, 0x30, 0x58, 0x33, 0x72,
+    0x2f, 0x66, 0x76, 0x67, 0x59, 0x79, 0x2b, 0x64, 0x45, 0x6c, 0x32, 0x6a,
+    0x6e, 0x61, 0x41, 0x36, 0x7a, 0x67, 0x63, 0x37, 0x52, 0x7a, 0x4d, 0x47,
+    0x6c, 0x39, 0x55, 0x31, 0x31, 0x64, 0x35, 0x36, 0x67, 0x50, 0x39, 0x46,
+    0x69, 0x44, 0x43, 0x32, 0x31, 0x39, 0x30, 0x6d, 0x76, 0x50, 0x2f, 0x68,
+    0x70, 0x71, 0x32, 0x78, 0x4c, 0x5a, 0x0a, 0x43, 0x54, 0x62, 0x49, 0x78,
+    0x69, 0x6d, 0x70, 0x6d, 0x61, 0x6f, 0x51, 0x79, 0x78, 0x75, 0x75, 0x48,
+    0x31, 0x62, 0x62, 0x59, 0x75, 0x6e, 0x65, 0x73, 0x49, 0x47, 0x2f, 0x41,
+    0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67, 0x59, 0x41, 0x64, 0x71,
+    0x4a, 0x43, 0x45, 0x7a, 0x4d, 0x49, 0x79, 0x5a, 0x45, 0x37, 0x6f, 0x61,
+    0x57, 0x30, 0x74, 0x4f, 0x70, 0x63, 0x42, 0x30, 0x42, 0x69, 0x50, 0x0a,
+    0x46, 0x59, 0x6f, 0x49, 0x76, 0x48, 0x34, 0x42, 0x4b, 0x52, 0x48, 0x38,
+    0x65, 0x48, 0x76, 0x52, 0x34, 0x37, 0x36, 0x6d, 0x74, 0x2b, 0x59, 0x64,
+    0x44, 0x68, 0x42, 0x50, 0x31, 0x73, 0x63, 0x47, 0x55, 0x6d, 0x59, 0x65,
+    0x43, 0x54, 0x34, 0x45, 0x6a, 0x2b, 0x52, 0x67, 0x48, 0x76, 0x32, 0x4c,
+    0x50, 0x54, 0x67, 0x56, 0x59, 0x77, 0x54, 0x39, 0x65, 0x63, 0x69, 0x50,
+    0x32, 0x2b, 0x45, 0x2f, 0x0a, 0x43, 0x42, 0x43, 0x4e, 0x52, 0x65, 0x6c,
+    0x30, 0x53, 0x77, 0x39, 0x4a, 0x65, 0x70, 0x77, 0x57, 0x30, 0x72, 0x2b,
+    0x6a, 0x57, 0x4a, 0x74, 0x44, 0x59, 0x31, 0x70, 0x70, 0x36, 0x59, 0x58,
+    0x41, 0x67, 0x4e, 0x52, 0x47, 0x58, 0x32, 0x55, 0x66, 0x6c, 0x76, 0x55,
+    0x73, 0x54, 0x2b, 0x6f, 0x39, 0x6c, 0x5a, 0x76, 0x61, 0x67, 0x66, 0x39,
+    0x6d, 0x6f, 0x4c, 0x54, 0x4d, 0x79, 0x47, 0x76, 0x55, 0x0a, 0x75, 0x4c,
+    0x46, 0x6e, 0x73, 0x79, 0x66, 0x4c, 0x69, 0x6d, 0x31, 0x42, 0x34, 0x76,
+    0x58, 0x76, 0x57, 0x51, 0x4a, 0x42, 0x41, 0x4e, 0x6f, 0x75, 0x5a, 0x6c,
+    0x6c, 0x58, 0x47, 0x5a, 0x6f, 0x53, 0x72, 0x5a, 0x4c, 0x74, 0x52, 0x33,
+    0x56, 0x67, 0x56, 0x34, 0x74, 0x7a, 0x52, 0x51, 0x76, 0x4a, 0x78, 0x75,
+    0x38, 0x34, 0x6b, 0x4c, 0x65, 0x49, 0x6b, 0x36, 0x34, 0x4f, 0x76, 0x34,
+    0x37, 0x58, 0x0a, 0x70, 0x48, 0x56, 0x42, 0x4d, 0x54, 0x52, 0x42, 0x66,
+    0x7a, 0x50, 0x45, 0x68, 0x62, 0x42, 0x6f, 0x64, 0x6a, 0x72, 0x31, 0x6d,
+    0x35, 0x4f, 0x4c, 0x61, 0x56, 0x4c, 0x71, 0x6b, 0x46, 0x63, 0x58, 0x66,
+    0x74, 0x7a, 0x52, 0x43, 0x72, 0x62, 0x57, 0x6f, 0x4b, 0x73, 0x43, 0x51,
+    0x51, 0x44, 0x52, 0x53, 0x6f, 0x4c, 0x4c, 0x58, 0x4f, 0x69, 0x4c, 0x72,
+    0x74, 0x4a, 0x33, 0x44, 0x4c, 0x4a, 0x43, 0x0a, 0x72, 0x58, 0x37, 0x59,
+    0x38, 0x77, 0x72, 0x48, 0x5a, 0x72, 0x71, 0x6b, 0x35, 0x62, 0x4d, 0x64,
+    0x5a, 0x4c, 0x47, 0x61, 0x2f, 0x55, 0x58, 0x38, 0x52, 0x61, 0x6e, 0x68,
+    0x56, 0x77, 0x33, 0x2b, 0x58, 0x70, 0x2b, 0x75, 0x72, 0x64, 0x31, 0x37,
+    0x31, 0x31, 0x75, 0x6d, 0x65, 0x4e, 0x4a, 0x66, 0x7a, 0x75, 0x2f, 0x4d,
+    0x43, 0x6b, 0x34, 0x61, 0x31, 0x4b, 0x6b, 0x47, 0x2f, 0x43, 0x55, 0x30,
+    0x0a, 0x72, 0x71, 0x73, 0x39, 0x41, 0x6b, 0x41, 0x34, 0x63, 0x53, 0x78,
+    0x31, 0x44, 0x44, 0x31, 0x4a, 0x53, 0x47, 0x2b, 0x79, 0x78, 0x4d, 0x4e,
+    0x70, 0x73, 0x41, 0x53, 0x31, 0x78, 0x4a, 0x6f, 0x6d, 0x46, 0x49, 0x72,
+    0x73, 0x4d, 0x39, 0x76, 0x73, 0x50, 0x74, 0x37, 0x46, 0x64, 0x6e, 0x64,
+    0x44, 0x77, 0x72, 0x46, 0x2b, 0x79, 0x2b, 0x43, 0x6f, 0x76, 0x68, 0x44,
+    0x6b, 0x47, 0x59, 0x44, 0x6b, 0x0a, 0x52, 0x41, 0x48, 0x68, 0x2b, 0x73,
+    0x76, 0x47, 0x66, 0x5a, 0x67, 0x2f, 0x70, 0x51, 0x4b, 0x32, 0x4a, 0x52,
+    0x50, 0x69, 0x6d, 0x41, 0x6d, 0x48, 0x68, 0x7a, 0x71, 0x46, 0x41, 0x6b,
+    0x45, 0x41, 0x75, 0x36, 0x59, 0x61, 0x37, 0x30, 0x73, 0x32, 0x46, 0x55,
+    0x65, 0x42, 0x33, 0x4d, 0x75, 0x39, 0x61, 0x4a, 0x73, 0x32, 0x43, 0x44,
+    0x36, 0x68, 0x67, 0x33, 0x64, 0x51, 0x45, 0x56, 0x6b, 0x42, 0x0a, 0x35,
+    0x33, 0x44, 0x49, 0x37, 0x54, 0x58, 0x34, 0x38, 0x64, 0x39, 0x6b, 0x47,
+    0x57, 0x35, 0x38, 0x56, 0x58, 0x31, 0x78, 0x6e, 0x71, 0x53, 0x30, 0x32,
+    0x4c, 0x79, 0x57, 0x71, 0x41, 0x50, 0x63, 0x57, 0x35, 0x71, 0x6d, 0x31,
+    0x6b, 0x4c, 0x48, 0x46, 0x4c, 0x64, 0x6e, 0x64, 0x61, 0x50, 0x4e, 0x6d,
+    0x42, 0x61, 0x6a, 0x34, 0x51, 0x4a, 0x42, 0x41, 0x4a, 0x75, 0x67, 0x6c,
+    0x33, 0x36, 0x37, 0x0a, 0x39, 0x64, 0x39, 0x74, 0x2f, 0x51, 0x4c, 0x54,
+    0x53, 0x75, 0x55, 0x4c, 0x4c, 0x61, 0x6f, 0x59, 0x76, 0x32, 0x76, 0x4a,
+    0x54, 0x33, 0x73, 0x31, 0x79, 0x39, 0x48, 0x4e, 0x38, 0x39, 0x45, 0x6f,
+    0x61, 0x44, 0x44, 0x45, 0x6b, 0x50, 0x56, 0x66, 0x51, 0x75, 0x36, 0x47,
+    0x56, 0x45, 0x58, 0x67, 0x49, 0x42, 0x74, 0x69, 0x6d, 0x31, 0x73, 0x49,
+    0x2f, 0x56, 0x50, 0x53, 0x7a, 0x49, 0x38, 0x48, 0x0a, 0x61, 0x58, 0x76,
+    0x61, 0x54, 0x55, 0x77, 0x62, 0x6c, 0x46, 0x57, 0x53, 0x4d, 0x37, 0x30,
+    0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50,
+    0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d,
+    0x2d, 0x2d, 0x2d, 0x0a, 0x00};
+
+const char test_signed_client_cert[] = {
+    0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
+    0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
+    0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x48, 0x7a, 0x43, 0x43,
+    0x41, 0x59, 0x67, 0x43, 0x41, 0x51, 0x45, 0x77, 0x44, 0x51, 0x59, 0x4a,
+    0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x46,
+    0x42, 0x51, 0x41, 0x77, 0x56, 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47,
+    0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, 0x43, 0x51, 0x56, 0x55, 0x78,
+    0x45, 0x7a, 0x41, 0x52, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x67,
+    0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62, 0x57, 0x55, 0x74, 0x55, 0x33, 0x52,
+    0x68, 0x64, 0x47, 0x55, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4e,
+    0x56, 0x42, 0x41, 0x6f, 0x4d, 0x47, 0x45, 0x6c, 0x75, 0x64, 0x47, 0x56,
+    0x79, 0x62, 0x6d, 0x56, 0x30, 0x49, 0x46, 0x64, 0x70, 0x5a, 0x47, 0x64,
+    0x70, 0x64, 0x48, 0x4d, 0x67, 0x55, 0x48, 0x52, 0x35, 0x49, 0x45, 0x78,
+    0x30, 0x0a, 0x5a, 0x44, 0x45, 0x50, 0x4d, 0x41, 0x30, 0x47, 0x41, 0x31,
+    0x55, 0x45, 0x41, 0x77, 0x77, 0x47, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x47,
+    0x4e, 0x68, 0x4d, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x30, 0x4d, 0x44,
+    0x63, 0x78, 0x4e, 0x7a, 0x49, 0x7a, 0x4e, 0x54, 0x59, 0x77, 0x4d, 0x6c,
+    0x6f, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x44, 0x63, 0x78, 0x4e, 0x44,
+    0x49, 0x7a, 0x4e, 0x54, 0x59, 0x77, 0x0a, 0x4d, 0x6c, 0x6f, 0x77, 0x57,
+    0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42,
+    0x68, 0x4d, 0x43, 0x51, 0x56, 0x55, 0x78, 0x45, 0x7a, 0x41, 0x52, 0x42,
+    0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, 0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62,
+    0x57, 0x55, 0x74, 0x55, 0x33, 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x49,
+    0x54, 0x41, 0x66, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x0a,
+    0x47, 0x45, 0x6c, 0x75, 0x64, 0x47, 0x56, 0x79, 0x62, 0x6d, 0x56, 0x30,
+    0x49, 0x46, 0x64, 0x70, 0x5a, 0x47, 0x64, 0x70, 0x64, 0x48, 0x4d, 0x67,
+    0x55, 0x48, 0x52, 0x35, 0x49, 0x45, 0x78, 0x30, 0x5a, 0x44, 0x45, 0x54,
+    0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4b,
+    0x64, 0x47, 0x56, 0x7a, 0x64, 0x47, 0x4e, 0x73, 0x61, 0x57, 0x56, 0x75,
+    0x64, 0x44, 0x43, 0x42, 0x0a, 0x6e, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b,
+    0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45,
+    0x46, 0x41, 0x41, 0x4f, 0x42, 0x6a, 0x51, 0x41, 0x77, 0x67, 0x59, 0x6b,
+    0x43, 0x67, 0x59, 0x45, 0x41, 0x37, 0x46, 0x52, 0x48, 0x32, 0x36, 0x47,
+    0x2b, 0x46, 0x74, 0x35, 0x56, 0x51, 0x67, 0x79, 0x7a, 0x6c, 0x5a, 0x73,
+    0x66, 0x53, 0x6e, 0x48, 0x53, 0x5a, 0x36, 0x47, 0x58, 0x0a, 0x62, 0x37,
+    0x71, 0x78, 0x6d, 0x6b, 0x32, 0x50, 0x4f, 0x38, 0x54, 0x59, 0x71, 0x4b,
+    0x5a, 0x6d, 0x6b, 0x66, 0x4d, 0x77, 0x6b, 0x65, 0x36, 0x52, 0x55, 0x66,
+    0x51, 0x56, 0x2b, 0x53, 0x2b, 0x47, 0x7a, 0x52, 0x76, 0x7a, 0x35, 0x4c,
+    0x6c, 0x53, 0x33, 0x31, 0x55, 0x31, 0x51, 0x43, 0x70, 0x33, 0x63, 0x67,
+    0x77, 0x6b, 0x49, 0x49, 0x41, 0x51, 0x61, 0x31, 0x45, 0x32, 0x68, 0x43,
+    0x45, 0x7a, 0x0a, 0x57, 0x33, 0x31, 0x69, 0x76, 0x62, 0x4d, 0x42, 0x79,
+    0x52, 0x4b, 0x39, 0x74, 0x46, 0x70, 0x79, 0x6e, 0x34, 0x55, 0x76, 0x38,
+    0x4b, 0x50, 0x31, 0x34, 0x4f, 0x62, 0x4b, 0x6a, 0x54, 0x51, 0x71, 0x78,
+    0x55, 0x5a, 0x70, 0x35, 0x35, 0x38, 0x44, 0x67, 0x4f, 0x48, 0x67, 0x35,
+    0x62, 0x35, 0x6d, 0x47, 0x52, 0x4d, 0x30, 0x70, 0x79, 0x56, 0x31, 0x65,
+    0x71, 0x52, 0x4b, 0x36, 0x50, 0x57, 0x77, 0x0a, 0x52, 0x2f, 0x62, 0x6a,
+    0x67, 0x6c, 0x6c, 0x69, 0x36, 0x70, 0x6d, 0x6e, 0x72, 0x2b, 0x30, 0x43,
+    0x41, 0x77, 0x45, 0x41, 0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71,
+    0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46,
+    0x41, 0x41, 0x4f, 0x42, 0x67, 0x51, 0x41, 0x53, 0x74, 0x53, 0x6d, 0x35,
+    0x50, 0x4d, 0x37, 0x75, 0x62, 0x52, 0x4f, 0x69, 0x4b, 0x4b, 0x36, 0x2f,
+    0x0a, 0x54, 0x32, 0x46, 0x6b, 0x4b, 0x6c, 0x68, 0x69, 0x54, 0x4f, 0x78,
+    0x2b, 0x52, 0x79, 0x65, 0x6e, 0x6d, 0x33, 0x45, 0x69, 0x6f, 0x35, 0x39,
+    0x65, 0x6d, 0x71, 0x2b, 0x6a, 0x58, 0x6c, 0x2b, 0x31, 0x6e, 0x68, 0x50,
+    0x79, 0x53, 0x58, 0x35, 0x47, 0x32, 0x50, 0x51, 0x7a, 0x53, 0x52, 0x35,
+    0x76, 0x64, 0x31, 0x64, 0x49, 0x68, 0x77, 0x67, 0x5a, 0x53, 0x52, 0x34,
+    0x47, 0x79, 0x74, 0x74, 0x6b, 0x0a, 0x74, 0x52, 0x5a, 0x35, 0x37, 0x6b,
+    0x2f, 0x4e, 0x49, 0x31, 0x62, 0x72, 0x55, 0x57, 0x38, 0x6a, 0x6f, 0x69,
+    0x45, 0x4f, 0x4d, 0x4a, 0x41, 0x2f, 0x4d, 0x72, 0x37, 0x48, 0x37, 0x61,
+    0x73, 0x78, 0x37, 0x77, 0x49, 0x52, 0x59, 0x44, 0x45, 0x39, 0x31, 0x46,
+    0x73, 0x38, 0x47, 0x6b, 0x4b, 0x57, 0x64, 0x35, 0x4c, 0x68, 0x6f, 0x50,
+    0x41, 0x51, 0x6a, 0x2b, 0x71, 0x64, 0x47, 0x33, 0x35, 0x43, 0x0a, 0x4f,
+    0x4f, 0x2b, 0x73, 0x76, 0x64, 0x6b, 0x6d, 0x71, 0x48, 0x30, 0x4b, 0x5a,
+    0x6f, 0x33, 0x32, 0x30, 0x5a, 0x55, 0x71, 0x64, 0x6c, 0x32, 0x6f, 0x6f,
+    0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44,
+    0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45,
+    0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00};
+
+const char test_signed_client_key[] = {
+    0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50,
+    0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d,
+    0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x65, 0x51, 0x49, 0x42,
+    0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47,
+    0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43,
+    0x41, 0x6d, 0x4d, 0x77, 0x67, 0x67, 0x4a, 0x66, 0x41, 0x67, 0x45, 0x41,
+    0x41, 0x6f, 0x47, 0x42, 0x41, 0x4f, 0x78, 0x55, 0x52, 0x39, 0x75, 0x68,
+    0x76, 0x68, 0x62, 0x65, 0x56, 0x55, 0x49, 0x4d, 0x0a, 0x73, 0x35, 0x57,
+    0x62, 0x48, 0x30, 0x70, 0x78, 0x30, 0x6d, 0x65, 0x68, 0x6c, 0x32, 0x2b,
+    0x36, 0x73, 0x5a, 0x70, 0x4e, 0x6a, 0x7a, 0x76, 0x45, 0x32, 0x4b, 0x69,
+    0x6d, 0x5a, 0x70, 0x48, 0x7a, 0x4d, 0x4a, 0x48, 0x75, 0x6b, 0x56, 0x48,
+    0x30, 0x46, 0x66, 0x6b, 0x76, 0x68, 0x73, 0x30, 0x62, 0x38, 0x2b, 0x53,
+    0x35, 0x55, 0x74, 0x39, 0x56, 0x4e, 0x55, 0x41, 0x71, 0x64, 0x33, 0x49,
+    0x4d, 0x0a, 0x4a, 0x43, 0x43, 0x41, 0x45, 0x47, 0x74, 0x52, 0x4e, 0x6f,
+    0x51, 0x68, 0x4d, 0x31, 0x74, 0x39, 0x59, 0x72, 0x32, 0x7a, 0x41, 0x63,
+    0x6b, 0x53, 0x76, 0x62, 0x52, 0x61, 0x63, 0x70, 0x2b, 0x46, 0x4c, 0x2f,
+    0x43, 0x6a, 0x39, 0x65, 0x44, 0x6d, 0x79, 0x6f, 0x30, 0x30, 0x4b, 0x73,
+    0x56, 0x47, 0x61, 0x65, 0x65, 0x66, 0x41, 0x34, 0x44, 0x68, 0x34, 0x4f,
+    0x57, 0x2b, 0x5a, 0x68, 0x6b, 0x54, 0x0a, 0x4e, 0x4b, 0x63, 0x6c, 0x64,
+    0x58, 0x71, 0x6b, 0x53, 0x75, 0x6a, 0x31, 0x73, 0x45, 0x66, 0x32, 0x34,
+    0x34, 0x4a, 0x5a, 0x59, 0x75, 0x71, 0x5a, 0x70, 0x36, 0x2f, 0x74, 0x41,
+    0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67, 0x59, 0x45, 0x41, 0x69,
+    0x32, 0x4e, 0x53, 0x56, 0x71, 0x70, 0x5a, 0x4d, 0x61, 0x66, 0x45, 0x35,
+    0x59, 0x59, 0x55, 0x54, 0x63, 0x4d, 0x47, 0x65, 0x36, 0x51, 0x53, 0x0a,
+    0x6b, 0x32, 0x6a, 0x74, 0x70, 0x73, 0x71, 0x59, 0x67, 0x67, 0x67, 0x49,
+    0x32, 0x52, 0x6e, 0x4c, 0x4a, 0x2f, 0x32, 0x74, 0x4e, 0x5a, 0x77, 0x59,
+    0x49, 0x35, 0x70, 0x77, 0x50, 0x38, 0x51, 0x56, 0x53, 0x62, 0x6e, 0x4d,
+    0x61, 0x69, 0x46, 0x34, 0x67, 0x6f, 0x6b, 0x44, 0x35, 0x68, 0x47, 0x64,
+    0x72, 0x4e, 0x44, 0x66, 0x54, 0x6e, 0x62, 0x32, 0x76, 0x2b, 0x79, 0x49,
+    0x77, 0x59, 0x45, 0x48, 0x0a, 0x30, 0x77, 0x38, 0x2b, 0x6f, 0x47, 0x37,
+    0x5a, 0x38, 0x31, 0x4b, 0x6f, 0x64, 0x73, 0x69, 0x5a, 0x53, 0x49, 0x44,
+    0x4a, 0x66, 0x54, 0x47, 0x73, 0x41, 0x5a, 0x68, 0x56, 0x4e, 0x77, 0x4f,
+    0x7a, 0x39, 0x79, 0x30, 0x56, 0x44, 0x38, 0x42, 0x42, 0x5a, 0x5a, 0x31,
+    0x2f, 0x32, 0x37, 0x34, 0x5a, 0x68, 0x35, 0x32, 0x41, 0x55, 0x4b, 0x4c,
+    0x6a, 0x5a, 0x53, 0x2f, 0x5a, 0x77, 0x49, 0x62, 0x53, 0x0a, 0x57, 0x32,
+    0x79, 0x77, 0x79, 0x61, 0x38, 0x35, 0x35, 0x64, 0x50, 0x6e, 0x48, 0x2f,
+    0x77, 0x6a, 0x2b, 0x30, 0x45, 0x43, 0x51, 0x51, 0x44, 0x39, 0x58, 0x38,
+    0x44, 0x39, 0x32, 0x30, 0x6b, 0x42, 0x79, 0x54, 0x4e, 0x48, 0x68, 0x42,
+    0x47, 0x31, 0x38, 0x62, 0x69, 0x41, 0x45, 0x5a, 0x34, 0x70, 0x78, 0x73,
+    0x39, 0x66, 0x30, 0x4f, 0x41, 0x47, 0x38, 0x33, 0x33, 0x33, 0x65, 0x56,
+    0x63, 0x49, 0x0a, 0x77, 0x32, 0x6c, 0x4a, 0x44, 0x4c, 0x73, 0x59, 0x44,
+    0x5a, 0x72, 0x43, 0x42, 0x32, 0x6f, 0x63, 0x67, 0x41, 0x33, 0x6c, 0x55,
+    0x64, 0x6f, 0x7a, 0x6c, 0x7a, 0x50, 0x43, 0x37, 0x59, 0x44, 0x59, 0x77,
+    0x38, 0x72, 0x65, 0x67, 0x30, 0x74, 0x6b, 0x69, 0x52, 0x59, 0x35, 0x41,
+    0x6b, 0x45, 0x41, 0x37, 0x73, 0x64, 0x4e, 0x7a, 0x4f, 0x65, 0x51, 0x73,
+    0x51, 0x52, 0x6e, 0x37, 0x2b, 0x2b, 0x35, 0x0a, 0x30, 0x62, 0x50, 0x39,
+    0x44, 0x74, 0x54, 0x2f, 0x69, 0x4f, 0x4e, 0x31, 0x67, 0x62, 0x66, 0x78,
+    0x52, 0x7a, 0x43, 0x66, 0x43, 0x66, 0x58, 0x64, 0x6f, 0x4f, 0x74, 0x66,
+    0x51, 0x57, 0x49, 0x7a, 0x54, 0x65, 0x50, 0x57, 0x74, 0x55, 0x52, 0x74,
+    0x39, 0x58, 0x2f, 0x35, 0x44, 0x39, 0x4e, 0x6f, 0x66, 0x49, 0x30, 0x52,
+    0x67, 0x35, 0x57, 0x32, 0x6f, 0x47, 0x79, 0x2f, 0x4d, 0x4c, 0x65, 0x35,
+    0x0a, 0x2f, 0x73, 0x58, 0x48, 0x56, 0x51, 0x4a, 0x42, 0x41, 0x49, 0x75,
+    0x70, 0x35, 0x58, 0x72, 0x4a, 0x44, 0x6b, 0x51, 0x79, 0x77, 0x4e, 0x5a,
+    0x79, 0x41, 0x55, 0x55, 0x32, 0x65, 0x63, 0x6e, 0x32, 0x62, 0x43, 0x57,
+    0x42, 0x46, 0x6a, 0x77, 0x74, 0x71, 0x64, 0x2b, 0x4c, 0x42, 0x6d, 0x75,
+    0x4d, 0x63, 0x69, 0x49, 0x39, 0x66, 0x4f, 0x4b, 0x73, 0x5a, 0x74, 0x45,
+    0x4b, 0x5a, 0x72, 0x7a, 0x2f, 0x0a, 0x55, 0x30, 0x6c, 0x6b, 0x65, 0x4d,
+    0x52, 0x6f, 0x53, 0x77, 0x76, 0x58, 0x45, 0x38, 0x77, 0x6d, 0x47, 0x4c,
+    0x6a, 0x6a, 0x72, 0x41, 0x62, 0x64, 0x66, 0x6f, 0x68, 0x72, 0x58, 0x46,
+    0x6b, 0x43, 0x51, 0x51, 0x44, 0x5a, 0x45, 0x78, 0x2f, 0x4c, 0x74, 0x49,
+    0x6c, 0x36, 0x4a, 0x49, 0x4e, 0x4a, 0x51, 0x69, 0x73, 0x77, 0x56, 0x65,
+    0x30, 0x74, 0x57, 0x72, 0x36, 0x6b, 0x2b, 0x41, 0x53, 0x50, 0x0a, 0x31,
+    0x57, 0x58, 0x6f, 0x54, 0x6d, 0x2b, 0x48, 0x59, 0x70, 0x6f, 0x46, 0x2f,
+    0x58, 0x55, 0x76, 0x76, 0x39, 0x4c, 0x63, 0x63, 0x4e, 0x46, 0x31, 0x49,
+    0x61, 0x7a, 0x46, 0x6a, 0x33, 0x34, 0x68, 0x77, 0x52, 0x51, 0x77, 0x68,
+    0x78, 0x37, 0x77, 0x2f, 0x56, 0x35, 0x32, 0x49, 0x65, 0x62, 0x2b, 0x70,
+    0x30, 0x6a, 0x55, 0x4d, 0x59, 0x47, 0x78, 0x41, 0x6b, 0x45, 0x41, 0x6a,
+    0x44, 0x68, 0x64, 0x0a, 0x39, 0x70, 0x42, 0x4f, 0x31, 0x66, 0x4b, 0x58,
+    0x57, 0x69, 0x58, 0x7a, 0x69, 0x39, 0x5a, 0x4b, 0x66, 0x6f, 0x79, 0x54,
+    0x4e, 0x63, 0x55, 0x71, 0x33, 0x65, 0x42, 0x53, 0x56, 0x4b, 0x77, 0x50,
+    0x47, 0x32, 0x6e, 0x49, 0x74, 0x67, 0x35, 0x79, 0x63, 0x58, 0x65, 0x6e,
+    0x67, 0x6a, 0x54, 0x35, 0x73, 0x67, 0x63, 0x57, 0x44, 0x6e, 0x63, 0x69,
+    0x49, 0x7a, 0x57, 0x37, 0x42, 0x49, 0x56, 0x49, 0x0a, 0x4a, 0x69, 0x71,
+    0x4f, 0x73, 0x7a, 0x71, 0x39, 0x47, 0x57, 0x45, 0x53, 0x45, 0x72, 0x41,
+    0x61, 0x74, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45,
+    0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b,
+    0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00};
diff --git a/test/core/end2end/data/ssl_test_data.h b/test/core/end2end/data/ssl_test_data.h
index 675249d..4a64af1 100644
--- a/test/core/end2end/data/ssl_test_data.h
+++ b/test/core/end2end/data/ssl_test_data.h
@@ -37,5 +37,9 @@
 extern const char test_root_cert[];
 extern const char test_server1_cert[];
 extern const char test_server1_key[];
+extern const char test_self_signed_client_cert[];
+extern const char test_self_signed_client_key[];
+extern const char test_signed_client_cert[];
+extern const char test_signed_client_key[];
 
 #endif /* GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H */
diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c
index 58e13a4..81f76ea 100644
--- a/test/core/end2end/dualstack_socket_test.c
+++ b/test/core/end2end/dualstack_socket_test.c
@@ -39,9 +39,9 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/support/string.h"
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/socket_utils_posix.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/support/string.h"
 
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/util/port.h"
@@ -168,7 +168,7 @@
   op = ops;
   op->op = GRPC_OP_SEND_INITIAL_METADATA;
   op->data.send_initial_metadata.count = 0;
-  op->flags = 0;
+  op->flags = expect_ok ? GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY : 0;
   op->reserved = NULL;
   op++;
   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
@@ -237,7 +237,7 @@
     cq_expect_completion(cqv, tag(1), 1);
     cq_verify(cqv);
 
-    GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
+    GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
   }
 
   grpc_call_destroy(c);
@@ -249,9 +249,9 @@
 
   /* Destroy server. */
   grpc_server_shutdown_and_notify(server, cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(server);
   grpc_completion_queue_shutdown(cq);
   drain_cq(cq);
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c
index 17dc190..b71299c 100644
--- a/test/core/end2end/end2end_nosec_tests.c
+++ b/test/core/end2end/end2end_nosec_tests.c
@@ -1,7 +1,7 @@
 
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,49 +35,137 @@
 /* This file is auto-generated */
 
 #include "test/core/end2end/end2end_tests.h"
+
+#include <stdbool.h>
 #include <string.h>
+
 #include <grpc/support/log.h>
 
+static bool g_pre_init_called = false;
+
 extern void bad_hostname(grpc_end2end_test_config config);
+extern void bad_hostname_pre_init(void);
 extern void binary_metadata(grpc_end2end_test_config config);
+extern void binary_metadata_pre_init(void);
 extern void cancel_after_accept(grpc_end2end_test_config config);
+extern void cancel_after_accept_pre_init(void);
 extern void cancel_after_client_done(grpc_end2end_test_config config);
+extern void cancel_after_client_done_pre_init(void);
 extern void cancel_after_invoke(grpc_end2end_test_config config);
+extern void cancel_after_invoke_pre_init(void);
 extern void cancel_before_invoke(grpc_end2end_test_config config);
+extern void cancel_before_invoke_pre_init(void);
 extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
+extern void cancel_in_a_vacuum_pre_init(void);
 extern void cancel_with_status(grpc_end2end_test_config config);
+extern void cancel_with_status_pre_init(void);
 extern void compressed_payload(grpc_end2end_test_config config);
+extern void compressed_payload_pre_init(void);
 extern void connectivity(grpc_end2end_test_config config);
+extern void connectivity_pre_init(void);
 extern void default_host(grpc_end2end_test_config config);
+extern void default_host_pre_init(void);
 extern void disappearing_server(grpc_end2end_test_config config);
+extern void disappearing_server_pre_init(void);
 extern void empty_batch(grpc_end2end_test_config config);
+extern void empty_batch_pre_init(void);
+extern void filter_causes_close(grpc_end2end_test_config config);
+extern void filter_causes_close_pre_init(void);
 extern void graceful_server_shutdown(grpc_end2end_test_config config);
+extern void graceful_server_shutdown_pre_init(void);
 extern void high_initial_seqno(grpc_end2end_test_config config);
+extern void high_initial_seqno_pre_init(void);
 extern void hpack_size(grpc_end2end_test_config config);
+extern void hpack_size_pre_init(void);
+extern void idempotent_request(grpc_end2end_test_config config);
+extern void idempotent_request_pre_init(void);
 extern void invoke_large_request(grpc_end2end_test_config config);
+extern void invoke_large_request_pre_init(void);
 extern void large_metadata(grpc_end2end_test_config config);
+extern void large_metadata_pre_init(void);
 extern void max_concurrent_streams(grpc_end2end_test_config config);
+extern void max_concurrent_streams_pre_init(void);
 extern void max_message_length(grpc_end2end_test_config config);
+extern void max_message_length_pre_init(void);
 extern void negative_deadline(grpc_end2end_test_config config);
+extern void negative_deadline_pre_init(void);
 extern void no_op(grpc_end2end_test_config config);
+extern void no_op_pre_init(void);
 extern void payload(grpc_end2end_test_config config);
+extern void payload_pre_init(void);
 extern void ping(grpc_end2end_test_config config);
+extern void ping_pre_init(void);
 extern void ping_pong_streaming(grpc_end2end_test_config config);
+extern void ping_pong_streaming_pre_init(void);
 extern void registered_call(grpc_end2end_test_config config);
+extern void registered_call_pre_init(void);
 extern void request_with_flags(grpc_end2end_test_config config);
+extern void request_with_flags_pre_init(void);
 extern void request_with_payload(grpc_end2end_test_config config);
+extern void request_with_payload_pre_init(void);
 extern void server_finishes_request(grpc_end2end_test_config config);
+extern void server_finishes_request_pre_init(void);
 extern void shutdown_finishes_calls(grpc_end2end_test_config config);
+extern void shutdown_finishes_calls_pre_init(void);
 extern void shutdown_finishes_tags(grpc_end2end_test_config config);
+extern void shutdown_finishes_tags_pre_init(void);
 extern void simple_delayed_request(grpc_end2end_test_config config);
+extern void simple_delayed_request_pre_init(void);
 extern void simple_metadata(grpc_end2end_test_config config);
+extern void simple_metadata_pre_init(void);
 extern void simple_request(grpc_end2end_test_config config);
+extern void simple_request_pre_init(void);
 extern void trailing_metadata(grpc_end2end_test_config config);
+extern void trailing_metadata_pre_init(void);
+
+void grpc_end2end_tests_pre_init(void) {
+  GPR_ASSERT(!g_pre_init_called);
+  g_pre_init_called = true;
+  bad_hostname_pre_init();
+  binary_metadata_pre_init();
+  cancel_after_accept_pre_init();
+  cancel_after_client_done_pre_init();
+  cancel_after_invoke_pre_init();
+  cancel_before_invoke_pre_init();
+  cancel_in_a_vacuum_pre_init();
+  cancel_with_status_pre_init();
+  compressed_payload_pre_init();
+  connectivity_pre_init();
+  default_host_pre_init();
+  disappearing_server_pre_init();
+  empty_batch_pre_init();
+  filter_causes_close_pre_init();
+  graceful_server_shutdown_pre_init();
+  high_initial_seqno_pre_init();
+  hpack_size_pre_init();
+  idempotent_request_pre_init();
+  invoke_large_request_pre_init();
+  large_metadata_pre_init();
+  max_concurrent_streams_pre_init();
+  max_message_length_pre_init();
+  negative_deadline_pre_init();
+  no_op_pre_init();
+  payload_pre_init();
+  ping_pre_init();
+  ping_pong_streaming_pre_init();
+  registered_call_pre_init();
+  request_with_flags_pre_init();
+  request_with_payload_pre_init();
+  server_finishes_request_pre_init();
+  shutdown_finishes_calls_pre_init();
+  shutdown_finishes_tags_pre_init();
+  simple_delayed_request_pre_init();
+  simple_metadata_pre_init();
+  simple_request_pre_init();
+  trailing_metadata_pre_init();
+}
 
 void grpc_end2end_tests(int argc, char **argv,
                         grpc_end2end_test_config config) {
   int i;
 
+  GPR_ASSERT(g_pre_init_called);
+
   if (argc <= 1) {
     bad_hostname(config);
     binary_metadata(config);
@@ -92,9 +180,11 @@
     default_host(config);
     disappearing_server(config);
     empty_batch(config);
+    filter_causes_close(config);
     graceful_server_shutdown(config);
     high_initial_seqno(config);
     hpack_size(config);
+    idempotent_request(config);
     invoke_large_request(config);
     large_metadata(config);
     max_concurrent_streams(config);
@@ -170,6 +260,10 @@
       empty_batch(config);
       continue;
     }
+    if (0 == strcmp("filter_causes_close", argv[i])) {
+      filter_causes_close(config);
+      continue;
+    }
     if (0 == strcmp("graceful_server_shutdown", argv[i])) {
       graceful_server_shutdown(config);
       continue;
@@ -182,6 +276,10 @@
       hpack_size(config);
       continue;
     }
+    if (0 == strcmp("idempotent_request", argv[i])) {
+      idempotent_request(config);
+      continue;
+    }
     if (0 == strcmp("invoke_large_request", argv[i])) {
       invoke_large_request(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c
index 6f2f5af..00c9c44 100644
--- a/test/core/end2end/end2end_tests.c
+++ b/test/core/end2end/end2end_tests.c
@@ -1,7 +1,7 @@
 
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,50 +35,140 @@
 /* This file is auto-generated */
 
 #include "test/core/end2end/end2end_tests.h"
+
+#include <stdbool.h>
 #include <string.h>
+
 #include <grpc/support/log.h>
 
+static bool g_pre_init_called = false;
+
 extern void bad_hostname(grpc_end2end_test_config config);
+extern void bad_hostname_pre_init(void);
 extern void binary_metadata(grpc_end2end_test_config config);
+extern void binary_metadata_pre_init(void);
 extern void call_creds(grpc_end2end_test_config config);
+extern void call_creds_pre_init(void);
 extern void cancel_after_accept(grpc_end2end_test_config config);
+extern void cancel_after_accept_pre_init(void);
 extern void cancel_after_client_done(grpc_end2end_test_config config);
+extern void cancel_after_client_done_pre_init(void);
 extern void cancel_after_invoke(grpc_end2end_test_config config);
+extern void cancel_after_invoke_pre_init(void);
 extern void cancel_before_invoke(grpc_end2end_test_config config);
+extern void cancel_before_invoke_pre_init(void);
 extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
+extern void cancel_in_a_vacuum_pre_init(void);
 extern void cancel_with_status(grpc_end2end_test_config config);
+extern void cancel_with_status_pre_init(void);
 extern void compressed_payload(grpc_end2end_test_config config);
+extern void compressed_payload_pre_init(void);
 extern void connectivity(grpc_end2end_test_config config);
+extern void connectivity_pre_init(void);
 extern void default_host(grpc_end2end_test_config config);
+extern void default_host_pre_init(void);
 extern void disappearing_server(grpc_end2end_test_config config);
+extern void disappearing_server_pre_init(void);
 extern void empty_batch(grpc_end2end_test_config config);
+extern void empty_batch_pre_init(void);
+extern void filter_causes_close(grpc_end2end_test_config config);
+extern void filter_causes_close_pre_init(void);
 extern void graceful_server_shutdown(grpc_end2end_test_config config);
+extern void graceful_server_shutdown_pre_init(void);
 extern void high_initial_seqno(grpc_end2end_test_config config);
+extern void high_initial_seqno_pre_init(void);
 extern void hpack_size(grpc_end2end_test_config config);
+extern void hpack_size_pre_init(void);
+extern void idempotent_request(grpc_end2end_test_config config);
+extern void idempotent_request_pre_init(void);
 extern void invoke_large_request(grpc_end2end_test_config config);
+extern void invoke_large_request_pre_init(void);
 extern void large_metadata(grpc_end2end_test_config config);
+extern void large_metadata_pre_init(void);
 extern void max_concurrent_streams(grpc_end2end_test_config config);
+extern void max_concurrent_streams_pre_init(void);
 extern void max_message_length(grpc_end2end_test_config config);
+extern void max_message_length_pre_init(void);
 extern void negative_deadline(grpc_end2end_test_config config);
+extern void negative_deadline_pre_init(void);
 extern void no_op(grpc_end2end_test_config config);
+extern void no_op_pre_init(void);
 extern void payload(grpc_end2end_test_config config);
+extern void payload_pre_init(void);
 extern void ping(grpc_end2end_test_config config);
+extern void ping_pre_init(void);
 extern void ping_pong_streaming(grpc_end2end_test_config config);
+extern void ping_pong_streaming_pre_init(void);
 extern void registered_call(grpc_end2end_test_config config);
+extern void registered_call_pre_init(void);
 extern void request_with_flags(grpc_end2end_test_config config);
+extern void request_with_flags_pre_init(void);
 extern void request_with_payload(grpc_end2end_test_config config);
+extern void request_with_payload_pre_init(void);
 extern void server_finishes_request(grpc_end2end_test_config config);
+extern void server_finishes_request_pre_init(void);
 extern void shutdown_finishes_calls(grpc_end2end_test_config config);
+extern void shutdown_finishes_calls_pre_init(void);
 extern void shutdown_finishes_tags(grpc_end2end_test_config config);
+extern void shutdown_finishes_tags_pre_init(void);
 extern void simple_delayed_request(grpc_end2end_test_config config);
+extern void simple_delayed_request_pre_init(void);
 extern void simple_metadata(grpc_end2end_test_config config);
+extern void simple_metadata_pre_init(void);
 extern void simple_request(grpc_end2end_test_config config);
+extern void simple_request_pre_init(void);
 extern void trailing_metadata(grpc_end2end_test_config config);
+extern void trailing_metadata_pre_init(void);
+
+void grpc_end2end_tests_pre_init(void) {
+  GPR_ASSERT(!g_pre_init_called);
+  g_pre_init_called = true;
+  bad_hostname_pre_init();
+  binary_metadata_pre_init();
+  call_creds_pre_init();
+  cancel_after_accept_pre_init();
+  cancel_after_client_done_pre_init();
+  cancel_after_invoke_pre_init();
+  cancel_before_invoke_pre_init();
+  cancel_in_a_vacuum_pre_init();
+  cancel_with_status_pre_init();
+  compressed_payload_pre_init();
+  connectivity_pre_init();
+  default_host_pre_init();
+  disappearing_server_pre_init();
+  empty_batch_pre_init();
+  filter_causes_close_pre_init();
+  graceful_server_shutdown_pre_init();
+  high_initial_seqno_pre_init();
+  hpack_size_pre_init();
+  idempotent_request_pre_init();
+  invoke_large_request_pre_init();
+  large_metadata_pre_init();
+  max_concurrent_streams_pre_init();
+  max_message_length_pre_init();
+  negative_deadline_pre_init();
+  no_op_pre_init();
+  payload_pre_init();
+  ping_pre_init();
+  ping_pong_streaming_pre_init();
+  registered_call_pre_init();
+  request_with_flags_pre_init();
+  request_with_payload_pre_init();
+  server_finishes_request_pre_init();
+  shutdown_finishes_calls_pre_init();
+  shutdown_finishes_tags_pre_init();
+  simple_delayed_request_pre_init();
+  simple_metadata_pre_init();
+  simple_request_pre_init();
+  trailing_metadata_pre_init();
+}
 
 void grpc_end2end_tests(int argc, char **argv,
                         grpc_end2end_test_config config) {
   int i;
 
+  GPR_ASSERT(g_pre_init_called);
+
   if (argc <= 1) {
     bad_hostname(config);
     binary_metadata(config);
@@ -94,9 +184,11 @@
     default_host(config);
     disappearing_server(config);
     empty_batch(config);
+    filter_causes_close(config);
     graceful_server_shutdown(config);
     high_initial_seqno(config);
     hpack_size(config);
+    idempotent_request(config);
     invoke_large_request(config);
     large_metadata(config);
     max_concurrent_streams(config);
@@ -176,6 +268,10 @@
       empty_batch(config);
       continue;
     }
+    if (0 == strcmp("filter_causes_close", argv[i])) {
+      filter_causes_close(config);
+      continue;
+    }
     if (0 == strcmp("graceful_server_shutdown", argv[i])) {
       graceful_server_shutdown(config);
       continue;
@@ -188,6 +284,10 @@
       hpack_size(config);
       continue;
     }
+    if (0 == strcmp("idempotent_request", argv[i])) {
+      idempotent_request(config);
+      continue;
+    }
     if (0 == strcmp("invoke_large_request", argv[i])) {
       invoke_large_request(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index bc44f43..dfa041c 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -64,6 +64,7 @@
   void (*tear_down_data)(grpc_end2end_test_fixture *f);
 };
 
+void grpc_end2end_tests_pre_init(void);
 void grpc_end2end_tests(int argc, char **argv, grpc_end2end_test_config config);
 
 #endif /* GRPC_TEST_CORE_END2END_END2END_TESTS_H */
diff --git a/test/core/end2end/fixtures/h2_census.c b/test/core/end2end/fixtures/h2_census.c
index e74c9ae..ff2f028 100644
--- a/test/core/end2end/fixtures/h2_census.c
+++ b/test/core/end2end/fixtures/h2_census.c
@@ -35,19 +35,19 @@
 
 #include <string.h>
 
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -120,6 +120,7 @@
   size_t i;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_compress.c b/test/core/end2end/fixtures/h2_compress.c
index fea8a4f..8f9b7c9 100644
--- a/test/core/end2end/fixtures/h2_compress.c
+++ b/test/core/end2end/fixtures/h2_compress.c
@@ -35,19 +35,19 @@
 
 #include <string.h>
 
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -124,6 +124,7 @@
   size_t i;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_fakesec.c b/test/core/end2end/fixtures/h2_fakesec.c
index 2767f1d..246619b 100644
--- a/test/core/end2end/fixtures/h2_fakesec.c
+++ b/test/core/end2end/fixtures/h2_fakesec.c
@@ -36,14 +36,14 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/channel/channel_args.h"
-#include "src/core/security/credentials.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
-#include "test/core/util/test_config.h"
-#include "test/core/util/port.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/security/credentials.h"
 #include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
 
 typedef struct fullstack_secure_fixture_data {
   char *localaddr;
@@ -150,7 +150,7 @@
 int main(int argc, char **argv) {
   size_t i;
   grpc_test_init(argc, argv);
-
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_full+pipe.c b/test/core/end2end/fixtures/h2_full+pipe.c
index 4b93581..e7dfc56 100644
--- a/test/core/end2end/fixtures/h2_full+pipe.c
+++ b/test/core/end2end/fixtures/h2_full+pipe.c
@@ -35,21 +35,21 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
-#include "src/core/iomgr/wakeup_fd_posix.h"
 
 typedef struct fullstack_fixture_data {
   char *localaddr;
@@ -108,6 +108,7 @@
   grpc_allow_specialized_wakeup_fd = 0;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_full+poll+pipe.c b/test/core/end2end/fixtures/h2_full+poll+pipe.c
deleted file mode 100644
index 682598f..0000000
--- a/test/core/end2end/fixtures/h2_full+poll+pipe.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *
- * 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 "test/core/end2end/end2end_tests.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/iomgr/wakeup_fd_posix.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-typedef struct fullstack_fixture_data {
-  char *localaddr;
-} fullstack_fixture_data;
-
-static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
-    grpc_channel_args *client_args, grpc_channel_args *server_args) {
-  grpc_end2end_test_fixture f;
-  int port = grpc_pick_unused_port_or_die();
-  fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data));
-  memset(&f, 0, sizeof(f));
-
-  gpr_join_host_port(&ffd->localaddr, "localhost", port);
-
-  f.fixture_data = ffd;
-  f.cq = grpc_completion_queue_create(NULL);
-
-  return f;
-}
-
-void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f,
-                                  grpc_channel_args *client_args) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL);
-}
-
-void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
-                                  grpc_channel_args *server_args) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  if (f->server) {
-    grpc_server_destroy(f->server);
-  }
-  f->server = grpc_server_create(server_args, NULL);
-  grpc_server_register_completion_queue(f->server, f->cq, NULL);
-  GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr));
-  grpc_server_start(f->server);
-}
-
-void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  gpr_free(ffd->localaddr);
-  gpr_free(ffd);
-}
-
-/* All test configurations */
-static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
-     chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
-};
-
-int main(int argc, char **argv) {
-  size_t i;
-
-  grpc_allow_specialized_wakeup_fd = 0;
-  grpc_platform_become_multipoller = grpc_poll_become_multipoller;
-
-  grpc_test_init(argc, argv);
-  grpc_init();
-
-  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
-    grpc_end2end_tests(argc, argv, configs[i]);
-  }
-
-  grpc_shutdown();
-
-  return 0;
-}
diff --git a/test/core/end2end/fixtures/h2_full+poll.c b/test/core/end2end/fixtures/h2_full+poll.c
deleted file mode 100644
index 5a0b2ef..0000000
--- a/test/core/end2end/fixtures/h2_full+poll.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *
- * 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 "test/core/end2end/end2end_tests.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-typedef struct fullstack_fixture_data {
-  char *localaddr;
-} fullstack_fixture_data;
-
-static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
-    grpc_channel_args *client_args, grpc_channel_args *server_args) {
-  grpc_end2end_test_fixture f;
-  int port = grpc_pick_unused_port_or_die();
-  fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data));
-  memset(&f, 0, sizeof(f));
-
-  gpr_join_host_port(&ffd->localaddr, "localhost", port);
-
-  f.fixture_data = ffd;
-  f.cq = grpc_completion_queue_create(NULL);
-
-  return f;
-}
-
-void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f,
-                                  grpc_channel_args *client_args) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL);
-}
-
-void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
-                                  grpc_channel_args *server_args) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  if (f->server) {
-    grpc_server_destroy(f->server);
-  }
-  f->server = grpc_server_create(server_args, NULL);
-  grpc_server_register_completion_queue(f->server, f->cq, NULL);
-  GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr));
-  grpc_server_start(f->server);
-}
-
-void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  gpr_free(ffd->localaddr);
-  gpr_free(ffd);
-}
-
-/* All test configurations */
-static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
-     chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
-};
-
-int main(int argc, char **argv) {
-  size_t i;
-
-  grpc_platform_become_multipoller = grpc_poll_become_multipoller;
-
-  grpc_test_init(argc, argv);
-  grpc_init();
-
-  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
-    grpc_end2end_tests(argc, argv, configs[i]);
-  }
-
-  grpc_shutdown();
-
-  return 0;
-}
diff --git a/test/core/end2end/fixtures/h2_full+trace.c b/test/core/end2end/fixtures/h2_full+trace.c
index 90b0063..c4dc5b9 100644
--- a/test/core/end2end/fixtures/h2_full+trace.c
+++ b/test/core/end2end/fixtures/h2_full+trace.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,21 +35,21 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
-#include "src/core/support/env.h"
 
 typedef struct fullstack_fixture_data {
   char *localaddr;
@@ -116,16 +116,17 @@
 #endif
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
-  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
-    grpc_end2end_tests(argc, argv, configs[i]);
-  }
-
   GPR_ASSERT(0 == grpc_tracer_set_enabled("also-doesnt-exist", 0));
   GPR_ASSERT(1 == grpc_tracer_set_enabled("http", 1));
   GPR_ASSERT(1 == grpc_tracer_set_enabled("all", 1));
 
+  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
+    grpc_end2end_tests(argc, argv, configs[i]);
+  }
+
   grpc_shutdown();
 
   return 0;
diff --git a/test/core/end2end/fixtures/h2_full.c b/test/core/end2end/fixtures/h2_full.c
index ebaa1c6..4a2f17e 100644
--- a/test/core/end2end/fixtures/h2_full.c
+++ b/test/core/end2end/fixtures/h2_full.c
@@ -35,18 +35,18 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -105,6 +105,7 @@
   size_t i;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c
index e2c8291..550ff33 100644
--- a/test/core/end2end/fixtures/h2_oauth2.c
+++ b/test/core/end2end/fixtures/h2_oauth2.c
@@ -36,15 +36,15 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/channel/channel_args.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/security/credentials.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
-#include "test/core/util/test_config.h"
-#include "test/core/util/port.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/security/credentials.h"
 #include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
 
 static const char oauth2_md[] = "Bearer aaslkfjs424535asdf";
 static const char *client_identity_property_name = "smurf_name";
@@ -226,7 +226,7 @@
 int main(int argc, char **argv) {
   size_t i;
   grpc_test_init(argc, argv);
-
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_proxy.c b/test/core/end2end/fixtures/h2_proxy.c
index 8bcc1b6..863673a 100644
--- a/test/core/end2end/fixtures/h2_proxy.c
+++ b/test/core/end2end/fixtures/h2_proxy.c
@@ -35,18 +35,18 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/end2end/fixtures/proxy.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -120,6 +120,7 @@
   size_t i;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c
index 482aa8d..87533a9 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.c
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,22 +35,22 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_client_filter.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/support/env.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/iomgr/endpoint_pair.h"
+#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/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -150,6 +150,7 @@
 #endif
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
   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 cf1c4ac..f28147c 100644
--- a/test/core/end2end/fixtures/h2_sockpair.c
+++ b/test/core/end2end/fixtures/h2_sockpair.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,21 +35,21 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_client_filter.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#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/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -139,6 +139,7 @@
   size_t i;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c
index f49938c..302b16b 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.c
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,21 +35,21 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_client_filter.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#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/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -139,6 +139,7 @@
   size_t i;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/h2_ssl+poll.c b/test/core/end2end/fixtures/h2_ssl+poll.c
deleted file mode 100644
index 66268c7..0000000
--- a/test/core/end2end/fixtures/h2_ssl+poll.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- *
- * 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 "test/core/end2end/end2end_tests.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-
-#include "src/core/channel/channel_args.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/security/credentials.h"
-#include "src/core/support/env.h"
-#include "src/core/support/tmpfile.h"
-#include "src/core/support/string.h"
-#include "test/core/end2end/data/ssl_test_data.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-typedef struct fullstack_secure_fixture_data {
-  char *localaddr;
-} fullstack_secure_fixture_data;
-
-static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
-    grpc_channel_args *client_args, grpc_channel_args *server_args) {
-  grpc_end2end_test_fixture f;
-  int port = grpc_pick_unused_port_or_die();
-  fullstack_secure_fixture_data *ffd =
-      gpr_malloc(sizeof(fullstack_secure_fixture_data));
-  memset(&f, 0, sizeof(f));
-
-  gpr_join_host_port(&ffd->localaddr, "localhost", port);
-
-  f.fixture_data = ffd;
-  f.cq = grpc_completion_queue_create(NULL);
-
-  return f;
-}
-
-static void process_auth_failure(void *state, grpc_auth_context *ctx,
-                                 const grpc_metadata *md, size_t md_count,
-                                 grpc_process_auth_metadata_done_cb cb,
-                                 void *user_data) {
-  GPR_ASSERT(state == NULL);
-  cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
-}
-
-static void chttp2_init_client_secure_fullstack(
-    grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
-    grpc_channel_credentials *creds) {
-  fullstack_secure_fixture_data *ffd = f->fixture_data;
-  f->client =
-      grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL);
-  GPR_ASSERT(f->client != NULL);
-  grpc_channel_credentials_release(creds);
-}
-
-static void chttp2_init_server_secure_fullstack(
-    grpc_end2end_test_fixture *f, grpc_channel_args *server_args,
-    grpc_server_credentials *server_creds) {
-  fullstack_secure_fixture_data *ffd = f->fixture_data;
-  if (f->server) {
-    grpc_server_destroy(f->server);
-  }
-  f->server = grpc_server_create(server_args, NULL);
-  grpc_server_register_completion_queue(f->server, f->cq, NULL);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr,
-                                               server_creds));
-  grpc_server_credentials_release(server_creds);
-  grpc_server_start(f->server);
-}
-
-void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
-  fullstack_secure_fixture_data *ffd = f->fixture_data;
-  gpr_free(ffd->localaddr);
-  gpr_free(ffd);
-}
-
-static void chttp2_init_client_simple_ssl_secure_fullstack(
-    grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
-  grpc_channel_credentials *ssl_creds =
-      grpc_ssl_credentials_create(NULL, NULL, NULL);
-  grpc_arg ssl_name_override = {GRPC_ARG_STRING,
-                                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
-                                {"foo.test.google.fr"}};
-  grpc_channel_args *new_client_args =
-      grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
-  chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);
-  grpc_channel_args_destroy(new_client_args);
-}
-
-static int fail_server_auth_check(grpc_channel_args *server_args) {
-  size_t i;
-  if (server_args == NULL) return 0;
-  for (i = 0; i < server_args->num_args; i++) {
-    if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) ==
-        0) {
-      return 1;
-    }
-  }
-  return 0;
-}
-
-static void chttp2_init_server_simple_ssl_secure_fullstack(
-    grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
-  grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,
-                                                  test_server1_cert};
-  grpc_server_credentials *ssl_creds =
-      grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
-  if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
-    grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
-  }
-  chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
-}
-
-/* All test configurations */
-
-static grpc_end2end_test_config configs[] = {
-    {"chttp2/simple_ssl_fullstack",
-     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
-     chttp2_create_fixture_secure_fullstack,
-     chttp2_init_client_simple_ssl_secure_fullstack,
-     chttp2_init_server_simple_ssl_secure_fullstack,
-     chttp2_tear_down_secure_fullstack},
-};
-
-int main(int argc, char **argv) {
-  size_t i;
-  FILE *roots_file;
-  size_t roots_size = strlen(test_root_cert);
-  char *roots_filename;
-
-  grpc_platform_become_multipoller = grpc_poll_become_multipoller;
-
-  grpc_test_init(argc, argv);
-
-  /* Set the SSL roots env var. */
-  roots_file = gpr_tmpfile("chttp2_simple_ssl_with_poll_fullstack_test",
-                           &roots_filename);
-  GPR_ASSERT(roots_filename != NULL);
-  GPR_ASSERT(roots_file != NULL);
-  GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size);
-  fclose(roots_file);
-  gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename);
-
-  grpc_init();
-
-  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
-    grpc_end2end_tests(argc, argv, configs[i]);
-  }
-
-  grpc_shutdown();
-
-  /* Cleanup. */
-  remove(roots_filename);
-  gpr_free(roots_filename);
-
-  return 0;
-}
diff --git a/test/core/end2end/fixtures/h2_ssl.c b/test/core/end2end/fixtures/h2_ssl.c
index e21a347..69f7616 100644
--- a/test/core/end2end/fixtures/h2_ssl.c
+++ b/test/core/end2end/fixtures/h2_ssl.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,11 +40,11 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 
-#include "src/core/channel/channel_args.h"
-#include "src/core/security/credentials.h"
-#include "src/core/support/env.h"
-#include "src/core/support/tmpfile.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/tmpfile.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -165,6 +165,7 @@
   char *roots_filename;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
 
   /* Set the SSL roots env var. */
   roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename);
diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/fixtures/h2_ssl_cert.c
new file mode 100644
index 0000000..cd031ca
--- /dev/null
+++ b/test/core/end2end/fixtures/h2_ssl_cert.c
@@ -0,0 +1,376 @@
+/*
+ *
+ * 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 "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#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/support/env.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/tmpfile.h"
+#include "test/core/end2end/cq_verifier.h"
+#include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+extern void simple_request(grpc_end2end_test_config config);
+
+typedef struct fullstack_secure_fixture_data {
+  char *localaddr;
+} fullstack_secure_fixture_data;
+
+static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
+    grpc_channel_args *client_args, grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  int port = grpc_pick_unused_port_or_die();
+  fullstack_secure_fixture_data *ffd =
+      gpr_malloc(sizeof(fullstack_secure_fixture_data));
+  memset(&f, 0, sizeof(f));
+
+  gpr_join_host_port(&ffd->localaddr, "localhost", port);
+
+  f.fixture_data = ffd;
+  f.cq = grpc_completion_queue_create(NULL);
+
+  return f;
+}
+
+static void process_auth_failure(void *state, grpc_auth_context *ctx,
+                                 const grpc_metadata *md, size_t md_count,
+                                 grpc_process_auth_metadata_done_cb cb,
+                                 void *user_data) {
+  GPR_ASSERT(state == NULL);
+  cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
+}
+
+static void chttp2_init_client_secure_fullstack(
+    grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
+    grpc_channel_credentials *creds) {
+  fullstack_secure_fixture_data *ffd = f->fixture_data;
+  f->client =
+      grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL);
+  GPR_ASSERT(f->client != NULL);
+  grpc_channel_credentials_release(creds);
+}
+
+static void chttp2_init_server_secure_fullstack(
+    grpc_end2end_test_fixture *f, grpc_channel_args *server_args,
+    grpc_server_credentials *server_creds) {
+  fullstack_secure_fixture_data *ffd = f->fixture_data;
+  if (f->server) {
+    grpc_server_destroy(f->server);
+  }
+  f->server = grpc_server_create(server_args, NULL);
+  grpc_server_register_completion_queue(f->server, f->cq, NULL);
+  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr,
+                                               server_creds));
+  grpc_server_credentials_release(server_creds);
+  grpc_server_start(f->server);
+}
+
+void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
+  fullstack_secure_fixture_data *ffd = f->fixture_data;
+  gpr_free(ffd->localaddr);
+  gpr_free(ffd);
+}
+
+static int fail_server_auth_check(grpc_channel_args *server_args) {
+  size_t i;
+  if (server_args == NULL) return 0;
+  for (i = 0; i < server_args->num_args; i++) {
+    if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) ==
+        0) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+#define SERVER_INIT_NAME(REQUEST_TYPE) \
+  chttp2_init_server_simple_ssl_secure_fullstack_##REQUEST_TYPE
+
+#define SERVER_INIT(REQUEST_TYPE)                                           \
+  static void SERVER_INIT_NAME(REQUEST_TYPE)(                               \
+      grpc_end2end_test_fixture * f, grpc_channel_args * server_args) {     \
+    grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,       \
+                                                    test_server1_cert};     \
+    grpc_server_credentials *ssl_creds =                                    \
+        grpc_ssl_server_credentials_create_ex(                              \
+            test_root_cert, &pem_cert_key_pair, 1, REQUEST_TYPE, NULL);     \
+    if (fail_server_auth_check(server_args)) {                              \
+      grpc_auth_metadata_processor processor = {process_auth_failure, NULL, \
+                                                NULL};                      \
+      grpc_server_credentials_set_auth_metadata_processor(ssl_creds,        \
+                                                          processor);       \
+    }                                                                       \
+    chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);         \
+  }
+
+SERVER_INIT(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
+SERVER_INIT(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY);
+SERVER_INIT(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY);
+SERVER_INIT(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY);
+SERVER_INIT(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
+
+#define CLIENT_INIT_NAME(cert_type) \
+  chttp2_init_client_simple_ssl_secure_fullstack_##cert_type
+
+typedef enum { NONE, SELF_SIGNED, SIGNED, BAD_CERT_PAIR } certtype;
+
+#define CLIENT_INIT(cert_type)                                               \
+  static void CLIENT_INIT_NAME(cert_type)(grpc_end2end_test_fixture * f,     \
+                                          grpc_channel_args * client_args) { \
+    grpc_channel_credentials *ssl_creds = NULL;                              \
+    grpc_ssl_pem_key_cert_pair self_signed_client_key_cert_pair = {          \
+        test_self_signed_client_key, test_self_signed_client_cert};          \
+    grpc_ssl_pem_key_cert_pair signed_client_key_cert_pair = {               \
+        test_signed_client_key, test_signed_client_cert};                    \
+    grpc_ssl_pem_key_cert_pair bad_client_key_cert_pair = {                  \
+        test_self_signed_client_key, test_signed_client_cert};               \
+    grpc_ssl_pem_key_cert_pair *key_cert_pair = NULL;                        \
+    switch (cert_type) {                                                     \
+      case SELF_SIGNED:                                                      \
+        key_cert_pair = &self_signed_client_key_cert_pair;                   \
+        break;                                                               \
+      case SIGNED:                                                           \
+        key_cert_pair = &signed_client_key_cert_pair;                        \
+        break;                                                               \
+      case BAD_CERT_PAIR:                                                    \
+        key_cert_pair = &bad_client_key_cert_pair;                           \
+        break;                                                               \
+      default:                                                               \
+        break;                                                               \
+    }                                                                        \
+    ssl_creds =                                                              \
+        grpc_ssl_credentials_create(test_root_cert, key_cert_pair, NULL);    \
+    grpc_arg ssl_name_override = {GRPC_ARG_STRING,                           \
+                                  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,         \
+                                  {"foo.test.google.fr"}};                   \
+    grpc_channel_args *new_client_args =                                     \
+        grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);  \
+    chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);      \
+    grpc_channel_args_destroy(new_client_args);                              \
+  }
+
+CLIENT_INIT(NONE);
+CLIENT_INIT(SELF_SIGNED);
+CLIENT_INIT(SIGNED);
+CLIENT_INIT(BAD_CERT_PAIR);
+
+#define TEST_NAME(enum_name, cert_type, result) \
+  "chttp2/ssl_" #enum_name "_" #cert_type "_" #result "_"
+
+typedef enum { SUCCESS, FAIL } test_result;
+
+#define SSL_TEST(request_type, cert_type, result)                         \
+  {                                                                       \
+    {TEST_NAME(request_type, cert_type, result),                          \
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |                           \
+         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,                      \
+     chttp2_create_fixture_secure_fullstack, CLIENT_INIT_NAME(cert_type), \
+     SERVER_INIT_NAME(request_type), chttp2_tear_down_secure_fullstack},  \
+        result                                                            \
+  }
+
+/* All test configurations */
+typedef struct grpc_end2end_test_config_wrapper {
+  grpc_end2end_test_config config;
+  test_result result;
+} grpc_end2end_test_config_wrapper;
+
+static grpc_end2end_test_config_wrapper configs[] = {
+    SSL_TEST(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NONE, SUCCESS),
+    SSL_TEST(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, SELF_SIGNED, SUCCESS),
+    SSL_TEST(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, SIGNED, SUCCESS),
+    SSL_TEST(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, BAD_CERT_PAIR, FAIL),
+
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, NONE,
+             SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, SELF_SIGNED,
+             SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, SIGNED,
+             SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, BAD_CERT_PAIR,
+             FAIL),
+
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, NONE, SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, SELF_SIGNED, FAIL),
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, SIGNED, SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, BAD_CERT_PAIR,
+             FAIL),
+
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+             NONE, FAIL),
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+             SELF_SIGNED, SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+             SIGNED, SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+             BAD_CERT_PAIR, FAIL),
+
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, NONE,
+             FAIL),
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY,
+             SELF_SIGNED, FAIL),
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, SIGNED,
+             SUCCESS),
+    SSL_TEST(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY,
+             BAD_CERT_PAIR, FAIL),
+};
+
+static void *tag(intptr_t t) { return (void *)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char *test_name,
+                                            grpc_channel_args *client_args,
+                                            grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_server(&f, server_args);
+  config.init_client(&f, client_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_time(int n) {
+  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+}
+
+static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
+
+static void drain_cq(grpc_completion_queue *cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture *f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = NULL;
+}
+
+static void end_test(grpc_end2end_test_fixture *f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+}
+
+static void simple_request_body(grpc_end2end_test_fixture f,
+                                test_result expected_result) {
+  grpc_call *c;
+  gpr_timespec deadline = five_seconds_time();
+  cq_verifier *cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op *op;
+  grpc_call_error error;
+
+  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               "/foo", "foo.test.google.fr:1234", deadline,
+                               NULL);
+  GPR_ASSERT(c);
+
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  cq_expect_completion(cqv, tag(1), expected_result == SUCCESS);
+  cq_verify(cqv);
+
+  grpc_call_destroy(c);
+  cq_verifier_destroy(cqv);
+}
+
+int main(int argc, char **argv) {
+  size_t i;
+  FILE *roots_file;
+  size_t roots_size = strlen(test_root_cert);
+  char *roots_filename;
+
+  grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
+
+  /* Set the SSL roots env var. */
+  roots_file =
+      gpr_tmpfile("chttp2_simple_ssl_cert_fullstack_test", &roots_filename);
+  GPR_ASSERT(roots_filename != NULL);
+  GPR_ASSERT(roots_file != NULL);
+  GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size);
+  fclose(roots_file);
+  gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename);
+
+  grpc_init();
+
+  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
+    grpc_end2end_test_fixture f =
+        begin_test(configs[i].config, "SSL_CERT_tests", NULL, NULL);
+
+    simple_request_body(f, configs[i].result);
+    end_test(&f);
+    configs[i].config.tear_down_data(&f);
+  }
+
+  grpc_shutdown();
+
+  /* Cleanup. */
+  remove(roots_filename);
+  gpr_free(roots_filename);
+
+  return 0;
+}
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c
index 6340d3f..1403b76 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.c
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,11 +40,11 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 
-#include "src/core/channel/channel_args.h"
-#include "src/core/security/credentials.h"
-#include "src/core/support/env.h"
-#include "src/core/support/tmpfile.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/tmpfile.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/end2end/fixtures/proxy.h"
 #include "test/core/util/port.h"
@@ -195,6 +195,7 @@
   char *roots_filename;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
 
   /* Set the SSL roots env var. */
   roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename);
diff --git a/test/core/end2end/fixtures/h2_uchannel.c b/test/core/end2end/fixtures/h2_uchannel.c
deleted file mode 100644
index 25a4804..0000000
--- a/test/core/end2end/fixtures/h2_uchannel.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- *
- * 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 "test/core/end2end/end2end_tests.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/useful.h>
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/client_uchannel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_client_filter.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/client_config/resolver_registry.h"
-#include "src/core/iomgr/tcp_client.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-typedef struct {
-  grpc_connector base;
-  gpr_refcount refs;
-
-  grpc_closure *notify;
-  grpc_connect_in_args args;
-  grpc_connect_out_args *result;
-
-  grpc_endpoint *tcp;
-
-  grpc_closure connected;
-} connector;
-
-static void connector_ref(grpc_connector *con) {
-  connector *c = (connector *)con;
-  gpr_ref(&c->refs);
-}
-
-static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
-  connector *c = (connector *)con;
-  if (gpr_unref(&c->refs)) {
-    gpr_free(c);
-  }
-}
-
-static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  connector *c = arg;
-  grpc_closure *notify;
-  grpc_endpoint *tcp = c->tcp;
-  if (tcp != NULL) {
-    c->result->transport =
-        grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1);
-    grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
-                                        0);
-    GPR_ASSERT(c->result->transport);
-  } else {
-    memset(c->result, 0, sizeof(*c->result));
-  }
-  notify = c->notify;
-  c->notify = NULL;
-  notify->cb(exec_ctx, notify->cb_arg, 1);
-}
-
-static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}
-
-static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
-                              const grpc_connect_in_args *args,
-                              grpc_connect_out_args *result,
-                              grpc_closure *notify) {
-  connector *c = (connector *)con;
-  GPR_ASSERT(c->notify == NULL);
-  GPR_ASSERT(notify->cb);
-  c->notify = notify;
-  c->args = *args;
-  c->result = result;
-  c->tcp = NULL;
-  grpc_closure_init(&c->connected, connected, c);
-  grpc_tcp_client_connect(exec_ctx, &c->connected, &c->tcp,
-                          args->interested_parties, args->addr, args->addr_len,
-                          args->deadline);
-}
-
-static const grpc_connector_vtable connector_vtable = {
-    connector_ref, connector_unref, connector_shutdown, connector_connect};
-
-typedef struct {
-  grpc_subchannel_factory base;
-  gpr_refcount refs;
-  grpc_channel_args *merge_args;
-  grpc_channel *master;
-  grpc_subchannel **sniffed_subchannel;
-} subchannel_factory;
-
-static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  gpr_ref(&f->refs);
-}
-
-static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_factory *scf) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  if (gpr_unref(&f->refs)) {
-    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
-    grpc_channel_args_destroy(f->merge_args);
-    gpr_free(f);
-  }
-}
-
-static grpc_subchannel *subchannel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
-    grpc_subchannel_args *args) {
-  subchannel_factory *f = (subchannel_factory *)scf;
-  connector *c = gpr_malloc(sizeof(*c));
-  grpc_channel_args *final_args =
-      grpc_channel_args_merge(args->args, f->merge_args);
-  grpc_subchannel *s;
-  memset(c, 0, sizeof(*c));
-  c->base.vtable = &connector_vtable;
-  gpr_ref_init(&c->refs, 1);
-  args->args = final_args;
-  s = grpc_subchannel_create(exec_ctx, &c->base, args);
-  grpc_connector_unref(exec_ctx, &c->base);
-  grpc_channel_args_destroy(final_args);
-  if (*f->sniffed_subchannel) {
-    GRPC_SUBCHANNEL_UNREF(exec_ctx, *f->sniffed_subchannel, "sniffed");
-  }
-  *f->sniffed_subchannel = s;
-  GRPC_SUBCHANNEL_REF(s, "sniffed");
-  return s;
-}
-
-static const grpc_subchannel_factory_vtable test_subchannel_factory_vtable = {
-    subchannel_factory_ref, subchannel_factory_unref,
-    subchannel_factory_create_subchannel};
-
-/* The evil twin of grpc_insecure_channel_create. It allows the test to use the
- * custom-built sniffing subchannel_factory */
-grpc_channel *channel_create(const char *target, const grpc_channel_args *args,
-                             grpc_subchannel **sniffed_subchannel) {
-  grpc_channel *channel = NULL;
-  grpc_resolver *resolver;
-  subchannel_factory *f;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  channel =
-      grpc_channel_create(&exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
-
-  f = gpr_malloc(sizeof(*f));
-  f->sniffed_subchannel = sniffed_subchannel;
-  f->base.vtable = &test_subchannel_factory_vtable;
-  gpr_ref_init(&f->refs, 1);
-  f->merge_args = grpc_channel_args_copy(args);
-  f->master = channel;
-  GRPC_CHANNEL_INTERNAL_REF(f->master, "test_subchannel_factory");
-  resolver = grpc_resolver_create(target, &f->base);
-  if (!resolver) {
-    return NULL;
-  }
-
-  grpc_client_channel_set_resolver(
-      &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
-  GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_create");
-  grpc_subchannel_factory_unref(&exec_ctx, &f->base);
-
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  return channel;
-}
-
-typedef struct micro_fullstack_fixture_data {
-  char *localaddr;
-  grpc_channel *master_channel;
-  grpc_subchannel *sniffed_subchannel;
-} micro_fullstack_fixture_data;
-
-static grpc_end2end_test_fixture chttp2_create_fixture_micro_fullstack(
-    grpc_channel_args *client_args, grpc_channel_args *server_args) {
-  grpc_end2end_test_fixture f;
-  int port = grpc_pick_unused_port_or_die();
-  micro_fullstack_fixture_data *ffd =
-      gpr_malloc(sizeof(micro_fullstack_fixture_data));
-  memset(&f, 0, sizeof(f));
-  memset(ffd, 0, sizeof(*ffd));
-
-  gpr_join_host_port(&ffd->localaddr, "127.0.0.1", port);
-
-  f.fixture_data = ffd;
-  f.cq = grpc_completion_queue_create(NULL);
-
-  return f;
-}
-
-grpc_connectivity_state g_state = GRPC_CHANNEL_IDLE;
-grpc_pollset_set *g_interested_parties;
-
-static void state_changed(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  if (g_state != GRPC_CHANNEL_READY) {
-    grpc_subchannel_notify_on_state_change(
-        exec_ctx, arg, g_interested_parties, &g_state,
-        grpc_closure_create(state_changed, arg));
-  }
-}
-
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  grpc_pollset_destroy(arg);
-}
-
-static grpc_connected_subchannel *connect_subchannel(grpc_subchannel *c) {
-  gpr_mu *mu;
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_pollset_init(pollset, &mu);
-  g_interested_parties = grpc_pollset_set_create();
-  grpc_pollset_set_add_pollset(&exec_ctx, g_interested_parties, pollset);
-  grpc_subchannel_notify_on_state_change(&exec_ctx, c, g_interested_parties,
-                                         &g_state,
-                                         grpc_closure_create(state_changed, c));
-  grpc_exec_ctx_flush(&exec_ctx);
-  gpr_mu_lock(mu);
-  while (g_state != GRPC_CHANNEL_READY) {
-    grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
-                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
-    gpr_mu_unlock(mu);
-    grpc_exec_ctx_flush(&exec_ctx);
-    gpr_mu_lock(mu);
-  }
-  grpc_pollset_shutdown(&exec_ctx, pollset,
-                        grpc_closure_create(destroy_pollset, pollset));
-  grpc_pollset_set_destroy(g_interested_parties);
-  gpr_mu_unlock(mu);
-  grpc_exec_ctx_finish(&exec_ctx);
-  gpr_free(pollset);
-  return grpc_subchannel_get_connected_subchannel(c);
-}
-
-static void chttp2_init_client_micro_fullstack(grpc_end2end_test_fixture *f,
-                                               grpc_channel_args *client_args) {
-  micro_fullstack_fixture_data *ffd = f->fixture_data;
-  grpc_connectivity_state conn_state;
-  grpc_connected_subchannel *connected_subchannel;
-  char *ipv4_localaddr;
-
-  gpr_asprintf(&ipv4_localaddr, "ipv4:%s", ffd->localaddr);
-  ffd->master_channel =
-      channel_create(ipv4_localaddr, client_args, &ffd->sniffed_subchannel);
-  gpr_free(ipv4_localaddr);
-  gpr_log(GPR_INFO, "MASTER CHANNEL %p ", ffd->master_channel);
-  /* the following will block. That's ok for this test */
-  conn_state = grpc_channel_check_connectivity_state(ffd->master_channel,
-                                                     1 /* try to connect */);
-  GPR_ASSERT(conn_state == GRPC_CHANNEL_IDLE);
-
-  /* here sniffed_subchannel should be ready to use */
-  GPR_ASSERT(conn_state == GRPC_CHANNEL_IDLE);
-  GPR_ASSERT(ffd->sniffed_subchannel != NULL);
-
-  connected_subchannel = connect_subchannel(ffd->sniffed_subchannel);
-  f->client = grpc_client_uchannel_create(ffd->sniffed_subchannel, client_args);
-  grpc_client_uchannel_set_connected_subchannel(f->client,
-                                                connected_subchannel);
-  gpr_log(GPR_INFO, "CHANNEL WRAPPING SUBCHANNEL: %p(%p)", f->client,
-          ffd->sniffed_subchannel);
-
-  GPR_ASSERT(f->client);
-}
-
-static void chttp2_init_server_micro_fullstack(grpc_end2end_test_fixture *f,
-                                               grpc_channel_args *server_args) {
-  micro_fullstack_fixture_data *ffd = f->fixture_data;
-  if (f->server) {
-    grpc_server_destroy(f->server);
-  }
-  f->server = grpc_server_create(server_args, NULL);
-  grpc_server_register_completion_queue(f->server, f->cq, NULL);
-  GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr));
-  grpc_server_start(f->server);
-}
-
-static void chttp2_tear_down_micro_fullstack(grpc_end2end_test_fixture *f) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  micro_fullstack_fixture_data *ffd = f->fixture_data;
-  grpc_channel_destroy(ffd->master_channel);
-  if (ffd->sniffed_subchannel) {
-    GRPC_SUBCHANNEL_UNREF(&exec_ctx, ffd->sniffed_subchannel, "sniffed");
-  }
-  gpr_free(ffd->localaddr);
-  gpr_free(ffd);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-/* All test configurations */
-static grpc_end2end_test_config configs[] = {
-    {"chttp2/micro_fullstack", 0, chttp2_create_fixture_micro_fullstack,
-     chttp2_init_client_micro_fullstack, chttp2_init_server_micro_fullstack,
-     chttp2_tear_down_micro_fullstack},
-};
-
-int main(int argc, char **argv) {
-  size_t i;
-
-  grpc_test_init(argc, argv);
-  grpc_init();
-
-  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
-    grpc_end2end_tests(argc, argv, configs[i]);
-  }
-
-  grpc_shutdown();
-
-  return 0;
-}
diff --git a/test/core/end2end/fixtures/h2_uds+poll.c b/test/core/end2end/fixtures/h2_uds+poll.c
deleted file mode 100644
index c3a855f..0000000
--- a/test/core/end2end/fixtures/h2_uds+poll.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *
- * 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 "test/core/end2end/end2end_tests.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-typedef struct fullstack_fixture_data {
-  char *localaddr;
-} fullstack_fixture_data;
-
-static int unique = 1;
-
-static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
-    grpc_channel_args *client_args, grpc_channel_args *server_args) {
-  grpc_end2end_test_fixture f;
-  fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data));
-  memset(&f, 0, sizeof(f));
-
-  gpr_asprintf(&ffd->localaddr, "unix:/tmp/grpc_fullstack_test.%d.%d", getpid(),
-               unique++);
-
-  f.fixture_data = ffd;
-  f.cq = grpc_completion_queue_create(NULL);
-
-  return f;
-}
-
-void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f,
-                                  grpc_channel_args *client_args) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL);
-}
-
-void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
-                                  grpc_channel_args *server_args) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  if (f->server) {
-    grpc_server_destroy(f->server);
-  }
-  f->server = grpc_server_create(server_args, NULL);
-  grpc_server_register_completion_queue(f->server, f->cq, NULL);
-  GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr));
-  grpc_server_start(f->server);
-}
-
-void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) {
-  fullstack_fixture_data *ffd = f->fixture_data;
-  gpr_free(ffd->localaddr);
-  gpr_free(ffd);
-}
-
-/* All test configurations */
-static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack_uds", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
-     chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
-};
-
-int main(int argc, char **argv) {
-  size_t i;
-
-  grpc_platform_become_multipoller = grpc_poll_become_multipoller;
-
-  grpc_test_init(argc, argv);
-  grpc_init();
-
-  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
-    grpc_end2end_tests(argc, argv, configs[i]);
-  }
-
-  grpc_shutdown();
-
-  return 0;
-}
diff --git a/test/core/end2end/fixtures/h2_uds.c b/test/core/end2end/fixtures/h2_uds.c
index 3092827..cffbeaf 100644
--- a/test/core/end2end/fixtures/h2_uds.c
+++ b/test/core/end2end/fixtures/h2_uds.c
@@ -37,13 +37,6 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
@@ -51,6 +44,13 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/client_config/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -110,6 +110,7 @@
   size_t i;
 
   grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
   grpc_init();
 
   for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index 434e75d..a6487a1 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -338,10 +338,10 @@
         proxy->new_call_details.deadline, NULL);
     gpr_ref_init(&pc->refs, 1);
 
-    op.flags = 0;
     op.reserved = NULL;
 
     op.op = GRPC_OP_RECV_INITIAL_METADATA;
+    op.flags = 0;
     op.data.recv_initial_metadata = &pc->p2s_initial_metadata;
     refpc(pc, "on_p2s_recv_initial_metadata");
     err = grpc_call_start_batch(
@@ -349,6 +349,7 @@
     GPR_ASSERT(err == GRPC_CALL_OK);
 
     op.op = GRPC_OP_SEND_INITIAL_METADATA;
+    op.flags = proxy->new_call_details.flags;
     op.data.send_initial_metadata.count = pc->c2p_initial_metadata.count;
     op.data.send_initial_metadata.metadata = pc->c2p_initial_metadata.metadata;
     refpc(pc, "on_p2s_sent_initial_metadata");
@@ -357,6 +358,7 @@
     GPR_ASSERT(err == GRPC_CALL_OK);
 
     op.op = GRPC_OP_RECV_MESSAGE;
+    op.flags = 0;
     op.data.recv_message = &pc->c2p_msg;
     refpc(pc, "on_c2p_recv_msg");
     err = grpc_call_start_batch(pc->c2p, &op, 1,
@@ -364,6 +366,7 @@
     GPR_ASSERT(err == GRPC_CALL_OK);
 
     op.op = GRPC_OP_RECV_MESSAGE;
+    op.flags = 0;
     op.data.recv_message = &pc->p2s_msg;
     refpc(pc, "on_p2s_recv_msg");
     err = grpc_call_start_batch(pc->p2s, &op, 1,
@@ -371,6 +374,7 @@
     GPR_ASSERT(err == GRPC_CALL_OK);
 
     op.op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+    op.flags = 0;
     op.data.recv_status_on_client.trailing_metadata =
         &pc->p2s_trailing_metadata;
     op.data.recv_status_on_client.status = &pc->p2s_status;
@@ -383,6 +387,7 @@
     GPR_ASSERT(err == GRPC_CALL_OK);
 
     op.op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+    op.flags = 0;
     op.data.recv_close_on_server.cancelled = &pc->c2p_server_cancelled;
     refpc(pc, "on_c2p_closed");
     err = grpc_call_start_batch(pc->c2p, &op, 1, new_closure(on_c2p_closed, pc),
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
new file mode 100644
index 0000000..b133a94
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -0,0 +1,896 @@
+/*
+ *
+ * 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 <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/tcp_client.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/surface/server.h"
+#include "src/core/lib/transport/metadata.h"
+#include "test/core/util/passthru_endpoint.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// logging
+
+static const bool squelch = true;
+
+static void dont_log(gpr_log_func_args *args) {}
+
+////////////////////////////////////////////////////////////////////////////////
+// input_stream: allows easy access to input bytes, and allows reading a little
+//               past the end (avoiding needing to check everywhere)
+
+typedef struct {
+  const uint8_t *cur;
+  const uint8_t *end;
+} input_stream;
+
+static uint8_t next_byte(input_stream *inp) {
+  if (inp->cur == inp->end) {
+    return 0;
+  }
+  return *inp->cur++;
+}
+
+static void end(input_stream *inp) { inp->cur = inp->end; }
+
+static char *read_string(input_stream *inp) {
+  char *str = NULL;
+  size_t cap = 0;
+  size_t sz = 0;
+  char c;
+  do {
+    if (cap == sz) {
+      cap = GPR_MAX(3 * cap / 2, cap + 8);
+      str = gpr_realloc(str, cap);
+    }
+    c = (char)next_byte(inp);
+    str[sz++] = c;
+  } while (c != 0);
+  return str;
+}
+
+static void read_buffer(input_stream *inp, char **buffer, size_t *length) {
+  *length = next_byte(inp);
+  *buffer = gpr_malloc(*length);
+  for (size_t i = 0; i < *length; i++) {
+    (*buffer)[i] = (char)next_byte(inp);
+  }
+}
+
+static uint32_t read_uint22(input_stream *inp) {
+  uint8_t b = next_byte(inp);
+  uint32_t x = b & 0x7f;
+  if (b & 0x80) {
+    x <<= 7;
+    b = next_byte(inp);
+    x |= b & 0x7f;
+    if (b & 0x80) {
+      x <<= 8;
+      x |= next_byte(inp);
+    }
+  }
+  return x;
+}
+
+static uint32_t read_uint32(input_stream *inp) {
+  uint8_t b = next_byte(inp);
+  uint32_t x = b & 0x7f;
+  if (b & 0x80) {
+    x <<= 7;
+    b = next_byte(inp);
+    x |= b & 0x7f;
+    if (b & 0x80) {
+      x <<= 7;
+      b = next_byte(inp);
+      x |= b & 0x7f;
+      if (b & 0x80) {
+        x <<= 7;
+        b = next_byte(inp);
+        x |= b & 0x7f;
+        if (b & 0x80) {
+          x = (x << 4) | (next_byte(inp) & 0x0f);
+        }
+      }
+    }
+  }
+  return x;
+}
+
+static grpc_byte_buffer *read_message(input_stream *inp) {
+  gpr_slice slice = gpr_slice_malloc(read_uint22(inp));
+  memset(GPR_SLICE_START_PTR(slice), 0, GPR_SLICE_LENGTH(slice));
+  grpc_byte_buffer *out = grpc_raw_byte_buffer_create(&slice, 1);
+  gpr_slice_unref(slice);
+  return out;
+}
+
+static int read_int(input_stream *inp) { return (int)read_uint32(inp); }
+
+static grpc_channel_args *read_args(input_stream *inp) {
+  size_t n = next_byte(inp);
+  grpc_arg *args = gpr_malloc(sizeof(*args) * n);
+  for (size_t i = 0; i < n; i++) {
+    bool is_string = next_byte(inp) & 1;
+    args[i].type = is_string ? GRPC_ARG_STRING : GRPC_ARG_INTEGER;
+    args[i].key = read_string(inp);
+    if (is_string) {
+      args[i].value.string = read_string(inp);
+    } else {
+      args[i].value.integer = read_int(inp);
+    }
+  }
+  grpc_channel_args *a = gpr_malloc(sizeof(*a));
+  a->args = args;
+  a->num_args = n;
+  return a;
+}
+
+static bool is_eof(input_stream *inp) { return inp->cur == inp->end; }
+
+////////////////////////////////////////////////////////////////////////////////
+// global state
+
+static gpr_timespec g_now;
+static grpc_server *g_server;
+static grpc_channel *g_channel;
+
+extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
+
+static gpr_timespec now_impl(gpr_clock_type clock_type) {
+  GPR_ASSERT(clock_type != GPR_TIMESPAN);
+  return g_now;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// dns resolution
+
+typedef struct addr_req {
+  grpc_timer timer;
+  char *addr;
+  grpc_resolve_cb cb;
+  void *arg;
+} addr_req;
+
+static void finish_resolve(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  addr_req *r = arg;
+
+  if (success && 0 == strcmp(r->addr, "server")) {
+    grpc_resolved_addresses *addrs = gpr_malloc(sizeof(*addrs));
+    addrs->naddrs = 1;
+    addrs->addrs = gpr_malloc(sizeof(*addrs->addrs));
+    addrs->addrs[0].len = 0;
+    r->cb(exec_ctx, r->arg, addrs);
+  } else {
+    r->cb(exec_ctx, r->arg, NULL);
+  }
+
+  gpr_free(r->addr);
+  gpr_free(r);
+}
+
+void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
+                        const char *default_port, grpc_resolve_cb cb,
+                        void *arg) {
+  addr_req *r = gpr_malloc(sizeof(*r));
+  r->addr = gpr_strdup(addr);
+  r->cb = cb;
+  r->arg = arg;
+  grpc_timer_init(exec_ctx, &r->timer,
+                  gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                               gpr_time_from_seconds(1, GPR_TIMESPAN)),
+                  finish_resolve, r, gpr_now(GPR_CLOCK_MONOTONIC));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// client connection
+
+// defined in tcp_client_posix.c
+extern void (*grpc_tcp_client_connect_impl)(
+    grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
+    grpc_pollset_set *interested_parties, const struct sockaddr *addr,
+    size_t addr_len, gpr_timespec deadline);
+
+static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                          grpc_endpoint **ep, gpr_timespec deadline);
+
+typedef struct {
+  grpc_timer timer;
+  grpc_closure *closure;
+  grpc_endpoint **ep;
+  gpr_timespec deadline;
+} future_connect;
+
+static void do_connect(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  future_connect *fc = arg;
+  if (!success) {
+    *fc->ep = NULL;
+    grpc_exec_ctx_enqueue(exec_ctx, fc->closure, false, NULL);
+  } else if (g_server != NULL) {
+    grpc_endpoint *client;
+    grpc_endpoint *server;
+    grpc_passthru_endpoint_create(&client, &server);
+    *fc->ep = client;
+
+    grpc_transport *transport =
+        grpc_create_chttp2_transport(exec_ctx, NULL, server, 0);
+    grpc_server_setup_transport(exec_ctx, g_server, transport, NULL);
+    grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
+
+    grpc_exec_ctx_enqueue(exec_ctx, fc->closure, false, NULL);
+  } else {
+    sched_connect(exec_ctx, fc->closure, fc->ep, fc->deadline);
+  }
+  gpr_free(fc);
+}
+
+static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                          grpc_endpoint **ep, gpr_timespec deadline) {
+  if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) {
+    *ep = NULL;
+    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+    return;
+  }
+
+  future_connect *fc = gpr_malloc(sizeof(*fc));
+  fc->closure = closure;
+  fc->ep = ep;
+  fc->deadline = deadline;
+  grpc_timer_init(exec_ctx, &fc->timer,
+                  gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                               gpr_time_from_millis(1, GPR_TIMESPAN)),
+                  do_connect, fc, gpr_now(GPR_CLOCK_MONOTONIC));
+}
+
+static void my_tcp_client_connect(grpc_exec_ctx *exec_ctx,
+                                  grpc_closure *closure, grpc_endpoint **ep,
+                                  grpc_pollset_set *interested_parties,
+                                  const struct sockaddr *addr, size_t addr_len,
+                                  gpr_timespec deadline) {
+  sched_connect(exec_ctx, closure, ep, deadline);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// test driver
+
+typedef struct validator {
+  void (*validate)(void *arg, bool success);
+  void *arg;
+} validator;
+
+static validator *create_validator(void (*validate)(void *arg, bool success),
+                                   void *arg) {
+  validator *v = gpr_malloc(sizeof(*v));
+  v->validate = validate;
+  v->arg = arg;
+  return v;
+}
+
+static void assert_success_and_decrement(void *counter, bool success) {
+  GPR_ASSERT(success);
+  --*(int *)counter;
+}
+
+static void decrement(void *counter, bool success) { --*(int *)counter; }
+
+typedef struct connectivity_watch {
+  int *counter;
+  gpr_timespec deadline;
+} connectivity_watch;
+
+static connectivity_watch *make_connectivity_watch(gpr_timespec s,
+                                                   int *counter) {
+  connectivity_watch *o = gpr_malloc(sizeof(*o));
+  o->deadline = s;
+  o->counter = counter;
+  return o;
+}
+
+static void validate_connectivity_watch(void *p, bool success) {
+  connectivity_watch *w = p;
+  if (!success) {
+    GPR_ASSERT(gpr_time_cmp(gpr_now(w->deadline.clock_type), w->deadline) >= 0);
+  }
+  --*w->counter;
+  gpr_free(w);
+}
+
+static void free_non_null(void *p) {
+  GPR_ASSERT(p != NULL);
+  gpr_free(p);
+}
+
+typedef enum { ROOT, CLIENT, SERVER, PENDING_SERVER } call_state_type;
+
+typedef struct call_state {
+  call_state_type type;
+  grpc_call *call;
+  grpc_byte_buffer *recv_message;
+  grpc_status_code status;
+  grpc_metadata_array recv_initial_metadata;
+  grpc_metadata_array recv_trailing_metadata;
+  char *recv_status_details;
+  size_t recv_status_details_capacity;
+  int cancelled;
+  int pending_ops;
+  grpc_call_details call_details;
+
+  // array of pointers to free later
+  size_t num_to_free;
+  size_t cap_to_free;
+  void **to_free;
+
+  struct call_state *next;
+  struct call_state *prev;
+} call_state;
+
+static call_state *g_active_call;
+
+static call_state *new_call(call_state *sibling, call_state_type type) {
+  call_state *c = gpr_malloc(sizeof(*c));
+  memset(c, 0, sizeof(*c));
+  if (sibling != NULL) {
+    c->next = sibling;
+    c->prev = sibling->prev;
+    c->next->prev = c->prev->next = c;
+  } else {
+    c->next = c->prev = c;
+  }
+  c->type = type;
+  return c;
+}
+
+static call_state *maybe_delete_call_state(call_state *call) {
+  call_state *next = call->next;
+
+  if (call->call != NULL) return next;
+  if (call->pending_ops != 0) return next;
+
+  if (call == g_active_call) {
+    g_active_call = call->next;
+    GPR_ASSERT(call != g_active_call);
+  }
+
+  call->prev->next = call->next;
+  call->next->prev = call->prev;
+  grpc_metadata_array_destroy(&call->recv_initial_metadata);
+  grpc_metadata_array_destroy(&call->recv_trailing_metadata);
+  gpr_free(call->recv_status_details);
+  grpc_call_details_destroy(&call->call_details);
+
+  for (size_t i = 0; i < call->num_to_free; i++) {
+    gpr_free(call->to_free[i]);
+  }
+  gpr_free(call->to_free);
+
+  gpr_free(call);
+
+  return next;
+}
+
+static void add_to_free(call_state *call, void *p) {
+  if (call->num_to_free == call->cap_to_free) {
+    call->cap_to_free = GPR_MAX(8, 2 * call->cap_to_free);
+    call->to_free =
+        gpr_realloc(call->to_free, sizeof(*call->to_free) * call->cap_to_free);
+  }
+  call->to_free[call->num_to_free++] = p;
+}
+
+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);
+  }
+  add_to_free(cs, *metadata);
+}
+
+static call_state *destroy_call(call_state *call) {
+  grpc_call_destroy(call->call);
+  call->call = NULL;
+  return maybe_delete_call_state(call);
+}
+
+static void finished_request_call(void *csp, bool success) {
+  call_state *cs = csp;
+  GPR_ASSERT(cs->pending_ops > 0);
+  --cs->pending_ops;
+  if (success) {
+    GPR_ASSERT(cs->call != NULL);
+    cs->type = SERVER;
+  } else {
+    maybe_delete_call_state(cs);
+  }
+}
+
+static void finished_batch(void *csp, bool success) {
+  call_state *cs = csp;
+  --cs->pending_ops;
+  maybe_delete_call_state(cs);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  grpc_test_only_set_metadata_hash_seed(0);
+  if (squelch) gpr_set_log_function(dont_log);
+  input_stream inp = {data, data + size};
+  grpc_resolve_address = my_resolve_address;
+  grpc_tcp_client_connect_impl = my_tcp_client_connect;
+  gpr_now_impl = now_impl;
+  grpc_init();
+
+  GPR_ASSERT(g_channel == NULL);
+  GPR_ASSERT(g_server == NULL);
+
+  bool server_shutdown = false;
+  int pending_server_shutdowns = 0;
+  int pending_channel_watches = 0;
+  int pending_pings = 0;
+
+  g_active_call = new_call(NULL, ROOT);
+
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+
+  while (!is_eof(&inp) || g_channel != NULL || g_server != NULL ||
+         pending_channel_watches > 0 || pending_pings > 0 ||
+         g_active_call->type != ROOT || g_active_call->next != g_active_call) {
+    if (is_eof(&inp)) {
+      if (g_channel != NULL) {
+        grpc_channel_destroy(g_channel);
+        g_channel = NULL;
+      }
+      if (g_server != NULL) {
+        if (!server_shutdown) {
+          grpc_server_shutdown_and_notify(
+              g_server, cq, create_validator(assert_success_and_decrement,
+                                             &pending_server_shutdowns));
+          server_shutdown = true;
+          pending_server_shutdowns++;
+        } else if (pending_server_shutdowns == 0) {
+          grpc_server_destroy(g_server);
+          g_server = NULL;
+        }
+      }
+      call_state *s = g_active_call;
+      do {
+        if (s->type != PENDING_SERVER && s->call != NULL) {
+          s = destroy_call(s);
+        } else {
+          s = s->next;
+        }
+      } while (s != g_active_call);
+
+      g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN));
+    }
+
+    switch (next_byte(&inp)) {
+      // terminate on bad bytes
+      default:
+        end(&inp);
+        break;
+      // tickle completion queue
+      case 0: {
+        grpc_event ev = grpc_completion_queue_next(
+            cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
+        switch (ev.type) {
+          case GRPC_OP_COMPLETE: {
+            validator *v = ev.tag;
+            v->validate(v->arg, ev.success);
+            gpr_free(v);
+            break;
+          }
+          case GRPC_QUEUE_TIMEOUT:
+            break;
+          case GRPC_QUEUE_SHUTDOWN:
+            abort();
+            break;
+        }
+        break;
+      }
+      // increment global time
+      case 1: {
+        g_now = gpr_time_add(
+            g_now, gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
+        break;
+      }
+      // create an insecure channel
+      case 2: {
+        if (g_channel == NULL) {
+          char *target = read_string(&inp);
+          char *target_uri;
+          gpr_asprintf(&target_uri, "dns:%s", target);
+          grpc_channel_args *args = read_args(&inp);
+          g_channel = grpc_insecure_channel_create(target_uri, args, NULL);
+          GPR_ASSERT(g_channel != NULL);
+          grpc_channel_args_destroy(args);
+          gpr_free(target_uri);
+          gpr_free(target);
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // destroy a channel
+      case 3: {
+        if (g_channel != NULL) {
+          grpc_channel_destroy(g_channel);
+          g_channel = NULL;
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // bring up a server
+      case 4: {
+        if (g_server == NULL) {
+          grpc_channel_args *args = read_args(&inp);
+          g_server = grpc_server_create(args, NULL);
+          GPR_ASSERT(g_server != NULL);
+          grpc_channel_args_destroy(args);
+          grpc_server_register_completion_queue(g_server, cq, NULL);
+          grpc_server_start(g_server);
+          server_shutdown = false;
+          GPR_ASSERT(pending_server_shutdowns == 0);
+        } else {
+          end(&inp);
+        }
+      }
+      // begin server shutdown
+      case 5: {
+        if (g_server != NULL) {
+          grpc_server_shutdown_and_notify(
+              g_server, cq, create_validator(assert_success_and_decrement,
+                                             &pending_server_shutdowns));
+          pending_server_shutdowns++;
+          server_shutdown = true;
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // cancel all calls if shutdown
+      case 6: {
+        if (g_server != NULL && server_shutdown) {
+          grpc_server_cancel_all_calls(g_server);
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // destroy server
+      case 7: {
+        if (g_server != NULL && server_shutdown &&
+            pending_server_shutdowns == 0) {
+          grpc_server_destroy(g_server);
+          g_server = NULL;
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // check connectivity
+      case 8: {
+        if (g_channel != NULL) {
+          uint8_t try_to_connect = next_byte(&inp);
+          if (try_to_connect == 0 || try_to_connect == 1) {
+            grpc_channel_check_connectivity_state(g_channel, try_to_connect);
+          } else {
+            end(&inp);
+          }
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // watch connectivity
+      case 9: {
+        if (g_channel != NULL) {
+          grpc_connectivity_state st =
+              grpc_channel_check_connectivity_state(g_channel, 0);
+          if (st != GRPC_CHANNEL_FATAL_FAILURE) {
+            gpr_timespec deadline = gpr_time_add(
+                gpr_now(GPR_CLOCK_REALTIME),
+                gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
+            grpc_channel_watch_connectivity_state(
+                g_channel, st, deadline, cq,
+                create_validator(validate_connectivity_watch,
+                                 make_connectivity_watch(
+                                     deadline, &pending_channel_watches)));
+            pending_channel_watches++;
+          }
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // create a call
+      case 10: {
+        bool ok = true;
+        if (g_channel == NULL) ok = false;
+        grpc_call *parent_call = NULL;
+        if (g_active_call->type != ROOT) {
+          if (g_active_call->call == NULL || g_active_call->type == CLIENT) {
+            end(&inp);
+            break;
+          }
+          parent_call = g_active_call->call;
+        }
+        uint32_t propagation_mask = read_uint32(&inp);
+        char *method = read_string(&inp);
+        char *host = read_string(&inp);
+        gpr_timespec deadline =
+            gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                         gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
+
+        if (ok) {
+          call_state *cs = new_call(g_active_call, CLIENT);
+          cs->call =
+              grpc_channel_create_call(g_channel, parent_call, propagation_mask,
+                                       cq, method, host, deadline, NULL);
+        } else {
+          end(&inp);
+        }
+        gpr_free(method);
+        gpr_free(host);
+        break;
+      }
+      // switch the 'current' call
+      case 11: {
+        g_active_call = g_active_call->next;
+        break;
+      }
+      // queue some ops on a call
+      case 12: {
+        if (g_active_call->type == PENDING_SERVER ||
+            g_active_call->type == ROOT || g_active_call->call == NULL) {
+          end(&inp);
+          break;
+        }
+        size_t num_ops = next_byte(&inp);
+        if (num_ops > 6) {
+          end(&inp);
+          break;
+        }
+        grpc_op *ops = gpr_malloc(sizeof(grpc_op) * num_ops);
+        bool ok = true;
+        size_t i;
+        grpc_op *op;
+        for (i = 0; i < num_ops; i++) {
+          op = &ops[i];
+          switch (next_byte(&inp)) {
+            default:
+              /* invalid value */
+              op->op = (grpc_op_type)-1;
+              ok = false;
+              break;
+            case GRPC_OP_SEND_INITIAL_METADATA:
+              op->op = 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);
+              break;
+            case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+              op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+              break;
+            case GRPC_OP_SEND_STATUS_FROM_SERVER:
+              op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+              read_metadata(
+                  &inp,
+                  &op->data.send_status_from_server.trailing_metadata_count,
+                  &op->data.send_status_from_server.trailing_metadata,
+                  g_active_call);
+              op->data.send_status_from_server.status = next_byte(&inp);
+              op->data.send_status_from_server.status_details =
+                  read_string(&inp);
+              break;
+            case GRPC_OP_RECV_INITIAL_METADATA:
+              op->op = 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;
+              op->data.recv_message = &g_active_call->recv_message;
+              break;
+            case GRPC_OP_RECV_STATUS_ON_CLIENT:
+              op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+              op->data.recv_status_on_client.status = &g_active_call->status;
+              op->data.recv_status_on_client.trailing_metadata =
+                  &g_active_call->recv_trailing_metadata;
+              op->data.recv_status_on_client.status_details =
+                  &g_active_call->recv_status_details;
+              op->data.recv_status_on_client.status_details_capacity =
+                  &g_active_call->recv_status_details_capacity;
+              break;
+            case GRPC_OP_RECV_CLOSE_ON_SERVER:
+              op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+              op->data.recv_close_on_server.cancelled =
+                  &g_active_call->cancelled;
+              break;
+          }
+          op->reserved = NULL;
+          op->flags = read_uint32(&inp);
+        }
+        if (ok) {
+          validator *v = create_validator(finished_batch, g_active_call);
+          g_active_call->pending_ops++;
+          grpc_call_error error =
+              grpc_call_start_batch(g_active_call->call, ops, num_ops, v, NULL);
+          if (error != GRPC_CALL_OK) {
+            v->validate(v->arg, false);
+            gpr_free(v);
+          }
+        } else {
+          end(&inp);
+        }
+        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_CLOSE_FROM_CLIENT:
+            case GRPC_OP_RECV_INITIAL_METADATA:
+            case GRPC_OP_RECV_MESSAGE:
+            case GRPC_OP_RECV_STATUS_ON_CLIENT:
+            case GRPC_OP_RECV_CLOSE_ON_SERVER:
+              break;
+          }
+        }
+        gpr_free(ops);
+
+        break;
+      }
+      // cancel current call
+      case 13: {
+        if (g_active_call->type != ROOT && g_active_call->call != NULL) {
+          grpc_call_cancel(g_active_call->call, NULL);
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // get a calls peer
+      case 14: {
+        if (g_active_call->type != ROOT && g_active_call->call != NULL) {
+          free_non_null(grpc_call_get_peer(g_active_call->call));
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // get a channels target
+      case 15: {
+        if (g_channel != NULL) {
+          free_non_null(grpc_channel_get_target(g_channel));
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // send a ping on a channel
+      case 16: {
+        if (g_channel != NULL) {
+          pending_pings++;
+          grpc_channel_ping(g_channel, cq,
+                            create_validator(decrement, &pending_pings), NULL);
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+      // enable a tracer
+      case 17: {
+        char *tracer = read_string(&inp);
+        grpc_tracer_set_enabled(tracer, 1);
+        gpr_free(tracer);
+        break;
+      }
+      // disable a tracer
+      case 18: {
+        char *tracer = read_string(&inp);
+        grpc_tracer_set_enabled(tracer, 0);
+        gpr_free(tracer);
+        break;
+      }
+      // request a server call
+      case 19: {
+        if (g_server == NULL) {
+          end(&inp);
+          break;
+        }
+        call_state *cs = new_call(g_active_call, PENDING_SERVER);
+        cs->pending_ops++;
+        validator *v = create_validator(finished_request_call, cs);
+        grpc_call_error error =
+            grpc_server_request_call(g_server, &cs->call, &cs->call_details,
+                                     &cs->recv_initial_metadata, cq, cq, v);
+        if (error != GRPC_CALL_OK) {
+          v->validate(v->arg, false);
+          gpr_free(v);
+        }
+        break;
+      }
+      // destroy a call
+      case 20: {
+        if (g_active_call->type != ROOT &&
+            g_active_call->type != PENDING_SERVER &&
+            g_active_call->call != NULL) {
+          destroy_call(g_active_call);
+        } else {
+          end(&inp);
+        }
+        break;
+      }
+    }
+  }
+
+  GPR_ASSERT(g_channel == NULL);
+  GPR_ASSERT(g_server == NULL);
+  GPR_ASSERT(g_active_call->type == ROOT);
+  GPR_ASSERT(g_active_call->next == g_active_call);
+  gpr_free(g_active_call);
+
+  grpc_completion_queue_shutdown(cq);
+  GPR_ASSERT(
+      grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL)
+          .type == GRPC_QUEUE_SHUTDOWN);
+  grpc_completion_queue_destroy(cq);
+
+  grpc_shutdown();
+  return 0;
+}
diff --git a/test/core/end2end/fuzzers/api_fuzzer.dictionary b/test/core/end2end/fuzzers/api_fuzzer.dictionary
new file mode 100644
index 0000000..c8dcc56
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer.dictionary
@@ -0,0 +1,27 @@
+# tracers
+"api\x00"
+"channel\x00"
+"channel_stack_builder\x00"
+"connectivity_state\x00"
+"flowctl\x00"
+"http\x00"
+"http1\x00"
+"round_robin\x00"
+"secure_endpoint\x00"
+"tcp\x00"
+"transport_security\x00"
+
+# channel args
+"\x00grpc.census\x00"
+"\x00grpc.max_concurrent_streams\x00"
+"\x00grpc.max_message_length\x00"
+"\x00grpc.http2.initial_sequence_number\x00"
+"\x00grpc.http2.lookahead_bytes\x00"
+"\x00grpc.http2.hpack_table_size.decoder\x00"
+"\x00grpc.http2.hpack_table_size.encoder\x00"
+"\x01grpc.default_authority\x00"
+"\x01grpc.primary_user_agent\x00"
+"\x01grpc.secondary_user_agent\x00"
+"\x00grpc.max_reconnect_backoff_ms\x00"
+"\x01grpc.ssl_target_name_override\x00"
+
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/00.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/00.bin
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/00.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/01.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/01.bin
new file mode 100644
index 0000000..6b2aaa7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/01.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0159f564d91869bc07239f5551a493c2845a4524 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0159f564d91869bc07239f5551a493c2845a4524
new file mode 100644
index 0000000..fc0942d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0159f564d91869bc07239f5551a493c2845a4524
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/02.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/02.bin
new file mode 100644
index 0000000..25cb955
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/02.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0211f960c2da343c3cde6406e650d73278e01e47 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0211f960c2da343c3cde6406e650d73278e01e47
new file mode 100644
index 0000000..1a2c219
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0211f960c2da343c3cde6406e650d73278e01e47
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0236f28708dcc2e044d67ecf93539ce6c33a727a b/test/core/end2end/fuzzers/api_fuzzer_corpus/0236f28708dcc2e044d67ecf93539ce6c33a727a
new file mode 100644
index 0000000..3e11c30
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0236f28708dcc2e044d67ecf93539ce6c33a727a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/02434dcdaca96b9eacee76eb351e99f015eaa05e b/test/core/end2end/fuzzers/api_fuzzer_corpus/02434dcdaca96b9eacee76eb351e99f015eaa05e
new file mode 100644
index 0000000..9ba80bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/02434dcdaca96b9eacee76eb351e99f015eaa05e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/03.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/03.bin
new file mode 100644
index 0000000..fc2b569
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/03.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0302b90625ac9f61f45b45d043fda23b5472d711 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0302b90625ac9f61f45b45d043fda23b5472d711
new file mode 100644
index 0000000..4044081
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0302b90625ac9f61f45b45d043fda23b5472d711
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/04.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/04.bin
new file mode 100644
index 0000000..45a8ca0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/04.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0433cabb8c28820bda0a6eac35d17d120f1b6865 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0433cabb8c28820bda0a6eac35d17d120f1b6865
new file mode 100644
index 0000000..0507679
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0433cabb8c28820bda0a6eac35d17d120f1b6865
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0452ea591951af85724608917fda16926dad7451 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0452ea591951af85724608917fda16926dad7451
new file mode 100644
index 0000000..8803e43
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0452ea591951af85724608917fda16926dad7451
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0468ab4bf4f7e10b680f43efae4bf9686834d220 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0468ab4bf4f7e10b680f43efae4bf9686834d220
new file mode 100644
index 0000000..6bc9334
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0468ab4bf4f7e10b680f43efae4bf9686834d220
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/04e01f399f194434b2b724877df64828e8f52c14 b/test/core/end2end/fuzzers/api_fuzzer_corpus/04e01f399f194434b2b724877df64828e8f52c14
new file mode 100644
index 0000000..f65526c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/04e01f399f194434b2b724877df64828e8f52c14
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/05.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/05.bin
new file mode 100644
index 0000000..b0b2b1c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/05.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0539bf31b2310091ce30d0123142d63589939105 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0539bf31b2310091ce30d0123142d63589939105
new file mode 100644
index 0000000..37bb90d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0539bf31b2310091ce30d0123142d63589939105
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0542a0e5aeb1658cc965724bfced56770569263b b/test/core/end2end/fuzzers/api_fuzzer_corpus/0542a0e5aeb1658cc965724bfced56770569263b
new file mode 100644
index 0000000..15ed709
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0542a0e5aeb1658cc965724bfced56770569263b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/056e56878b249c7fd0b95576b352ab2f4d46582e b/test/core/end2end/fuzzers/api_fuzzer_corpus/056e56878b249c7fd0b95576b352ab2f4d46582e
new file mode 100644
index 0000000..5713da5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/056e56878b249c7fd0b95576b352ab2f4d46582e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/05dee1c3847f2bca29bd14ed701ce64999b298b2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/05dee1c3847f2bca29bd14ed701ce64999b298b2
new file mode 100644
index 0000000..2f2494d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/05dee1c3847f2bca29bd14ed701ce64999b298b2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/06.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/06.bin
new file mode 100644
index 0000000..f8fa5a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/06.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/064d3beeef29a647deb1b345426ea7212de71cfe b/test/core/end2end/fuzzers/api_fuzzer_corpus/064d3beeef29a647deb1b345426ea7212de71cfe
new file mode 100644
index 0000000..1ca4fad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/064d3beeef29a647deb1b345426ea7212de71cfe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/067298a97640cc5e212647864d21bc1fa6bb7e75 b/test/core/end2end/fuzzers/api_fuzzer_corpus/067298a97640cc5e212647864d21bc1fa6bb7e75
new file mode 100644
index 0000000..d430eb6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/067298a97640cc5e212647864d21bc1fa6bb7e75
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/07.bin
new file mode 100644
index 0000000..303e398
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/070c7005e63abba72c6bc1a0ee6d44e340f2d2be b/test/core/end2end/fuzzers/api_fuzzer_corpus/070c7005e63abba72c6bc1a0ee6d44e340f2d2be
new file mode 100644
index 0000000..2ca9049
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/070c7005e63abba72c6bc1a0ee6d44e340f2d2be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07674d39538e07c29342cb2ee8856bc71fc06638 b/test/core/end2end/fuzzers/api_fuzzer_corpus/07674d39538e07c29342cb2ee8856bc71fc06638
new file mode 100644
index 0000000..42d6082
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07674d39538e07c29342cb2ee8856bc71fc06638
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07aa7d6c71878eb78b25ca12d79082f70ae7f64c b/test/core/end2end/fuzzers/api_fuzzer_corpus/07aa7d6c71878eb78b25ca12d79082f70ae7f64c
new file mode 100644
index 0000000..e87065d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07aa7d6c71878eb78b25ca12d79082f70ae7f64c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07ae5ed3dedbd83e376c892a9546cc0cd733c26f b/test/core/end2end/fuzzers/api_fuzzer_corpus/07ae5ed3dedbd83e376c892a9546cc0cd733c26f
new file mode 100644
index 0000000..e814b6e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07ae5ed3dedbd83e376c892a9546cc0cd733c26f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07cc8b298d1502d0c30f3f160871e66e5a1f3fe1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/07cc8b298d1502d0c30f3f160871e66e5a1f3fe1
new file mode 100644
index 0000000..45c4b81
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07cc8b298d1502d0c30f3f160871e66e5a1f3fe1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/08.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/08.bin
new file mode 100644
index 0000000..5a77f05
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/08.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/085865a209776911782f592c9f30ffe0ad3814a0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/085865a209776911782f592c9f30ffe0ad3814a0
new file mode 100644
index 0000000..85820f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/085865a209776911782f592c9f30ffe0ad3814a0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/09.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/09.bin
new file mode 100644
index 0000000..501a6bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/09.bin
@@ -0,0 +1 @@
+	
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/092b85d1f5c922287e476e6e75ad8a0a80c779a6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/092b85d1f5c922287e476e6e75ad8a0a80c779a6
new file mode 100644
index 0000000..766c0ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/092b85d1f5c922287e476e6e75ad8a0a80c779a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/09923e3ef02243b1902406c637f9516cbe99d7cb b/test/core/end2end/fuzzers/api_fuzzer_corpus/09923e3ef02243b1902406c637f9516cbe99d7cb
new file mode 100644
index 0000000..e2f0da6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/09923e3ef02243b1902406c637f9516cbe99d7cb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0a.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a.bin
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a.bin
@@ -0,0 +1 @@
+
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0a71ae781345f9ee2b08008a81f9055e6c1d5256 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a71ae781345f9ee2b08008a81f9055e6c1d5256
new file mode 100644
index 0000000..c7464b2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a71ae781345f9ee2b08008a81f9055e6c1d5256
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0a7aad5682c304b0cbda31445b221238e0293a9f b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a7aad5682c304b0cbda31445b221238e0293a9f
new file mode 100644
index 0000000..706aab1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a7aad5682c304b0cbda31445b221238e0293a9f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0b.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/0b.bin
new file mode 100644
index 0000000..2725bca
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0b.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0b6f0ea99a329e054032e6c292b99c3bcad0c9f2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0b6f0ea99a329e054032e6c292b99c3bcad0c9f2
new file mode 100644
index 0000000..e165c8c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0b6f0ea99a329e054032e6c292b99c3bcad0c9f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0bbd89b21cfd192174c25803c7f1afeec88e6524 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0bbd89b21cfd192174c25803c7f1afeec88e6524
new file mode 100644
index 0000000..b1776ca
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0bbd89b21cfd192174c25803c7f1afeec88e6524
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0c.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c.bin
new file mode 100644
index 0000000..8214d0e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d.bin
new file mode 100644
index 0000000..67c3297
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d16d6c2c128ac4ee7b596b763822b4194968533 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d16d6c2c128ac4ee7b596b763822b4194968533
new file mode 100644
index 0000000..6ff033e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d16d6c2c128ac4ee7b596b763822b4194968533
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d8bd296d63a5aca5f80d7a7d00387048babda36 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d8bd296d63a5aca5f80d7a7d00387048babda36
new file mode 100644
index 0000000..4c0ac75
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d8bd296d63a5aca5f80d7a7d00387048babda36
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d9d8241c5568fea586d21f91ae1891dac31ba24 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d9d8241c5568fea586d21f91ae1891dac31ba24
new file mode 100644
index 0000000..2516485
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d9d8241c5568fea586d21f91ae1891dac31ba24
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0e.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e.bin
new file mode 100644
index 0000000..9280c0d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0e2a9ad3aacba320563095a874768a9e546a3db2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e2a9ad3aacba320563095a874768a9e546a3db2
new file mode 100644
index 0000000..b8e356f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e2a9ad3aacba320563095a874768a9e546a3db2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0f.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f.bin
new file mode 100644
index 0000000..c30d058
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f.bin
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0f2831e0f73521a0991e11115c16847afca16bb3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f2831e0f73521a0991e11115c16847afca16bb3
new file mode 100644
index 0000000..50e9c19
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f2831e0f73521a0991e11115c16847afca16bb3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0fa216ec645b3973b5e6d28baedd5acc1542e69e b/test/core/end2end/fuzzers/api_fuzzer_corpus/0fa216ec645b3973b5e6d28baedd5acc1542e69e
new file mode 100644
index 0000000..3f97dd4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0fa216ec645b3973b5e6d28baedd5acc1542e69e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/10302aa7598eb36d0ac22d0478eb0f2a6b010ea6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/10302aa7598eb36d0ac22d0478eb0f2a6b010ea6
new file mode 100644
index 0000000..239e86c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/10302aa7598eb36d0ac22d0478eb0f2a6b010ea6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1109cb814fd134862a3f5ef5c9b2244585882b8f b/test/core/end2end/fuzzers/api_fuzzer_corpus/1109cb814fd134862a3f5ef5c9b2244585882b8f
new file mode 100644
index 0000000..217fed2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1109cb814fd134862a3f5ef5c9b2244585882b8f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/119410315423e5f37919886ced7f03235e5792aa b/test/core/end2end/fuzzers/api_fuzzer_corpus/119410315423e5f37919886ced7f03235e5792aa
new file mode 100644
index 0000000..38d3368
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/119410315423e5f37919886ced7f03235e5792aa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/12083209096187575021a775826b08b70b39ed4c b/test/core/end2end/fuzzers/api_fuzzer_corpus/12083209096187575021a775826b08b70b39ed4c
new file mode 100644
index 0000000..65728fa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/12083209096187575021a775826b08b70b39ed4c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1254c9256157e6362003c97c8c93d8cd67a28772 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1254c9256157e6362003c97c8c93d8cd67a28772
new file mode 100644
index 0000000..20ece80
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1254c9256157e6362003c97c8c93d8cd67a28772
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/12a97827d0f817e3ffd8d9cf1bdba0f945b6fda4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/12a97827d0f817e3ffd8d9cf1bdba0f945b6fda4
new file mode 100644
index 0000000..f12e858
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/12a97827d0f817e3ffd8d9cf1bdba0f945b6fda4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/12ef45f6beba92677a2a7508fc5e1bfef30ded66 b/test/core/end2end/fuzzers/api_fuzzer_corpus/12ef45f6beba92677a2a7508fc5e1bfef30ded66
new file mode 100644
index 0000000..f62faf3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/12ef45f6beba92677a2a7508fc5e1bfef30ded66
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/130c41e2dd87c36b4079c8e5bd380dbe3e0a2b38 b/test/core/end2end/fuzzers/api_fuzzer_corpus/130c41e2dd87c36b4079c8e5bd380dbe3e0a2b38
new file mode 100644
index 0000000..c737ee5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/130c41e2dd87c36b4079c8e5bd380dbe3e0a2b38
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/13c409dcf7752c25b2b51ac5fad9201b505d7059 b/test/core/end2end/fuzzers/api_fuzzer_corpus/13c409dcf7752c25b2b51ac5fad9201b505d7059
new file mode 100644
index 0000000..7edcab6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/13c409dcf7752c25b2b51ac5fad9201b505d7059
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/143789594154049441d565b65ce725fc4f8c12bc b/test/core/end2end/fuzzers/api_fuzzer_corpus/143789594154049441d565b65ce725fc4f8c12bc
new file mode 100644
index 0000000..9091ea3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/143789594154049441d565b65ce725fc4f8c12bc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/149044286608a7945721c61f12196bebd5adb2ee b/test/core/end2end/fuzzers/api_fuzzer_corpus/149044286608a7945721c61f12196bebd5adb2ee
new file mode 100644
index 0000000..049b4f5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/149044286608a7945721c61f12196bebd5adb2ee
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/157586c7c0ba8fd0dc9bfc2426229a7da934cec2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/157586c7c0ba8fd0dc9bfc2426229a7da934cec2
new file mode 100644
index 0000000..9e30b101
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/157586c7c0ba8fd0dc9bfc2426229a7da934cec2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/15c37fe5be9f23c0f0e59e12ee7666007acdb3c5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/15c37fe5be9f23c0f0e59e12ee7666007acdb3c5
new file mode 100644
index 0000000..33e9109
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/15c37fe5be9f23c0f0e59e12ee7666007acdb3c5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1661d0799cbf2015fd64e9f648ebb49281d41c6d b/test/core/end2end/fuzzers/api_fuzzer_corpus/1661d0799cbf2015fd64e9f648ebb49281d41c6d
new file mode 100644
index 0000000..363345d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1661d0799cbf2015fd64e9f648ebb49281d41c6d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1671cf01e5baf796c5572b7b0e15d226a5c93f23 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1671cf01e5baf796c5572b7b0e15d226a5c93f23
new file mode 100644
index 0000000..7a8b503
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1671cf01e5baf796c5572b7b0e15d226a5c93f23
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/16a9beb811f836a444172a5da9290b47d77c32ef b/test/core/end2end/fuzzers/api_fuzzer_corpus/16a9beb811f836a444172a5da9290b47d77c32ef
new file mode 100644
index 0000000..3b40d05
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/16a9beb811f836a444172a5da9290b47d77c32ef
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/16d52016278caebf92ba455f7ac8a8c7482c3563 b/test/core/end2end/fuzzers/api_fuzzer_corpus/16d52016278caebf92ba455f7ac8a8c7482c3563
new file mode 100644
index 0000000..68cd7d5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/16d52016278caebf92ba455f7ac8a8c7482c3563
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/173ebf4139ee6d7a574b6767059d82375674bbf4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/173ebf4139ee6d7a574b6767059d82375674bbf4
new file mode 100644
index 0000000..7ddf9b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/173ebf4139ee6d7a574b6767059d82375674bbf4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17cfb281eaa8a17d77e08c3648bb93f3b5aa5297 b/test/core/end2end/fuzzers/api_fuzzer_corpus/17cfb281eaa8a17d77e08c3648bb93f3b5aa5297
new file mode 100644
index 0000000..b951e5a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17cfb281eaa8a17d77e08c3648bb93f3b5aa5297
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/183c878064b6a0ddf6a22dc4a2aa0d33a2d802d0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/183c878064b6a0ddf6a22dc4a2aa0d33a2d802d0
new file mode 100644
index 0000000..79e5993
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/183c878064b6a0ddf6a22dc4a2aa0d33a2d802d0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1887558eb48d6a4341610fd0395cef8e87744044 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1887558eb48d6a4341610fd0395cef8e87744044
new file mode 100644
index 0000000..32ed928
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1887558eb48d6a4341610fd0395cef8e87744044
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/18c856af1e2ebb934401e523043eaf80aecc8363 b/test/core/end2end/fuzzers/api_fuzzer_corpus/18c856af1e2ebb934401e523043eaf80aecc8363
new file mode 100644
index 0000000..2affb44
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/18c856af1e2ebb934401e523043eaf80aecc8363
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/18f2d7626b6ad4859e735e448b00b6916f1d3e2e b/test/core/end2end/fuzzers/api_fuzzer_corpus/18f2d7626b6ad4859e735e448b00b6916f1d3e2e
new file mode 100644
index 0000000..728aabd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/18f2d7626b6ad4859e735e448b00b6916f1d3e2e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/19dcc3082c76b85177ce6a56d195473aaa285268 b/test/core/end2end/fuzzers/api_fuzzer_corpus/19dcc3082c76b85177ce6a56d195473aaa285268
new file mode 100644
index 0000000..03dd65a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/19dcc3082c76b85177ce6a56d195473aaa285268
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1a6b907bfa02ceebeb80aab47b3c3c51161eb868 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1a6b907bfa02ceebeb80aab47b3c3c51161eb868
new file mode 100644
index 0000000..ebd58f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1a6b907bfa02ceebeb80aab47b3c3c51161eb868
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1b699132724acab3d42fb5210c07b74343449873 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b699132724acab3d42fb5210c07b74343449873
new file mode 100644
index 0000000..5ca4b56
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b699132724acab3d42fb5210c07b74343449873
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c0417c96e6408d2902ef8fe4b8cd05f1ce4a50f b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c0417c96e6408d2902ef8fe4b8cd05f1ce4a50f
new file mode 100644
index 0000000..22ff0e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c0417c96e6408d2902ef8fe4b8cd05f1ce4a50f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c6e5ad8dbff133707cc85b05a0057abf55d08ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c6e5ad8dbff133707cc85b05a0057abf55d08ad
new file mode 100644
index 0000000..031f444
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c6e5ad8dbff133707cc85b05a0057abf55d08ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c73564518349ebc87c4023b9d9a3cbc4fbc6cdd b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c73564518349ebc87c4023b9d9a3cbc4fbc6cdd
new file mode 100644
index 0000000..8cf36c2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c73564518349ebc87c4023b9d9a3cbc4fbc6cdd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c98433d827ea4aae2ba8a68c4d11bc2527cb15d b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c98433d827ea4aae2ba8a68c4d11bc2527cb15d
new file mode 100644
index 0000000..2bc525e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c98433d827ea4aae2ba8a68c4d11bc2527cb15d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1ccd81836f26b7ececde2b02a22b19ab2a498631 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1ccd81836f26b7ececde2b02a22b19ab2a498631
new file mode 100644
index 0000000..a581ee2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1ccd81836f26b7ececde2b02a22b19ab2a498631
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1d8b40b4798e652184df3bcffe1b1d7e32648f79 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d8b40b4798e652184df3bcffe1b1d7e32648f79
new file mode 100644
index 0000000..e7456f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d8b40b4798e652184df3bcffe1b1d7e32648f79
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1e4a2a6998218ea8f475aa2ee27869207b33b612 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e4a2a6998218ea8f475aa2ee27869207b33b612
new file mode 100644
index 0000000..f736392
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e4a2a6998218ea8f475aa2ee27869207b33b612
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1e55e5f47b550bab133099e5a98d7c751a0a2d7b b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e55e5f47b550bab133099e5a98d7c751a0a2d7b
new file mode 100644
index 0000000..1a2c262
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e55e5f47b550bab133099e5a98d7c751a0a2d7b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1e7d2d8f6109f4c02815ce8582c799134f2ff5dc b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e7d2d8f6109f4c02815ce8582c799134f2ff5dc
new file mode 100644
index 0000000..4b9572f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e7d2d8f6109f4c02815ce8582c799134f2ff5dc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1fda93a85f7b5b7a0c2d68a03123e58a6d20f124 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1fda93a85f7b5b7a0c2d68a03123e58a6d20f124
new file mode 100644
index 0000000..ec9aed1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1fda93a85f7b5b7a0c2d68a03123e58a6d20f124
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/20322515ebf6df572cb2f596d8a20d3d8893193d b/test/core/end2end/fuzzers/api_fuzzer_corpus/20322515ebf6df572cb2f596d8a20d3d8893193d
new file mode 100644
index 0000000..0e9a66e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/20322515ebf6df572cb2f596d8a20d3d8893193d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/207c5a0f80f052ac7b48f6dd45cd33987be27f32 b/test/core/end2end/fuzzers/api_fuzzer_corpus/207c5a0f80f052ac7b48f6dd45cd33987be27f32
new file mode 100644
index 0000000..ee45b1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/207c5a0f80f052ac7b48f6dd45cd33987be27f32
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2099db589f606dd8932a950280f5d2b23751af9f b/test/core/end2end/fuzzers/api_fuzzer_corpus/2099db589f606dd8932a950280f5d2b23751af9f
new file mode 100644
index 0000000..085168f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2099db589f606dd8932a950280f5d2b23751af9f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/21f3be485826850e4f4670bb81982e2827815426 b/test/core/end2end/fuzzers/api_fuzzer_corpus/21f3be485826850e4f4670bb81982e2827815426
new file mode 100644
index 0000000..c8c5daa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/21f3be485826850e4f4670bb81982e2827815426
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/240afe42d3e2834c46a79d9df0dd6ca018831398 b/test/core/end2end/fuzzers/api_fuzzer_corpus/240afe42d3e2834c46a79d9df0dd6ca018831398
new file mode 100644
index 0000000..9007ade
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/240afe42d3e2834c46a79d9df0dd6ca018831398
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/24a87af0954c808fbd3f2c55185d4b1fa9459f4e b/test/core/end2end/fuzzers/api_fuzzer_corpus/24a87af0954c808fbd3f2c55185d4b1fa9459f4e
new file mode 100644
index 0000000..9bdcea1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/24a87af0954c808fbd3f2c55185d4b1fa9459f4e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/24df70902c288fcac060365c2e6f61269a3606b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/24df70902c288fcac060365c2e6f61269a3606b4
new file mode 100644
index 0000000..2ba0d07
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/24df70902c288fcac060365c2e6f61269a3606b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2500fc12d5d1b5ed99fc3fe518c28849d1c8d6e8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2500fc12d5d1b5ed99fc3fe518c28849d1c8d6e8
new file mode 100644
index 0000000..519134a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2500fc12d5d1b5ed99fc3fe518c28849d1c8d6e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2501c7c3f78829725e6bf556277785588318106b b/test/core/end2end/fuzzers/api_fuzzer_corpus/2501c7c3f78829725e6bf556277785588318106b
new file mode 100644
index 0000000..f5308f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2501c7c3f78829725e6bf556277785588318106b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2507810915aecd3adf1287edf8c9f54b23a8ebd5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2507810915aecd3adf1287edf8c9f54b23a8ebd5
new file mode 100644
index 0000000..403316b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2507810915aecd3adf1287edf8c9f54b23a8ebd5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/253b8946a7cf403dd466f1685df2f741d4660a34 b/test/core/end2end/fuzzers/api_fuzzer_corpus/253b8946a7cf403dd466f1685df2f741d4660a34
new file mode 100644
index 0000000..4102118
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/253b8946a7cf403dd466f1685df2f741d4660a34
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/26865cd90c1461694d94d96232436372df2a91fb b/test/core/end2end/fuzzers/api_fuzzer_corpus/26865cd90c1461694d94d96232436372df2a91fb
new file mode 100644
index 0000000..3f9d579
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/26865cd90c1461694d94d96232436372df2a91fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2743ee5a764fb0c4e04cdf84c9b3810ac8093998 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2743ee5a764fb0c4e04cdf84c9b3810ac8093998
new file mode 100644
index 0000000..a070f08
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2743ee5a764fb0c4e04cdf84c9b3810ac8093998
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2748d28f2e03d740a89f7a50ea52450d0c5523f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2748d28f2e03d740a89f7a50ea52450d0c5523f1
new file mode 100644
index 0000000..cbe1656
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2748d28f2e03d740a89f7a50ea52450d0c5523f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2837baed2fbf1612f88224e91ddc46241dd9d972 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2837baed2fbf1612f88224e91ddc46241dd9d972
new file mode 100644
index 0000000..5914914
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2837baed2fbf1612f88224e91ddc46241dd9d972
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/28f8c7af6aab3bbabe028f780e174b27b924a146 b/test/core/end2end/fuzzers/api_fuzzer_corpus/28f8c7af6aab3bbabe028f780e174b27b924a146
new file mode 100644
index 0000000..cda8bc5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/28f8c7af6aab3bbabe028f780e174b27b924a146
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2942908b7973da7113098a0ea25487e3372db173 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2942908b7973da7113098a0ea25487e3372db173
new file mode 100644
index 0000000..b794909
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2942908b7973da7113098a0ea25487e3372db173
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/296c3f5b9880fe7ccff4d2a67f489b38b5b6fd6e b/test/core/end2end/fuzzers/api_fuzzer_corpus/296c3f5b9880fe7ccff4d2a67f489b38b5b6fd6e
new file mode 100644
index 0000000..42819bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/296c3f5b9880fe7ccff4d2a67f489b38b5b6fd6e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2a600cae342e8e9e23406bb1e76133f48d936766 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a600cae342e8e9e23406bb1e76133f48d936766
new file mode 100644
index 0000000..c66d5d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a600cae342e8e9e23406bb1e76133f48d936766
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2ab009994e603404e194ebe0120840d388fb765e b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ab009994e603404e194ebe0120840d388fb765e
new file mode 100644
index 0000000..2972ed8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ab009994e603404e194ebe0120840d388fb765e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2ad5ed48b598bd9e2d486a21eed5314736e5b56a b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ad5ed48b598bd9e2d486a21eed5314736e5b56a
new file mode 100644
index 0000000..ee07f6f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ad5ed48b598bd9e2d486a21eed5314736e5b56a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2aee21e4d1175963fa719d376406bb10d4818bdd b/test/core/end2end/fuzzers/api_fuzzer_corpus/2aee21e4d1175963fa719d376406bb10d4818bdd
new file mode 100644
index 0000000..92989f7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2aee21e4d1175963fa719d376406bb10d4818bdd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2af392765963966f2d1ddd5d5af4fcadd93c3b06 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2af392765963966f2d1ddd5d5af4fcadd93c3b06
new file mode 100644
index 0000000..121947f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2af392765963966f2d1ddd5d5af4fcadd93c3b06
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2af4e625522d128d03252f35b5fa5094cbcebc9f b/test/core/end2end/fuzzers/api_fuzzer_corpus/2af4e625522d128d03252f35b5fa5094cbcebc9f
new file mode 100644
index 0000000..9ee2514
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2af4e625522d128d03252f35b5fa5094cbcebc9f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2b931953e9bd02c3310a05234e91550bcd8ddf62 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2b931953e9bd02c3310a05234e91550bcd8ddf62
new file mode 100644
index 0000000..e6b03b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2b931953e9bd02c3310a05234e91550bcd8ddf62
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2b933a0ede25a06e32c7d9cc5a3eda78086f3060 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2b933a0ede25a06e32c7d9cc5a3eda78086f3060
new file mode 100644
index 0000000..fb5a647
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2b933a0ede25a06e32c7d9cc5a3eda78086f3060
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2bbe5b2c12a964b53a5e6f78cdd5f595d95082a9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2bbe5b2c12a964b53a5e6f78cdd5f595d95082a9
new file mode 100644
index 0000000..4929da7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2bbe5b2c12a964b53a5e6f78cdd5f595d95082a9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2bc326b3ecf6d069595bc27cc1bca76b374c8e85 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2bc326b3ecf6d069595bc27cc1bca76b374c8e85
new file mode 100644
index 0000000..c2d133e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2bc326b3ecf6d069595bc27cc1bca76b374c8e85
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2c917a39d34aad10d611a1647a6df6502b4d4d59 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2c917a39d34aad10d611a1647a6df6502b4d4d59
new file mode 100644
index 0000000..39c7904
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2c917a39d34aad10d611a1647a6df6502b4d4d59
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d61ec2cff75eadbc47e0932998b8a797e0cd96c b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d61ec2cff75eadbc47e0932998b8a797e0cd96c
new file mode 100644
index 0000000..f0e23fc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d61ec2cff75eadbc47e0932998b8a797e0cd96c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d9440daa210b9298f34982dcf7adc3564ad965c b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d9440daa210b9298f34982dcf7adc3564ad965c
new file mode 100644
index 0000000..4d2752c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d9440daa210b9298f34982dcf7adc3564ad965c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d974f9fd1c57bce55cb9f1bbc25eb1e7a10454b b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d974f9fd1c57bce55cb9f1bbc25eb1e7a10454b
new file mode 100644
index 0000000..038b916
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d974f9fd1c57bce55cb9f1bbc25eb1e7a10454b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2db3a358c43c179a728f0650a00be295e88f8060 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2db3a358c43c179a728f0650a00be295e88f8060
new file mode 100644
index 0000000..9108f0f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2db3a358c43c179a728f0650a00be295e88f8060
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2e21a2f9bff2514667aaec75629c82daa067ff57 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e21a2f9bff2514667aaec75629c82daa067ff57
new file mode 100644
index 0000000..771749c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e21a2f9bff2514667aaec75629c82daa067ff57
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2e82bfb7e8eede401ce75f6afe8c15ffd06130db b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e82bfb7e8eede401ce75f6afe8c15ffd06130db
new file mode 100644
index 0000000..8412599
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e82bfb7e8eede401ce75f6afe8c15ffd06130db
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2f0a8f0f96402ba1681ab3a9095a3dea47cdc53f b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f0a8f0f96402ba1681ab3a9095a3dea47cdc53f
new file mode 100644
index 0000000..818728a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f0a8f0f96402ba1681ab3a9095a3dea47cdc53f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2f120ceed5250084f62010df9bf8fe8e8f3f643b b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f120ceed5250084f62010df9bf8fe8e8f3f643b
new file mode 100644
index 0000000..356f4a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f120ceed5250084f62010df9bf8fe8e8f3f643b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2f44fd38efef5818750f9adc9b133e40f9cdec71 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f44fd38efef5818750f9adc9b133e40f9cdec71
new file mode 100644
index 0000000..561eb03
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f44fd38efef5818750f9adc9b133e40f9cdec71
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2f57224df35ff1583d14436a477330db23d70b0a b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f57224df35ff1583d14436a477330db23d70b0a
new file mode 100644
index 0000000..341c0d1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f57224df35ff1583d14436a477330db23d70b0a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2fa6a874e625ca4d71941408d94698f898be4ea1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2fa6a874e625ca4d71941408d94698f898be4ea1
new file mode 100644
index 0000000..c336404
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2fa6a874e625ca4d71941408d94698f898be4ea1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/301c057536319f49dcec68ab96677714e3dbf793 b/test/core/end2end/fuzzers/api_fuzzer_corpus/301c057536319f49dcec68ab96677714e3dbf793
new file mode 100644
index 0000000..0e89861
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/301c057536319f49dcec68ab96677714e3dbf793
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30694ac08ff5a6a10cc781b9042c89f4019cfe0a b/test/core/end2end/fuzzers/api_fuzzer_corpus/30694ac08ff5a6a10cc781b9042c89f4019cfe0a
new file mode 100644
index 0000000..735ac97
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30694ac08ff5a6a10cc781b9042c89f4019cfe0a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/307a91e344b94923837e01a1657ff277f44db07d b/test/core/end2end/fuzzers/api_fuzzer_corpus/307a91e344b94923837e01a1657ff277f44db07d
new file mode 100644
index 0000000..5336672
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/307a91e344b94923837e01a1657ff277f44db07d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30fbe0ac4c74e2be3edd4f21b72bcae02e6c623f b/test/core/end2end/fuzzers/api_fuzzer_corpus/30fbe0ac4c74e2be3edd4f21b72bcae02e6c623f
new file mode 100644
index 0000000..7dcc2a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30fbe0ac4c74e2be3edd4f21b72bcae02e6c623f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/313001e1cc15ef9887b43e0c6de398eea2f20e00 b/test/core/end2end/fuzzers/api_fuzzer_corpus/313001e1cc15ef9887b43e0c6de398eea2f20e00
new file mode 100644
index 0000000..ec61304
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/313001e1cc15ef9887b43e0c6de398eea2f20e00
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/31429d04a34cc6643eebed7eeb8a807a83b57b1f b/test/core/end2end/fuzzers/api_fuzzer_corpus/31429d04a34cc6643eebed7eeb8a807a83b57b1f
new file mode 100644
index 0000000..5713b9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/31429d04a34cc6643eebed7eeb8a807a83b57b1f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3230d9876d770657d86dfb768b80494cda52abc8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3230d9876d770657d86dfb768b80494cda52abc8
new file mode 100644
index 0000000..cdfd293
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3230d9876d770657d86dfb768b80494cda52abc8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/32594aaa716c1a04b0f927ef964f1593735cb289 b/test/core/end2end/fuzzers/api_fuzzer_corpus/32594aaa716c1a04b0f927ef964f1593735cb289
new file mode 100644
index 0000000..390f90e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/32594aaa716c1a04b0f927ef964f1593735cb289
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/32b9de8461fd32b1236abb86abc91c82652d6e2c b/test/core/end2end/fuzzers/api_fuzzer_corpus/32b9de8461fd32b1236abb86abc91c82652d6e2c
new file mode 100644
index 0000000..e7b70fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/32b9de8461fd32b1236abb86abc91c82652d6e2c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/32c108ead009572fbe9a216b372e5c0b3843238e b/test/core/end2end/fuzzers/api_fuzzer_corpus/32c108ead009572fbe9a216b372e5c0b3843238e
new file mode 100644
index 0000000..6ec8cba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/32c108ead009572fbe9a216b372e5c0b3843238e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3399ac8bb9e0d3a2cbf22a95d1e20c70e2415e41 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3399ac8bb9e0d3a2cbf22a95d1e20c70e2415e41
new file mode 100644
index 0000000..3868160
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3399ac8bb9e0d3a2cbf22a95d1e20c70e2415e41
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/342d148e59fb500ad76d583cf828c16cd3d3ed2e b/test/core/end2end/fuzzers/api_fuzzer_corpus/342d148e59fb500ad76d583cf828c16cd3d3ed2e
new file mode 100644
index 0000000..726f356
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/342d148e59fb500ad76d583cf828c16cd3d3ed2e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3465fb573ac3c59a0804aadeba2f205870abcc3d b/test/core/end2end/fuzzers/api_fuzzer_corpus/3465fb573ac3c59a0804aadeba2f205870abcc3d
new file mode 100644
index 0000000..58f59a4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3465fb573ac3c59a0804aadeba2f205870abcc3d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/364f77bffd55805e2be9d2b3a071012e8fc3a083 b/test/core/end2end/fuzzers/api_fuzzer_corpus/364f77bffd55805e2be9d2b3a071012e8fc3a083
new file mode 100644
index 0000000..720baf7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/364f77bffd55805e2be9d2b3a071012e8fc3a083
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/368d2b5d4c6776afbed8e5e76cc3a4ccdde1df42 b/test/core/end2end/fuzzers/api_fuzzer_corpus/368d2b5d4c6776afbed8e5e76cc3a4ccdde1df42
new file mode 100644
index 0000000..3e2cf5e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/368d2b5d4c6776afbed8e5e76cc3a4ccdde1df42
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/383043f6c05edc5a18f5c8e7b9d0314db63eab5e b/test/core/end2end/fuzzers/api_fuzzer_corpus/383043f6c05edc5a18f5c8e7b9d0314db63eab5e
new file mode 100644
index 0000000..816d9e2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/383043f6c05edc5a18f5c8e7b9d0314db63eab5e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3850b085a0a33fa2a08630dddb03e0f1adb1bee9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3850b085a0a33fa2a08630dddb03e0f1adb1bee9
new file mode 100644
index 0000000..e48f730
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3850b085a0a33fa2a08630dddb03e0f1adb1bee9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/38c609f72f5a2cf977788afef9c34652f754add0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/38c609f72f5a2cf977788afef9c34652f754add0
new file mode 100644
index 0000000..7ab84cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/38c609f72f5a2cf977788afef9c34652f754add0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3a287590e2d38d5dbc0b85d29ae2497d27aa0305 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a287590e2d38d5dbc0b85d29ae2497d27aa0305
new file mode 100644
index 0000000..266d308
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a287590e2d38d5dbc0b85d29ae2497d27aa0305
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3a4fa4e81b78cae093b2d53b0a6f272a398a7cda b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a4fa4e81b78cae093b2d53b0a6f272a398a7cda
new file mode 100644
index 0000000..796be8e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a4fa4e81b78cae093b2d53b0a6f272a398a7cda
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3aee5ced2869452b8ed65313d01b9b9c87144cd4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3aee5ced2869452b8ed65313d01b9b9c87144cd4
new file mode 100644
index 0000000..ee9bcbd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3aee5ced2869452b8ed65313d01b9b9c87144cd4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3b002ab57ff8080fbb1e72d985ca6f59f96a171e b/test/core/end2end/fuzzers/api_fuzzer_corpus/3b002ab57ff8080fbb1e72d985ca6f59f96a171e
new file mode 100644
index 0000000..f3518a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3b002ab57ff8080fbb1e72d985ca6f59f96a171e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3c84d21c46b89e7573750dd4517ea2eb58e37e27 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c84d21c46b89e7573750dd4517ea2eb58e37e27
new file mode 100644
index 0000000..1ae200f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c84d21c46b89e7573750dd4517ea2eb58e37e27
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3c8e6352f6c2a07bd5ef2b9a93c103935c8eaf0d b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c8e6352f6c2a07bd5ef2b9a93c103935c8eaf0d
new file mode 100644
index 0000000..e631a79
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c8e6352f6c2a07bd5ef2b9a93c103935c8eaf0d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3d8c66be71e0ae0dfb0c2c7b84e4d8336f92b7ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d8c66be71e0ae0dfb0c2c7b84e4d8336f92b7ab
new file mode 100644
index 0000000..43f3e76
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d8c66be71e0ae0dfb0c2c7b84e4d8336f92b7ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3dedcaf501bc9718e5d372862b081fc9fdfb3959 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3dedcaf501bc9718e5d372862b081fc9fdfb3959
new file mode 100644
index 0000000..25dbe28
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3dedcaf501bc9718e5d372862b081fc9fdfb3959
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3df06a68edfc53fa88634c657a50cc6820354165 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3df06a68edfc53fa88634c657a50cc6820354165
new file mode 100644
index 0000000..daadca7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3df06a68edfc53fa88634c657a50cc6820354165
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3f36ae935255c4bbd2bd8d4a85bfa92bba02225c b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f36ae935255c4bbd2bd8d4a85bfa92bba02225c
new file mode 100644
index 0000000..6d4b5bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f36ae935255c4bbd2bd8d4a85bfa92bba02225c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3f47ad9ab401599f42d3c4f37ab9f702e3ff0fc9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f47ad9ab401599f42d3c4f37ab9f702e3ff0fc9
new file mode 100644
index 0000000..b4a080c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f47ad9ab401599f42d3c4f37ab9f702e3ff0fc9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42324d3d9e013cd43d4feeed1b48fbe1ea18a732 b/test/core/end2end/fuzzers/api_fuzzer_corpus/42324d3d9e013cd43d4feeed1b48fbe1ea18a732
new file mode 100644
index 0000000..c904776
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42324d3d9e013cd43d4feeed1b48fbe1ea18a732
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42a8e7c267f66a0747f30b4053ec79325074dc97 b/test/core/end2end/fuzzers/api_fuzzer_corpus/42a8e7c267f66a0747f30b4053ec79325074dc97
new file mode 100644
index 0000000..2b343fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42a8e7c267f66a0747f30b4053ec79325074dc97
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42c3c4a4e7d21e79d1e36494d5324f10a5ecbb04 b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c3c4a4e7d21e79d1e36494d5324f10a5ecbb04
new file mode 100644
index 0000000..b9b569f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c3c4a4e7d21e79d1e36494d5324f10a5ecbb04
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43676969fb81dcc1699b6a17eb465ef3cd4c2ab8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/43676969fb81dcc1699b6a17eb465ef3cd4c2ab8
new file mode 100644
index 0000000..5f918d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43676969fb81dcc1699b6a17eb465ef3cd4c2ab8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/439d4e4ed3ab9fe77e2bbda5b2be3d123beefa00 b/test/core/end2end/fuzzers/api_fuzzer_corpus/439d4e4ed3ab9fe77e2bbda5b2be3d123beefa00
new file mode 100644
index 0000000..100fcdc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/439d4e4ed3ab9fe77e2bbda5b2be3d123beefa00
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/441c94c010d19206c337d3c850cc449523ab480d b/test/core/end2end/fuzzers/api_fuzzer_corpus/441c94c010d19206c337d3c850cc449523ab480d
new file mode 100644
index 0000000..1885de7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/441c94c010d19206c337d3c850cc449523ab480d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4449ec3eda232c394fad83e34b002e9bb46862e1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4449ec3eda232c394fad83e34b002e9bb46862e1
new file mode 100644
index 0000000..9536b25
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4449ec3eda232c394fad83e34b002e9bb46862e1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/449ece0109a8543f26311f3ddc23525a2f288b64 b/test/core/end2end/fuzzers/api_fuzzer_corpus/449ece0109a8543f26311f3ddc23525a2f288b64
new file mode 100644
index 0000000..edfd64c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/449ece0109a8543f26311f3ddc23525a2f288b64
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/44bf16b9eb7302a6b02a600ac92dadf916c4e629 b/test/core/end2end/fuzzers/api_fuzzer_corpus/44bf16b9eb7302a6b02a600ac92dadf916c4e629
new file mode 100644
index 0000000..5105d99
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/44bf16b9eb7302a6b02a600ac92dadf916c4e629
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/44e1fdcc46db56bf61a6702fd10766b56d35bc74 b/test/core/end2end/fuzzers/api_fuzzer_corpus/44e1fdcc46db56bf61a6702fd10766b56d35bc74
new file mode 100644
index 0000000..eb48a38
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/44e1fdcc46db56bf61a6702fd10766b56d35bc74
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/45657516294c5426c490e6aa522a79077c972856 b/test/core/end2end/fuzzers/api_fuzzer_corpus/45657516294c5426c490e6aa522a79077c972856
new file mode 100644
index 0000000..6b9c07e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/45657516294c5426c490e6aa522a79077c972856
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/465b299ab3509b61016406e0d1d93f7774c03c8c b/test/core/end2end/fuzzers/api_fuzzer_corpus/465b299ab3509b61016406e0d1d93f7774c03c8c
new file mode 100644
index 0000000..931425b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/465b299ab3509b61016406e0d1d93f7774c03c8c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/46efabc911aab09a5e7a34a19ef97ce710594a77 b/test/core/end2end/fuzzers/api_fuzzer_corpus/46efabc911aab09a5e7a34a19ef97ce710594a77
new file mode 100644
index 0000000..068dfb5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/46efabc911aab09a5e7a34a19ef97ce710594a77
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/472adcbc2a1970f2392e596c28bd44087b8f3431 b/test/core/end2end/fuzzers/api_fuzzer_corpus/472adcbc2a1970f2392e596c28bd44087b8f3431
new file mode 100644
index 0000000..703f60d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/472adcbc2a1970f2392e596c28bd44087b8f3431
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/47e402f3386843e0055431750f30b710e10295dd b/test/core/end2end/fuzzers/api_fuzzer_corpus/47e402f3386843e0055431750f30b710e10295dd
new file mode 100644
index 0000000..c390193
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/47e402f3386843e0055431750f30b710e10295dd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/47ecf4079ea23d4de5fd9282f733eb5429f7ab05 b/test/core/end2end/fuzzers/api_fuzzer_corpus/47ecf4079ea23d4de5fd9282f733eb5429f7ab05
new file mode 100644
index 0000000..d64a5a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/47ecf4079ea23d4de5fd9282f733eb5429f7ab05
@@ -0,0 +1 @@
+í
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/484ab9d070fffe7e3d1a1704c9fa2ce01e192450 b/test/core/end2end/fuzzers/api_fuzzer_corpus/484ab9d070fffe7e3d1a1704c9fa2ce01e192450
new file mode 100644
index 0000000..d9d30e2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/484ab9d070fffe7e3d1a1704c9fa2ce01e192450
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4905b3fb0f7d2196a5612e8e432abda666e4317d b/test/core/end2end/fuzzers/api_fuzzer_corpus/4905b3fb0f7d2196a5612e8e432abda666e4317d
new file mode 100644
index 0000000..597e1a3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4905b3fb0f7d2196a5612e8e432abda666e4317d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/490f5aa97dc05ef1ce089fa9d4fd377bacafcf18 b/test/core/end2end/fuzzers/api_fuzzer_corpus/490f5aa97dc05ef1ce089fa9d4fd377bacafcf18
new file mode 100644
index 0000000..987f4c5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/490f5aa97dc05ef1ce089fa9d4fd377bacafcf18
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4a3eae69f4c5dc768b166620af348316c9fac3e6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a3eae69f4c5dc768b166620af348316c9fac3e6
new file mode 100644
index 0000000..0b1b0ef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a3eae69f4c5dc768b166620af348316c9fac3e6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4c3dcb9cb14f89b3616fc7cca78f2ebc502907eb b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c3dcb9cb14f89b3616fc7cca78f2ebc502907eb
new file mode 100644
index 0000000..54856ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c3dcb9cb14f89b3616fc7cca78f2ebc502907eb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4c686a41d4d2226b3cc76b8154d8df090d075f00 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c686a41d4d2226b3cc76b8154d8df090d075f00
new file mode 100644
index 0000000..84021f1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c686a41d4d2226b3cc76b8154d8df090d075f00
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4d472e5a8e8ee92be6f23a101babbc601dd2512c b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d472e5a8e8ee92be6f23a101babbc601dd2512c
new file mode 100644
index 0000000..fa3adc9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d472e5a8e8ee92be6f23a101babbc601dd2512c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4d4aa6ddd6404300e5278682e560f25292e9804e b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d4aa6ddd6404300e5278682e560f25292e9804e
new file mode 100644
index 0000000..3cf9915
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d4aa6ddd6404300e5278682e560f25292e9804e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4e36813fde9b5de1b62de95f498f2e0a48b5c5f7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4e36813fde9b5de1b62de95f498f2e0a48b5c5f7
new file mode 100644
index 0000000..d59ec70
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4e36813fde9b5de1b62de95f498f2e0a48b5c5f7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4ef22ea5b0aa8b80a180a9654f5aef121c5aad83 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4ef22ea5b0aa8b80a180a9654f5aef121c5aad83
new file mode 100644
index 0000000..76d9ac8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4ef22ea5b0aa8b80a180a9654f5aef121c5aad83
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4f53cc7b3ed0c77c3b5e4478f54caa40e0bf64b6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4f53cc7b3ed0c77c3b5e4478f54caa40e0bf64b6
new file mode 100644
index 0000000..099cb9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4f53cc7b3ed0c77c3b5e4478f54caa40e0bf64b6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5000fa3e29de15e7533b0e04b37eb1985ae69891 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5000fa3e29de15e7533b0e04b37eb1985ae69891
new file mode 100644
index 0000000..9e84699
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5000fa3e29de15e7533b0e04b37eb1985ae69891
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/50841095cafd9f9de6684fb3d89cd5fe148494ef b/test/core/end2end/fuzzers/api_fuzzer_corpus/50841095cafd9f9de6684fb3d89cd5fe148494ef
new file mode 100644
index 0000000..1e289ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/50841095cafd9f9de6684fb3d89cd5fe148494ef
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/50bfe6100bf11339372ba29fe0c9b38c3ec2ebf0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/50bfe6100bf11339372ba29fe0c9b38c3ec2ebf0
new file mode 100644
index 0000000..f561f60
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/50bfe6100bf11339372ba29fe0c9b38c3ec2ebf0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/51d7466ac65468db7094bdedc60d1604231acc05 b/test/core/end2end/fuzzers/api_fuzzer_corpus/51d7466ac65468db7094bdedc60d1604231acc05
new file mode 100644
index 0000000..63c7a11
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/51d7466ac65468db7094bdedc60d1604231acc05
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/51ed796a5f8d8fccebe013ccccdc1ed5d8b8b4c0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/51ed796a5f8d8fccebe013ccccdc1ed5d8b8b4c0
new file mode 100644
index 0000000..2a0713c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/51ed796a5f8d8fccebe013ccccdc1ed5d8b8b4c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/528cc09294d2288fc91a4bab7cf6ec621c6621b0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/528cc09294d2288fc91a4bab7cf6ec621c6621b0
new file mode 100644
index 0000000..0d9559d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/528cc09294d2288fc91a4bab7cf6ec621c6621b0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5298ce28a7eab28c99964c0d838b017355607c92 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5298ce28a7eab28c99964c0d838b017355607c92
new file mode 100644
index 0000000..811352a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5298ce28a7eab28c99964c0d838b017355607c92
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/52dba1b997f903c5fa3d7da71421b36d96d9f55c b/test/core/end2end/fuzzers/api_fuzzer_corpus/52dba1b997f903c5fa3d7da71421b36d96d9f55c
new file mode 100644
index 0000000..94f82bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/52dba1b997f903c5fa3d7da71421b36d96d9f55c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/53e68cd362f3c8d64941efbb0b527c52da5e8424 b/test/core/end2end/fuzzers/api_fuzzer_corpus/53e68cd362f3c8d64941efbb0b527c52da5e8424
new file mode 100644
index 0000000..dd76b48
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/53e68cd362f3c8d64941efbb0b527c52da5e8424
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/546fe2e2b1e2756c3f121d0545866798c85c9b8b b/test/core/end2end/fuzzers/api_fuzzer_corpus/546fe2e2b1e2756c3f121d0545866798c85c9b8b
new file mode 100644
index 0000000..5c0c9c6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/546fe2e2b1e2756c3f121d0545866798c85c9b8b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/54a0a2c37ce1830f241f6e2828adc8057cfa385f b/test/core/end2end/fuzzers/api_fuzzer_corpus/54a0a2c37ce1830f241f6e2828adc8057cfa385f
new file mode 100644
index 0000000..82627f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/54a0a2c37ce1830f241f6e2828adc8057cfa385f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/55ed466781b547db5957233bd8db0ce1f189183f b/test/core/end2end/fuzzers/api_fuzzer_corpus/55ed466781b547db5957233bd8db0ce1f189183f
new file mode 100644
index 0000000..0c955ea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/55ed466781b547db5957233bd8db0ce1f189183f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5677b3500e9353856c8d87fbe1476a22df4231f8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5677b3500e9353856c8d87fbe1476a22df4231f8
new file mode 100644
index 0000000..0ae5f8f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5677b3500e9353856c8d87fbe1476a22df4231f8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/56f3ca8174d263240113de88e7547e7b1c5cb2cf b/test/core/end2end/fuzzers/api_fuzzer_corpus/56f3ca8174d263240113de88e7547e7b1c5cb2cf
new file mode 100644
index 0000000..a9a45d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/56f3ca8174d263240113de88e7547e7b1c5cb2cf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/57798cc4375de344391221fd07d591f5c64d646d b/test/core/end2end/fuzzers/api_fuzzer_corpus/57798cc4375de344391221fd07d591f5c64d646d
new file mode 100644
index 0000000..3f34fcd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/57798cc4375de344391221fd07d591f5c64d646d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/57da1745490c2f21ecb86370f1f72f77752bc739 b/test/core/end2end/fuzzers/api_fuzzer_corpus/57da1745490c2f21ecb86370f1f72f77752bc739
new file mode 100644
index 0000000..78bc4be
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/57da1745490c2f21ecb86370f1f72f77752bc739
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/57dea4528141649208fa2af10c18e98e80c1758b b/test/core/end2end/fuzzers/api_fuzzer_corpus/57dea4528141649208fa2af10c18e98e80c1758b
new file mode 100644
index 0000000..73bb474
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/57dea4528141649208fa2af10c18e98e80c1758b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/588f9166c839baf3102185d38f77f9a750e62c7f b/test/core/end2end/fuzzers/api_fuzzer_corpus/588f9166c839baf3102185d38f77f9a750e62c7f
new file mode 100644
index 0000000..5c328a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/588f9166c839baf3102185d38f77f9a750e62c7f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5939ec5fd8f4e02ff0720cfa3ef685876bb3549d b/test/core/end2end/fuzzers/api_fuzzer_corpus/5939ec5fd8f4e02ff0720cfa3ef685876bb3549d
new file mode 100644
index 0000000..416f83d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5939ec5fd8f4e02ff0720cfa3ef685876bb3549d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/594d676c8c05d75ba8587d9e900850dff5e21ff8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/594d676c8c05d75ba8587d9e900850dff5e21ff8
new file mode 100644
index 0000000..def1bd1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/594d676c8c05d75ba8587d9e900850dff5e21ff8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/595603f4ed37e3716cbe53b3ef180e5cdf8005f0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/595603f4ed37e3716cbe53b3ef180e5cdf8005f0
new file mode 100644
index 0000000..ceee8e5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/595603f4ed37e3716cbe53b3ef180e5cdf8005f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5a3c9d98651a315b5bde737482ff54f6b90361e0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a3c9d98651a315b5bde737482ff54f6b90361e0
new file mode 100644
index 0000000..191e720
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a3c9d98651a315b5bde737482ff54f6b90361e0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5a6491ab9c23fae58967d4a4b5d5cfb23f620001 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a6491ab9c23fae58967d4a4b5d5cfb23f620001
new file mode 100644
index 0000000..7904c17
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a6491ab9c23fae58967d4a4b5d5cfb23f620001
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5a85c9bd6a6d7a2f753dd315e4747fc0249c8799 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a85c9bd6a6d7a2f753dd315e4747fc0249c8799
new file mode 100644
index 0000000..d30cbc4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a85c9bd6a6d7a2f753dd315e4747fc0249c8799
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5a8ca84c7d4d9b055f05c55b1f707f223979d387 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a8ca84c7d4d9b055f05c55b1f707f223979d387
new file mode 100644
index 0000000..54a81dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a8ca84c7d4d9b055f05c55b1f707f223979d387
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5be956066b72ea1799e333a7bd17fb0b8fc2b91c b/test/core/end2end/fuzzers/api_fuzzer_corpus/5be956066b72ea1799e333a7bd17fb0b8fc2b91c
new file mode 100644
index 0000000..701a108
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5be956066b72ea1799e333a7bd17fb0b8fc2b91c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5d0137a19ae57cfdf5172a8b51e8ea0a0a893690 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d0137a19ae57cfdf5172a8b51e8ea0a0a893690
new file mode 100644
index 0000000..21cd7ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d0137a19ae57cfdf5172a8b51e8ea0a0a893690
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5d2f29b31d78b47077b15779d620747034d18c05 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d2f29b31d78b47077b15779d620747034d18c05
new file mode 100644
index 0000000..88f6ab1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d2f29b31d78b47077b15779d620747034d18c05
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5d765c856a9a8650e1b17813340b9b6ba0989b58 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d765c856a9a8650e1b17813340b9b6ba0989b58
new file mode 100644
index 0000000..6219b46
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d765c856a9a8650e1b17813340b9b6ba0989b58
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5e1391f44f904fa54e66ec174e4c8879921e842a b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e1391f44f904fa54e66ec174e4c8879921e842a
new file mode 100644
index 0000000..83d17fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e1391f44f904fa54e66ec174e4c8879921e842a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ea01efbec747fc55ae29eb2b779f00889ca6922 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ea01efbec747fc55ae29eb2b779f00889ca6922
new file mode 100644
index 0000000..f76c4ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ea01efbec747fc55ae29eb2b779f00889ca6922
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/60e8618c075ec5fd47a1699271c6da1b5befd579 b/test/core/end2end/fuzzers/api_fuzzer_corpus/60e8618c075ec5fd47a1699271c6da1b5befd579
new file mode 100644
index 0000000..4f21985
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/60e8618c075ec5fd47a1699271c6da1b5befd579
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6184ea16753b0827f728285f18dad4b3bde00024 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6184ea16753b0827f728285f18dad4b3bde00024
new file mode 100644
index 0000000..f617147
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6184ea16753b0827f728285f18dad4b3bde00024
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6186bfc21ff7df3982e5d9757e5c7160da0f493a b/test/core/end2end/fuzzers/api_fuzzer_corpus/6186bfc21ff7df3982e5d9757e5c7160da0f493a
new file mode 100644
index 0000000..45ec1dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6186bfc21ff7df3982e5d9757e5c7160da0f493a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6230cce2862a18c4c92dc6fb4e034a1d15e1ff18 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6230cce2862a18c4c92dc6fb4e034a1d15e1ff18
new file mode 100644
index 0000000..f3320f1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6230cce2862a18c4c92dc6fb4e034a1d15e1ff18
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/62fbfe90a1b9ac471bc2644c896f64515f6b3c7e b/test/core/end2end/fuzzers/api_fuzzer_corpus/62fbfe90a1b9ac471bc2644c896f64515f6b3c7e
new file mode 100644
index 0000000..27d1678
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/62fbfe90a1b9ac471bc2644c896f64515f6b3c7e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/638c36cfe098b98008e594eddf90fdacfc078fae b/test/core/end2end/fuzzers/api_fuzzer_corpus/638c36cfe098b98008e594eddf90fdacfc078fae
new file mode 100644
index 0000000..153b006
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/638c36cfe098b98008e594eddf90fdacfc078fae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6421db654fff309bc191aba0330fbcd1347655e3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6421db654fff309bc191aba0330fbcd1347655e3
new file mode 100644
index 0000000..9b68f66
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6421db654fff309bc191aba0330fbcd1347655e3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2
new file mode 100644
index 0000000..d00b12c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/64c572e594c2d491a902e8fdff7b617ac0c6881b b/test/core/end2end/fuzzers/api_fuzzer_corpus/64c572e594c2d491a902e8fdff7b617ac0c6881b
new file mode 100644
index 0000000..c96d8a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/64c572e594c2d491a902e8fdff7b617ac0c6881b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/64eb970cc80162a4b80d49364f4227db3429e156 b/test/core/end2end/fuzzers/api_fuzzer_corpus/64eb970cc80162a4b80d49364f4227db3429e156
new file mode 100644
index 0000000..ad33025
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/64eb970cc80162a4b80d49364f4227db3429e156
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/655b880459e6e00100727af9df52b64f6d77a653 b/test/core/end2end/fuzzers/api_fuzzer_corpus/655b880459e6e00100727af9df52b64f6d77a653
new file mode 100644
index 0000000..abc2929
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/655b880459e6e00100727af9df52b64f6d77a653
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/660c071578cbdccb503317ecbf2fd331bc4ac82d b/test/core/end2end/fuzzers/api_fuzzer_corpus/660c071578cbdccb503317ecbf2fd331bc4ac82d
new file mode 100644
index 0000000..df8b58f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/660c071578cbdccb503317ecbf2fd331bc4ac82d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/66ac31199d08e7a3b066059cd409457a850847b2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/66ac31199d08e7a3b066059cd409457a850847b2
new file mode 100644
index 0000000..dececd4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/66ac31199d08e7a3b066059cd409457a850847b2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/66ef59d5da68fdb5e55b60fc8a8a764afb021b4b b/test/core/end2end/fuzzers/api_fuzzer_corpus/66ef59d5da68fdb5e55b60fc8a8a764afb021b4b
new file mode 100644
index 0000000..46172fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/66ef59d5da68fdb5e55b60fc8a8a764afb021b4b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/682cb8ad9fe4641e7a140ae3d3ee27c841ba397f b/test/core/end2end/fuzzers/api_fuzzer_corpus/682cb8ad9fe4641e7a140ae3d3ee27c841ba397f
new file mode 100644
index 0000000..a25e182
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/682cb8ad9fe4641e7a140ae3d3ee27c841ba397f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/696ea30e2e1490f2f31b153641b2c29152ded5c2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/696ea30e2e1490f2f31b153641b2c29152ded5c2
new file mode 100644
index 0000000..7b43eeb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/696ea30e2e1490f2f31b153641b2c29152ded5c2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6a10118289fe7179c4e9bb6a1b466ba34c582bfb b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a10118289fe7179c4e9bb6a1b466ba34c582bfb
new file mode 100644
index 0000000..8f0834b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a10118289fe7179c4e9bb6a1b466ba34c582bfb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6bfbea131237606756a12f275e736045c0956536 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6bfbea131237606756a12f275e736045c0956536
new file mode 100644
index 0000000..b483671
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6bfbea131237606756a12f275e736045c0956536
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6c1c2177f3483086607c717d0c6c35a81d79e18e b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c1c2177f3483086607c717d0c6c35a81d79e18e
new file mode 100644
index 0000000..717269d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c1c2177f3483086607c717d0c6c35a81d79e18e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ded157ecd3fce79fa69c51ee9ecb4639013e6ba b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ded157ecd3fce79fa69c51ee9ecb4639013e6ba
new file mode 100644
index 0000000..106fdb8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ded157ecd3fce79fa69c51ee9ecb4639013e6ba
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6e1cf196e7c8ad4226d89f3ca2c6f7949598bec2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e1cf196e7c8ad4226d89f3ca2c6f7949598bec2
new file mode 100644
index 0000000..a49762b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e1cf196e7c8ad4226d89f3ca2c6f7949598bec2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ef96bc0c5b6ab5f8a4453b9cf5784fd55e3b59f b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ef96bc0c5b6ab5f8a4453b9cf5784fd55e3b59f
new file mode 100644
index 0000000..b8fb6fa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ef96bc0c5b6ab5f8a4453b9cf5784fd55e3b59f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6f88ae246aa4af9c74732d87a758ba5ca0f40caf b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f88ae246aa4af9c74732d87a758ba5ca0f40caf
new file mode 100644
index 0000000..7f32cc0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f88ae246aa4af9c74732d87a758ba5ca0f40caf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6f8ffc96f9ebe390929165e32bdc187afb7a40ce b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f8ffc96f9ebe390929165e32bdc187afb7a40ce
new file mode 100644
index 0000000..420c2c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f8ffc96f9ebe390929165e32bdc187afb7a40ce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/70bd921a3d4700d49ad6b99e0cfee42c36a13b3a b/test/core/end2end/fuzzers/api_fuzzer_corpus/70bd921a3d4700d49ad6b99e0cfee42c36a13b3a
new file mode 100644
index 0000000..86d3175
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/70bd921a3d4700d49ad6b99e0cfee42c36a13b3a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/710f61e5765c91bcf9cf2e07264771cf2feae48d b/test/core/end2end/fuzzers/api_fuzzer_corpus/710f61e5765c91bcf9cf2e07264771cf2feae48d
new file mode 100644
index 0000000..e7db033
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/710f61e5765c91bcf9cf2e07264771cf2feae48d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/71c01818823d5c5fd8a3d1cb4c5db4aca51efdb2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/71c01818823d5c5fd8a3d1cb4c5db4aca51efdb2
new file mode 100644
index 0000000..aeebc9b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/71c01818823d5c5fd8a3d1cb4c5db4aca51efdb2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/71e2b03b503dbbdc0d2e724c562b9f1c77f972fa b/test/core/end2end/fuzzers/api_fuzzer_corpus/71e2b03b503dbbdc0d2e724c562b9f1c77f972fa
new file mode 100644
index 0000000..14cf1a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/71e2b03b503dbbdc0d2e724c562b9f1c77f972fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7240f3408714c2dcdcb448f234efef4f08e6b2fb b/test/core/end2end/fuzzers/api_fuzzer_corpus/7240f3408714c2dcdcb448f234efef4f08e6b2fb
new file mode 100644
index 0000000..095396d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7240f3408714c2dcdcb448f234efef4f08e6b2fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/727f43500183aec9c0d9be7d2363fa1761cda5d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/727f43500183aec9c0d9be7d2363fa1761cda5d5
new file mode 100644
index 0000000..a30b54a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/727f43500183aec9c0d9be7d2363fa1761cda5d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/72a3729a9bb74378156dcd42171e39ec348c71d7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/72a3729a9bb74378156dcd42171e39ec348c71d7
new file mode 100644
index 0000000..ab3ed16
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/72a3729a9bb74378156dcd42171e39ec348c71d7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/72c363848fe754c23e1f9f2acc2f025666417d2d b/test/core/end2end/fuzzers/api_fuzzer_corpus/72c363848fe754c23e1f9f2acc2f025666417d2d
new file mode 100644
index 0000000..03662b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/72c363848fe754c23e1f9f2acc2f025666417d2d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/73889340124f1f88859aab4e6ce36c0019a44218 b/test/core/end2end/fuzzers/api_fuzzer_corpus/73889340124f1f88859aab4e6ce36c0019a44218
new file mode 100644
index 0000000..64d1845
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/73889340124f1f88859aab4e6ce36c0019a44218
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7462e4d1834938e8a5fb975da6865cc7d6b225f3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7462e4d1834938e8a5fb975da6865cc7d6b225f3
new file mode 100644
index 0000000..2db7068
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7462e4d1834938e8a5fb975da6865cc7d6b225f3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/74b69a49c2df95009ff18d820bbe7fe6ae797aae b/test/core/end2end/fuzzers/api_fuzzer_corpus/74b69a49c2df95009ff18d820bbe7fe6ae797aae
new file mode 100644
index 0000000..e2da05f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/74b69a49c2df95009ff18d820bbe7fe6ae797aae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/74cc62178f9c631dc49cf09b0ff5884322d33969 b/test/core/end2end/fuzzers/api_fuzzer_corpus/74cc62178f9c631dc49cf09b0ff5884322d33969
new file mode 100644
index 0000000..2abdc95
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/74cc62178f9c631dc49cf09b0ff5884322d33969
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/74eef5817db3984a020b2868f3c9979d0220c829 b/test/core/end2end/fuzzers/api_fuzzer_corpus/74eef5817db3984a020b2868f3c9979d0220c829
new file mode 100644
index 0000000..266e5c4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/74eef5817db3984a020b2868f3c9979d0220c829
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/758ce3af56f75edb8faa20ef78ffda5511dffb3a b/test/core/end2end/fuzzers/api_fuzzer_corpus/758ce3af56f75edb8faa20ef78ffda5511dffb3a
new file mode 100644
index 0000000..901a1fc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/758ce3af56f75edb8faa20ef78ffda5511dffb3a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/761f683f6486e3efb606bf08fa527a4c1a51f302 b/test/core/end2end/fuzzers/api_fuzzer_corpus/761f683f6486e3efb606bf08fa527a4c1a51f302
new file mode 100644
index 0000000..99a5968
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/761f683f6486e3efb606bf08fa527a4c1a51f302
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/76487a234f6f7276d8eba4edabef7623a592fdf6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/76487a234f6f7276d8eba4edabef7623a592fdf6
new file mode 100644
index 0000000..f1405c9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/76487a234f6f7276d8eba4edabef7623a592fdf6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/767c4f399ccca740ea3032eeade86851f12e7f9a b/test/core/end2end/fuzzers/api_fuzzer_corpus/767c4f399ccca740ea3032eeade86851f12e7f9a
new file mode 100644
index 0000000..62e3aa3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/767c4f399ccca740ea3032eeade86851f12e7f9a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/767d136ac4b3e33d9aa5320d941693e09648e59b b/test/core/end2end/fuzzers/api_fuzzer_corpus/767d136ac4b3e33d9aa5320d941693e09648e59b
new file mode 100644
index 0000000..932db9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/767d136ac4b3e33d9aa5320d941693e09648e59b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/768b6302130ac824947f956e062184afaafcdbab b/test/core/end2end/fuzzers/api_fuzzer_corpus/768b6302130ac824947f956e062184afaafcdbab
new file mode 100644
index 0000000..71e1c98
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/768b6302130ac824947f956e062184afaafcdbab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/77d4480781e1e1a9d5d5c02ff53fba10127f8b6a b/test/core/end2end/fuzzers/api_fuzzer_corpus/77d4480781e1e1a9d5d5c02ff53fba10127f8b6a
new file mode 100644
index 0000000..6926e26
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/77d4480781e1e1a9d5d5c02ff53fba10127f8b6a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/77e8407dfe09892312213f7d6b2ad8a961b6b88e b/test/core/end2end/fuzzers/api_fuzzer_corpus/77e8407dfe09892312213f7d6b2ad8a961b6b88e
new file mode 100644
index 0000000..bdd1772
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/77e8407dfe09892312213f7d6b2ad8a961b6b88e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/792276ed826b9078ecfbd51e0136962f5e10ed6e b/test/core/end2end/fuzzers/api_fuzzer_corpus/792276ed826b9078ecfbd51e0136962f5e10ed6e
new file mode 100644
index 0000000..b79e3dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/792276ed826b9078ecfbd51e0136962f5e10ed6e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7a0b2f8659484409af6a76d1df273b8dc66e3439 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7a0b2f8659484409af6a76d1df273b8dc66e3439
new file mode 100644
index 0000000..83f1f33
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7a0b2f8659484409af6a76d1df273b8dc66e3439
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7be89fb64b3d931387e8a5b1ef51bf9cda18006a b/test/core/end2end/fuzzers/api_fuzzer_corpus/7be89fb64b3d931387e8a5b1ef51bf9cda18006a
new file mode 100644
index 0000000..651c1ab
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7be89fb64b3d931387e8a5b1ef51bf9cda18006a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7c026422a34cb34de673a1d6702cbde67d112d27 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c026422a34cb34de673a1d6702cbde67d112d27
new file mode 100644
index 0000000..e85bb86
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c026422a34cb34de673a1d6702cbde67d112d27
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7c58daa09675ba2b11e69636bb78dc0d1343bb51 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c58daa09675ba2b11e69636bb78dc0d1343bb51
new file mode 100644
index 0000000..babac68
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c58daa09675ba2b11e69636bb78dc0d1343bb51
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7c9b4e2ea03542254235893edd042a822145e504 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c9b4e2ea03542254235893edd042a822145e504
new file mode 100644
index 0000000..42751a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c9b4e2ea03542254235893edd042a822145e504
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7cdff0948ef64e551ad02f857acd5956d91530c9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cdff0948ef64e551ad02f857acd5956d91530c9
new file mode 100644
index 0000000..250f095
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cdff0948ef64e551ad02f857acd5956d91530c9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7d33039255c9611d0e9e0cc7e230f87ad55c007f b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d33039255c9611d0e9e0cc7e230f87ad55c007f
new file mode 100644
index 0000000..e1ab5b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d33039255c9611d0e9e0cc7e230f87ad55c007f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7d6713afac17551fc2628c0f9f18c41a1aa9c2f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d6713afac17551fc2628c0f9f18c41a1aa9c2f1
new file mode 100644
index 0000000..450fc23
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d6713afac17551fc2628c0f9f18c41a1aa9c2f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7d88455cc77259c8bf17c1cdc0b24edf5667c79c b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d88455cc77259c8bf17c1cdc0b24edf5667c79c
new file mode 100644
index 0000000..a2c9a09
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d88455cc77259c8bf17c1cdc0b24edf5667c79c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7de73ddcb20d0940b937323599a5094bfb26ae6c b/test/core/end2end/fuzzers/api_fuzzer_corpus/7de73ddcb20d0940b937323599a5094bfb26ae6c
new file mode 100644
index 0000000..83262c0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7de73ddcb20d0940b937323599a5094bfb26ae6c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7e8f7517bb0bb95011b48f1f4f4a631d4d756a5f b/test/core/end2end/fuzzers/api_fuzzer_corpus/7e8f7517bb0bb95011b48f1f4f4a631d4d756a5f
new file mode 100644
index 0000000..e550cfc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7e8f7517bb0bb95011b48f1f4f4a631d4d756a5f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/80a249d17248e0dc7dcc9fb64d8ac2dd0320a544 b/test/core/end2end/fuzzers/api_fuzzer_corpus/80a249d17248e0dc7dcc9fb64d8ac2dd0320a544
new file mode 100644
index 0000000..8f68ee5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/80a249d17248e0dc7dcc9fb64d8ac2dd0320a544
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/80a56bd23287d856a653f22f57f7d1442235b713 b/test/core/end2end/fuzzers/api_fuzzer_corpus/80a56bd23287d856a653f22f57f7d1442235b713
new file mode 100644
index 0000000..94190e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/80a56bd23287d856a653f22f57f7d1442235b713
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/80b6a3cf5bb7cdeffcb6cbaaa10889168542a25a b/test/core/end2end/fuzzers/api_fuzzer_corpus/80b6a3cf5bb7cdeffcb6cbaaa10889168542a25a
new file mode 100644
index 0000000..30dacae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/80b6a3cf5bb7cdeffcb6cbaaa10889168542a25a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/811533455c494627bb5b5802f4ed7a386f57cb1e b/test/core/end2end/fuzzers/api_fuzzer_corpus/811533455c494627bb5b5802f4ed7a386f57cb1e
new file mode 100644
index 0000000..85a94fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/811533455c494627bb5b5802f4ed7a386f57cb1e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8123e9dc4d43115412f07fcf9946c99d9a1a55c3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8123e9dc4d43115412f07fcf9946c99d9a1a55c3
new file mode 100644
index 0000000..7de0814
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8123e9dc4d43115412f07fcf9946c99d9a1a55c3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/820d5ba2e9d91563dae39a1b02833fbef1e6d8f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/820d5ba2e9d91563dae39a1b02833fbef1e6d8f1
new file mode 100644
index 0000000..7bd4f7a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/820d5ba2e9d91563dae39a1b02833fbef1e6d8f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/83c29132911949c65d508753420708e9a0ffd6ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/83c29132911949c65d508753420708e9a0ffd6ab
new file mode 100644
index 0000000..405d28e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/83c29132911949c65d508753420708e9a0ffd6ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8492f54a92f9a2a05af1a078489a3a68145d8985 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8492f54a92f9a2a05af1a078489a3a68145d8985
new file mode 100644
index 0000000..d489faf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8492f54a92f9a2a05af1a078489a3a68145d8985
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/84c995b299f8d6fa0733d11f0b1a0b4414a7e232 b/test/core/end2end/fuzzers/api_fuzzer_corpus/84c995b299f8d6fa0733d11f0b1a0b4414a7e232
new file mode 100644
index 0000000..75a242f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/84c995b299f8d6fa0733d11f0b1a0b4414a7e232
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/85220ed0c63891f376bee53c785b407fd9548f8b b/test/core/end2end/fuzzers/api_fuzzer_corpus/85220ed0c63891f376bee53c785b407fd9548f8b
new file mode 100644
index 0000000..aeb5046
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/85220ed0c63891f376bee53c785b407fd9548f8b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8554d0f8fc68c84fbd8515165a3d98aad0dfab3e b/test/core/end2end/fuzzers/api_fuzzer_corpus/8554d0f8fc68c84fbd8515165a3d98aad0dfab3e
new file mode 100644
index 0000000..befef24
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8554d0f8fc68c84fbd8515165a3d98aad0dfab3e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/856fb7cd57f36cfcc8a2cad0cf61f9fff9696776 b/test/core/end2end/fuzzers/api_fuzzer_corpus/856fb7cd57f36cfcc8a2cad0cf61f9fff9696776
new file mode 100644
index 0000000..33c1ae6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/856fb7cd57f36cfcc8a2cad0cf61f9fff9696776
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8711e2f477871e3ca68642bbb388e7f473f25394 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8711e2f477871e3ca68642bbb388e7f473f25394
new file mode 100644
index 0000000..df9762c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8711e2f477871e3ca68642bbb388e7f473f25394
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8713d28e8cf45d3670ad40829a83b1fc7cd41a75 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8713d28e8cf45d3670ad40829a83b1fc7cd41a75
new file mode 100644
index 0000000..08044b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8713d28e8cf45d3670ad40829a83b1fc7cd41a75
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8778868ac7a23d552d93772aa8566cf427a0c1f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8778868ac7a23d552d93772aa8566cf427a0c1f1
new file mode 100644
index 0000000..616d28a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8778868ac7a23d552d93772aa8566cf427a0c1f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8791b58ad0dbfdf9c37d48bc60940f86c6c7e3b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8791b58ad0dbfdf9c37d48bc60940f86c6c7e3b4
new file mode 100644
index 0000000..fdd8d37
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8791b58ad0dbfdf9c37d48bc60940f86c6c7e3b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/87add83a18a25fe585df8adc124eae6d70733f74 b/test/core/end2end/fuzzers/api_fuzzer_corpus/87add83a18a25fe585df8adc124eae6d70733f74
new file mode 100644
index 0000000..87c5683
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/87add83a18a25fe585df8adc124eae6d70733f74
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/880070b48f04fd1c8ffafd750e1c4d37ff404c6c b/test/core/end2end/fuzzers/api_fuzzer_corpus/880070b48f04fd1c8ffafd750e1c4d37ff404c6c
new file mode 100644
index 0000000..a9e62d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/880070b48f04fd1c8ffafd750e1c4d37ff404c6c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/885267691bb42bc807b6e578571430a81513eee0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/885267691bb42bc807b6e578571430a81513eee0
new file mode 100644
index 0000000..982d5ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/885267691bb42bc807b6e578571430a81513eee0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/88be31c841a66f523045f7bd1708ce64272e4276 b/test/core/end2end/fuzzers/api_fuzzer_corpus/88be31c841a66f523045f7bd1708ce64272e4276
new file mode 100644
index 0000000..9c09044
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/88be31c841a66f523045f7bd1708ce64272e4276
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/893ea11ec0c4425940d18a32acf23d5967d98dd9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/893ea11ec0c4425940d18a32acf23d5967d98dd9
new file mode 100644
index 0000000..9a4f343
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/893ea11ec0c4425940d18a32acf23d5967d98dd9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8949e5c946cf6ec7d1981d553972d4f3a6026987 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8949e5c946cf6ec7d1981d553972d4f3a6026987
new file mode 100644
index 0000000..1363ede
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8949e5c946cf6ec7d1981d553972d4f3a6026987
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8a034b07b9baf1b441c0fb0322652772973f20ff b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a034b07b9baf1b441c0fb0322652772973f20ff
new file mode 100644
index 0000000..21cfb9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a034b07b9baf1b441c0fb0322652772973f20ff
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8a912877743b165b233303efaf502f5092b3c5b0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a912877743b165b233303efaf502f5092b3c5b0
new file mode 100644
index 0000000..1e978a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a912877743b165b233303efaf502f5092b3c5b0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8a9f7329b30a562837353767313df7fa9a1f31f7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a9f7329b30a562837353767313df7fa9a1f31f7
new file mode 100644
index 0000000..6a18877
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a9f7329b30a562837353767313df7fa9a1f31f7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8b253ba946d6768c147f5d52552e150b703437e0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b253ba946d6768c147f5d52552e150b703437e0
new file mode 100644
index 0000000..6985667
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b253ba946d6768c147f5d52552e150b703437e0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8b53f252f8558726dc0daaee84e2b4d2f0835f44 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b53f252f8558726dc0daaee84e2b4d2f0835f44
new file mode 100644
index 0000000..48e9805
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b53f252f8558726dc0daaee84e2b4d2f0835f44
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8b7ebe7fb16e63e2584595ee77afb19359356eda b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b7ebe7fb16e63e2584595ee77afb19359356eda
new file mode 100644
index 0000000..0411175
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b7ebe7fb16e63e2584595ee77afb19359356eda
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8c501e1c87c42c4b7765ab027bd537ef72656605 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c501e1c87c42c4b7765ab027bd537ef72656605
new file mode 100644
index 0000000..02c1629
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c501e1c87c42c4b7765ab027bd537ef72656605
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8d7bb385d6b13b0e689a1e81e29113746218ba99 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d7bb385d6b13b0e689a1e81e29113746218ba99
new file mode 100644
index 0000000..66ee1d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d7bb385d6b13b0e689a1e81e29113746218ba99
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8d951b7ab0231fb1dc573433b354eac58c699c36 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d951b7ab0231fb1dc573433b354eac58c699c36
new file mode 100644
index 0000000..ad52abe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d951b7ab0231fb1dc573433b354eac58c699c36
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8e94dd64fdbf453f06b351d6a8f77a43cc34e4bc b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e94dd64fdbf453f06b351d6a8f77a43cc34e4bc
new file mode 100644
index 0000000..25e0f9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e94dd64fdbf453f06b351d6a8f77a43cc34e4bc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8ea86819b4ac803bb12fd6b63e6496238aa329c1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ea86819b4ac803bb12fd6b63e6496238aa329c1
new file mode 100644
index 0000000..270798c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ea86819b4ac803bb12fd6b63e6496238aa329c1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8f43b11f10961dcce8eaa8340c96d10bdbc937ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f43b11f10961dcce8eaa8340c96d10bdbc937ad
new file mode 100644
index 0000000..c12934d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f43b11f10961dcce8eaa8340c96d10bdbc937ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8f8b66436bade06813ec9ed4fce6774914b73db3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f8b66436bade06813ec9ed4fce6774914b73db3
new file mode 100644
index 0000000..ab0b0ca
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f8b66436bade06813ec9ed4fce6774914b73db3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8ff5277cdbe1417da64bfdb342747a23f5e4f956 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ff5277cdbe1417da64bfdb342747a23f5e4f956
new file mode 100644
index 0000000..1d4e2a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ff5277cdbe1417da64bfdb342747a23f5e4f956
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/901c9a33205897999e7e78063ccdc5d363267568 b/test/core/end2end/fuzzers/api_fuzzer_corpus/901c9a33205897999e7e78063ccdc5d363267568
new file mode 100644
index 0000000..48e9279
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/901c9a33205897999e7e78063ccdc5d363267568
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/90230730fae07c8eeb6b5bd571a119b486a21473 b/test/core/end2end/fuzzers/api_fuzzer_corpus/90230730fae07c8eeb6b5bd571a119b486a21473
new file mode 100644
index 0000000..d8db0eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/90230730fae07c8eeb6b5bd571a119b486a21473
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7
new file mode 100644
index 0000000..9b48e68
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/91e2f574e7ceb7f69a93011aac68903cd014a6c7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/91e2f574e7ceb7f69a93011aac68903cd014a6c7
new file mode 100644
index 0000000..89f012a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/91e2f574e7ceb7f69a93011aac68903cd014a6c7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/92273cf09f18534ae700c1f35dfab49faa091c54 b/test/core/end2end/fuzzers/api_fuzzer_corpus/92273cf09f18534ae700c1f35dfab49faa091c54
new file mode 100644
index 0000000..d176aba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/92273cf09f18534ae700c1f35dfab49faa091c54
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/929980ce480ca47855bdebb8f6ebef7fa447fd5b b/test/core/end2end/fuzzers/api_fuzzer_corpus/929980ce480ca47855bdebb8f6ebef7fa447fd5b
new file mode 100644
index 0000000..b8f15bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/929980ce480ca47855bdebb8f6ebef7fa447fd5b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9379dd6ade6947a59a1786435a2d55a705161ae5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9379dd6ade6947a59a1786435a2d55a705161ae5
new file mode 100644
index 0000000..3880e46
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9379dd6ade6947a59a1786435a2d55a705161ae5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/950511efda7aea60b3bfae95e31683210a88792c b/test/core/end2end/fuzzers/api_fuzzer_corpus/950511efda7aea60b3bfae95e31683210a88792c
new file mode 100644
index 0000000..1b2a6ef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/950511efda7aea60b3bfae95e31683210a88792c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9538327ef9f0a8d380a473bd25114b6859acf9b7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9538327ef9f0a8d380a473bd25114b6859acf9b7
new file mode 100644
index 0000000..8b997a5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9538327ef9f0a8d380a473bd25114b6859acf9b7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9629c9a0c98f15eec2b7fd114fa5ff9ff5c61a19 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9629c9a0c98f15eec2b7fd114fa5ff9ff5c61a19
new file mode 100644
index 0000000..d773433
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9629c9a0c98f15eec2b7fd114fa5ff9ff5c61a19
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/96a80511d8ef3ffdd370a3cc9467713a538259bb b/test/core/end2end/fuzzers/api_fuzzer_corpus/96a80511d8ef3ffdd370a3cc9467713a538259bb
new file mode 100644
index 0000000..b9b1311
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/96a80511d8ef3ffdd370a3cc9467713a538259bb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/984b6ee241b92be62923c6dc5bacaadb36183b89 b/test/core/end2end/fuzzers/api_fuzzer_corpus/984b6ee241b92be62923c6dc5bacaadb36183b89
new file mode 100644
index 0000000..26439ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/984b6ee241b92be62923c6dc5bacaadb36183b89
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/98b88c0751f1d9e5dc3d4751d2cb52ed8f0b008d b/test/core/end2end/fuzzers/api_fuzzer_corpus/98b88c0751f1d9e5dc3d4751d2cb52ed8f0b008d
new file mode 100644
index 0000000..aa53a22
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/98b88c0751f1d9e5dc3d4751d2cb52ed8f0b008d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9a0de0d63d44e00fc88e6cb88f4b8665db3b4b5e b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a0de0d63d44e00fc88e6cb88f4b8665db3b4b5e
new file mode 100644
index 0000000..cb87caa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a0de0d63d44e00fc88e6cb88f4b8665db3b4b5e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9a24710002a240ad32b7adb5310f4970c09cc8ca b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a24710002a240ad32b7adb5310f4970c09cc8ca
new file mode 100644
index 0000000..acc82fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a24710002a240ad32b7adb5310f4970c09cc8ca
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9a425eda58b05407e671f6b86a6664eb728843cb b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a425eda58b05407e671f6b86a6664eb728843cb
new file mode 100644
index 0000000..bccfd30
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a425eda58b05407e671f6b86a6664eb728843cb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9b6f00dd2752afbd223aad960168e4e535330d30 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b6f00dd2752afbd223aad960168e4e535330d30
new file mode 100644
index 0000000..bb31085
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b6f00dd2752afbd223aad960168e4e535330d30
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9bc5b4a9a81905cbc7ee4a25482068dcab93898d b/test/core/end2end/fuzzers/api_fuzzer_corpus/9bc5b4a9a81905cbc7ee4a25482068dcab93898d
new file mode 100644
index 0000000..251a506
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9bc5b4a9a81905cbc7ee4a25482068dcab93898d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9bfd723bfa4162bb5801a6050af0a8b2db10d4ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/9bfd723bfa4162bb5801a6050af0a8b2db10d4ab
new file mode 100644
index 0000000..4259817
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9bfd723bfa4162bb5801a6050af0a8b2db10d4ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9c0911c1a4b91f842670082c14af67d1f4b7bb6f b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c0911c1a4b91f842670082c14af67d1f4b7bb6f
new file mode 100644
index 0000000..09c1a72
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c0911c1a4b91f842670082c14af67d1f4b7bb6f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9c5538a5492013e6bdbcce2a373be19fc97c4f20 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c5538a5492013e6bdbcce2a373be19fc97c4f20
new file mode 100644
index 0000000..ef72f01
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c5538a5492013e6bdbcce2a373be19fc97c4f20
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9c837f4e6cb572b3431b3a5065b889273712810e b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c837f4e6cb572b3431b3a5065b889273712810e
new file mode 100644
index 0000000..762d870
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c837f4e6cb572b3431b3a5065b889273712810e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9d91fac343dd8a7848746ca5472fb1452052bfb7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d91fac343dd8a7848746ca5472fb1452052bfb7
new file mode 100644
index 0000000..f5412a5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d91fac343dd8a7848746ca5472fb1452052bfb7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9ebd34b96faba2fea70a50533df78a8c1dc35247 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9ebd34b96faba2fea70a50533df78a8c1dc35247
new file mode 100644
index 0000000..2f7309c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9ebd34b96faba2fea70a50533df78a8c1dc35247
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9f1db4144e46f913ca02e0abe2ccd5c7481e2a92 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f1db4144e46f913ca02e0abe2ccd5c7481e2a92
new file mode 100644
index 0000000..e4be2bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f1db4144e46f913ca02e0abe2ccd5c7481e2a92
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9f77859f13bbe482011164f7a5e1a2a77d8596f2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f77859f13bbe482011164f7a5e1a2a77d8596f2
new file mode 100644
index 0000000..0eeb166
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f77859f13bbe482011164f7a5e1a2a77d8596f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9fb07d3aba4e2d39eff7d31111515d7df2c981ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/9fb07d3aba4e2d39eff7d31111515d7df2c981ab
new file mode 100644
index 0000000..028086f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9fb07d3aba4e2d39eff7d31111515d7df2c981ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a074a30fc5c627e8093a8f860d67661df22f8148 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a074a30fc5c627e8093a8f860d67661df22f8148
new file mode 100644
index 0000000..8841eb0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a074a30fc5c627e8093a8f860d67661df22f8148
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a10775155c8eb3a834d067c0978753513d5e1d75 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a10775155c8eb3a834d067c0978753513d5e1d75
new file mode 100644
index 0000000..6c7b032
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a10775155c8eb3a834d067c0978753513d5e1d75
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b04c2504a75f50d47875bd1db804cef3674cf0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b04c2504a75f50d47875bd1db804cef3674cf0
new file mode 100644
index 0000000..6e59646
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b04c2504a75f50d47875bd1db804cef3674cf0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b153e4cde45a7302094f6c751e3248d2f0fb8e b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b153e4cde45a7302094f6c751e3248d2f0fb8e
new file mode 100644
index 0000000..132222c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b153e4cde45a7302094f6c751e3248d2f0fb8e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a1dffc6b0fabef88188bc4c140bc2d331d73f997 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1dffc6b0fabef88188bc4c140bc2d331d73f997
new file mode 100644
index 0000000..794a50a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1dffc6b0fabef88188bc4c140bc2d331d73f997
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a25eb9c166a097ea3afa590e3584eb9986bd9445 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a25eb9c166a097ea3afa590e3584eb9986bd9445
new file mode 100644
index 0000000..122a725
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a25eb9c166a097ea3afa590e3584eb9986bd9445
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a2ac5153026b26fcbea42786e238b15017a684be b/test/core/end2end/fuzzers/api_fuzzer_corpus/a2ac5153026b26fcbea42786e238b15017a684be
new file mode 100644
index 0000000..2730045
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a2ac5153026b26fcbea42786e238b15017a684be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a3026496fa01a4cae2682da4b3e7cfae09929698 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3026496fa01a4cae2682da4b3e7cfae09929698
new file mode 100644
index 0000000..593e45b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3026496fa01a4cae2682da4b3e7cfae09929698
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a3c9b6e89b534d02bdad07207c4fdcda536f28a4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3c9b6e89b534d02bdad07207c4fdcda536f28a4
new file mode 100644
index 0000000..296a734
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3c9b6e89b534d02bdad07207c4fdcda536f28a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a3cc00f1a2020ff2e2d53bc91a212b5fdbe5c006 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3cc00f1a2020ff2e2d53bc91a212b5fdbe5c006
new file mode 100644
index 0000000..be8da6c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3cc00f1a2020ff2e2d53bc91a212b5fdbe5c006
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a55fb292d4e1ffcdaf933f2dbdd8410628eb7acc b/test/core/end2end/fuzzers/api_fuzzer_corpus/a55fb292d4e1ffcdaf933f2dbdd8410628eb7acc
new file mode 100644
index 0000000..ab98a60
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a55fb292d4e1ffcdaf933f2dbdd8410628eb7acc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a6914c7bbe81fd2138bc20e63b27c0cadd0471ee b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6914c7bbe81fd2138bc20e63b27c0cadd0471ee
new file mode 100644
index 0000000..5fee533
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6914c7bbe81fd2138bc20e63b27c0cadd0471ee
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a693801403d7721b5b3d7d4525cc0b830ab35e06 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a693801403d7721b5b3d7d4525cc0b830ab35e06
new file mode 100644
index 0000000..016b041
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a693801403d7721b5b3d7d4525cc0b830ab35e06
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a6f614d434a1fe2162f7872100baef21b2051b53 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6f614d434a1fe2162f7872100baef21b2051b53
new file mode 100644
index 0000000..f21a84f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6f614d434a1fe2162f7872100baef21b2051b53
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a78a65e7bd4c3cf41fce74155e97a758658fe8b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a78a65e7bd4c3cf41fce74155e97a758658fe8b4
new file mode 100644
index 0000000..dff4613
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a78a65e7bd4c3cf41fce74155e97a758658fe8b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a8d353c157cc3788a86a0d572adcc7744e7e902a b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8d353c157cc3788a86a0d572adcc7744e7e902a
new file mode 100644
index 0000000..ba9a3e1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8d353c157cc3788a86a0d572adcc7744e7e902a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a8f87a7038125bd0e3b753c2a42ebdc3e4c75cba b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8f87a7038125bd0e3b753c2a42ebdc3e4c75cba
new file mode 100644
index 0000000..219182e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8f87a7038125bd0e3b753c2a42ebdc3e4c75cba
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a9548cec37ad3c54d4bff10c9127db3638065d77 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a9548cec37ad3c54d4bff10c9127db3638065d77
new file mode 100644
index 0000000..5e2b705
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a9548cec37ad3c54d4bff10c9127db3638065d77
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a967ca556a517366de03b8a9d21e991783f0896c b/test/core/end2end/fuzzers/api_fuzzer_corpus/a967ca556a517366de03b8a9d21e991783f0896c
new file mode 100644
index 0000000..f9524b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a967ca556a517366de03b8a9d21e991783f0896c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a96e54f84588c424c5ff2615fb0745684a11de39 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a96e54f84588c424c5ff2615fb0745684a11de39
new file mode 100644
index 0000000..c05b8bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a96e54f84588c424c5ff2615fb0745684a11de39
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a994ed559126fb75d245d34816a727d8585045ac b/test/core/end2end/fuzzers/api_fuzzer_corpus/a994ed559126fb75d245d34816a727d8585045ac
new file mode 100644
index 0000000..8c6ef7a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a994ed559126fb75d245d34816a727d8585045ac
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa926963580066aa503c5433dad9889fabc4ee08 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa926963580066aa503c5433dad9889fabc4ee08
new file mode 100644
index 0000000..08243a9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa926963580066aa503c5433dad9889fabc4ee08
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aabcb4ea803e0b5399cb7a2cca8d28baa3f6c4ae b/test/core/end2end/fuzzers/api_fuzzer_corpus/aabcb4ea803e0b5399cb7a2cca8d28baa3f6c4ae
new file mode 100644
index 0000000..712d2a9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aabcb4ea803e0b5399cb7a2cca8d28baa3f6c4ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aaf2bf9eaf71df9e0c597335e8d6f8c2d370b093 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aaf2bf9eaf71df9e0c597335e8d6f8c2d370b093
new file mode 100644
index 0000000..5cde5e0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aaf2bf9eaf71df9e0c597335e8d6f8c2d370b093
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ab013aca29d6027d443e9dc0c550a26e7a23f01d b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab013aca29d6027d443e9dc0c550a26e7a23f01d
new file mode 100644
index 0000000..f18a856
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab013aca29d6027d443e9dc0c550a26e7a23f01d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ab1a75a7dec4c780749be5afa45fdb9e7e7907ee b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab1a75a7dec4c780749be5afa45fdb9e7e7907ee
new file mode 100644
index 0000000..14d56dd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab1a75a7dec4c780749be5afa45fdb9e7e7907ee
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ab4a63521f8afd81d6f5bf117597039cb02d453a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab4a63521f8afd81d6f5bf117597039cb02d453a
new file mode 100644
index 0000000..5adc2cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab4a63521f8afd81d6f5bf117597039cb02d453a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ab850ea6858b0b4798d8d8c60cf7d715b9064c85 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab850ea6858b0b4798d8d8c60cf7d715b9064c85
new file mode 100644
index 0000000..1bfc3e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab850ea6858b0b4798d8d8c60cf7d715b9064c85
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ab8c19341f57f87c38055a9aaee515f8e65a33f3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab8c19341f57f87c38055a9aaee515f8e65a33f3
new file mode 100644
index 0000000..5b75ff5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ab8c19341f57f87c38055a9aaee515f8e65a33f3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/abe27eee1a472ac0dafe73619602ff44bf7d0657 b/test/core/end2end/fuzzers/api_fuzzer_corpus/abe27eee1a472ac0dafe73619602ff44bf7d0657
new file mode 100644
index 0000000..245d0d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/abe27eee1a472ac0dafe73619602ff44bf7d0657
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/acb49fc7f5d61f15e2e0b8f391678365381c5ab9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/acb49fc7f5d61f15e2e0b8f391678365381c5ab9
new file mode 100644
index 0000000..65d0ca9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/acb49fc7f5d61f15e2e0b8f391678365381c5ab9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ad8f14d76933f67a10d9e8442eaa1b88b2395cd7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ad8f14d76933f67a10d9e8442eaa1b88b2395cd7
new file mode 100644
index 0000000..31fae78
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ad8f14d76933f67a10d9e8442eaa1b88b2395cd7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/af042d0ae8cd624acfa12788ffc0154e6f49394b b/test/core/end2end/fuzzers/api_fuzzer_corpus/af042d0ae8cd624acfa12788ffc0154e6f49394b
new file mode 100644
index 0000000..8f4a63e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/af042d0ae8cd624acfa12788ffc0154e6f49394b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/af0a181159725d308833841738c5d14d478228e8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/af0a181159725d308833841738c5d14d478228e8
new file mode 100644
index 0000000..c79a555
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/af0a181159725d308833841738c5d14d478228e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b05cbc7820c94bb3ee46dd3869ea39923338b4ba b/test/core/end2end/fuzzers/api_fuzzer_corpus/b05cbc7820c94bb3ee46dd3869ea39923338b4ba
new file mode 100644
index 0000000..1ef06a4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b05cbc7820c94bb3ee46dd3869ea39923338b4ba
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b0ff62377b87b846f720a70f0b7f7bdc76aa1315 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b0ff62377b87b846f720a70f0b7f7bdc76aa1315
new file mode 100644
index 0000000..a502809
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b0ff62377b87b846f720a70f0b7f7bdc76aa1315
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b12be9771ea0f5b687f50fa9abe5cb8bb688fa6a b/test/core/end2end/fuzzers/api_fuzzer_corpus/b12be9771ea0f5b687f50fa9abe5cb8bb688fa6a
new file mode 100644
index 0000000..74c9041
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b12be9771ea0f5b687f50fa9abe5cb8bb688fa6a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b23f1233d0e21c4aaaebe2fe5931903698b2408c b/test/core/end2end/fuzzers/api_fuzzer_corpus/b23f1233d0e21c4aaaebe2fe5931903698b2408c
new file mode 100644
index 0000000..118202f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b23f1233d0e21c4aaaebe2fe5931903698b2408c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b29d3c87c76355ce07ea4d4c354bf9d40294abb3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b29d3c87c76355ce07ea4d4c354bf9d40294abb3
new file mode 100644
index 0000000..f24ab1f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b29d3c87c76355ce07ea4d4c354bf9d40294abb3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b33f833f291ebba4d777c2bae51193553c27d138 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b33f833f291ebba4d777c2bae51193553c27d138
new file mode 100644
index 0000000..16ffa9d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b33f833f291ebba4d777c2bae51193553c27d138
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b37f3e85a80b5dcde6b48b46f162418fd2ee83ec b/test/core/end2end/fuzzers/api_fuzzer_corpus/b37f3e85a80b5dcde6b48b46f162418fd2ee83ec
new file mode 100644
index 0000000..7df891c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b37f3e85a80b5dcde6b48b46f162418fd2ee83ec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b3b9e307ce3af6fa515a33668374e15fcc909ae5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b3b9e307ce3af6fa515a33668374e15fcc909ae5
new file mode 100644
index 0000000..df23e88
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b3b9e307ce3af6fa515a33668374e15fcc909ae5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b4037205abce710935a93d656f69928ecc814b50 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4037205abce710935a93d656f69928ecc814b50
new file mode 100644
index 0000000..b2b21d7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4037205abce710935a93d656f69928ecc814b50
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b436d6ea729dd071f87b21819cf1f32979216aee b/test/core/end2end/fuzzers/api_fuzzer_corpus/b436d6ea729dd071f87b21819cf1f32979216aee
new file mode 100644
index 0000000..ba84b6d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b436d6ea729dd071f87b21819cf1f32979216aee
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b46794fb4115e84da13a79153b2ea44d89d952a5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b46794fb4115e84da13a79153b2ea44d89d952a5
new file mode 100644
index 0000000..1c0d75a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b46794fb4115e84da13a79153b2ea44d89d952a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b49df296137b4c86eef0fd5fc55bbdd1cb3c4a7e b/test/core/end2end/fuzzers/api_fuzzer_corpus/b49df296137b4c86eef0fd5fc55bbdd1cb3c4a7e
new file mode 100644
index 0000000..1b86b75
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b49df296137b4c86eef0fd5fc55bbdd1cb3c4a7e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b4dfbd50da81516e8afcd93def813b4b813c3ae1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4dfbd50da81516e8afcd93def813b4b813c3ae1
new file mode 100644
index 0000000..a194e60
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4dfbd50da81516e8afcd93def813b4b813c3ae1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b51853fe4f799f7f959922fda1b3500668a45157 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b51853fe4f799f7f959922fda1b3500668a45157
new file mode 100644
index 0000000..7bdf2e4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b51853fe4f799f7f959922fda1b3500668a45157
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b56db2235df5a81ff15d0c07612de7eee0272304 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b56db2235df5a81ff15d0c07612de7eee0272304
new file mode 100644
index 0000000..114700c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b56db2235df5a81ff15d0c07612de7eee0272304
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b5daec8e0821e8626c9b93ece56ccfef0511346b b/test/core/end2end/fuzzers/api_fuzzer_corpus/b5daec8e0821e8626c9b93ece56ccfef0511346b
new file mode 100644
index 0000000..3f5561a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b5daec8e0821e8626c9b93ece56ccfef0511346b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b61f6be57dd30d8c76aae7b966ffee26093f49ea b/test/core/end2end/fuzzers/api_fuzzer_corpus/b61f6be57dd30d8c76aae7b966ffee26093f49ea
new file mode 100644
index 0000000..04ae4ab
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b61f6be57dd30d8c76aae7b966ffee26093f49ea
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b766e4a3e84ee0a2f57fccbc3a7f7f812b2032d3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b766e4a3e84ee0a2f57fccbc3a7f7f812b2032d3
new file mode 100644
index 0000000..52d70c3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b766e4a3e84ee0a2f57fccbc3a7f7f812b2032d3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b77ca0306f700c8c88854e73ccbdf470fba3f820 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b77ca0306f700c8c88854e73ccbdf470fba3f820
new file mode 100644
index 0000000..afbc92d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b77ca0306f700c8c88854e73ccbdf470fba3f820
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b792b464ceb568355e80a4588a3ae1b43f05a34d b/test/core/end2end/fuzzers/api_fuzzer_corpus/b792b464ceb568355e80a4588a3ae1b43f05a34d
new file mode 100644
index 0000000..03239ec
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b792b464ceb568355e80a4588a3ae1b43f05a34d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b7f282fbd77193d822df9c8156370398e1fd099c b/test/core/end2end/fuzzers/api_fuzzer_corpus/b7f282fbd77193d822df9c8156370398e1fd099c
new file mode 100644
index 0000000..f9b3cda
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b7f282fbd77193d822df9c8156370398e1fd099c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b821e8d3e12441e1120723cf4eda4d939794b17f b/test/core/end2end/fuzzers/api_fuzzer_corpus/b821e8d3e12441e1120723cf4eda4d939794b17f
new file mode 100644
index 0000000..d8830f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b821e8d3e12441e1120723cf4eda4d939794b17f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8a74cc440fbfaa2a523f20ca964976bde128fd0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8a74cc440fbfaa2a523f20ca964976bde128fd0
new file mode 100644
index 0000000..44c904c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8a74cc440fbfaa2a523f20ca964976bde128fd0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8cd185f946c392f8fb5adca4851043df849ac6e b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8cd185f946c392f8fb5adca4851043df849ac6e
new file mode 100644
index 0000000..d9b0e8c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8cd185f946c392f8fb5adca4851043df849ac6e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b93e4c7538558dfe92d2925646029b5dafe653d0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b93e4c7538558dfe92d2925646029b5dafe653d0
new file mode 100644
index 0000000..1fb2345
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b93e4c7538558dfe92d2925646029b5dafe653d0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b94adf31dbe157a38e8b3a873658b8dace55f517 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b94adf31dbe157a38e8b3a873658b8dace55f517
new file mode 100644
index 0000000..605bf00
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b94adf31dbe157a38e8b3a873658b8dace55f517
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b96fd7809c6f18c465e834a96dd60b43b32fac73 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b96fd7809c6f18c465e834a96dd60b43b32fac73
new file mode 100644
index 0000000..3f2fcf2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b96fd7809c6f18c465e834a96dd60b43b32fac73
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bad.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/bad.bin
new file mode 100644
index 0000000..5cb3083
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bad.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bb349c691efa909b4c5412b9210e1acf4a4b7505 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb349c691efa909b4c5412b9210e1acf4a4b7505
new file mode 100644
index 0000000..b22a768
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb349c691efa909b4c5412b9210e1acf4a4b7505
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bbf053837b7e0e2adc868be62fc91248b8dce176 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bbf053837b7e0e2adc868be62fc91248b8dce176
new file mode 100644
index 0000000..af7b33e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bbf053837b7e0e2adc868be62fc91248b8dce176
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bbf7ccb14d60a1d4fa79e572464c687530ca6c2a b/test/core/end2end/fuzzers/api_fuzzer_corpus/bbf7ccb14d60a1d4fa79e572464c687530ca6c2a
new file mode 100644
index 0000000..354e7f7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bbf7ccb14d60a1d4fa79e572464c687530ca6c2a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc5e743f85f6632110277f09847381a402e1624c b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc5e743f85f6632110277f09847381a402e1624c
new file mode 100644
index 0000000..39affe1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc5e743f85f6632110277f09847381a402e1624c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc6770a9bad24599ea4970735e9b17702a12b651 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc6770a9bad24599ea4970735e9b17702a12b651
new file mode 100644
index 0000000..57a17c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc6770a9bad24599ea4970735e9b17702a12b651
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc7f0b79a1781772d7f48e168462f99da27b03e2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc7f0b79a1781772d7f48e168462f99da27b03e2
new file mode 100644
index 0000000..fdc020d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc7f0b79a1781772d7f48e168462f99da27b03e2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc96b9415e9bb48d27f37d91c51d10ec08139974 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc96b9415e9bb48d27f37d91c51d10ec08139974
new file mode 100644
index 0000000..d7eb001
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc96b9415e9bb48d27f37d91c51d10ec08139974
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc9b5b6ba4b6ccbb9e5ff75edd0df8eef9c36d4c b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc9b5b6ba4b6ccbb9e5ff75edd0df8eef9c36d4c
new file mode 100644
index 0000000..f1f0f72
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc9b5b6ba4b6ccbb9e5ff75edd0df8eef9c36d4c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bcae3229d884c5cfc36ae28c672f9b960e30042f b/test/core/end2end/fuzzers/api_fuzzer_corpus/bcae3229d884c5cfc36ae28c672f9b960e30042f
new file mode 100644
index 0000000..95ba743
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bcae3229d884c5cfc36ae28c672f9b960e30042f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bcc7eb464ff05cd0cd2669611776e55ca4dcb2b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bcc7eb464ff05cd0cd2669611776e55ca4dcb2b4
new file mode 100644
index 0000000..295f781
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bcc7eb464ff05cd0cd2669611776e55ca4dcb2b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd1ed73f6cf97f980d23ff2e9f4f4e78b80bda57 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd1ed73f6cf97f980d23ff2e9f4f4e78b80bda57
new file mode 100644
index 0000000..7f959dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd1ed73f6cf97f980d23ff2e9f4f4e78b80bda57
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd459204c5fee8000abc7d895a317028351d0dec b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd459204c5fee8000abc7d895a317028351d0dec
new file mode 100644
index 0000000..19eb541
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd459204c5fee8000abc7d895a317028351d0dec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd4786be14d852c68e605eaefa782f79064f32e2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd4786be14d852c68e605eaefa782f79064f32e2
new file mode 100644
index 0000000..9f54339
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd4786be14d852c68e605eaefa782f79064f32e2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd5c6df9c2cfaa96d768b1fe6e8fff57bf1d02c9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd5c6df9c2cfaa96d768b1fe6e8fff57bf1d02c9
new file mode 100644
index 0000000..8ed1db6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd5c6df9c2cfaa96d768b1fe6e8fff57bf1d02c9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd7314ef323557ccf3a97c1b1ba4bed0a9b24de2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd7314ef323557ccf3a97c1b1ba4bed0a9b24de2
new file mode 100644
index 0000000..c4bc898
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd7314ef323557ccf3a97c1b1ba4bed0a9b24de2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd891b3b4256f1c4207c3bbe5bd86f5e90a49ee2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd891b3b4256f1c4207c3bbe5bd86f5e90a49ee2
new file mode 100644
index 0000000..4f3ce3a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd891b3b4256f1c4207c3bbe5bd86f5e90a49ee2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bde8a553b10a613c32f800429a07f0b5a2d37e53 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bde8a553b10a613c32f800429a07f0b5a2d37e53
new file mode 100644
index 0000000..e450022
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bde8a553b10a613c32f800429a07f0b5a2d37e53
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/be0ccf7b9b4581e01a42e9cad6343c93ccf6f362 b/test/core/end2end/fuzzers/api_fuzzer_corpus/be0ccf7b9b4581e01a42e9cad6343c93ccf6f362
new file mode 100644
index 0000000..985e30a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/be0ccf7b9b4581e01a42e9cad6343c93ccf6f362
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/be40890ee61e101a7429d53cd9ffd59ee600e0f6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/be40890ee61e101a7429d53cd9ffd59ee600e0f6
new file mode 100644
index 0000000..24f4459
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/be40890ee61e101a7429d53cd9ffd59ee600e0f6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bef8cedf1a792786a027114c85a89a1bef3155c4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bef8cedf1a792786a027114c85a89a1bef3155c4
new file mode 100644
index 0000000..b3c115e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bef8cedf1a792786a027114c85a89a1bef3155c4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bf0d70e0d09e5c2ddd79b55dbabdd58b385307f2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bf0d70e0d09e5c2ddd79b55dbabdd58b385307f2
new file mode 100644
index 0000000..63cc356
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bf0d70e0d09e5c2ddd79b55dbabdd58b385307f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c004d2a6d36524db9e0c18c5df6170366dd2b6f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c004d2a6d36524db9e0c18c5df6170366dd2b6f1
new file mode 100644
index 0000000..5cc30a3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c004d2a6d36524db9e0c18c5df6170366dd2b6f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c17ca23726e7bca7b0d92398f827cfb25c7f0d40 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c17ca23726e7bca7b0d92398f827cfb25c7f0d40
new file mode 100644
index 0000000..5a6bb8e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c17ca23726e7bca7b0d92398f827cfb25c7f0d40
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c1937db2c3dff32ff22a53a8b76614602cf41d73 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1937db2c3dff32ff22a53a8b76614602cf41d73
new file mode 100644
index 0000000..eef122a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1937db2c3dff32ff22a53a8b76614602cf41d73
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c2d14ed959df62d2f6dbe46c71489bed68e3c0f0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c2d14ed959df62d2f6dbe46c71489bed68e3c0f0
new file mode 100644
index 0000000..4bb3e9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c2d14ed959df62d2f6dbe46c71489bed68e3c0f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c343ddb31042500e460861abc70e98ce3088ceed b/test/core/end2end/fuzzers/api_fuzzer_corpus/c343ddb31042500e460861abc70e98ce3088ceed
new file mode 100644
index 0000000..c0223ed
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c343ddb31042500e460861abc70e98ce3088ceed
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c45cc40cc387134dec06733a01bde8fc44a2c9d9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c45cc40cc387134dec06733a01bde8fc44a2c9d9
new file mode 100644
index 0000000..68e78cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c45cc40cc387134dec06733a01bde8fc44a2c9d9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c4a63251d65cb186242e7aba5ab3d4709d3f0065 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c4a63251d65cb186242e7aba5ab3d4709d3f0065
new file mode 100644
index 0000000..240cc20
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c4a63251d65cb186242e7aba5ab3d4709d3f0065
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c53efcb830c4ae5cba7b3e0803635445e1469103 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c53efcb830c4ae5cba7b3e0803635445e1469103
new file mode 100644
index 0000000..2554e37
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c53efcb830c4ae5cba7b3e0803635445e1469103
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c56726277ddeb233e30b6223158042aafb944191 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c56726277ddeb233e30b6223158042aafb944191
new file mode 100644
index 0000000..bbb533a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c56726277ddeb233e30b6223158042aafb944191
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c5e5b4c1e4e2bae55c1355950c3c7a593cb3fc04 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5e5b4c1e4e2bae55c1355950c3c7a593cb3fc04
new file mode 100644
index 0000000..c7f3acd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5e5b4c1e4e2bae55c1355950c3c7a593cb3fc04
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c69863dd21c782e609d6ecdb9150f887a0f39989 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c69863dd21c782e609d6ecdb9150f887a0f39989
new file mode 100644
index 0000000..52b683c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c69863dd21c782e609d6ecdb9150f887a0f39989
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c73e85bdaa195d9659ae9b08995a9fb716f9c92a b/test/core/end2end/fuzzers/api_fuzzer_corpus/c73e85bdaa195d9659ae9b08995a9fb716f9c92a
new file mode 100644
index 0000000..6b3f2b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c73e85bdaa195d9659ae9b08995a9fb716f9c92a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c73fbc2e78f496b5666da99bccac9445ac9feeac b/test/core/end2end/fuzzers/api_fuzzer_corpus/c73fbc2e78f496b5666da99bccac9445ac9feeac
new file mode 100644
index 0000000..8837ba5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c73fbc2e78f496b5666da99bccac9445ac9feeac
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c76a1cca503160ca659aad6f7a05ca8fe5db439e b/test/core/end2end/fuzzers/api_fuzzer_corpus/c76a1cca503160ca659aad6f7a05ca8fe5db439e
new file mode 100644
index 0000000..9714a3b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c76a1cca503160ca659aad6f7a05ca8fe5db439e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c7c13a37189ce2482f5517f6ef0903431194e11b b/test/core/end2end/fuzzers/api_fuzzer_corpus/c7c13a37189ce2482f5517f6ef0903431194e11b
new file mode 100644
index 0000000..8428cca
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c7c13a37189ce2482f5517f6ef0903431194e11b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c837e4dc49146de843c9556c1b3c886abb552db7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c837e4dc49146de843c9556c1b3c886abb552db7
new file mode 100644
index 0000000..4073984
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c837e4dc49146de843c9556c1b3c886abb552db7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c918b9e3e9cdfdb21d94ef0fba85b25f3ed9d098 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c918b9e3e9cdfdb21d94ef0fba85b25f3ed9d098
new file mode 100644
index 0000000..9135162
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c918b9e3e9cdfdb21d94ef0fba85b25f3ed9d098
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c957b37c99c5bb22b2c1f6dd050c57e685505599 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c957b37c99c5bb22b2c1f6dd050c57e685505599
new file mode 100644
index 0000000..82635d7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c957b37c99c5bb22b2c1f6dd050c57e685505599
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c978dc651b961f2d48aad95b40ac761b3467f212 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c978dc651b961f2d48aad95b40ac761b3467f212
new file mode 100644
index 0000000..bf077fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c978dc651b961f2d48aad95b40ac761b3467f212
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c9bda5eb1a93526b4809d147647cc78452988e29 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c9bda5eb1a93526b4809d147647cc78452988e29
new file mode 100644
index 0000000..3b389cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c9bda5eb1a93526b4809d147647cc78452988e29
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ca086cf78308275212c52012f06edf3b4152204a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca086cf78308275212c52012f06edf3b4152204a
new file mode 100644
index 0000000..564a12e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca086cf78308275212c52012f06edf3b4152204a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ca6add6699d063e2212335264ad3e004327afc1a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca6add6699d063e2212335264ad3e004327afc1a
new file mode 100644
index 0000000..dd9229e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca6add6699d063e2212335264ad3e004327afc1a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ca6b20544c093b14703410d792c8f73e73205bce b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca6b20544c093b14703410d792c8f73e73205bce
new file mode 100644
index 0000000..b9aaab3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca6b20544c093b14703410d792c8f73e73205bce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cc34f9a0d85a22556faffadf90182f7c44bf168a b/test/core/end2end/fuzzers/api_fuzzer_corpus/cc34f9a0d85a22556faffadf90182f7c44bf168a
new file mode 100644
index 0000000..e9fa513
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cc34f9a0d85a22556faffadf90182f7c44bf168a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cc7087fd7c7398e7c2afe3fb03e705262b5e843a b/test/core/end2end/fuzzers/api_fuzzer_corpus/cc7087fd7c7398e7c2afe3fb03e705262b5e843a
new file mode 100644
index 0000000..ee363c7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cc7087fd7c7398e7c2afe3fb03e705262b5e843a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cca20202993dda83570ac83c0b1967ce225c78b9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cca20202993dda83570ac83c0b1967ce225c78b9
new file mode 100644
index 0000000..663f216
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cca20202993dda83570ac83c0b1967ce225c78b9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ccdff5940d61b708f67fcc55dc26ac1ad4f4c298 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ccdff5940d61b708f67fcc55dc26ac1ad4f4c298
new file mode 100644
index 0000000..3992529
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ccdff5940d61b708f67fcc55dc26ac1ad4f4c298
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cd0e7c4cd361b786b6f27c481ed601fd373cb221 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd0e7c4cd361b786b6f27c481ed601fd373cb221
new file mode 100644
index 0000000..be7a170
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd0e7c4cd361b786b6f27c481ed601fd373cb221
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4f2c59f0cf55d9a73fb0b96d701c784c446048 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4f2c59f0cf55d9a73fb0b96d701c784c446048
new file mode 100644
index 0000000..bed26bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4f2c59f0cf55d9a73fb0b96d701c784c446048
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cdc064f39a9a67210b1be6b195d38d5d0d73eaa0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cdc064f39a9a67210b1be6b195d38d5d0d73eaa0
new file mode 100644
index 0000000..7b9d3a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cdc064f39a9a67210b1be6b195d38d5d0d73eaa0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ce02561c4cfd1ec7e272cf81678149350f8a066c b/test/core/end2end/fuzzers/api_fuzzer_corpus/ce02561c4cfd1ec7e272cf81678149350f8a066c
new file mode 100644
index 0000000..3c0ba41
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ce02561c4cfd1ec7e272cf81678149350f8a066c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cf26c6969c0f649a2ccd780edb8b3dc314ff7701 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cf26c6969c0f649a2ccd780edb8b3dc314ff7701
new file mode 100644
index 0000000..5398b2c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cf26c6969c0f649a2ccd780edb8b3dc314ff7701
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0a0ee428270236e707457b9560a91c233ed2326c b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0a0ee428270236e707457b9560a91c233ed2326c
new file mode 100644
index 0000000..8eb262b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0a0ee428270236e707457b9560a91c233ed2326c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0b1b50227d01f99998b01ed218f5d4dc3839d44f b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0b1b50227d01f99998b01ed218f5d4dc3839d44f
new file mode 100644
index 0000000..3dbc7a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0b1b50227d01f99998b01ed218f5d4dc3839d44f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-14359c8f754c2ecdae21deeeec033ae10360033a b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-14359c8f754c2ecdae21deeeec033ae10360033a
new file mode 100644
index 0000000..66c443e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-14359c8f754c2ecdae21deeeec033ae10360033a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1b9aeaf762bb1a972dda8f3a455df2628efd693b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1b9aeaf762bb1a972dda8f3a455df2628efd693b
new file mode 100644
index 0000000..a0e609b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1b9aeaf762bb1a972dda8f3a455df2628efd693b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1bc1a02532d212c8975e0cdcd5127c98fcaf752b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1bc1a02532d212c8975e0cdcd5127c98fcaf752b
new file mode 100644
index 0000000..4f6122d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1bc1a02532d212c8975e0cdcd5127c98fcaf752b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-212c3b09f310867e1e8ffa7faecac75c12f4cda3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-212c3b09f310867e1e8ffa7faecac75c12f4cda3
new file mode 100644
index 0000000..61af110
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-212c3b09f310867e1e8ffa7faecac75c12f4cda3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2ccee0e61103a767acec12b9146d478202b93b27 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2ccee0e61103a767acec12b9146d478202b93b27
new file mode 100644
index 0000000..73d90f6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2ccee0e61103a767acec12b9146d478202b93b27
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2f1092c48db455fbe1ae5e275f8d221dc8c52f00 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2f1092c48db455fbe1ae5e275f8d221dc8c52f00
new file mode 100644
index 0000000..59860c6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2f1092c48db455fbe1ae5e275f8d221dc8c52f00
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4ae4941b4c3f857966a0e3c05f789a0a5ae15bbf b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4ae4941b4c3f857966a0e3c05f789a0a5ae15bbf
new file mode 100644
index 0000000..44d268f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4ae4941b4c3f857966a0e3c05f789a0a5ae15bbf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4e4d7a383785c83b78ed6597bfed360079a49a08 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4e4d7a383785c83b78ed6597bfed360079a49a08
new file mode 100644
index 0000000..b275994
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4e4d7a383785c83b78ed6597bfed360079a49a08
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5c774460d2dc7ae9d471ef4b87609b13e4e95219 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5c774460d2dc7ae9d471ef4b87609b13e4e95219
new file mode 100644
index 0000000..fb139f9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5c774460d2dc7ae9d471ef4b87609b13e4e95219
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-6db86c556caf542fe8c3345ef396467b1d609d32 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-6db86c556caf542fe8c3345ef396467b1d609d32
new file mode 100644
index 0000000..b0777be
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-6db86c556caf542fe8c3345ef396467b1d609d32
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-72ab4efc255cfc55ed03c1002187a68e2e18e33b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-72ab4efc255cfc55ed03c1002187a68e2e18e33b
new file mode 100644
index 0000000..770cee3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-72ab4efc255cfc55ed03c1002187a68e2e18e33b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-7ca23a3e10cdbf579cf81a50e51af358f86631eb b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-7ca23a3e10cdbf579cf81a50e51af358f86631eb
new file mode 100644
index 0000000..9618323
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-7ca23a3e10cdbf579cf81a50e51af358f86631eb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1
new file mode 100644
index 0000000..63ab352
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-89e1b03278bad9790ae0f8614a8389414d1eab37 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-89e1b03278bad9790ae0f8614a8389414d1eab37
new file mode 100644
index 0000000..b5adace
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-89e1b03278bad9790ae0f8614a8389414d1eab37
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8ab0b6e57b90ab4c6b8d5de8278464eb428f4668 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8ab0b6e57b90ab4c6b8d5de8278464eb428f4668
new file mode 100644
index 0000000..b50fdee
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8ab0b6e57b90ab4c6b8d5de8278464eb428f4668
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8e2e3975a865fb107fff8060f4f949aa235727d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8e2e3975a865fb107fff8060f4f949aa235727d5
new file mode 100644
index 0000000..0059b4b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8e2e3975a865fb107fff8060f4f949aa235727d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-916f6ab61cd358be9a241e2eb09851f700335eda b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-916f6ab61cd358be9a241e2eb09851f700335eda
new file mode 100644
index 0000000..e3ca42a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-916f6ab61cd358be9a241e2eb09851f700335eda
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-97ec5404605d0d7bed44c2b845e06f6d9479c152 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-97ec5404605d0d7bed44c2b845e06f6d9479c152
new file mode 100644
index 0000000..92b9810
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-97ec5404605d0d7bed44c2b845e06f6d9479c152
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9862337313ff89e8dd6fbd6f870a568ec4bd6ecc b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9862337313ff89e8dd6fbd6f870a568ec4bd6ecc
new file mode 100644
index 0000000..4114505
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9862337313ff89e8dd6fbd6f870a568ec4bd6ecc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9e53b8c6ea7f6ae5c53e5834c50eac8e9f33259a b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9e53b8c6ea7f6ae5c53e5834c50eac8e9f33259a
new file mode 100644
index 0000000..45529a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9e53b8c6ea7f6ae5c53e5834c50eac8e9f33259a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-a6224f954d8234d45e6f6ea27aca4d65ca77b6c7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-a6224f954d8234d45e6f6ea27aca4d65ca77b6c7
new file mode 100644
index 0000000..d89f32b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-a6224f954d8234d45e6f6ea27aca4d65ca77b6c7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ba2c1509ff87865d9e23c056b9c7fe2732825ef0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ba2c1509ff87865d9e23c056b9c7fe2732825ef0
new file mode 100644
index 0000000..48a51f9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ba2c1509ff87865d9e23c056b9c7fe2732825ef0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bac7a77b50e53ff71b0f52ce635e64ac15a787dc b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bac7a77b50e53ff71b0f52ce635e64ac15a787dc
new file mode 100644
index 0000000..c8c2ffd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bac7a77b50e53ff71b0f52ce635e64ac15a787dc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bebee7dd27c149af9e7b573300c686969fde9eb3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bebee7dd27c149af9e7b573300c686969fde9eb3
new file mode 100644
index 0000000..f6d8e2e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bebee7dd27c149af9e7b573300c686969fde9eb3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ca8aa113c22037a2a552c1763f845609d555ef9b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ca8aa113c22037a2a552c1763f845609d555ef9b
new file mode 100644
index 0000000..2869844
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ca8aa113c22037a2a552c1763f845609d555ef9b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-cce6ffed471344173c135e536b454f469bd07e03 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-cce6ffed471344173c135e536b454f469bd07e03
new file mode 100644
index 0000000..d56a63a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-cce6ffed471344173c135e536b454f469bd07e03
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-dc6abf90d5e8e1b96f7e25f418b1a7f572e6a738 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-dc6abf90d5e8e1b96f7e25f418b1a7f572e6a738
new file mode 100644
index 0000000..6a10e38
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-dc6abf90d5e8e1b96f7e25f418b1a7f572e6a738
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e45753da8952c41715a65010250efba0a4a4d243 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e45753da8952c41715a65010250efba0a4a4d243
new file mode 100644
index 0000000..ad8031d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e45753da8952c41715a65010250efba0a4a4d243
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e7930097a989131890a316b0b1ed85801699562b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e7930097a989131890a316b0b1ed85801699562b
new file mode 100644
index 0000000..ce70a12
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e7930097a989131890a316b0b1ed85801699562b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed3086c0ca03a427fca1817b52a4d6530fb4096b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed3086c0ca03a427fca1817b52a4d6530fb4096b
new file mode 100644
index 0000000..d644b94
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed3086c0ca03a427fca1817b52a4d6530fb4096b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed7959740df2fdcf62626e370dcd7eb43963731b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed7959740df2fdcf62626e370dcd7eb43963731b
new file mode 100644
index 0000000..59f7709
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed7959740df2fdcf62626e370dcd7eb43963731b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ef09afe157880d7f363fb87f6bc194ce1a72554c b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ef09afe157880d7f363fb87f6bc194ce1a72554c
new file mode 100644
index 0000000..62b7e81
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ef09afe157880d7f363fb87f6bc194ce1a72554c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499
new file mode 100644
index 0000000..8475e63
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f8bf4b7d89c07d661b695a3e4fdf269b853fe168 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f8bf4b7d89c07d661b695a3e4fdf269b853fe168
new file mode 100644
index 0000000..464e436
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f8bf4b7d89c07d661b695a3e4fdf269b853fe168
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-fb41c97305a2c94d367e40863dc046c8f78a57c9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-fb41c97305a2c94d367e40863dc046c8f78a57c9
new file mode 100644
index 0000000..d957c60
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-fb41c97305a2c94d367e40863dc046c8f78a57c9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d00326f1b0a93acb1cb7fe02ba0342cc6e1875e6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d00326f1b0a93acb1cb7fe02ba0342cc6e1875e6
new file mode 100644
index 0000000..6d6bd6f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d00326f1b0a93acb1cb7fe02ba0342cc6e1875e6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d0692d73e38ed8c154ebddd627ce99890a1cf798 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0692d73e38ed8c154ebddd627ce99890a1cf798
new file mode 100644
index 0000000..c329964
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0692d73e38ed8c154ebddd627ce99890a1cf798
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d0fcc9d6dc91ead9fd27f0c613ea031f21fb4de4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0fcc9d6dc91ead9fd27f0c613ea031f21fb4de4
new file mode 100644
index 0000000..f7892d3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0fcc9d6dc91ead9fd27f0c613ea031f21fb4de4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d17e7451bcef39ce542d84f2539f9586ea35f21e b/test/core/end2end/fuzzers/api_fuzzer_corpus/d17e7451bcef39ce542d84f2539f9586ea35f21e
new file mode 100644
index 0000000..0608163
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d17e7451bcef39ce542d84f2539f9586ea35f21e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d18b5e648be40b0ea52fc8b10bcbae9bd4325f0e b/test/core/end2end/fuzzers/api_fuzzer_corpus/d18b5e648be40b0ea52fc8b10bcbae9bd4325f0e
new file mode 100644
index 0000000..fe40b79
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d18b5e648be40b0ea52fc8b10bcbae9bd4325f0e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d194d6aa501f75ed24fc399ee594fb77341e5d38 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d194d6aa501f75ed24fc399ee594fb77341e5d38
new file mode 100644
index 0000000..7211377
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d194d6aa501f75ed24fc399ee594fb77341e5d38
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d1ade96319d9de82cf3b0480d226a5ad9f31eaa1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d1ade96319d9de82cf3b0480d226a5ad9f31eaa1
new file mode 100644
index 0000000..89ecdbc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d1ade96319d9de82cf3b0480d226a5ad9f31eaa1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d1b53c2a386259ce958c34e2cb281514e14e0d03 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d1b53c2a386259ce958c34e2cb281514e14e0d03
new file mode 100644
index 0000000..478c05f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d1b53c2a386259ce958c34e2cb281514e14e0d03
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d290717010121ba2745e551e7a80be6e9f6d59e2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d290717010121ba2745e551e7a80be6e9f6d59e2
new file mode 100644
index 0000000..25ab2ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d290717010121ba2745e551e7a80be6e9f6d59e2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d2956eabd7b8b9d6b136731a3a4fa077f184aa13 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2956eabd7b8b9d6b136731a3a4fa077f184aa13
new file mode 100644
index 0000000..73c8d71
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2956eabd7b8b9d6b136731a3a4fa077f184aa13
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d2c828ee88b3e352fad3263f1e1ff901a41fc7a6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2c828ee88b3e352fad3263f1e1ff901a41fc7a6
new file mode 100644
index 0000000..3052b65
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2c828ee88b3e352fad3263f1e1ff901a41fc7a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d3124f8fe39ebe943d0d5a7087a51d7e852505bd b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3124f8fe39ebe943d0d5a7087a51d7e852505bd
new file mode 100644
index 0000000..50760fa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3124f8fe39ebe943d0d5a7087a51d7e852505bd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d333dc3999c6dcca82d85f72e65e10c07f12d978 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d333dc3999c6dcca82d85f72e65e10c07f12d978
new file mode 100644
index 0000000..9086fb3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d333dc3999c6dcca82d85f72e65e10c07f12d978
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d3bec93d378e7466bacd95be431500ed30cba449 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3bec93d378e7466bacd95be431500ed30cba449
new file mode 100644
index 0000000..51c7569
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3bec93d378e7466bacd95be431500ed30cba449
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d48a5cefe695d0494df4540ea395dcdd90a332ef b/test/core/end2end/fuzzers/api_fuzzer_corpus/d48a5cefe695d0494df4540ea395dcdd90a332ef
new file mode 100644
index 0000000..e123671
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d48a5cefe695d0494df4540ea395dcdd90a332ef
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d4c3ed789ef8a888244504601964f0a0c994a66d b/test/core/end2end/fuzzers/api_fuzzer_corpus/d4c3ed789ef8a888244504601964f0a0c994a66d
new file mode 100644
index 0000000..454c205
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d4c3ed789ef8a888244504601964f0a0c994a66d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d4caa070bca058455b68c7b96961e3ca0f151b32 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d4caa070bca058455b68c7b96961e3ca0f151b32
new file mode 100644
index 0000000..f077bfc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d4caa070bca058455b68c7b96961e3ca0f151b32
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d63251b34cf38052b657d62e353aa42d905e52c4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d63251b34cf38052b657d62e353aa42d905e52c4
new file mode 100644
index 0000000..bed1f46
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d63251b34cf38052b657d62e353aa42d905e52c4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d65f32b4af92080a496fb0965075c060c70ee444 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d65f32b4af92080a496fb0965075c060c70ee444
new file mode 100644
index 0000000..6817649
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d65f32b4af92080a496fb0965075c060c70ee444
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d712d007679af5438c7bda723ddc724c2e57b0c1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d712d007679af5438c7bda723ddc724c2e57b0c1
new file mode 100644
index 0000000..81295b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d712d007679af5438c7bda723ddc724c2e57b0c1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d80ba5bbc230065821c0c6530f70bdf205e817cc b/test/core/end2end/fuzzers/api_fuzzer_corpus/d80ba5bbc230065821c0c6530f70bdf205e817cc
new file mode 100644
index 0000000..64d1577
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d80ba5bbc230065821c0c6530f70bdf205e817cc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d8137be32de0a676678672fe6f82992b2ca61fef b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8137be32de0a676678672fe6f82992b2ca61fef
new file mode 100644
index 0000000..11ae89a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8137be32de0a676678672fe6f82992b2ca61fef
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d8bbba8dd44b71161c835cb09610e47401de44e3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8bbba8dd44b71161c835cb09610e47401de44e3
new file mode 100644
index 0000000..46940bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8bbba8dd44b71161c835cb09610e47401de44e3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d913cc4e8f2900d7035d196fd62707cf1194e02b b/test/core/end2end/fuzzers/api_fuzzer_corpus/d913cc4e8f2900d7035d196fd62707cf1194e02b
new file mode 100644
index 0000000..111b8a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d913cc4e8f2900d7035d196fd62707cf1194e02b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d91e9bf6b6c78f35a68ba877f3325b3c1ee3db35 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d91e9bf6b6c78f35a68ba877f3325b3c1ee3db35
new file mode 100644
index 0000000..6386318
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d91e9bf6b6c78f35a68ba877f3325b3c1ee3db35
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d97ade864dccd3eea245411665e5126f97302063 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d97ade864dccd3eea245411665e5126f97302063
new file mode 100644
index 0000000..d873e14
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d97ade864dccd3eea245411665e5126f97302063
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d9f752e6e02987d7bfe6f0f4c4d70644d357fef5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d9f752e6e02987d7bfe6f0f4c4d70644d357fef5
new file mode 100644
index 0000000..1a323ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d9f752e6e02987d7bfe6f0f4c4d70644d357fef5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/da23c62c70f6c1174adc08093c429f1ec657921a b/test/core/end2end/fuzzers/api_fuzzer_corpus/da23c62c70f6c1174adc08093c429f1ec657921a
new file mode 100644
index 0000000..8ec7fec
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/da23c62c70f6c1174adc08093c429f1ec657921a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dab32e8bb17a9bd7b04b8b895b7b48c27d38ef51 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dab32e8bb17a9bd7b04b8b895b7b48c27d38ef51
new file mode 100644
index 0000000..1cb1a80
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dab32e8bb17a9bd7b04b8b895b7b48c27d38ef51
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dacc3689e0a7b90aeebfaee000adf89e95e50cf9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dacc3689e0a7b90aeebfaee000adf89e95e50cf9
new file mode 100644
index 0000000..4f07ff1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dacc3689e0a7b90aeebfaee000adf89e95e50cf9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dad2c9af972d2e21c4437f0d94fdeacd7c8c7641 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dad2c9af972d2e21c4437f0d94fdeacd7c8c7641
new file mode 100644
index 0000000..7a20024
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dad2c9af972d2e21c4437f0d94fdeacd7c8c7641
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/db7c4b56e701832634e61cc0b3ab5206fabf518d b/test/core/end2end/fuzzers/api_fuzzer_corpus/db7c4b56e701832634e61cc0b3ab5206fabf518d
new file mode 100644
index 0000000..69a3dfb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/db7c4b56e701832634e61cc0b3ab5206fabf518d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dd0e562fcf5edda051585b70d3b3780a9a6a2818 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dd0e562fcf5edda051585b70d3b3780a9a6a2818
new file mode 100644
index 0000000..6cc9039
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dd0e562fcf5edda051585b70d3b3780a9a6a2818
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dddf3303e3e8e558ca6f147ec11d8195b6de30bb b/test/core/end2end/fuzzers/api_fuzzer_corpus/dddf3303e3e8e558ca6f147ec11d8195b6de30bb
new file mode 100644
index 0000000..cc23afe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dddf3303e3e8e558ca6f147ec11d8195b6de30bb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dde3b1c08399b61df7de4997194d9392c2e4c3cb b/test/core/end2end/fuzzers/api_fuzzer_corpus/dde3b1c08399b61df7de4997194d9392c2e4c3cb
new file mode 100644
index 0000000..b293fcd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dde3b1c08399b61df7de4997194d9392c2e4c3cb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/de838de0352fc7ee32452bc83043cf587176e120 b/test/core/end2end/fuzzers/api_fuzzer_corpus/de838de0352fc7ee32452bc83043cf587176e120
new file mode 100644
index 0000000..5f84542
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/de838de0352fc7ee32452bc83043cf587176e120
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/deeec423355ed885b906c6770c96d3f17583fdf3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/deeec423355ed885b906c6770c96d3f17583fdf3
new file mode 100644
index 0000000..83e059c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/deeec423355ed885b906c6770c96d3f17583fdf3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/df616ee922cc89908b771e5276e47abcbaff1346 b/test/core/end2end/fuzzers/api_fuzzer_corpus/df616ee922cc89908b771e5276e47abcbaff1346
new file mode 100644
index 0000000..5255ca3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/df616ee922cc89908b771e5276e47abcbaff1346
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/df8ef8bf4069afd375066fbb74cbe137f73db829 b/test/core/end2end/fuzzers/api_fuzzer_corpus/df8ef8bf4069afd375066fbb74cbe137f73db829
new file mode 100644
index 0000000..fc656a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/df8ef8bf4069afd375066fbb74cbe137f73db829
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/df949398b0b614309219c4128b167746e16a1ead b/test/core/end2end/fuzzers/api_fuzzer_corpus/df949398b0b614309219c4128b167746e16a1ead
new file mode 100644
index 0000000..2299710
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/df949398b0b614309219c4128b167746e16a1ead
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dfe6d60fd53eb8f4174366d1515c5a90ce10bf1b b/test/core/end2end/fuzzers/api_fuzzer_corpus/dfe6d60fd53eb8f4174366d1515c5a90ce10bf1b
new file mode 100644
index 0000000..6eaeab5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dfe6d60fd53eb8f4174366d1515c5a90ce10bf1b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dfefc5d84c18606a3aefd5bb721a06e192b4420e b/test/core/end2end/fuzzers/api_fuzzer_corpus/dfefc5d84c18606a3aefd5bb721a06e192b4420e
new file mode 100644
index 0000000..5ad30f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dfefc5d84c18606a3aefd5bb721a06e192b4420e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e022322a04b3ac1452055563bb41976a03a146ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/e022322a04b3ac1452055563bb41976a03a146ad
new file mode 100644
index 0000000..d8445c7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e022322a04b3ac1452055563bb41976a03a146ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e06db057637f6738a48464cc2d65d7399fe296e8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e06db057637f6738a48464cc2d65d7399fe296e8
new file mode 100644
index 0000000..53daab2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e06db057637f6738a48464cc2d65d7399fe296e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e0e7112238b555fdc12a1c5e9adb50703ae56a43 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e0e7112238b555fdc12a1c5e9adb50703ae56a43
new file mode 100644
index 0000000..e8dec0a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e0e7112238b555fdc12a1c5e9adb50703ae56a43
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e140f7efd72850d181a0145bb9ea7d92e61dec95 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e140f7efd72850d181a0145bb9ea7d92e61dec95
new file mode 100644
index 0000000..fb2d960
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e140f7efd72850d181a0145bb9ea7d92e61dec95
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e1a0398910c28ad61e065e98e884a7492f6dc594 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e1a0398910c28ad61e065e98e884a7492f6dc594
new file mode 100644
index 0000000..71cdbf0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e1a0398910c28ad61e065e98e884a7492f6dc594
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e212833dd63750f436254c0c81f1ddd42fb9a17e b/test/core/end2end/fuzzers/api_fuzzer_corpus/e212833dd63750f436254c0c81f1ddd42fb9a17e
new file mode 100644
index 0000000..bdfd942
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e212833dd63750f436254c0c81f1ddd42fb9a17e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e23c0abb4f625880dbae1cc81ce5b146992f5d36 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e23c0abb4f625880dbae1cc81ce5b146992f5d36
new file mode 100644
index 0000000..9e6351c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e23c0abb4f625880dbae1cc81ce5b146992f5d36
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e33f7d7998fe6e12ecc4014c8434e4ca591371b3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e33f7d7998fe6e12ecc4014c8434e4ca591371b3
new file mode 100644
index 0000000..6b3cf73
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e33f7d7998fe6e12ecc4014c8434e4ca591371b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e401c1abdd1ef0458dd46e35167c4734667ebcc0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e401c1abdd1ef0458dd46e35167c4734667ebcc0
new file mode 100644
index 0000000..c059a1b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e401c1abdd1ef0458dd46e35167c4734667ebcc0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e42a9e07845680b8aad95408657c87b01873bcbe b/test/core/end2end/fuzzers/api_fuzzer_corpus/e42a9e07845680b8aad95408657c87b01873bcbe
new file mode 100644
index 0000000..60e70cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e42a9e07845680b8aad95408657c87b01873bcbe
@@ -0,0 +1 @@
+S.
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e42fc248764aac6f6e0af5b5705272f82101287f b/test/core/end2end/fuzzers/api_fuzzer_corpus/e42fc248764aac6f6e0af5b5705272f82101287f
new file mode 100644
index 0000000..3431cfa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e42fc248764aac6f6e0af5b5705272f82101287f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e4ba9f46387c5687fb9003724893c0b199debf2d b/test/core/end2end/fuzzers/api_fuzzer_corpus/e4ba9f46387c5687fb9003724893c0b199debf2d
new file mode 100644
index 0000000..92bd6e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e4ba9f46387c5687fb9003724893c0b199debf2d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e55693473101ac4626e04012beb1b9b6d93a0a94 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e55693473101ac4626e04012beb1b9b6d93a0a94
new file mode 100644
index 0000000..18305cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e55693473101ac4626e04012beb1b9b6d93a0a94
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e57acbf9e36c755cc50b00bc868c01ca1c1f6842 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e57acbf9e36c755cc50b00bc868c01ca1c1f6842
new file mode 100644
index 0000000..e1c3566
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e57acbf9e36c755cc50b00bc868c01ca1c1f6842
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e590a42febe0442ddf632b05cda112b3aca43380 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e590a42febe0442ddf632b05cda112b3aca43380
new file mode 100644
index 0000000..5fed465
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e590a42febe0442ddf632b05cda112b3aca43380
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e5afbabdb437dfc44f06ddf8b9f793868e8fdde0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e5afbabdb437dfc44f06ddf8b9f793868e8fdde0
new file mode 100644
index 0000000..27e4644
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e5afbabdb437dfc44f06ddf8b9f793868e8fdde0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e5d120938961b8ed1e0f46e342683432b9081dd1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e5d120938961b8ed1e0f46e342683432b9081dd1
new file mode 100644
index 0000000..d17f0ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e5d120938961b8ed1e0f46e342683432b9081dd1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e62f5243dd375cb4b71c864a18ddd50b5b99762f b/test/core/end2end/fuzzers/api_fuzzer_corpus/e62f5243dd375cb4b71c864a18ddd50b5b99762f
new file mode 100644
index 0000000..853d3c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e62f5243dd375cb4b71c864a18ddd50b5b99762f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e6660a661f0adb7be809c558ca15573add24f686 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e6660a661f0adb7be809c558ca15573add24f686
new file mode 100644
index 0000000..511d681
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e6660a661f0adb7be809c558ca15573add24f686
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e66b054263dd9e7ea90d7dfaee555e2f24bfb60f b/test/core/end2end/fuzzers/api_fuzzer_corpus/e66b054263dd9e7ea90d7dfaee555e2f24bfb60f
new file mode 100644
index 0000000..9a1d60d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e66b054263dd9e7ea90d7dfaee555e2f24bfb60f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e72218971bac83f556e86b0a65ec303e2a05eac8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e72218971bac83f556e86b0a65ec303e2a05eac8
new file mode 100644
index 0000000..032e076
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e72218971bac83f556e86b0a65ec303e2a05eac8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e73a05b1cf7dfeeada6356bb18ec4381485bb3d0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e73a05b1cf7dfeeada6356bb18ec4381485bb3d0
new file mode 100644
index 0000000..c32657f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e73a05b1cf7dfeeada6356bb18ec4381485bb3d0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e75fa90650f1d67ff9849024e88a91300690778c b/test/core/end2end/fuzzers/api_fuzzer_corpus/e75fa90650f1d67ff9849024e88a91300690778c
new file mode 100644
index 0000000..49790fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e75fa90650f1d67ff9849024e88a91300690778c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e79ffffd4bd565b2b5bb8d0f191c8e34385de085 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e79ffffd4bd565b2b5bb8d0f191c8e34385de085
new file mode 100644
index 0000000..9e6dbef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e79ffffd4bd565b2b5bb8d0f191c8e34385de085
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e8c24e95b095fee6053a49f51326479b60949424 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8c24e95b095fee6053a49f51326479b60949424
new file mode 100644
index 0000000..cbd97af
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8c24e95b095fee6053a49f51326479b60949424
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e8fd7c4270b5f2cb56fb06684858c39c7ccfa909 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8fd7c4270b5f2cb56fb06684858c39c7ccfa909
new file mode 100644
index 0000000..e2d0ca3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8fd7c4270b5f2cb56fb06684858c39c7ccfa909
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e921037de2e963b653e881fba095eeb33799d749 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e921037de2e963b653e881fba095eeb33799d749
new file mode 100644
index 0000000..cd03dcd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e921037de2e963b653e881fba095eeb33799d749
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ea2cf809383d8725bec1b44ab774f04b3e6d5ae5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea2cf809383d8725bec1b44ab774f04b3e6d5ae5
new file mode 100644
index 0000000..7c3ca90
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea2cf809383d8725bec1b44ab774f04b3e6d5ae5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ea351febbe2c4e73fb0e0d34e7d2a23ff46b79f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea351febbe2c4e73fb0e0d34e7d2a23ff46b79f4
new file mode 100644
index 0000000..28c93e6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea351febbe2c4e73fb0e0d34e7d2a23ff46b79f4
@@ -0,0 +1 @@
+S.
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ea6cc4b0a83ac8d578c4927f3c9d5a57a4464df3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea6cc4b0a83ac8d578c4927f3c9d5a57a4464df3
new file mode 100644
index 0000000..7b8a04e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea6cc4b0a83ac8d578c4927f3c9d5a57a4464df3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eb342f6fd92411d7beb1f82983a19849d45ff46f b/test/core/end2end/fuzzers/api_fuzzer_corpus/eb342f6fd92411d7beb1f82983a19849d45ff46f
new file mode 100644
index 0000000..b4298ca
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eb342f6fd92411d7beb1f82983a19849d45ff46f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eb9367a74ba61abe8d5f5fdb7c1c840b2d27dab7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/eb9367a74ba61abe8d5f5fdb7c1c840b2d27dab7
new file mode 100644
index 0000000..a1c7e56
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eb9367a74ba61abe8d5f5fdb7c1c840b2d27dab7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eb9faf5efb229c562a6825f930b8316f2aff2864 b/test/core/end2end/fuzzers/api_fuzzer_corpus/eb9faf5efb229c562a6825f930b8316f2aff2864
new file mode 100644
index 0000000..1592c16
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eb9faf5efb229c562a6825f930b8316f2aff2864
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ebbc2aa89ec745a7201eb4aa1aded15d35e4206c b/test/core/end2end/fuzzers/api_fuzzer_corpus/ebbc2aa89ec745a7201eb4aa1aded15d35e4206c
new file mode 100644
index 0000000..accca98
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ebbc2aa89ec745a7201eb4aa1aded15d35e4206c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ec012a94d14659f311451e89e757bd06a93d30b8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec012a94d14659f311451e89e757bd06a93d30b8
new file mode 100644
index 0000000..f4f01dd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec012a94d14659f311451e89e757bd06a93d30b8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eca1d41de5486c09c6aa7767289daa7185379220 b/test/core/end2end/fuzzers/api_fuzzer_corpus/eca1d41de5486c09c6aa7767289daa7185379220
new file mode 100644
index 0000000..dc9c483
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eca1d41de5486c09c6aa7767289daa7185379220
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ed9a1a597bad76e9ed9e52ba2e5c80304583c006 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed9a1a597bad76e9ed9e52ba2e5c80304583c006
new file mode 100644
index 0000000..fd2e76f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed9a1a597bad76e9ed9e52ba2e5c80304583c006
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eda5d435276e002a08358fd67a2bbd75902236a3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/eda5d435276e002a08358fd67a2bbd75902236a3
new file mode 100644
index 0000000..7cb7b45
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eda5d435276e002a08358fd67a2bbd75902236a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/edfcf299569efc4788937d2cd4ca0e625fb9e527 b/test/core/end2end/fuzzers/api_fuzzer_corpus/edfcf299569efc4788937d2cd4ca0e625fb9e527
new file mode 100644
index 0000000..cd303ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/edfcf299569efc4788937d2cd4ca0e625fb9e527
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef264406b5a2263cd7a9145f7ca68ed8fd6c50ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef264406b5a2263cd7a9145f7ca68ed8fd6c50ad
new file mode 100644
index 0000000..3a571ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef264406b5a2263cd7a9145f7ca68ed8fd6c50ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef4127bfbb6d1b7490a076c4af795b1e40b2bcd8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef4127bfbb6d1b7490a076c4af795b1e40b2bcd8
new file mode 100644
index 0000000..e34bbe8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef4127bfbb6d1b7490a076c4af795b1e40b2bcd8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef930a505edebc0ff6ca7eef7549bbaa21d95b4a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef930a505edebc0ff6ca7eef7549bbaa21d95b4a
new file mode 100644
index 0000000..c6c53a9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef930a505edebc0ff6ca7eef7549bbaa21d95b4a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/efa80ac7daa93de08fc91bdf2a912269a3f2396a b/test/core/end2end/fuzzers/api_fuzzer_corpus/efa80ac7daa93de08fc91bdf2a912269a3f2396a
new file mode 100644
index 0000000..6dfb6d0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/efa80ac7daa93de08fc91bdf2a912269a3f2396a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f0a7e39c194ee3f30312ae2f4827bdbd43416a42 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0a7e39c194ee3f30312ae2f4827bdbd43416a42
new file mode 100644
index 0000000..e791177
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0a7e39c194ee3f30312ae2f4827bdbd43416a42
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f0e8450c85a3c6dfaa50ee65399270c59a127088 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0e8450c85a3c6dfaa50ee65399270c59a127088
new file mode 100644
index 0000000..24aea11
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0e8450c85a3c6dfaa50ee65399270c59a127088
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f0ee077bc982be02a547d81d85e5c69e36fe38fc b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0ee077bc982be02a547d81d85e5c69e36fe38fc
new file mode 100644
index 0000000..ab8e5d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0ee077bc982be02a547d81d85e5c69e36fe38fc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f1a6421ddd077ba6971eee7ba1084ed66fd1bee3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1a6421ddd077ba6971eee7ba1084ed66fd1bee3
new file mode 100644
index 0000000..aef73bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1a6421ddd077ba6971eee7ba1084ed66fd1bee3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f1b592b7e1a5af83eea1bccc2d7bcca302173d57 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1b592b7e1a5af83eea1bccc2d7bcca302173d57
new file mode 100644
index 0000000..3a65338
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1b592b7e1a5af83eea1bccc2d7bcca302173d57
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f224ca8baea51bbc26a3814af9253483c66ad8f8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f224ca8baea51bbc26a3814af9253483c66ad8f8
new file mode 100644
index 0000000..98fb8a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f224ca8baea51bbc26a3814af9253483c66ad8f8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f238d0b5973d8d4081ba7036711d8c3091554e28 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f238d0b5973d8d4081ba7036711d8c3091554e28
new file mode 100644
index 0000000..eb03289
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f238d0b5973d8d4081ba7036711d8c3091554e28
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f2bb9fb90c0fb7dfd765e1c528330881e721c7d8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2bb9fb90c0fb7dfd765e1c528330881e721c7d8
new file mode 100644
index 0000000..e464d03
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2bb9fb90c0fb7dfd765e1c528330881e721c7d8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f37b108d4dca7cdd24f464ad880a57aa038528ae b/test/core/end2end/fuzzers/api_fuzzer_corpus/f37b108d4dca7cdd24f464ad880a57aa038528ae
new file mode 100644
index 0000000..72af822
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f37b108d4dca7cdd24f464ad880a57aa038528ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f3c0468b37c09b998096d18cd13a522dec09888b b/test/core/end2end/fuzzers/api_fuzzer_corpus/f3c0468b37c09b998096d18cd13a522dec09888b
new file mode 100644
index 0000000..bcc82a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f3c0468b37c09b998096d18cd13a522dec09888b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f47f636b8e22e8db428ea956d9336bd12b928a9e b/test/core/end2end/fuzzers/api_fuzzer_corpus/f47f636b8e22e8db428ea956d9336bd12b928a9e
new file mode 100644
index 0000000..75257d8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f47f636b8e22e8db428ea956d9336bd12b928a9e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f4d74d507a7171e5f116bf750a20435eeaf81f3f b/test/core/end2end/fuzzers/api_fuzzer_corpus/f4d74d507a7171e5f116bf750a20435eeaf81f3f
new file mode 100644
index 0000000..429971d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f4d74d507a7171e5f116bf750a20435eeaf81f3f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f4dc057d97c34f31ea542d67593b8d3a295bf52a b/test/core/end2end/fuzzers/api_fuzzer_corpus/f4dc057d97c34f31ea542d67593b8d3a295bf52a
new file mode 100644
index 0000000..f1b3ac7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f4dc057d97c34f31ea542d67593b8d3a295bf52a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f59e8ceab587254d408a4af86cd938d896eb0b6d b/test/core/end2end/fuzzers/api_fuzzer_corpus/f59e8ceab587254d408a4af86cd938d896eb0b6d
new file mode 100644
index 0000000..de01141
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f59e8ceab587254d408a4af86cd938d896eb0b6d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f65e41c8021049c4ca8782902de25d6791bae63a b/test/core/end2end/fuzzers/api_fuzzer_corpus/f65e41c8021049c4ca8782902de25d6791bae63a
new file mode 100644
index 0000000..2f0bb88
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f65e41c8021049c4ca8782902de25d6791bae63a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f693fbf860c6cd1090a6dc220c20eb5c51543208 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f693fbf860c6cd1090a6dc220c20eb5c51543208
new file mode 100644
index 0000000..a44ca0b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f693fbf860c6cd1090a6dc220c20eb5c51543208
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f71de0dac54e25fe658e8c78208b855d3f0db23c b/test/core/end2end/fuzzers/api_fuzzer_corpus/f71de0dac54e25fe658e8c78208b855d3f0db23c
new file mode 100644
index 0000000..37ef2a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f71de0dac54e25fe658e8c78208b855d3f0db23c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f73f63e243ea6484a97ece29bb8d4f33841410fc b/test/core/end2end/fuzzers/api_fuzzer_corpus/f73f63e243ea6484a97ece29bb8d4f33841410fc
new file mode 100644
index 0000000..3f5fd07
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f73f63e243ea6484a97ece29bb8d4f33841410fc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f788d2b893fe39fe24582acffa6a70f1ca4e3037 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f788d2b893fe39fe24582acffa6a70f1ca4e3037
new file mode 100644
index 0000000..53e0161
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f788d2b893fe39fe24582acffa6a70f1ca4e3037
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f7b309af25b6ae5029a9548142333a905e3c99be b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7b309af25b6ae5029a9548142333a905e3c99be
new file mode 100644
index 0000000..85b7650
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7b309af25b6ae5029a9548142333a905e3c99be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f7c45ab223810b0b6b77042055a86800e5ec213a b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7c45ab223810b0b6b77042055a86800e5ec213a
new file mode 100644
index 0000000..e0ffaae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7c45ab223810b0b6b77042055a86800e5ec213a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f7c686af20a3cf5b5c569a570656df83db3fe165 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7c686af20a3cf5b5c569a570656df83db3fe165
new file mode 100644
index 0000000..bebe30d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7c686af20a3cf5b5c569a570656df83db3fe165
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f8373fd74d8a4eafc7d015e2643c2a277656b716 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f8373fd74d8a4eafc7d015e2643c2a277656b716
new file mode 100644
index 0000000..8359f3a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f8373fd74d8a4eafc7d015e2643c2a277656b716
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f861e708b6d0e0ca691d88a31e73f3d2643deacd b/test/core/end2end/fuzzers/api_fuzzer_corpus/f861e708b6d0e0ca691d88a31e73f3d2643deacd
new file mode 100644
index 0000000..af6a83a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f861e708b6d0e0ca691d88a31e73f3d2643deacd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f8a02d7d9317428fd142c05f9428840d3d30aff4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f8a02d7d9317428fd142c05f9428840d3d30aff4
new file mode 100644
index 0000000..01e2f4e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f8a02d7d9317428fd142c05f9428840d3d30aff4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f91f27afa6e72fd653eb41b316ad2d2e88fc0bb7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f91f27afa6e72fd653eb41b316ad2d2e88fc0bb7
new file mode 100644
index 0000000..abf27f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f91f27afa6e72fd653eb41b316ad2d2e88fc0bb7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f9540ce65b08ec33d9157d03bf5231b767460d4a b/test/core/end2end/fuzzers/api_fuzzer_corpus/f9540ce65b08ec33d9157d03bf5231b767460d4a
new file mode 100644
index 0000000..e61833c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f9540ce65b08ec33d9157d03bf5231b767460d4a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f96f406763e8d6a53de319e67e942696cc10a4b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f96f406763e8d6a53de319e67e942696cc10a4b4
new file mode 100644
index 0000000..b99bc9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f96f406763e8d6a53de319e67e942696cc10a4b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f97d97545054500e8035ac3c73957d0f75b2715b b/test/core/end2end/fuzzers/api_fuzzer_corpus/f97d97545054500e8035ac3c73957d0f75b2715b
new file mode 100644
index 0000000..bf94981
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f97d97545054500e8035ac3c73957d0f75b2715b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fa423921deeaeda55d2ff74e9541e5d89ddc7d36 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa423921deeaeda55d2ff74e9541e5d89ddc7d36
new file mode 100644
index 0000000..dd7b2dd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa423921deeaeda55d2ff74e9541e5d89ddc7d36
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fa45cfbecd8680693570d90f214abd9febf681a6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa45cfbecd8680693570d90f214abd9febf681a6
new file mode 100644
index 0000000..6c2c0e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa45cfbecd8680693570d90f214abd9febf681a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fa99f1f9be3384be1229657b26374545228c2318 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa99f1f9be3384be1229657b26374545228c2318
new file mode 100644
index 0000000..6a5edea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa99f1f9be3384be1229657b26374545228c2318
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fae6e98220e0943926fe570bd32ea7f0dcd34feb b/test/core/end2end/fuzzers/api_fuzzer_corpus/fae6e98220e0943926fe570bd32ea7f0dcd34feb
new file mode 100644
index 0000000..02db763
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fae6e98220e0943926fe570bd32ea7f0dcd34feb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bfb049d4a99a529ff339218a5d962983118d0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bfb049d4a99a529ff339218a5d962983118d0
new file mode 100644
index 0000000..b1de1e2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bfb049d4a99a529ff339218a5d962983118d0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb9505e4511c982f4f26675979a138a3408d80e2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb9505e4511c982f4f26675979a138a3408d80e2
new file mode 100644
index 0000000..ff67372
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb9505e4511c982f4f26675979a138a3408d80e2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fc0cb8a6287528bfbe1e43d452fc40a180c221f2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc0cb8a6287528bfbe1e43d452fc40a180c221f2
new file mode 100644
index 0000000..c651ba4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc0cb8a6287528bfbe1e43d452fc40a180c221f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fc2bb278363a5f7d4dbfe8d123a8092a99d5a9f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc2bb278363a5f7d4dbfe8d123a8092a99d5a9f4
new file mode 100644
index 0000000..3b7c64d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc2bb278363a5f7d4dbfe8d123a8092a99d5a9f4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fc37856ff6d7a1cce83efad8cc7727f5aac44200 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc37856ff6d7a1cce83efad8cc7727f5aac44200
new file mode 100644
index 0000000..54fb727
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc37856ff6d7a1cce83efad8cc7727f5aac44200
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fc9879794ab7f7cdc4959c204788fce6146c0579 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc9879794ab7f7cdc4959c204788fce6146c0579
new file mode 100644
index 0000000..ff74700
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc9879794ab7f7cdc4959c204788fce6146c0579
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fda1618a9c7d2d7c22234b3c7f996116bc5e6e4b b/test/core/end2end/fuzzers/api_fuzzer_corpus/fda1618a9c7d2d7c22234b3c7f996116bc5e6e4b
new file mode 100644
index 0000000..38bf1ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fda1618a9c7d2d7c22234b3c7f996116bc5e6e4b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fe680903482b870b820690f61cc607e5d26a652a b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe680903482b870b820690f61cc607e5d26a652a
new file mode 100644
index 0000000..db3b2a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe680903482b870b820690f61cc607e5d26a652a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fef5208b90316cac47bdc95ffd384b9c9a8a7c78 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fef5208b90316cac47bdc95ffd384b9c9a8a7c78
new file mode 100644
index 0000000..064a200
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fef5208b90316cac47bdc95ffd384b9c9a8a7c78
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ff6138cc4a36bad9a76401072dbd41fd2ad437cc b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff6138cc4a36bad9a76401072dbd41fd2ad437cc
new file mode 100644
index 0000000..2bd5e02
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff6138cc4a36bad9a76401072dbd41fd2ad437cc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ffd263ba66c7dd7180f5b8e13a3f7b8bf169dd79 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ffd263ba66c7dd7180f5b8e13a3f7b8bf169dd79
new file mode 100644
index 0000000..af3f3f8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ffd263ba66c7dd7180f5b8e13a3f7b8bf169dd79
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-0fa0559576ad2a45b06d0bfb84115963d7d48206 b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-0fa0559576ad2a45b06d0bfb84115963d7d48206
new file mode 100644
index 0000000..8a2aa7d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-0fa0559576ad2a45b06d0bfb84115963d7d48206
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1
new file mode 100644
index 0000000..63ab352
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-e45753da8952c41715a65010250efba0a4a4d243 b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-e45753da8952c41715a65010250efba0a4a4d243
new file mode 100644
index 0000000..ad8031d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-e45753da8952c41715a65010250efba0a4a4d243
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f1536451f002afe7a6ff34a3755026e4ace1fee3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f1536451f002afe7a6ff34a3755026e4ace1fee3
new file mode 100644
index 0000000..74ce06a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f1536451f002afe7a6ff34a3755026e4ace1fee3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499 b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499
new file mode 100644
index 0000000..8475e63
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer.c b/test/core/end2end/fuzzers/client_fuzzer.c
new file mode 100644
index 0000000..afcf763
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer.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 <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/surface/channel.h"
+#include "test/core/util/memory_counters.h"
+#include "test/core/util/mock_endpoint.h"
+
+static const bool squelch = true;
+
+static void discard_write(gpr_slice slice) {}
+
+static void *tag(int n) { return (void *)(uintptr_t)n; }
+
+static void dont_log(gpr_log_func_args *args) {}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  grpc_test_only_set_metadata_hash_seed(0);
+  struct grpc_memory_counters counters;
+  if (squelch) gpr_set_log_function(dont_log);
+  grpc_memory_counters_init();
+  grpc_init();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  grpc_endpoint *mock_endpoint = grpc_mock_endpoint_create(discard_write);
+
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+  grpc_transport *transport =
+      grpc_create_chttp2_transport(&exec_ctx, NULL, mock_endpoint, 1);
+  grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0);
+
+  grpc_channel *channel = grpc_channel_create(
+      &exec_ctx, "test-target", NULL, GRPC_CLIENT_DIRECT_CHANNEL, transport);
+  grpc_call *call =
+      grpc_channel_create_call(channel, NULL, 0, cq, "/foo", "localhost",
+                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_byte_buffer *response_payload_recv = NULL;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_status_code status;
+  char *details = NULL;
+  size_t details_capacity = 0;
+
+  grpc_op ops[6];
+  grpc_op *op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_MESSAGE;
+  op->data.recv_message = &response_payload_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  grpc_call_error error =
+      grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(1), NULL);
+  int requested_calls = 1;
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  grpc_mock_endpoint_put_read(
+      &exec_ctx, mock_endpoint,
+      gpr_slice_from_copied_buffer((const char *)data, size));
+
+  grpc_event ev;
+  while (1) {
+    grpc_exec_ctx_flush(&exec_ctx);
+    ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
+    switch (ev.type) {
+      case GRPC_QUEUE_TIMEOUT:
+        goto done;
+      case GRPC_QUEUE_SHUTDOWN:
+        break;
+      case GRPC_OP_COMPLETE:
+        requested_calls--;
+        break;
+    }
+  }
+
+done:
+  if (requested_calls) {
+    grpc_call_cancel(call, NULL);
+  }
+  for (int i = 0; i < requested_calls; i++) {
+    ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
+    GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+  }
+  grpc_completion_queue_shutdown(cq);
+  for (int i = 0; i < requested_calls; i++) {
+    ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
+    GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN);
+  }
+  grpc_call_destroy(call);
+  grpc_completion_queue_destroy(cq);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  gpr_free(details);
+  grpc_channel_destroy(channel);
+  if (response_payload_recv != NULL) {
+    grpc_byte_buffer_destroy(response_payload_recv);
+  }
+  grpc_shutdown();
+  counters = grpc_memory_counters_snapshot();
+  grpc_memory_counters_destroy();
+  GPR_ASSERT(counters.total_size_relative == 0);
+  return 0;
+}
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/001946397b463a3562c5951f6325069d8a3a2ded b/test/core/end2end/fuzzers/client_fuzzer_corpus/001946397b463a3562c5951f6325069d8a3a2ded
new file mode 100644
index 0000000..59e6cda
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/001946397b463a3562c5951f6325069d8a3a2ded
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/00c8446b230bebbae2b473552b174a06b446337a b/test/core/end2end/fuzzers/client_fuzzer_corpus/00c8446b230bebbae2b473552b174a06b446337a
new file mode 100644
index 0000000..79ca915
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/00c8446b230bebbae2b473552b174a06b446337a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/01b05a9eaa95950f697627264bbd5006060f68e5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/01b05a9eaa95950f697627264bbd5006060f68e5
new file mode 100644
index 0000000..df36339
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/01b05a9eaa95950f697627264bbd5006060f68e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/01c9569f5835a576fc50ea03141662c7ef1aa088 b/test/core/end2end/fuzzers/client_fuzzer_corpus/01c9569f5835a576fc50ea03141662c7ef1aa088
new file mode 100644
index 0000000..dea2ff8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/01c9569f5835a576fc50ea03141662c7ef1aa088
@@ -0,0 +1 @@
+!‘!‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/025215e11687c7d2e0055e5b2b902d08e0436f78 b/test/core/end2end/fuzzers/client_fuzzer_corpus/025215e11687c7d2e0055e5b2b902d08e0436f78
new file mode 100644
index 0000000..bd442b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/025215e11687c7d2e0055e5b2b902d08e0436f78
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/02ba99615d1d69eb328adce99670f659959c1bc1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/02ba99615d1d69eb328adce99670f659959c1bc1
new file mode 100644
index 0000000..6eae44d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/02ba99615d1d69eb328adce99670f659959c1bc1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/03abf728ac1d833c2d4a9ff7e0c912b949edc04c b/test/core/end2end/fuzzers/client_fuzzer_corpus/03abf728ac1d833c2d4a9ff7e0c912b949edc04c
new file mode 100644
index 0000000..b5be432
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/03abf728ac1d833c2d4a9ff7e0c912b949edc04c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/03beeae554ed6952e94a0bf32cdbe9f97eb3ba43 b/test/core/end2end/fuzzers/client_fuzzer_corpus/03beeae554ed6952e94a0bf32cdbe9f97eb3ba43
new file mode 100644
index 0000000..58137ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/03beeae554ed6952e94a0bf32cdbe9f97eb3ba43
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/05b4eaa1e1a759aa6b23521c06d915174e8fec88 b/test/core/end2end/fuzzers/client_fuzzer_corpus/05b4eaa1e1a759aa6b23521c06d915174e8fec88
new file mode 100644
index 0000000..40fdd3a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/05b4eaa1e1a759aa6b23521c06d915174e8fec88
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/05cfa5deaead322efce84b710758a24440cef16e b/test/core/end2end/fuzzers/client_fuzzer_corpus/05cfa5deaead322efce84b710758a24440cef16e
new file mode 100644
index 0000000..4c0fd85
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/05cfa5deaead322efce84b710758a24440cef16e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/07048654244e377ddf246e8cc18f71443035cd2b b/test/core/end2end/fuzzers/client_fuzzer_corpus/07048654244e377ddf246e8cc18f71443035cd2b
new file mode 100644
index 0000000..142efb7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/07048654244e377ddf246e8cc18f71443035cd2b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/078232947d7ff25557e836b4e9e907214e99b320 b/test/core/end2end/fuzzers/client_fuzzer_corpus/078232947d7ff25557e836b4e9e907214e99b320
new file mode 100644
index 0000000..7c9c947
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/078232947d7ff25557e836b4e9e907214e99b320
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/08a8a647b6a8f47ae10852322d14832fc15021f1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/08a8a647b6a8f47ae10852322d14832fc15021f1
new file mode 100644
index 0000000..36f5a84
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/08a8a647b6a8f47ae10852322d14832fc15021f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0949f4ac376808482be6ab2dcb18a2ecb08d9a52 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0949f4ac376808482be6ab2dcb18a2ecb08d9a52
new file mode 100644
index 0000000..7de936a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0949f4ac376808482be6ab2dcb18a2ecb08d9a52
@@ -0,0 +1 @@
+!‘N
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0b6fa6330bce65dfe7f758bcbfca2a2844dd07a6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0b6fa6330bce65dfe7f758bcbfca2a2844dd07a6
new file mode 100644
index 0000000..a4cb1f9
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0b6fa6330bce65dfe7f758bcbfca2a2844dd07a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0c30868720d5e1a19ff23c53740749c37a43540d b/test/core/end2end/fuzzers/client_fuzzer_corpus/0c30868720d5e1a19ff23c53740749c37a43540d
new file mode 100644
index 0000000..e5a32af
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0c30868720d5e1a19ff23c53740749c37a43540d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0c5e0660ddf5f14af8f3fbcc754a967506994c9b b/test/core/end2end/fuzzers/client_fuzzer_corpus/0c5e0660ddf5f14af8f3fbcc754a967506994c9b
new file mode 100644
index 0000000..8ed6c6a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0c5e0660ddf5f14af8f3fbcc754a967506994c9b
@@ -0,0 +1 @@
+©¡‘N
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0d36da88698737ec1ca7b55b30fe2b2036de7e19 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0d36da88698737ec1ca7b55b30fe2b2036de7e19
new file mode 100644
index 0000000..d937ccc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0d36da88698737ec1ca7b55b30fe2b2036de7e19
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0d8c547f1d261ba07c2648bae009636c17709600 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0d8c547f1d261ba07c2648bae009636c17709600
new file mode 100644
index 0000000..07d6767
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0d8c547f1d261ba07c2648bae009636c17709600
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0dd33527db106a3e84172e8f2189734b00ced4ed b/test/core/end2end/fuzzers/client_fuzzer_corpus/0dd33527db106a3e84172e8f2189734b00ced4ed
new file mode 100644
index 0000000..dabf567
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0dd33527db106a3e84172e8f2189734b00ced4ed
@@ -0,0 +1 @@
+!mm!N!mmN•‘‘!‘m!‘NN'‘)‘‘•‘!‘m!‘NNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0e354d89d02c6c5cbba2f140dab7b609bf00793e b/test/core/end2end/fuzzers/client_fuzzer_corpus/0e354d89d02c6c5cbba2f140dab7b609bf00793e
new file mode 100644
index 0000000..66c69cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0e354d89d02c6c5cbba2f140dab7b609bf00793e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0e3a18f0f08dcb9dd174627bc997f74a5c7a1390 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0e3a18f0f08dcb9dd174627bc997f74a5c7a1390
new file mode 100644
index 0000000..f98c3a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0e3a18f0f08dcb9dd174627bc997f74a5c7a1390
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0f83cbec19c834f534f353f4fce20c0cd88231f5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0f83cbec19c834f534f353f4fce20c0cd88231f5
new file mode 100644
index 0000000..38e4714
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0f83cbec19c834f534f353f4fce20c0cd88231f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0f98d7d56e9a99b97e5dc7eb122ef22e9684077b b/test/core/end2end/fuzzers/client_fuzzer_corpus/0f98d7d56e9a99b97e5dc7eb122ef22e9684077b
new file mode 100644
index 0000000..3a55723
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0f98d7d56e9a99b97e5dc7eb122ef22e9684077b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0fd8859246740606c498755ab00d6147abcfec00 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0fd8859246740606c498755ab00d6147abcfec00
new file mode 100644
index 0000000..88c3f42
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0fd8859246740606c498755ab00d6147abcfec00
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/100bb8f2e6a0b41da13f4edb5c15d4a04e564840 b/test/core/end2end/fuzzers/client_fuzzer_corpus/100bb8f2e6a0b41da13f4edb5c15d4a04e564840
new file mode 100644
index 0000000..4e58e25
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/100bb8f2e6a0b41da13f4edb5c15d4a04e564840
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/101305ccd08c7a8bd0c2913c37d3dd0d39d4bb64 b/test/core/end2end/fuzzers/client_fuzzer_corpus/101305ccd08c7a8bd0c2913c37d3dd0d39d4bb64
new file mode 100644
index 0000000..b6e8b42
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/101305ccd08c7a8bd0c2913c37d3dd0d39d4bb64
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/10f5d1937cb068fee7f85e2654be2bfe77498bb9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/10f5d1937cb068fee7f85e2654be2bfe77498bb9
new file mode 100644
index 0000000..44932d7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/10f5d1937cb068fee7f85e2654be2bfe77498bb9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/110074f658208166d52897c9266fc46cbaa8af36 b/test/core/end2end/fuzzers/client_fuzzer_corpus/110074f658208166d52897c9266fc46cbaa8af36
new file mode 100644
index 0000000..a64e565
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/110074f658208166d52897c9266fc46cbaa8af36
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1160214cdb23e8fc187078a8d6796656c1ade925 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1160214cdb23e8fc187078a8d6796656c1ade925
new file mode 100644
index 0000000..cad5f5a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1160214cdb23e8fc187078a8d6796656c1ade925
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/118ffddb43ccf9dae8bdb4702232d1dc39b021f7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/118ffddb43ccf9dae8bdb4702232d1dc39b021f7
new file mode 100644
index 0000000..508f927
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/118ffddb43ccf9dae8bdb4702232d1dc39b021f7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1306c4c6ea714d4db0e4d814c944d8d40335e0fa b/test/core/end2end/fuzzers/client_fuzzer_corpus/1306c4c6ea714d4db0e4d814c944d8d40335e0fa
new file mode 100644
index 0000000..02aaaf9
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1306c4c6ea714d4db0e4d814c944d8d40335e0fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1402bbcac6fa24eeb0475250e33f704096e2fb45 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1402bbcac6fa24eeb0475250e33f704096e2fb45
new file mode 100644
index 0000000..9faa567
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1402bbcac6fa24eeb0475250e33f704096e2fb45
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/143e0d4f546bbb984a7c3ac1c60a37dcf85ea58d b/test/core/end2end/fuzzers/client_fuzzer_corpus/143e0d4f546bbb984a7c3ac1c60a37dcf85ea58d
new file mode 100644
index 0000000..8150470
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/143e0d4f546bbb984a7c3ac1c60a37dcf85ea58d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1576c915ee38f5bd19f285ed0ed47e36026518f2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1576c915ee38f5bd19f285ed0ed47e36026518f2
new file mode 100644
index 0000000..6150f0d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1576c915ee38f5bd19f285ed0ed47e36026518f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1602788cf33d0354d6d48ead549e5137cd211979 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1602788cf33d0354d6d48ead549e5137cd211979
new file mode 100644
index 0000000..57871eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1602788cf33d0354d6d48ead549e5137cd211979
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/17b1758fc7cd69a00d140f113b1ac894023ff20b b/test/core/end2end/fuzzers/client_fuzzer_corpus/17b1758fc7cd69a00d140f113b1ac894023ff20b
new file mode 100644
index 0000000..e9781cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/17b1758fc7cd69a00d140f113b1ac894023ff20b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/18185cbf9e9cfc1fd28d27ed0d651d7cee6a2c06 b/test/core/end2end/fuzzers/client_fuzzer_corpus/18185cbf9e9cfc1fd28d27ed0d651d7cee6a2c06
new file mode 100644
index 0000000..8471523
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/18185cbf9e9cfc1fd28d27ed0d651d7cee6a2c06
@@ -0,0 +1,2 @@
+!mm!N!mmÿ!m)m!‘‘N!‘‘Nð‘NN)‘
+‘a‘‘‘‘NNN•‘‘!‘m!)‘‘'NN‘‘•‘!‘Nm!N‘NNNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1875a4acdcffe505ca92ea8af8d9d6b174736e80 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1875a4acdcffe505ca92ea8af8d9d6b174736e80
new file mode 100644
index 0000000..9c35e25
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1875a4acdcffe505ca92ea8af8d9d6b174736e80
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/18850965807039500c7f5450a907e86825cf823d b/test/core/end2end/fuzzers/client_fuzzer_corpus/18850965807039500c7f5450a907e86825cf823d
new file mode 100644
index 0000000..3be28b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/18850965807039500c7f5450a907e86825cf823d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/18926cdc608599e8df6b0f4df99d4ad856ef4373 b/test/core/end2end/fuzzers/client_fuzzer_corpus/18926cdc608599e8df6b0f4df99d4ad856ef4373
new file mode 100644
index 0000000..25b94ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/18926cdc608599e8df6b0f4df99d4ad856ef4373
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1965cd58fc41578a837231c69075994da2e871d9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1965cd58fc41578a837231c69075994da2e871d9
new file mode 100644
index 0000000..9607361
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1965cd58fc41578a837231c69075994da2e871d9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/19e984af62c36fe982284c87421d8ee46173e9f0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/19e984af62c36fe982284c87421d8ee46173e9f0
new file mode 100644
index 0000000..b3e88e0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/19e984af62c36fe982284c87421d8ee46173e9f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1aee32faadffa3c2ec508e8fd30006423665488f b/test/core/end2end/fuzzers/client_fuzzer_corpus/1aee32faadffa3c2ec508e8fd30006423665488f
new file mode 100644
index 0000000..a70fff3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1aee32faadffa3c2ec508e8fd30006423665488f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1ba08b63181066ffab948eb301a6a2363a81872d b/test/core/end2end/fuzzers/client_fuzzer_corpus/1ba08b63181066ffab948eb301a6a2363a81872d
new file mode 100644
index 0000000..5b0a1b6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1ba08b63181066ffab948eb301a6a2363a81872d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1c222dae4e2cde1fca9f9bf6226200f70d625342 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1c222dae4e2cde1fca9f9bf6226200f70d625342
new file mode 100644
index 0000000..be79f96
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1c222dae4e2cde1fca9f9bf6226200f70d625342
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1ca51ab2fefef4f549c4a8e7f4910c6b5a4b4b1d b/test/core/end2end/fuzzers/client_fuzzer_corpus/1ca51ab2fefef4f549c4a8e7f4910c6b5a4b4b1d
new file mode 100644
index 0000000..5763104
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1ca51ab2fefef4f549c4a8e7f4910c6b5a4b4b1d
@@ -0,0 +1 @@
+!më¢!ÿÿÿÿÿÿÿ…
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1cbcaad71950c62d41bab50f9c242d014cc0d904 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1cbcaad71950c62d41bab50f9c242d014cc0d904
new file mode 100644
index 0000000..e56a789
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1cbcaad71950c62d41bab50f9c242d014cc0d904
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1d19042e6db2a90c52fcc3cb0aa76f2fd335014e b/test/core/end2end/fuzzers/client_fuzzer_corpus/1d19042e6db2a90c52fcc3cb0aa76f2fd335014e
new file mode 100644
index 0000000..61bd026
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1d19042e6db2a90c52fcc3cb0aa76f2fd335014e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1d458954e8174bbb5dd4d0053df47d6b7adf290a b/test/core/end2end/fuzzers/client_fuzzer_corpus/1d458954e8174bbb5dd4d0053df47d6b7adf290a
new file mode 100644
index 0000000..5580d48
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1d458954e8174bbb5dd4d0053df47d6b7adf290a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1dc86d0febe4adc5353230cea24b5f7cce829283 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1dc86d0febe4adc5353230cea24b5f7cce829283
new file mode 100644
index 0000000..3ea63ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1dc86d0febe4adc5353230cea24b5f7cce829283
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1e84d42fcf18bbf81ef6e8a16a0c57abbf8d292a b/test/core/end2end/fuzzers/client_fuzzer_corpus/1e84d42fcf18bbf81ef6e8a16a0c57abbf8d292a
new file mode 100644
index 0000000..995af89
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1e84d42fcf18bbf81ef6e8a16a0c57abbf8d292a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1f040e756f76357979f317e0c6541f72fd93df06 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1f040e756f76357979f317e0c6541f72fd93df06
new file mode 100644
index 0000000..0a2a1b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1f040e756f76357979f317e0c6541f72fd93df06
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1fe7d16ffc2084d5d3c5f23d16902ae8810a5393 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1fe7d16ffc2084d5d3c5f23d16902ae8810a5393
new file mode 100644
index 0000000..f57b0dd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1fe7d16ffc2084d5d3c5f23d16902ae8810a5393
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1ffc4952225dda41de59603e487ff7fd3026b958 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1ffc4952225dda41de59603e487ff7fd3026b958
new file mode 100644
index 0000000..7e89b67
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1ffc4952225dda41de59603e487ff7fd3026b958
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/20216d27af2b3dcc83d944e5f7a489ed2eff98fd b/test/core/end2end/fuzzers/client_fuzzer_corpus/20216d27af2b3dcc83d944e5f7a489ed2eff98fd
new file mode 100644
index 0000000..f79cdf2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/20216d27af2b3dcc83d944e5f7a489ed2eff98fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/204093594b568ada9c7857a971f2a4b42123ee1c b/test/core/end2end/fuzzers/client_fuzzer_corpus/204093594b568ada9c7857a971f2a4b42123ee1c
new file mode 100644
index 0000000..662e18e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/204093594b568ada9c7857a971f2a4b42123ee1c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/20539e464ced1a0a63d74bae731ca0a75db05967 b/test/core/end2end/fuzzers/client_fuzzer_corpus/20539e464ced1a0a63d74bae731ca0a75db05967
new file mode 100644
index 0000000..c3a9708
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/20539e464ced1a0a63d74bae731ca0a75db05967
@@ -0,0 +1 @@
+!mm	‘•N!‘‘NÿN'‘)‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/205cf2b6994f10b783aa0a06938a5e47cb581126 b/test/core/end2end/fuzzers/client_fuzzer_corpus/205cf2b6994f10b783aa0a06938a5e47cb581126
new file mode 100644
index 0000000..eafa9e1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/205cf2b6994f10b783aa0a06938a5e47cb581126
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/207e12d6a84dc8fa020b3a60b3f75932ca4f8fa5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/207e12d6a84dc8fa020b3a60b3f75932ca4f8fa5
new file mode 100644
index 0000000..1bbeccf
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/207e12d6a84dc8fa020b3a60b3f75932ca4f8fa5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/20ea73876cc9cd5b3d3efa1bda21deb5eac2d61e b/test/core/end2end/fuzzers/client_fuzzer_corpus/20ea73876cc9cd5b3d3efa1bda21deb5eac2d61e
new file mode 100644
index 0000000..9d59b19
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/20ea73876cc9cd5b3d3efa1bda21deb5eac2d61e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2166c7093c424a2136c4cb8b10d0b124047320d4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2166c7093c424a2136c4cb8b10d0b124047320d4
new file mode 100644
index 0000000..96ca5f7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2166c7093c424a2136c4cb8b10d0b124047320d4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/21a6a133f3d1e06c077032ba56a7df4161f62efe b/test/core/end2end/fuzzers/client_fuzzer_corpus/21a6a133f3d1e06c077032ba56a7df4161f62efe
new file mode 100644
index 0000000..e40f8e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/21a6a133f3d1e06c077032ba56a7df4161f62efe
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/224fa2e83fd8ecaa9059ad37a55238f74b8e0829 b/test/core/end2end/fuzzers/client_fuzzer_corpus/224fa2e83fd8ecaa9059ad37a55238f74b8e0829
new file mode 100644
index 0000000..0b48765
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/224fa2e83fd8ecaa9059ad37a55238f74b8e0829
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/230527b90b0179139c961aca426187893191fdf2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/230527b90b0179139c961aca426187893191fdf2
new file mode 100644
index 0000000..ed08b10
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/230527b90b0179139c961aca426187893191fdf2
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2467fa0f8a9f4bd121f544892f0782498b2df533 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2467fa0f8a9f4bd121f544892f0782498b2df533
new file mode 100644
index 0000000..0ee6efa
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2467fa0f8a9f4bd121f544892f0782498b2df533
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/246dcf347eba7f4d4e04d97dabc002f0acf2164e b/test/core/end2end/fuzzers/client_fuzzer_corpus/246dcf347eba7f4d4e04d97dabc002f0acf2164e
new file mode 100644
index 0000000..eb01953
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/246dcf347eba7f4d4e04d97dabc002f0acf2164e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/252de25a5237c830ad8c5e4732c176e03785042b b/test/core/end2end/fuzzers/client_fuzzer_corpus/252de25a5237c830ad8c5e4732c176e03785042b
new file mode 100644
index 0000000..df34cf3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/252de25a5237c830ad8c5e4732c176e03785042b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/25761748660a64111a8daa46f72ea1f336c2046a b/test/core/end2end/fuzzers/client_fuzzer_corpus/25761748660a64111a8daa46f72ea1f336c2046a
new file mode 100644
index 0000000..601df6f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/25761748660a64111a8daa46f72ea1f336c2046a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2585dc7b6c095e978b56e0249fe9b5c61a4840af b/test/core/end2end/fuzzers/client_fuzzer_corpus/2585dc7b6c095e978b56e0249fe9b5c61a4840af
new file mode 100644
index 0000000..c730530
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2585dc7b6c095e978b56e0249fe9b5c61a4840af
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/25949b623930511f9d43fea4aa56a4389a28e11a b/test/core/end2end/fuzzers/client_fuzzer_corpus/25949b623930511f9d43fea4aa56a4389a28e11a
new file mode 100644
index 0000000..012afab
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/25949b623930511f9d43fea4aa56a4389a28e11a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/26110f21dcb0fde99942e631366ebbd9d895860d b/test/core/end2end/fuzzers/client_fuzzer_corpus/26110f21dcb0fde99942e631366ebbd9d895860d
new file mode 100644
index 0000000..ffa8aca
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/26110f21dcb0fde99942e631366ebbd9d895860d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2663ce44ca5832381cbbdf7b252e39d6df021a93 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2663ce44ca5832381cbbdf7b252e39d6df021a93
new file mode 100644
index 0000000..821e28a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2663ce44ca5832381cbbdf7b252e39d6df021a93
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/269afce3bfff993c05c2a3b28c6cf3dfb3f461d7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/269afce3bfff993c05c2a3b28c6cf3dfb3f461d7
new file mode 100644
index 0000000..b686adb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/269afce3bfff993c05c2a3b28c6cf3dfb3f461d7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/26b8a9d27cef1ce4c3c5aefa2dee50001aab4b13 b/test/core/end2end/fuzzers/client_fuzzer_corpus/26b8a9d27cef1ce4c3c5aefa2dee50001aab4b13
new file mode 100644
index 0000000..6b4108b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/26b8a9d27cef1ce4c3c5aefa2dee50001aab4b13
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/27f37037525aac7a41ffbadd6ce52e5a1851a2b7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/27f37037525aac7a41ffbadd6ce52e5a1851a2b7
new file mode 100644
index 0000000..8ee3910
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/27f37037525aac7a41ffbadd6ce52e5a1851a2b7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/289cdf83f89f70a13e9078259f764a339617c827 b/test/core/end2end/fuzzers/client_fuzzer_corpus/289cdf83f89f70a13e9078259f764a339617c827
new file mode 100644
index 0000000..9a4560c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/289cdf83f89f70a13e9078259f764a339617c827
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/28ee8cae75efa07da9649933a9482d00643b5395 b/test/core/end2end/fuzzers/client_fuzzer_corpus/28ee8cae75efa07da9649933a9482d00643b5395
new file mode 100644
index 0000000..66a1990
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/28ee8cae75efa07da9649933a9482d00643b5395
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/299034b9e0cc8d91c049c489dca6d1a2b8b08959 b/test/core/end2end/fuzzers/client_fuzzer_corpus/299034b9e0cc8d91c049c489dca6d1a2b8b08959
new file mode 100644
index 0000000..0e3f61e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/299034b9e0cc8d91c049c489dca6d1a2b8b08959
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/29952a15459cce9c647255ab5d7486df0507eff4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/29952a15459cce9c647255ab5d7486df0507eff4
new file mode 100644
index 0000000..5a8c024
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/29952a15459cce9c647255ab5d7486df0507eff4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/299faa82b90ef12421d160148dfb6cd0077b57c0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/299faa82b90ef12421d160148dfb6cd0077b57c0
new file mode 100644
index 0000000..7dc85b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/299faa82b90ef12421d160148dfb6cd0077b57c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/29be7d33920998bae7329d77d4c81989eae91647 b/test/core/end2end/fuzzers/client_fuzzer_corpus/29be7d33920998bae7329d77d4c81989eae91647
new file mode 100644
index 0000000..73ca084
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/29be7d33920998bae7329d77d4c81989eae91647
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2a8260b23460f90f770cedcafa14868d24db201e b/test/core/end2end/fuzzers/client_fuzzer_corpus/2a8260b23460f90f770cedcafa14868d24db201e
new file mode 100644
index 0000000..555d059
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2a8260b23460f90f770cedcafa14868d24db201e
@@ -0,0 +1,2 @@
+!mm!N!mm!m)m!‘‘N!‘‘Nð‘NN)‘
+‘a‘‘‘‘NNN•‘‘!‘m!)‘‘'NN‘‘•‘!‘Nm!N‘NNNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2b230a7b55b17f2f8e89c4be73a662d781f7fb3c b/test/core/end2end/fuzzers/client_fuzzer_corpus/2b230a7b55b17f2f8e89c4be73a662d781f7fb3c
new file mode 100644
index 0000000..993dfb2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2b230a7b55b17f2f8e89c4be73a662d781f7fb3c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2b71439e9ebf611a92386b9f21ad44bde7926184 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2b71439e9ebf611a92386b9f21ad44bde7926184
new file mode 100644
index 0000000..f2e5d1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2b71439e9ebf611a92386b9f21ad44bde7926184
@@ -0,0 +1,2 @@
+!mm!N1mm!m)m!‘‘N!‘‘Nð‘NN)‘
+‘a‘‘‘‘NNN•‘‘!‘m!‘‘‘N'N‘•‘!‘mNN!‘NNN‘NNN'Ñ)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2c342f8715556398d49bcf3343b5a249d968e19e b/test/core/end2end/fuzzers/client_fuzzer_corpus/2c342f8715556398d49bcf3343b5a249d968e19e
new file mode 100644
index 0000000..5514236
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2c342f8715556398d49bcf3343b5a249d968e19e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2c6e69067c68c145dc5d3a60b86d8081fdf95d0d b/test/core/end2end/fuzzers/client_fuzzer_corpus/2c6e69067c68c145dc5d3a60b86d8081fdf95d0d
new file mode 100644
index 0000000..bebbd9c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2c6e69067c68c145dc5d3a60b86d8081fdf95d0d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2c79128c697b53256c56b9c57c7259866e0e2347 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2c79128c697b53256c56b9c57c7259866e0e2347
new file mode 100644
index 0000000..c0fc6eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2c79128c697b53256c56b9c57c7259866e0e2347
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2d83097b3cbd2245b085e749fe923fb590790e0c b/test/core/end2end/fuzzers/client_fuzzer_corpus/2d83097b3cbd2245b085e749fe923fb590790e0c
new file mode 100644
index 0000000..060316e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2d83097b3cbd2245b085e749fe923fb590790e0c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2dce4a1fc4bb00bfcd43d549a3785913c9280369 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2dce4a1fc4bb00bfcd43d549a3785913c9280369
new file mode 100644
index 0000000..e113d82
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2dce4a1fc4bb00bfcd43d549a3785913c9280369
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2deb1aeb93c2abca4177b1fe886eb354c83fe8af b/test/core/end2end/fuzzers/client_fuzzer_corpus/2deb1aeb93c2abca4177b1fe886eb354c83fe8af
new file mode 100644
index 0000000..138d1c6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2deb1aeb93c2abca4177b1fe886eb354c83fe8af
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2e9860242d55a74cec244bb5c5445eb2797a3157 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2e9860242d55a74cec244bb5c5445eb2797a3157
new file mode 100644
index 0000000..d6c36d0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2e9860242d55a74cec244bb5c5445eb2797a3157
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2f288409c5f3cf2a10b3e1970a9c3d037dabe080 b/test/core/end2end/fuzzers/client_fuzzer_corpus/2f288409c5f3cf2a10b3e1970a9c3d037dabe080
new file mode 100644
index 0000000..483cfb0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2f288409c5f3cf2a10b3e1970a9c3d037dabe080
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2f5f6d281a3d0473a04a17cbcbc6fd06cb73fd8b b/test/core/end2end/fuzzers/client_fuzzer_corpus/2f5f6d281a3d0473a04a17cbcbc6fd06cb73fd8b
new file mode 100644
index 0000000..bb39004
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2f5f6d281a3d0473a04a17cbcbc6fd06cb73fd8b
@@ -0,0 +1,2 @@
+!mm!N!mmÿÿ!m)m!‘‘N!‘±Nð‘NN)‘
+‘a‘‘‘‘NNN•‘‘!‘m!)‘‘'NN‘‘)•‘!‘Nm!N‘NJNN‘NNN–'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/301e10bb6d9f60d91efde4e0c48893203a5b8b88 b/test/core/end2end/fuzzers/client_fuzzer_corpus/301e10bb6d9f60d91efde4e0c48893203a5b8b88
new file mode 100644
index 0000000..348e748
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/301e10bb6d9f60d91efde4e0c48893203a5b8b88
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/302a11eb9b9687464b88c9a670da371f6a6c57e7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/302a11eb9b9687464b88c9a670da371f6a6c57e7
new file mode 100644
index 0000000..c9c0d2a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/302a11eb9b9687464b88c9a670da371f6a6c57e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3128887b8e02f1873ed6b36766a870543269ea00 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3128887b8e02f1873ed6b36766a870543269ea00
new file mode 100644
index 0000000..e87a1eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3128887b8e02f1873ed6b36766a870543269ea00
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/31545e9fe4c6aa43329dc0d4a735842574fcaaed b/test/core/end2end/fuzzers/client_fuzzer_corpus/31545e9fe4c6aa43329dc0d4a735842574fcaaed
new file mode 100644
index 0000000..a505a18
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/31545e9fe4c6aa43329dc0d4a735842574fcaaed
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/31d12a2b1378120d15b4097371d792daa95de0a9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/31d12a2b1378120d15b4097371d792daa95de0a9
new file mode 100644
index 0000000..df0ca43
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/31d12a2b1378120d15b4097371d792daa95de0a9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/320dc10f64b59b0eb0ae140912eded1ef9276556 b/test/core/end2end/fuzzers/client_fuzzer_corpus/320dc10f64b59b0eb0ae140912eded1ef9276556
new file mode 100644
index 0000000..e9fd16b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/320dc10f64b59b0eb0ae140912eded1ef9276556
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3336748264594689041e4080b51bc56f716d0689 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3336748264594689041e4080b51bc56f716d0689
new file mode 100644
index 0000000..d3eb5f7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3336748264594689041e4080b51bc56f716d0689
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/333d0554d91872e693d118d6988132d95b7920ae b/test/core/end2end/fuzzers/client_fuzzer_corpus/333d0554d91872e693d118d6988132d95b7920ae
new file mode 100644
index 0000000..ab9e141
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/333d0554d91872e693d118d6988132d95b7920ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/337d579ab5eb157d7d58e9287d447976062cbd8d b/test/core/end2end/fuzzers/client_fuzzer_corpus/337d579ab5eb157d7d58e9287d447976062cbd8d
new file mode 100644
index 0000000..1916f48
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/337d579ab5eb157d7d58e9287d447976062cbd8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/33c32a80db0ec311ee8744991c5b19345bfd8fe9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/33c32a80db0ec311ee8744991c5b19345bfd8fe9
new file mode 100644
index 0000000..13620b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/33c32a80db0ec311ee8744991c5b19345bfd8fe9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/35fbd748458e3fd6068957d46a9fbb2b0113d2b3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/35fbd748458e3fd6068957d46a9fbb2b0113d2b3
new file mode 100644
index 0000000..055866f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/35fbd748458e3fd6068957d46a9fbb2b0113d2b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/361c6f4374443671f039fd9659577e4460178020 b/test/core/end2end/fuzzers/client_fuzzer_corpus/361c6f4374443671f039fd9659577e4460178020
new file mode 100644
index 0000000..392bf57
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/361c6f4374443671f039fd9659577e4460178020
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/368c75135a7341a96627d0dcfc4b2081003d8979 b/test/core/end2end/fuzzers/client_fuzzer_corpus/368c75135a7341a96627d0dcfc4b2081003d8979
new file mode 100644
index 0000000..848ea7a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/368c75135a7341a96627d0dcfc4b2081003d8979
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/370b2c16cc353621091eda4964d4c4329205ffc3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/370b2c16cc353621091eda4964d4c4329205ffc3
new file mode 100644
index 0000000..78c4355
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/370b2c16cc353621091eda4964d4c4329205ffc3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/370f893353f792c99754ece93baed2105decd71e b/test/core/end2end/fuzzers/client_fuzzer_corpus/370f893353f792c99754ece93baed2105decd71e
new file mode 100644
index 0000000..8ee78b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/370f893353f792c99754ece93baed2105decd71e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/375c2462d6ae891222686f9519294811fa5de010 b/test/core/end2end/fuzzers/client_fuzzer_corpus/375c2462d6ae891222686f9519294811fa5de010
new file mode 100644
index 0000000..ae1b3af
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/375c2462d6ae891222686f9519294811fa5de010
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/379b177d55b1eb86ddb66dc3a037fd8283ee07c0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/379b177d55b1eb86ddb66dc3a037fd8283ee07c0
new file mode 100644
index 0000000..dcd7e64
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/379b177d55b1eb86ddb66dc3a037fd8283ee07c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3a01c85934363bd2067f76d0d40c491f9f846c8a b/test/core/end2end/fuzzers/client_fuzzer_corpus/3a01c85934363bd2067f76d0d40c491f9f846c8a
new file mode 100644
index 0000000..a90b8c9
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3a01c85934363bd2067f76d0d40c491f9f846c8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3a3eb65d51f30f4cd16cc6f8436a5b00702a5712 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3a3eb65d51f30f4cd16cc6f8436a5b00702a5712
new file mode 100644
index 0000000..2de9edb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3a3eb65d51f30f4cd16cc6f8436a5b00702a5712
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3ae87e3150628c422ada13002b08f2d9c5a9d78e b/test/core/end2end/fuzzers/client_fuzzer_corpus/3ae87e3150628c422ada13002b08f2d9c5a9d78e
new file mode 100644
index 0000000..41c0a26
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3ae87e3150628c422ada13002b08f2d9c5a9d78e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3afbc4c35885b79c6e6628afce93ce852d7767de b/test/core/end2end/fuzzers/client_fuzzer_corpus/3afbc4c35885b79c6e6628afce93ce852d7767de
new file mode 100644
index 0000000..dc4fde7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3afbc4c35885b79c6e6628afce93ce852d7767de
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3b3b4f9a985ec49f6c54bae798208625e5adb777 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3b3b4f9a985ec49f6c54bae798208625e5adb777
new file mode 100644
index 0000000..eb373a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3b3b4f9a985ec49f6c54bae798208625e5adb777
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3c7b516e302ad3503a933b5dcfb8c58acaea07a0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3c7b516e302ad3503a933b5dcfb8c58acaea07a0
new file mode 100644
index 0000000..201dc65
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3c7b516e302ad3503a933b5dcfb8c58acaea07a0
@@ -0,0 +1,2 @@
+!mm!mm!N•‘‘‘m!‘NN'‘)*‘‘•‘‘!‘m!‘NNN‘N!m)m!‘‘N!‘‘Nð‘NN)‘NN'‘)‘‘N
+‘a‘‘N‘‘‘NNNNNNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3d4d961511c1de95a81b129f2fe96390209de2e7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3d4d961511c1de95a81b129f2fe96390209de2e7
new file mode 100644
index 0000000..010625a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3d4d961511c1de95a81b129f2fe96390209de2e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3da7577acd806e1d92d48211b22fd9db352fd834 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3da7577acd806e1d92d48211b22fd9db352fd834
new file mode 100644
index 0000000..07bc85e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3da7577acd806e1d92d48211b22fd9db352fd834
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3e8f531043a07df2280bca73fe4a7987d82ce67e b/test/core/end2end/fuzzers/client_fuzzer_corpus/3e8f531043a07df2280bca73fe4a7987d82ce67e
new file mode 100644
index 0000000..c420a78
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3e8f531043a07df2280bca73fe4a7987d82ce67e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3fcc2da89f438b247cb5b4b41e15aceccfa75b36 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3fcc2da89f438b247cb5b4b41e15aceccfa75b36
new file mode 100644
index 0000000..3adb095
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3fcc2da89f438b247cb5b4b41e15aceccfa75b36
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4040224f3df361afe45bce682d56d26f13829413 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4040224f3df361afe45bce682d56d26f13829413
new file mode 100644
index 0000000..19b2c4e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4040224f3df361afe45bce682d56d26f13829413
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/41aad2f11a7ab418213352e84de872d9997db8d2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/41aad2f11a7ab418213352e84de872d9997db8d2
new file mode 100644
index 0000000..5881707
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/41aad2f11a7ab418213352e84de872d9997db8d2
@@ -0,0 +1 @@
+!‘!!‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/41b499e86caed7b48c59aaaf51360c3c71029400 b/test/core/end2end/fuzzers/client_fuzzer_corpus/41b499e86caed7b48c59aaaf51360c3c71029400
new file mode 100644
index 0000000..4684d27
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/41b499e86caed7b48c59aaaf51360c3c71029400
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/42554ddbe59429d30d718282ca606ed8b5a90eb3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/42554ddbe59429d30d718282ca606ed8b5a90eb3
new file mode 100644
index 0000000..467ae54
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/42554ddbe59429d30d718282ca606ed8b5a90eb3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/42c395ab373346fb283ace021bdc1f6428f92f80 b/test/core/end2end/fuzzers/client_fuzzer_corpus/42c395ab373346fb283ace021bdc1f6428f92f80
new file mode 100644
index 0000000..35e2498
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/42c395ab373346fb283ace021bdc1f6428f92f80
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/43202ad9b1a689d919ab9ae91c2d0223394867bf b/test/core/end2end/fuzzers/client_fuzzer_corpus/43202ad9b1a689d919ab9ae91c2d0223394867bf
new file mode 100644
index 0000000..bf0590c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/43202ad9b1a689d919ab9ae91c2d0223394867bf
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/438789ebe8a5d676f6f03ef8329c3d77579aeba4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/438789ebe8a5d676f6f03ef8329c3d77579aeba4
new file mode 100644
index 0000000..efce713
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/438789ebe8a5d676f6f03ef8329c3d77579aeba4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/44153f8b7af5a3b27625a46af89e1712daa3ae8a b/test/core/end2end/fuzzers/client_fuzzer_corpus/44153f8b7af5a3b27625a46af89e1712daa3ae8a
new file mode 100644
index 0000000..6a24eac
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/44153f8b7af5a3b27625a46af89e1712daa3ae8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/44d64196fb2e8d9506734a81304f6ef17b9bc29d b/test/core/end2end/fuzzers/client_fuzzer_corpus/44d64196fb2e8d9506734a81304f6ef17b9bc29d
new file mode 100644
index 0000000..30cd52c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/44d64196fb2e8d9506734a81304f6ef17b9bc29d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/44f0973ec77d6fb9eac931e84fa7ec6fdadccca6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/44f0973ec77d6fb9eac931e84fa7ec6fdadccca6
new file mode 100644
index 0000000..0e7c5a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/44f0973ec77d6fb9eac931e84fa7ec6fdadccca6
@@ -0,0 +1,2 @@
+!mm!N!mm!m)m!‘‘N!‘‘Nð‘NN)‘
+‘a‘‘‘‘NNN•‘‘!‘m!)‘‘'NN‘‘•‘!‘mNNN!‘NNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/450f9f56c80c8b71e37302a254ba7c3f7298dfd7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/450f9f56c80c8b71e37302a254ba7c3f7298dfd7
new file mode 100644
index 0000000..1902e24
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/450f9f56c80c8b71e37302a254ba7c3f7298dfd7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/451e69ab65e0fe0a5731622ed21ab2b5380df677 b/test/core/end2end/fuzzers/client_fuzzer_corpus/451e69ab65e0fe0a5731622ed21ab2b5380df677
new file mode 100644
index 0000000..c570c2b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/451e69ab65e0fe0a5731622ed21ab2b5380df677
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/46dcb1c399e5a514267fbbd5a50939f34e0ad6be b/test/core/end2end/fuzzers/client_fuzzer_corpus/46dcb1c399e5a514267fbbd5a50939f34e0ad6be
new file mode 100644
index 0000000..a67eac7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/46dcb1c399e5a514267fbbd5a50939f34e0ad6be
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/47e8aee44c2c7bd870f15b50fc085c5a8030edfc b/test/core/end2end/fuzzers/client_fuzzer_corpus/47e8aee44c2c7bd870f15b50fc085c5a8030edfc
new file mode 100644
index 0000000..765edbc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/47e8aee44c2c7bd870f15b50fc085c5a8030edfc
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/489e9830136adcc53f4b191199c33504685b3737 b/test/core/end2end/fuzzers/client_fuzzer_corpus/489e9830136adcc53f4b191199c33504685b3737
new file mode 100644
index 0000000..e11ab1f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/489e9830136adcc53f4b191199c33504685b3737
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/49112bf1277d93601eb6526fe9ee9d45864d759e b/test/core/end2end/fuzzers/client_fuzzer_corpus/49112bf1277d93601eb6526fe9ee9d45864d759e
new file mode 100644
index 0000000..35f970e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/49112bf1277d93601eb6526fe9ee9d45864d759e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4a11af9ef42aeb36691185520be281c4760ad27b b/test/core/end2end/fuzzers/client_fuzzer_corpus/4a11af9ef42aeb36691185520be281c4760ad27b
new file mode 100644
index 0000000..19db996
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4a11af9ef42aeb36691185520be281c4760ad27b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4a4553c2e939cd50981bc38e8ddb1f2109ddb3a4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4a4553c2e939cd50981bc38e8ddb1f2109ddb3a4
new file mode 100644
index 0000000..ba96c64
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4a4553c2e939cd50981bc38e8ddb1f2109ddb3a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4b2ce115b15082ed951f4dc0b432da6a9d37bf85 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4b2ce115b15082ed951f4dc0b432da6a9d37bf85
new file mode 100644
index 0000000..8f36f3c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4b2ce115b15082ed951f4dc0b432da6a9d37bf85
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4b585eb75ebca2187c0aa5a6abe4c8125aa80127 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4b585eb75ebca2187c0aa5a6abe4c8125aa80127
new file mode 100644
index 0000000..13a67df
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4b585eb75ebca2187c0aa5a6abe4c8125aa80127
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4b611a3748757e2fa89fcd2fb22d34444fbf5b42 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4b611a3748757e2fa89fcd2fb22d34444fbf5b42
new file mode 100644
index 0000000..2075a0d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4b611a3748757e2fa89fcd2fb22d34444fbf5b42
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4e21c4b5c454df51c102f09ea1ba78c42133ee16 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4e21c4b5c454df51c102f09ea1ba78c42133ee16
new file mode 100644
index 0000000..b5292de
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4e21c4b5c454df51c102f09ea1ba78c42133ee16
@@ -0,0 +1 @@
+!mm‘•N!‘‘NN'‘)‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4eaff3c3515a1ca019d46b9be0b7318eaffb63d1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4eaff3c3515a1ca019d46b9be0b7318eaffb63d1
new file mode 100644
index 0000000..0b726ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4eaff3c3515a1ca019d46b9be0b7318eaffb63d1
@@ -0,0 +1 @@
+!;m‘•N‘'Nƒ‘!)‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4ec113a0126fc5746fa3f955727d009040e8377f b/test/core/end2end/fuzzers/client_fuzzer_corpus/4ec113a0126fc5746fa3f955727d009040e8377f
new file mode 100644
index 0000000..30f730c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4ec113a0126fc5746fa3f955727d009040e8377f
@@ -0,0 +1 @@
+!mmR!‘N•‘‘!:‘m!‘NN'‘)‘‘‘‘NNNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4f5b9d5c707a35084918c272efd1295d301ca0b5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/4f5b9d5c707a35084918c272efd1295d301ca0b5
new file mode 100644
index 0000000..bf8cfc2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4f5b9d5c707a35084918c272efd1295d301ca0b5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4f8b5b7489cca36225acec0f9aa7f5c556d79d8d b/test/core/end2end/fuzzers/client_fuzzer_corpus/4f8b5b7489cca36225acec0f9aa7f5c556d79d8d
new file mode 100644
index 0000000..91d18f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4f8b5b7489cca36225acec0f9aa7f5c556d79d8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/50ece7ea16659b4e1a2284cea963fab662c19e6b b/test/core/end2end/fuzzers/client_fuzzer_corpus/50ece7ea16659b4e1a2284cea963fab662c19e6b
new file mode 100644
index 0000000..a70c07e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/50ece7ea16659b4e1a2284cea963fab662c19e6b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/514c9cd7b6519b596900d924ff2caa173d688f4b b/test/core/end2end/fuzzers/client_fuzzer_corpus/514c9cd7b6519b596900d924ff2caa173d688f4b
new file mode 100644
index 0000000..93561e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/514c9cd7b6519b596900d924ff2caa173d688f4b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/51c6c5297acebf9d21a8a7d6261d0a17c2adfb56 b/test/core/end2end/fuzzers/client_fuzzer_corpus/51c6c5297acebf9d21a8a7d6261d0a17c2adfb56
new file mode 100644
index 0000000..efb8e23
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/51c6c5297acebf9d21a8a7d6261d0a17c2adfb56
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/52c00bde7f4af95a86deb0a6717d1faf2828a939 b/test/core/end2end/fuzzers/client_fuzzer_corpus/52c00bde7f4af95a86deb0a6717d1faf2828a939
new file mode 100644
index 0000000..ae7f734
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/52c00bde7f4af95a86deb0a6717d1faf2828a939
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/534c900ade27c8f7fccb1f3b7e7703f77f13a8f5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/534c900ade27c8f7fccb1f3b7e7703f77f13a8f5
new file mode 100644
index 0000000..2fc38ec
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/534c900ade27c8f7fccb1f3b7e7703f77f13a8f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5360327e8bc8969f31b364df3081b51a1e03900c b/test/core/end2end/fuzzers/client_fuzzer_corpus/5360327e8bc8969f31b364df3081b51a1e03900c
new file mode 100644
index 0000000..ab9338a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5360327e8bc8969f31b364df3081b51a1e03900c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/542c958c84d1e319b9ba23c52de2c4bca08a8dc7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/542c958c84d1e319b9ba23c52de2c4bca08a8dc7
new file mode 100644
index 0000000..13f07aa
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/542c958c84d1e319b9ba23c52de2c4bca08a8dc7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5482dc4af170def9c183315efaa48f9c186926a1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/5482dc4af170def9c183315efaa48f9c186926a1
new file mode 100644
index 0000000..f6b3c8c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5482dc4af170def9c183315efaa48f9c186926a1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/54e67ed1036f3f5b315e0e3c02948c30eba900fd b/test/core/end2end/fuzzers/client_fuzzer_corpus/54e67ed1036f3f5b315e0e3c02948c30eba900fd
new file mode 100644
index 0000000..217591e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/54e67ed1036f3f5b315e0e3c02948c30eba900fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/55ca8f6d9928c239a7abb32554463e6e1e1ee084 b/test/core/end2end/fuzzers/client_fuzzer_corpus/55ca8f6d9928c239a7abb32554463e6e1e1ee084
new file mode 100644
index 0000000..037a1a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/55ca8f6d9928c239a7abb32554463e6e1e1ee084
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/570ca8d2555dde94aa3b3121e8f5256e83eabe5e b/test/core/end2end/fuzzers/client_fuzzer_corpus/570ca8d2555dde94aa3b3121e8f5256e83eabe5e
new file mode 100644
index 0000000..3ebb587
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/570ca8d2555dde94aa3b3121e8f5256e83eabe5e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/57ee6efc38f4c544a3ea3e5e73987e825bdf2980 b/test/core/end2end/fuzzers/client_fuzzer_corpus/57ee6efc38f4c544a3ea3e5e73987e825bdf2980
new file mode 100644
index 0000000..44854ee
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/57ee6efc38f4c544a3ea3e5e73987e825bdf2980
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/58a067ec6eda7191a5a910d8120633271d3af074 b/test/core/end2end/fuzzers/client_fuzzer_corpus/58a067ec6eda7191a5a910d8120633271d3af074
new file mode 100644
index 0000000..307416c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/58a067ec6eda7191a5a910d8120633271d3af074
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/58d6dffb65a1fe1bc4e3fa970a15459587a32f77 b/test/core/end2end/fuzzers/client_fuzzer_corpus/58d6dffb65a1fe1bc4e3fa970a15459587a32f77
new file mode 100644
index 0000000..1a1a94f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/58d6dffb65a1fe1bc4e3fa970a15459587a32f77
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/591ef436ef8cc982b48fd827a4555b57cd9780e5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/591ef436ef8cc982b48fd827a4555b57cd9780e5
new file mode 100644
index 0000000..a54bd66
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/591ef436ef8cc982b48fd827a4555b57cd9780e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/59d78f6397f0483d139f5bd0a9f264156f34acc4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/59d78f6397f0483d139f5bd0a9f264156f34acc4
new file mode 100644
index 0000000..dafd670
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/59d78f6397f0483d139f5bd0a9f264156f34acc4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5a2447fdfdbf123f4592c1284007b7d50a01750b b/test/core/end2end/fuzzers/client_fuzzer_corpus/5a2447fdfdbf123f4592c1284007b7d50a01750b
new file mode 100644
index 0000000..2089c49
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5a2447fdfdbf123f4592c1284007b7d50a01750b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5ca233a53e3e425cc12e04b466a49789291eaa00 b/test/core/end2end/fuzzers/client_fuzzer_corpus/5ca233a53e3e425cc12e04b466a49789291eaa00
new file mode 100644
index 0000000..2040605
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5ca233a53e3e425cc12e04b466a49789291eaa00
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5dc7b2086a39f56d8b9135f524d34a01fcabafd8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/5dc7b2086a39f56d8b9135f524d34a01fcabafd8
new file mode 100644
index 0000000..ba7eec5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5dc7b2086a39f56d8b9135f524d34a01fcabafd8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5e1659e7cd840ab3f958273ebffdd215f2c81da6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/5e1659e7cd840ab3f958273ebffdd215f2c81da6
new file mode 100644
index 0000000..3130ede
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5e1659e7cd840ab3f958273ebffdd215f2c81da6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/605e474e9d9436488dfe084d348908e4dfab81a3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/605e474e9d9436488dfe084d348908e4dfab81a3
new file mode 100644
index 0000000..d561e86
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/605e474e9d9436488dfe084d348908e4dfab81a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6066fc9e28b4ce704230f0e8cf21e7c3195aa2a3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/6066fc9e28b4ce704230f0e8cf21e7c3195aa2a3
new file mode 100644
index 0000000..2e62282
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6066fc9e28b4ce704230f0e8cf21e7c3195aa2a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/607dac8012f188cb035b189fc3637028137023e0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/607dac8012f188cb035b189fc3637028137023e0
new file mode 100644
index 0000000..993f096
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/607dac8012f188cb035b189fc3637028137023e0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/611343a6b8879b393ba2f38ed41c7f5355355920 b/test/core/end2end/fuzzers/client_fuzzer_corpus/611343a6b8879b393ba2f38ed41c7f5355355920
new file mode 100644
index 0000000..3c9af3d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/611343a6b8879b393ba2f38ed41c7f5355355920
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/62c843359941660da3fc9eea62a5732aaa3be283 b/test/core/end2end/fuzzers/client_fuzzer_corpus/62c843359941660da3fc9eea62a5732aaa3be283
new file mode 100644
index 0000000..e0f5eee
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/62c843359941660da3fc9eea62a5732aaa3be283
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/636a19b8f50c4efccccea83ab78a933d999e41fa b/test/core/end2end/fuzzers/client_fuzzer_corpus/636a19b8f50c4efccccea83ab78a933d999e41fa
new file mode 100644
index 0000000..948b362
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/636a19b8f50c4efccccea83ab78a933d999e41fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/64696e93ead18265cdac3fb37dae29ad3be6d764 b/test/core/end2end/fuzzers/client_fuzzer_corpus/64696e93ead18265cdac3fb37dae29ad3be6d764
new file mode 100644
index 0000000..e29a928
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/64696e93ead18265cdac3fb37dae29ad3be6d764
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/64c0e0b4d9c2d25fdcb1e2bdcb999487fc096dad b/test/core/end2end/fuzzers/client_fuzzer_corpus/64c0e0b4d9c2d25fdcb1e2bdcb999487fc096dad
new file mode 100644
index 0000000..741e688
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/64c0e0b4d9c2d25fdcb1e2bdcb999487fc096dad
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/64cad305e1858eae27cd723778fb9f4b7052eaa5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/64cad305e1858eae27cd723778fb9f4b7052eaa5
new file mode 100644
index 0000000..b062f22
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/64cad305e1858eae27cd723778fb9f4b7052eaa5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/64d27dc9f984c49d421a5b0cb0391992d5aac1a4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/64d27dc9f984c49d421a5b0cb0391992d5aac1a4
new file mode 100644
index 0000000..f57336b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/64d27dc9f984c49d421a5b0cb0391992d5aac1a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/653ec14661c40ea25bdbab4a7cb9371c669d10d9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/653ec14661c40ea25bdbab4a7cb9371c669d10d9
new file mode 100644
index 0000000..1f963c2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/653ec14661c40ea25bdbab4a7cb9371c669d10d9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/66145518601b1405361df12570f6e0b2b9a2e5b3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/66145518601b1405361df12570f6e0b2b9a2e5b3
new file mode 100644
index 0000000..cd97aa7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/66145518601b1405361df12570f6e0b2b9a2e5b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/662d81374a2c96f867ccd88a4295190827c45453 b/test/core/end2end/fuzzers/client_fuzzer_corpus/662d81374a2c96f867ccd88a4295190827c45453
new file mode 100644
index 0000000..8e3d152
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/662d81374a2c96f867ccd88a4295190827c45453
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/669256f857011c32f5757ec19b2e5b9a372f6c23 b/test/core/end2end/fuzzers/client_fuzzer_corpus/669256f857011c32f5757ec19b2e5b9a372f6c23
new file mode 100644
index 0000000..266d9cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/669256f857011c32f5757ec19b2e5b9a372f6c23
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6749752b02f7d14fff9ac35f6b68dd62f5b49fcd b/test/core/end2end/fuzzers/client_fuzzer_corpus/6749752b02f7d14fff9ac35f6b68dd62f5b49fcd
new file mode 100644
index 0000000..54b13f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6749752b02f7d14fff9ac35f6b68dd62f5b49fcd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/67e72cea2b7042f08e8dfba5191d27bb390e4d00 b/test/core/end2end/fuzzers/client_fuzzer_corpus/67e72cea2b7042f08e8dfba5191d27bb390e4d00
new file mode 100644
index 0000000..05c793f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/67e72cea2b7042f08e8dfba5191d27bb390e4d00
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/685fbddd9ea612b25e325a50bd659997b4d77da1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/685fbddd9ea612b25e325a50bd659997b4d77da1
new file mode 100644
index 0000000..c1a46bc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/685fbddd9ea612b25e325a50bd659997b4d77da1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/69542ed81b00a5ec8daaf4e8d509201eecd502c5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/69542ed81b00a5ec8daaf4e8d509201eecd502c5
new file mode 100644
index 0000000..85cb334
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/69542ed81b00a5ec8daaf4e8d509201eecd502c5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/69be4179b28e408a0574935e893c6986bbca0de9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/69be4179b28e408a0574935e893c6986bbca0de9
new file mode 100644
index 0000000..2a20634
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/69be4179b28e408a0574935e893c6986bbca0de9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/69e52eef5dd0c51012b5c974cf70f4074ba814a9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/69e52eef5dd0c51012b5c974cf70f4074ba814a9
new file mode 100644
index 0000000..d25a372
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/69e52eef5dd0c51012b5c974cf70f4074ba814a9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6b1698d096095d4035ce67a8680b52eada00cce2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/6b1698d096095d4035ce67a8680b52eada00cce2
new file mode 100644
index 0000000..4de55b2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6b1698d096095d4035ce67a8680b52eada00cce2
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6bfd3679f4e30aaaa1808e96c980edcfa9cac1c0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/6bfd3679f4e30aaaa1808e96c980edcfa9cac1c0
new file mode 100644
index 0000000..928473a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6bfd3679f4e30aaaa1808e96c980edcfa9cac1c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6e2796549e29e5066f780a5e926fd6e3bb362450 b/test/core/end2end/fuzzers/client_fuzzer_corpus/6e2796549e29e5066f780a5e926fd6e3bb362450
new file mode 100644
index 0000000..2825d7b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6e2796549e29e5066f780a5e926fd6e3bb362450
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6e71553967212dfea2c9995f3641e582d8c2105b b/test/core/end2end/fuzzers/client_fuzzer_corpus/6e71553967212dfea2c9995f3641e582d8c2105b
new file mode 100644
index 0000000..53641b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6e71553967212dfea2c9995f3641e582d8c2105b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/71106770243ccca03f5025aadb298ee3a825824b b/test/core/end2end/fuzzers/client_fuzzer_corpus/71106770243ccca03f5025aadb298ee3a825824b
new file mode 100644
index 0000000..8a1ad8a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/71106770243ccca03f5025aadb298ee3a825824b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/717695057d76b81c344ed8c23cc024195caa9405 b/test/core/end2end/fuzzers/client_fuzzer_corpus/717695057d76b81c344ed8c23cc024195caa9405
new file mode 100644
index 0000000..38480af
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/717695057d76b81c344ed8c23cc024195caa9405
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7353a7b2ea9f61325728b2f118416549e89dd79b b/test/core/end2end/fuzzers/client_fuzzer_corpus/7353a7b2ea9f61325728b2f118416549e89dd79b
new file mode 100644
index 0000000..9f665de
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7353a7b2ea9f61325728b2f118416549e89dd79b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/739228a1400cd69c47f110002c34dbe1661e8c41 b/test/core/end2end/fuzzers/client_fuzzer_corpus/739228a1400cd69c47f110002c34dbe1661e8c41
new file mode 100644
index 0000000..4e05077
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/739228a1400cd69c47f110002c34dbe1661e8c41
@@ -0,0 +1 @@
+!mmN•‘‘!‘m!‘NN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7465a4955a064e8f1bb777d4b0de5b3df8469831 b/test/core/end2end/fuzzers/client_fuzzer_corpus/7465a4955a064e8f1bb777d4b0de5b3df8469831
new file mode 100644
index 0000000..430c483
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7465a4955a064e8f1bb777d4b0de5b3df8469831
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/74e6831be67485fb59b8e226fb8a48d88faf57d6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/74e6831be67485fb59b8e226fb8a48d88faf57d6
new file mode 100644
index 0000000..7347fab
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/74e6831be67485fb59b8e226fb8a48d88faf57d6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/753efc088d6023ca113a12acc54015a22f7daf9f b/test/core/end2end/fuzzers/client_fuzzer_corpus/753efc088d6023ca113a12acc54015a22f7daf9f
new file mode 100644
index 0000000..bbb3463
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/753efc088d6023ca113a12acc54015a22f7daf9f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/759a1e2e34cad14321a5e5790b1e6a783312fea1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/759a1e2e34cad14321a5e5790b1e6a783312fea1
new file mode 100644
index 0000000..ebb0726
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/759a1e2e34cad14321a5e5790b1e6a783312fea1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/77ea9180617391d8503427a1c060538182f7729f b/test/core/end2end/fuzzers/client_fuzzer_corpus/77ea9180617391d8503427a1c060538182f7729f
new file mode 100644
index 0000000..ba195ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/77ea9180617391d8503427a1c060538182f7729f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7885df741c88ca4b539798d9985c445f41cc2929 b/test/core/end2end/fuzzers/client_fuzzer_corpus/7885df741c88ca4b539798d9985c445f41cc2929
new file mode 100644
index 0000000..1a40080
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7885df741c88ca4b539798d9985c445f41cc2929
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7af3156d286a32a6a6fede46d93ec12ded1ac138 b/test/core/end2end/fuzzers/client_fuzzer_corpus/7af3156d286a32a6a6fede46d93ec12ded1ac138
new file mode 100644
index 0000000..aec87c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7af3156d286a32a6a6fede46d93ec12ded1ac138
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7af41e5391204f4596cb1461792e2e23f9390b7b b/test/core/end2end/fuzzers/client_fuzzer_corpus/7af41e5391204f4596cb1461792e2e23f9390b7b
new file mode 100644
index 0000000..898709a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7af41e5391204f4596cb1461792e2e23f9390b7b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7c2e48b0d08aaeb95b5ca26036384aa2cec9de77 b/test/core/end2end/fuzzers/client_fuzzer_corpus/7c2e48b0d08aaeb95b5ca26036384aa2cec9de77
new file mode 100644
index 0000000..a8da834
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7c2e48b0d08aaeb95b5ca26036384aa2cec9de77
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7c73c0671308e37a8075a20863e70e180ef8b6ea b/test/core/end2end/fuzzers/client_fuzzer_corpus/7c73c0671308e37a8075a20863e70e180ef8b6ea
new file mode 100644
index 0000000..8aee3fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7c73c0671308e37a8075a20863e70e180ef8b6ea
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7e18989175bba8d9aea34413d6f328549e1c6825 b/test/core/end2end/fuzzers/client_fuzzer_corpus/7e18989175bba8d9aea34413d6f328549e1c6825
new file mode 100644
index 0000000..deb05e7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7e18989175bba8d9aea34413d6f328549e1c6825
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8021c689f0078c5c59419c9959f5c58472245bc7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8021c689f0078c5c59419c9959f5c58472245bc7
new file mode 100644
index 0000000..d513d57
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8021c689f0078c5c59419c9959f5c58472245bc7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/807b8c4ca068cff4bc0fc8e854c1215a2fe65960 b/test/core/end2end/fuzzers/client_fuzzer_corpus/807b8c4ca068cff4bc0fc8e854c1215a2fe65960
new file mode 100644
index 0000000..a577c53
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/807b8c4ca068cff4bc0fc8e854c1215a2fe65960
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/80bd4827db81a1da28fae8c150f5e2d46651c598 b/test/core/end2end/fuzzers/client_fuzzer_corpus/80bd4827db81a1da28fae8c150f5e2d46651c598
new file mode 100644
index 0000000..03267f1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/80bd4827db81a1da28fae8c150f5e2d46651c598
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/813d2c34c0df8d4a918e68e58cf0ae3703d0d46f b/test/core/end2end/fuzzers/client_fuzzer_corpus/813d2c34c0df8d4a918e68e58cf0ae3703d0d46f
new file mode 100644
index 0000000..20b84c0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/813d2c34c0df8d4a918e68e58cf0ae3703d0d46f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/824152f7bd022996b41327002f6971cd9900b265 b/test/core/end2end/fuzzers/client_fuzzer_corpus/824152f7bd022996b41327002f6971cd9900b265
new file mode 100644
index 0000000..1ec61bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/824152f7bd022996b41327002f6971cd9900b265
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/829a1dc2bcb22a230df8aa20540def0e16864983 b/test/core/end2end/fuzzers/client_fuzzer_corpus/829a1dc2bcb22a230df8aa20540def0e16864983
new file mode 100644
index 0000000..80de4dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/829a1dc2bcb22a230df8aa20540def0e16864983
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/82c0e02a867a5fdfb805e01ebf1a008220311e27 b/test/core/end2end/fuzzers/client_fuzzer_corpus/82c0e02a867a5fdfb805e01ebf1a008220311e27
new file mode 100644
index 0000000..a39f546
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/82c0e02a867a5fdfb805e01ebf1a008220311e27
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/831248cea079b629bf0ef6d9d02c159d6f8ed41b b/test/core/end2end/fuzzers/client_fuzzer_corpus/831248cea079b629bf0ef6d9d02c159d6f8ed41b
new file mode 100644
index 0000000..4bf2f2b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/831248cea079b629bf0ef6d9d02c159d6f8ed41b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/834527ef0bc1572c584938ca7fe5336961754708 b/test/core/end2end/fuzzers/client_fuzzer_corpus/834527ef0bc1572c584938ca7fe5336961754708
new file mode 100644
index 0000000..0cbead7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/834527ef0bc1572c584938ca7fe5336961754708
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8382c249fc9c7a248833d89de554e63807c475f7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8382c249fc9c7a248833d89de554e63807c475f7
new file mode 100644
index 0000000..748a4e0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8382c249fc9c7a248833d89de554e63807c475f7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/83baaee9b46770d9eef0e161a6e52cda76e3b043 b/test/core/end2end/fuzzers/client_fuzzer_corpus/83baaee9b46770d9eef0e161a6e52cda76e3b043
new file mode 100644
index 0000000..f24e8e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/83baaee9b46770d9eef0e161a6e52cda76e3b043
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/842cea88bccc41d7e2625dae8ff7268ee79e9f57 b/test/core/end2end/fuzzers/client_fuzzer_corpus/842cea88bccc41d7e2625dae8ff7268ee79e9f57
new file mode 100644
index 0000000..002466c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/842cea88bccc41d7e2625dae8ff7268ee79e9f57
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/850c639595eae3cc9c2cfef473e28fd4e8174dc8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/850c639595eae3cc9c2cfef473e28fd4e8174dc8
new file mode 100644
index 0000000..9677158
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/850c639595eae3cc9c2cfef473e28fd4e8174dc8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/857ce08213a5106c746767352c6863d7bd134208 b/test/core/end2end/fuzzers/client_fuzzer_corpus/857ce08213a5106c746767352c6863d7bd134208
new file mode 100644
index 0000000..dc539fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/857ce08213a5106c746767352c6863d7bd134208
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/86eb156ff8ddd7edc535840d412342ada6f3b184 b/test/core/end2end/fuzzers/client_fuzzer_corpus/86eb156ff8ddd7edc535840d412342ada6f3b184
new file mode 100644
index 0000000..fe1855b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/86eb156ff8ddd7edc535840d412342ada6f3b184
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/871a2e4d73a7fbb50f71558517a2f704b7fdb868 b/test/core/end2end/fuzzers/client_fuzzer_corpus/871a2e4d73a7fbb50f71558517a2f704b7fdb868
new file mode 100644
index 0000000..96387bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/871a2e4d73a7fbb50f71558517a2f704b7fdb868
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8795e24f23db36e4f9ab609c9faff601b984eb6f b/test/core/end2end/fuzzers/client_fuzzer_corpus/8795e24f23db36e4f9ab609c9faff601b984eb6f
new file mode 100644
index 0000000..1d60db5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8795e24f23db36e4f9ab609c9faff601b984eb6f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/87e97b460042d045629263ad10ff3de7b000f0a1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/87e97b460042d045629263ad10ff3de7b000f0a1
new file mode 100644
index 0000000..8ff5c7d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/87e97b460042d045629263ad10ff3de7b000f0a1
@@ -0,0 +1 @@
+!m;‘•N!‘#‘N¯)‘‘N‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/89cf42c02d7135afa6c81d8a0c2bc4c3df557769 b/test/core/end2end/fuzzers/client_fuzzer_corpus/89cf42c02d7135afa6c81d8a0c2bc4c3df557769
new file mode 100644
index 0000000..0a1b5dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/89cf42c02d7135afa6c81d8a0c2bc4c3df557769
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8b7b914723bfc23ec650cb91d209141641fba09f b/test/core/end2end/fuzzers/client_fuzzer_corpus/8b7b914723bfc23ec650cb91d209141641fba09f
new file mode 100644
index 0000000..fff77e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8b7b914723bfc23ec650cb91d209141641fba09f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8b8b9fcdfff1f891b1694614b7309cb4a2098f4b b/test/core/end2end/fuzzers/client_fuzzer_corpus/8b8b9fcdfff1f891b1694614b7309cb4a2098f4b
new file mode 100644
index 0000000..4de424b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8b8b9fcdfff1f891b1694614b7309cb4a2098f4b
@@ -0,0 +1 @@
+!m;‘•N!‘'‘N)‘‘N‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8b8f6d58dff9ab0c37183ec93c9a600d5ba5d9e6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8b8f6d58dff9ab0c37183ec93c9a600d5ba5d9e6
new file mode 100644
index 0000000..6519b1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8b8f6d58dff9ab0c37183ec93c9a600d5ba5d9e6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8ba00963037c9ff548b7a702497441799075f14b b/test/core/end2end/fuzzers/client_fuzzer_corpus/8ba00963037c9ff548b7a702497441799075f14b
new file mode 100644
index 0000000..345f8cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8ba00963037c9ff548b7a702497441799075f14b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8bacacba71bfa5c74fd74cb6577a49a7aec9cf1f b/test/core/end2end/fuzzers/client_fuzzer_corpus/8bacacba71bfa5c74fd74cb6577a49a7aec9cf1f
new file mode 100644
index 0000000..852d4d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8bacacba71bfa5c74fd74cb6577a49a7aec9cf1f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8c527bdf0f304a31866f71cdb298511041ecd320 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8c527bdf0f304a31866f71cdb298511041ecd320
new file mode 100644
index 0000000..0f6967b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8c527bdf0f304a31866f71cdb298511041ecd320
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8d352ea63259e26e1bb61f5a8f78254be4e3e7b1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8d352ea63259e26e1bb61f5a8f78254be4e3e7b1
new file mode 100644
index 0000000..047ebaa
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8d352ea63259e26e1bb61f5a8f78254be4e3e7b1
@@ -0,0 +1 @@
+!mmL)NXmmÿÿ
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8dfc4e78007040009f37109f9ca928c31b3ebb49 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8dfc4e78007040009f37109f9ca928c31b3ebb49
new file mode 100644
index 0000000..af1c15f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8dfc4e78007040009f37109f9ca928c31b3ebb49
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8ea624983d766ed45780378a3eec24eb2faeb229 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8ea624983d766ed45780378a3eec24eb2faeb229
new file mode 100644
index 0000000..d119f4c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8ea624983d766ed45780378a3eec24eb2faeb229
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8eeb8cf054ebd546ca0555ef1cd4ac6a08628917 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8eeb8cf054ebd546ca0555ef1cd4ac6a08628917
new file mode 100644
index 0000000..b4981f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8eeb8cf054ebd546ca0555ef1cd4ac6a08628917
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/90a9c3390752b94ca19a58cb2fe6267bc818f718 b/test/core/end2end/fuzzers/client_fuzzer_corpus/90a9c3390752b94ca19a58cb2fe6267bc818f718
new file mode 100644
index 0000000..19d7c4a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/90a9c3390752b94ca19a58cb2fe6267bc818f718
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9125277ed9ec5d59e51f3e1a8d97d25ef88a5d4f b/test/core/end2end/fuzzers/client_fuzzer_corpus/9125277ed9ec5d59e51f3e1a8d97d25ef88a5d4f
new file mode 100644
index 0000000..bab9abe
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9125277ed9ec5d59e51f3e1a8d97d25ef88a5d4f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/91916df7c8f04d8c2b6b8f4aeaeee6972ce0de74 b/test/core/end2end/fuzzers/client_fuzzer_corpus/91916df7c8f04d8c2b6b8f4aeaeee6972ce0de74
new file mode 100644
index 0000000..e25b4c6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/91916df7c8f04d8c2b6b8f4aeaeee6972ce0de74
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/92cce6dc5c31acd62347b15d89d52ab94b507e0f b/test/core/end2end/fuzzers/client_fuzzer_corpus/92cce6dc5c31acd62347b15d89d52ab94b507e0f
new file mode 100644
index 0000000..75914a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/92cce6dc5c31acd62347b15d89d52ab94b507e0f
@@ -0,0 +1 @@
+!mmN!mmN•‘‘!‘m!‘NN'‘)‘‘•‘‘!‘m!‘NNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/92ea0d3200665e1836ac12bed0837425cb9f43de b/test/core/end2end/fuzzers/client_fuzzer_corpus/92ea0d3200665e1836ac12bed0837425cb9f43de
new file mode 100644
index 0000000..2cc3ec6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/92ea0d3200665e1836ac12bed0837425cb9f43de
@@ -0,0 +1 @@
+)ÿ!mmm'mN!•½!æ
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9329b80d0125cc994d7ad36540c7a8265d76983c b/test/core/end2end/fuzzers/client_fuzzer_corpus/9329b80d0125cc994d7ad36540c7a8265d76983c
new file mode 100644
index 0000000..46a3f39
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9329b80d0125cc994d7ad36540c7a8265d76983c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/94108ac8420347598c7cee743b2a158b1270fb8f b/test/core/end2end/fuzzers/client_fuzzer_corpus/94108ac8420347598c7cee743b2a158b1270fb8f
new file mode 100644
index 0000000..56e1336
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/94108ac8420347598c7cee743b2a158b1270fb8f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/954ea72fdbeaf5b46d18c6d5bb77fc1a0f97569d b/test/core/end2end/fuzzers/client_fuzzer_corpus/954ea72fdbeaf5b46d18c6d5bb77fc1a0f97569d
new file mode 100644
index 0000000..6ca73fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/954ea72fdbeaf5b46d18c6d5bb77fc1a0f97569d
@@ -0,0 +1,2 @@
+!m)m!‘‘N!‘‘Nð‘NN)‘
+‘a‘‘‘‘NNNNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9552c3f6304af40224b800f3a3a5df3887a530f6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9552c3f6304af40224b800f3a3a5df3887a530f6
new file mode 100644
index 0000000..0db7584
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9552c3f6304af40224b800f3a3a5df3887a530f6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/96e5126447131d3d59cc6547f6b91d3433ce37c8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/96e5126447131d3d59cc6547f6b91d3433ce37c8
new file mode 100644
index 0000000..90f80d8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/96e5126447131d3d59cc6547f6b91d3433ce37c8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/970fccda0b34b59ade44d52e1212699b4d2419a8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/970fccda0b34b59ade44d52e1212699b4d2419a8
new file mode 100644
index 0000000..5c3a70c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/970fccda0b34b59ade44d52e1212699b4d2419a8
@@ -0,0 +1 @@
+!m;‘•N!‘'‘N)‘‘N‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/97c4b73f72b248b4ebf4bf30892d0db828a85297 b/test/core/end2end/fuzzers/client_fuzzer_corpus/97c4b73f72b248b4ebf4bf30892d0db828a85297
new file mode 100644
index 0000000..d60277f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/97c4b73f72b248b4ebf4bf30892d0db828a85297
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/98c0c0a3c8c05aec3082755a4635e65baecf4752 b/test/core/end2end/fuzzers/client_fuzzer_corpus/98c0c0a3c8c05aec3082755a4635e65baecf4752
new file mode 100644
index 0000000..07198d7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/98c0c0a3c8c05aec3082755a4635e65baecf4752
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/98da5edafac67704810f093b38c86e4c77b75349 b/test/core/end2end/fuzzers/client_fuzzer_corpus/98da5edafac67704810f093b38c86e4c77b75349
new file mode 100644
index 0000000..538a195
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/98da5edafac67704810f093b38c86e4c77b75349
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/98dddd3f679af150e9933bd864ae20e20b7aa25a b/test/core/end2end/fuzzers/client_fuzzer_corpus/98dddd3f679af150e9933bd864ae20e20b7aa25a
new file mode 100644
index 0000000..bea145a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/98dddd3f679af150e9933bd864ae20e20b7aa25a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/999d0995c2f09beda8783eac95d7643a11d5c89a b/test/core/end2end/fuzzers/client_fuzzer_corpus/999d0995c2f09beda8783eac95d7643a11d5c89a
new file mode 100644
index 0000000..b89a5f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/999d0995c2f09beda8783eac95d7643a11d5c89a
@@ -0,0 +1 @@
+!mm!‘‘N!‘‘NNN‘)‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9a43f48d4f6219618f8cc9e876880fe81109ad72 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9a43f48d4f6219618f8cc9e876880fe81109ad72
new file mode 100644
index 0000000..34a8803
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9a43f48d4f6219618f8cc9e876880fe81109ad72
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9a4da2a37a26c114e1226bfbe1cf80ec5ca99a66 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9a4da2a37a26c114e1226bfbe1cf80ec5ca99a66
new file mode 100644
index 0000000..f07452e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9a4da2a37a26c114e1226bfbe1cf80ec5ca99a66
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9abf980e8909aeb31936553ca22ccfd8680c4dab b/test/core/end2end/fuzzers/client_fuzzer_corpus/9abf980e8909aeb31936553ca22ccfd8680c4dab
new file mode 100644
index 0000000..d4a8912
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9abf980e8909aeb31936553ca22ccfd8680c4dab
@@ -0,0 +1 @@
+!mmN!mm•‘‘!‘m!‘NN'‘)‘‘•‘‘!‘m!‘NNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9b1355c6e2c43ce83001bbead09a79852e04feef b/test/core/end2end/fuzzers/client_fuzzer_corpus/9b1355c6e2c43ce83001bbead09a79852e04feef
new file mode 100644
index 0000000..27c512e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9b1355c6e2c43ce83001bbead09a79852e04feef
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9b4d4ce0457f5300d6b4b309762acfdbc41e3965 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9b4d4ce0457f5300d6b4b309762acfdbc41e3965
new file mode 100644
index 0000000..5482d38
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9b4d4ce0457f5300d6b4b309762acfdbc41e3965
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9bd059ff0a90e86ada1ba7e5b90ae04637ae9e90 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9bd059ff0a90e86ada1ba7e5b90ae04637ae9e90
new file mode 100644
index 0000000..f93a781
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9bd059ff0a90e86ada1ba7e5b90ae04637ae9e90
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9c4eac3dd734a74673c76e6b21fd9c18cdfa831c b/test/core/end2end/fuzzers/client_fuzzer_corpus/9c4eac3dd734a74673c76e6b21fd9c18cdfa831c
new file mode 100644
index 0000000..f31b062
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9c4eac3dd734a74673c76e6b21fd9c18cdfa831c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9d2dd744ba59c1e8ec091e23938e46d1bb5ee519 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9d2dd744ba59c1e8ec091e23938e46d1bb5ee519
new file mode 100644
index 0000000..5bd2474
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9d2dd744ba59c1e8ec091e23938e46d1bb5ee519
@@ -0,0 +1 @@
+!mm‘•N!‘‘NÿN'‘)‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9d362d2aaeee243a5b54621d8187c4b16f87c9f5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9d362d2aaeee243a5b54621d8187c4b16f87c9f5
new file mode 100644
index 0000000..affe61a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9d362d2aaeee243a5b54621d8187c4b16f87c9f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9d6947df24c9ebcbec72c568d9708d7b1ecae63c b/test/core/end2end/fuzzers/client_fuzzer_corpus/9d6947df24c9ebcbec72c568d9708d7b1ecae63c
new file mode 100644
index 0000000..031c0b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9d6947df24c9ebcbec72c568d9708d7b1ecae63c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9dfdce1b090a559a14f9a5852f78547413b1d1ed b/test/core/end2end/fuzzers/client_fuzzer_corpus/9dfdce1b090a559a14f9a5852f78547413b1d1ed
new file mode 100644
index 0000000..7b32fee
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9dfdce1b090a559a14f9a5852f78547413b1d1ed
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9e2ab07030bd35a4c31df32c79aca5e76c1d04f8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9e2ab07030bd35a4c31df32c79aca5e76c1d04f8
new file mode 100644
index 0000000..d992814
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9e2ab07030bd35a4c31df32c79aca5e76c1d04f8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9f0ab521c728be21e93112b2730c52bc1d6c0021 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9f0ab521c728be21e93112b2730c52bc1d6c0021
new file mode 100644
index 0000000..bd1364c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9f0ab521c728be21e93112b2730c52bc1d6c0021
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9f2316ddcea948c947fbbf35ae87b767b8c1dc55 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9f2316ddcea948c947fbbf35ae87b767b8c1dc55
new file mode 100644
index 0000000..7dfa020
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9f2316ddcea948c947fbbf35ae87b767b8c1dc55
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9f9ed47f98b4905f1f6ef2b552a66905bdf79b1b b/test/core/end2end/fuzzers/client_fuzzer_corpus/9f9ed47f98b4905f1f6ef2b552a66905bdf79b1b
new file mode 100644
index 0000000..afbd53b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9f9ed47f98b4905f1f6ef2b552a66905bdf79b1b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9fee3212240d4bccfdab3696dbbc579b06d39982 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9fee3212240d4bccfdab3696dbbc579b06d39982
new file mode 100644
index 0000000..7d30ec8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9fee3212240d4bccfdab3696dbbc579b06d39982
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a09ef34c93fe0ffc13045f67b7ecec683fb72e98 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a09ef34c93fe0ffc13045f67b7ecec683fb72e98
new file mode 100644
index 0000000..26173f6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a09ef34c93fe0ffc13045f67b7ecec683fb72e98
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a30fc2605f4e74f7003f902ea4a4c994e3ce9bfd b/test/core/end2end/fuzzers/client_fuzzer_corpus/a30fc2605f4e74f7003f902ea4a4c994e3ce9bfd
new file mode 100644
index 0000000..47cea8e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a30fc2605f4e74f7003f902ea4a4c994e3ce9bfd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a33e1b28074a41fc5c2611a67161ae5638a47dd5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a33e1b28074a41fc5c2611a67161ae5638a47dd5
new file mode 100644
index 0000000..6a2b6e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a33e1b28074a41fc5c2611a67161ae5638a47dd5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a3cd54d43d3b3bdfcf224d636dc11ce1b5ee4d30 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a3cd54d43d3b3bdfcf224d636dc11ce1b5ee4d30
new file mode 100644
index 0000000..19ca739
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a3cd54d43d3b3bdfcf224d636dc11ce1b5ee4d30
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a4874327383ca168f9d9d59cffe327f61e9a6610 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a4874327383ca168f9d9d59cffe327f61e9a6610
new file mode 100644
index 0000000..23069f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a4874327383ca168f9d9d59cffe327f61e9a6610
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a4e4a0473ac1f2b8de86efdf00fcb382a343126d b/test/core/end2end/fuzzers/client_fuzzer_corpus/a4e4a0473ac1f2b8de86efdf00fcb382a343126d
new file mode 100644
index 0000000..76cf810
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a4e4a0473ac1f2b8de86efdf00fcb382a343126d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a502dbaf3c842bd86e9ae513e8782eb23c70ad7a b/test/core/end2end/fuzzers/client_fuzzer_corpus/a502dbaf3c842bd86e9ae513e8782eb23c70ad7a
new file mode 100644
index 0000000..df6884f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a502dbaf3c842bd86e9ae513e8782eb23c70ad7a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a60ae4e21a913e84405814f18555f0c179c24167 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a60ae4e21a913e84405814f18555f0c179c24167
new file mode 100644
index 0000000..2d20d8d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a60ae4e21a913e84405814f18555f0c179c24167
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a6603e797695274d10bce000f66ca0a715f7d8c0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a6603e797695274d10bce000f66ca0a715f7d8c0
new file mode 100644
index 0000000..15a79e7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a6603e797695274d10bce000f66ca0a715f7d8c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a6d4b6043d86c376e9b166d5ca395f3e099ae229 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a6d4b6043d86c376e9b166d5ca395f3e099ae229
new file mode 100644
index 0000000..8354def
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a6d4b6043d86c376e9b166d5ca395f3e099ae229
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a6f0d1ed80393ec0a884718b44fe2dc9f852d38a b/test/core/end2end/fuzzers/client_fuzzer_corpus/a6f0d1ed80393ec0a884718b44fe2dc9f852d38a
new file mode 100644
index 0000000..ca7e66f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a6f0d1ed80393ec0a884718b44fe2dc9f852d38a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a706f2067bfbda7837eaad68972d60547e2957c3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a706f2067bfbda7837eaad68972d60547e2957c3
new file mode 100644
index 0000000..cf67f80
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a706f2067bfbda7837eaad68972d60547e2957c3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a814c5743d492b96d2b402f9e819bf8406262224 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a814c5743d492b96d2b402f9e819bf8406262224
new file mode 100644
index 0000000..6098cde
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a814c5743d492b96d2b402f9e819bf8406262224
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a8e67676784506d2e6eab3a0dfa25e53a80b40a0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a8e67676784506d2e6eab3a0dfa25e53a80b40a0
new file mode 100644
index 0000000..24dc2db
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a8e67676784506d2e6eab3a0dfa25e53a80b40a0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a9d71e1ff2912d8874e38fc61cbd9a8ef28af4a9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a9d71e1ff2912d8874e38fc61cbd9a8ef28af4a9
new file mode 100644
index 0000000..970e977
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a9d71e1ff2912d8874e38fc61cbd9a8ef28af4a9
@@ -0,0 +1 @@
+‘N
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/aaada46c7f3bff58c2dd6f4a8394135ed5f253ee b/test/core/end2end/fuzzers/client_fuzzer_corpus/aaada46c7f3bff58c2dd6f4a8394135ed5f253ee
new file mode 100644
index 0000000..77e30ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/aaada46c7f3bff58c2dd6f4a8394135ed5f253ee
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ab27fb527771c7d86f74afb6864e95402328ec0e b/test/core/end2end/fuzzers/client_fuzzer_corpus/ab27fb527771c7d86f74afb6864e95402328ec0e
new file mode 100644
index 0000000..462ae0b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ab27fb527771c7d86f74afb6864e95402328ec0e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ab8d6e1ecbd80c6223b8623a386c61023502a57c b/test/core/end2end/fuzzers/client_fuzzer_corpus/ab8d6e1ecbd80c6223b8623a386c61023502a57c
new file mode 100644
index 0000000..f5e5f0f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ab8d6e1ecbd80c6223b8623a386c61023502a57c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/abd52da5882855a63632a6917df3639538928cd3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/abd52da5882855a63632a6917df3639538928cd3
new file mode 100644
index 0000000..70e221d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/abd52da5882855a63632a6917df3639538928cd3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ac38a6572f8420b4df37d9e39088d1905fced71d b/test/core/end2end/fuzzers/client_fuzzer_corpus/ac38a6572f8420b4df37d9e39088d1905fced71d
new file mode 100644
index 0000000..b81b2e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ac38a6572f8420b4df37d9e39088d1905fced71d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ac727124e46a249419f088c8665324a11b357b84 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ac727124e46a249419f088c8665324a11b357b84
new file mode 100644
index 0000000..639fc84
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ac727124e46a249419f088c8665324a11b357b84
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/adb9bf315315338bcad85929917b9def2aa098cb b/test/core/end2end/fuzzers/client_fuzzer_corpus/adb9bf315315338bcad85929917b9def2aa098cb
new file mode 100644
index 0000000..b80872b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/adb9bf315315338bcad85929917b9def2aa098cb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ade2d2f0e120a9527487e9b92458ee6844800e4e b/test/core/end2end/fuzzers/client_fuzzer_corpus/ade2d2f0e120a9527487e9b92458ee6844800e4e
new file mode 100644
index 0000000..d533eec
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ade2d2f0e120a9527487e9b92458ee6844800e4e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ae8c538d4ad7f2996ac724bad7a075e1aea32556 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ae8c538d4ad7f2996ac724bad7a075e1aea32556
new file mode 100644
index 0000000..e047fb1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ae8c538d4ad7f2996ac724bad7a075e1aea32556
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/af8b24ffaecdfaf96c0cd7c76f31dc9e1b4d0935 b/test/core/end2end/fuzzers/client_fuzzer_corpus/af8b24ffaecdfaf96c0cd7c76f31dc9e1b4d0935
new file mode 100644
index 0000000..eb20913
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/af8b24ffaecdfaf96c0cd7c76f31dc9e1b4d0935
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/afcce9e02e0696a2af073855a386f589cc12c94d b/test/core/end2end/fuzzers/client_fuzzer_corpus/afcce9e02e0696a2af073855a386f589cc12c94d
new file mode 100644
index 0000000..bdac388
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/afcce9e02e0696a2af073855a386f589cc12c94d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b00a32e8bfb75e75f31410dfe3592da6248275c6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b00a32e8bfb75e75f31410dfe3592da6248275c6
new file mode 100644
index 0000000..f48b677
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b00a32e8bfb75e75f31410dfe3592da6248275c6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b09f98e13e5b67a4dd7f74eff00bb247b9967844 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b09f98e13e5b67a4dd7f74eff00bb247b9967844
new file mode 100644
index 0000000..5f2c006
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b09f98e13e5b67a4dd7f74eff00bb247b9967844
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b24a0dd1bc0bfabb832f0d1c8410c018c4ddaf4e b/test/core/end2end/fuzzers/client_fuzzer_corpus/b24a0dd1bc0bfabb832f0d1c8410c018c4ddaf4e
new file mode 100644
index 0000000..7cd2ed5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b24a0dd1bc0bfabb832f0d1c8410c018c4ddaf4e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b283eb8884c98dd50523995ce221aa1ecb3ca182 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b283eb8884c98dd50523995ce221aa1ecb3ca182
new file mode 100644
index 0000000..605a974
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b283eb8884c98dd50523995ce221aa1ecb3ca182
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b2a79b262ee3966c5ce7c7b42dcffd55d7d0956b b/test/core/end2end/fuzzers/client_fuzzer_corpus/b2a79b262ee3966c5ce7c7b42dcffd55d7d0956b
new file mode 100644
index 0000000..d1dc706
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b2a79b262ee3966c5ce7c7b42dcffd55d7d0956b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b2aa4861b5104e8bb8bb173f4b023a2172a7b9a2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b2aa4861b5104e8bb8bb173f4b023a2172a7b9a2
new file mode 100644
index 0000000..f1cc2d1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b2aa4861b5104e8bb8bb173f4b023a2172a7b9a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b33eb7e1bde4c69671dbbf9489b4d4b87c5d23fd b/test/core/end2end/fuzzers/client_fuzzer_corpus/b33eb7e1bde4c69671dbbf9489b4d4b87c5d23fd
new file mode 100644
index 0000000..8739cda
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b33eb7e1bde4c69671dbbf9489b4d4b87c5d23fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b39bfaf6a3072d8a50984dcc54967e9246f8d3e5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b39bfaf6a3072d8a50984dcc54967e9246f8d3e5
new file mode 100644
index 0000000..12f01c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b39bfaf6a3072d8a50984dcc54967e9246f8d3e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b3f33b78433af7f607bc99b569b0cef95a1a6ca0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b3f33b78433af7f607bc99b569b0cef95a1a6ca0
new file mode 100644
index 0000000..e27af01
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b3f33b78433af7f607bc99b569b0cef95a1a6ca0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b46e762671a5e28c7061da3baee6fc41dcc0122b b/test/core/end2end/fuzzers/client_fuzzer_corpus/b46e762671a5e28c7061da3baee6fc41dcc0122b
new file mode 100644
index 0000000..0d40881
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b46e762671a5e28c7061da3baee6fc41dcc0122b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b6d86bedf3cf19441114e463458a454709e627b4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b6d86bedf3cf19441114e463458a454709e627b4
new file mode 100644
index 0000000..f951be5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b6d86bedf3cf19441114e463458a454709e627b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b755933ad6e318ee9e0c430ff69be7a515d44def b/test/core/end2end/fuzzers/client_fuzzer_corpus/b755933ad6e318ee9e0c430ff69be7a515d44def
new file mode 100644
index 0000000..fb0b39f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b755933ad6e318ee9e0c430ff69be7a515d44def
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b7b664a39372dd6142b8ef7906857e4ab3f1fc84 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b7b664a39372dd6142b8ef7906857e4ab3f1fc84
new file mode 100644
index 0000000..a3ad3d2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b7b664a39372dd6142b8ef7906857e4ab3f1fc84
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b7c31bb5f6acc65b88e31400dcae71f7be392c86 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b7c31bb5f6acc65b88e31400dcae71f7be392c86
new file mode 100644
index 0000000..bd9a791
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b7c31bb5f6acc65b88e31400dcae71f7be392c86
@@ -0,0 +1 @@
+!mã!ÿÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ba942f8fb244b60561a067129c242c4bc4fdd5e1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ba942f8fb244b60561a067129c242c4bc4fdd5e1
new file mode 100644
index 0000000..4ed0662
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ba942f8fb244b60561a067129c242c4bc4fdd5e1
@@ -0,0 +1 @@
+!mã!mm‘•N!‘‘NÿN'‘!)‘‘ÿÿÿÿÿNNÿÿÿ
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/baa28a5baedb645f4430940a4b4b1142f4b03e0f b/test/core/end2end/fuzzers/client_fuzzer_corpus/baa28a5baedb645f4430940a4b4b1142f4b03e0f
new file mode 100644
index 0000000..2bfa053
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/baa28a5baedb645f4430940a4b4b1142f4b03e0f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/baf7839388e10ff0c410a58797482cb83693b309 b/test/core/end2end/fuzzers/client_fuzzer_corpus/baf7839388e10ff0c410a58797482cb83693b309
new file mode 100644
index 0000000..5f51d62
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/baf7839388e10ff0c410a58797482cb83693b309
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/bbc03bf6274a79528d43e200e8f1aaa770a155d6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/bbc03bf6274a79528d43e200e8f1aaa770a155d6
new file mode 100644
index 0000000..60bf6b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/bbc03bf6274a79528d43e200e8f1aaa770a155d6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/bc9e17fed43c5d0668a87e8d6354c344c5b4d00b b/test/core/end2end/fuzzers/client_fuzzer_corpus/bc9e17fed43c5d0668a87e8d6354c344c5b4d00b
new file mode 100644
index 0000000..2a279d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/bc9e17fed43c5d0668a87e8d6354c344c5b4d00b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/bcc7340f8876a7dff381ca676efc39d30eed9f48 b/test/core/end2end/fuzzers/client_fuzzer_corpus/bcc7340f8876a7dff381ca676efc39d30eed9f48
new file mode 100644
index 0000000..efecee7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/bcc7340f8876a7dff381ca676efc39d30eed9f48
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/bd0bef14e73aa1073eb5acb6e4cc901c976335f5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/bd0bef14e73aa1073eb5acb6e4cc901c976335f5
new file mode 100644
index 0000000..f8315c2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/bd0bef14e73aa1073eb5acb6e4cc901c976335f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/be3237e72b3d8d56eec0520145dd7d1a5064eede b/test/core/end2end/fuzzers/client_fuzzer_corpus/be3237e72b3d8d56eec0520145dd7d1a5064eede
new file mode 100644
index 0000000..82254af
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/be3237e72b3d8d56eec0520145dd7d1a5064eede
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/be8cc5bab95e0ea7af538ca11175d710da6207d9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/be8cc5bab95e0ea7af538ca11175d710da6207d9
new file mode 100644
index 0000000..6f7eaff
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/be8cc5bab95e0ea7af538ca11175d710da6207d9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/be988fc0c00a8422020dea3dc72451b09e25e1ad b/test/core/end2end/fuzzers/client_fuzzer_corpus/be988fc0c00a8422020dea3dc72451b09e25e1ad
new file mode 100644
index 0000000..a615cb6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/be988fc0c00a8422020dea3dc72451b09e25e1ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c0deaead93c9b3f2fc211fb7f0711ac192715a40 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c0deaead93c9b3f2fc211fb7f0711ac192715a40
new file mode 100644
index 0000000..fe16d39
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c0deaead93c9b3f2fc211fb7f0711ac192715a40
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c24143cf5f6f77f002e0ab82e3060906e2e7d062 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c24143cf5f6f77f002e0ab82e3060906e2e7d062
new file mode 100644
index 0000000..3326d07
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c24143cf5f6f77f002e0ab82e3060906e2e7d062
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c3afa705dab02fea4d892134e7c01c3af270cb6e b/test/core/end2end/fuzzers/client_fuzzer_corpus/c3afa705dab02fea4d892134e7c01c3af270cb6e
new file mode 100644
index 0000000..09ddeec
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c3afa705dab02fea4d892134e7c01c3af270cb6e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c3de41124a14ea562360aabc9e12666851bff2fe b/test/core/end2end/fuzzers/client_fuzzer_corpus/c3de41124a14ea562360aabc9e12666851bff2fe
new file mode 100644
index 0000000..7553442
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c3de41124a14ea562360aabc9e12666851bff2fe
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c4e60ae7c05b12a90dd7c43fbc85ae4be7540f18 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c4e60ae7c05b12a90dd7c43fbc85ae4be7540f18
new file mode 100644
index 0000000..11021a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c4e60ae7c05b12a90dd7c43fbc85ae4be7540f18
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c5d0c169d326d79fc4ee8521b282dbcbf33c1d5c b/test/core/end2end/fuzzers/client_fuzzer_corpus/c5d0c169d326d79fc4ee8521b282dbcbf33c1d5c
new file mode 100644
index 0000000..454fec8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c5d0c169d326d79fc4ee8521b282dbcbf33c1d5c
@@ -0,0 +1 @@
+!mm‘•N!‘‘N)ÿN'‘)‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c5dfb4a82f91d07041d4b0ca6cc34cfa1e9c7199 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c5dfb4a82f91d07041d4b0ca6cc34cfa1e9c7199
new file mode 100644
index 0000000..1877173
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c5dfb4a82f91d07041d4b0ca6cc34cfa1e9c7199
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c685689a9d5b259afe237d857b7c6551dc95c176 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c685689a9d5b259afe237d857b7c6551dc95c176
new file mode 100644
index 0000000..763b8dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c685689a9d5b259afe237d857b7c6551dc95c176
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c77087b4651f4c62a780d77a3b4c233490244e8a b/test/core/end2end/fuzzers/client_fuzzer_corpus/c77087b4651f4c62a780d77a3b4c233490244e8a
new file mode 100644
index 0000000..92280fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c77087b4651f4c62a780d77a3b4c233490244e8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c784ad2e205ba49b5bb1302746723dbc57320981 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c784ad2e205ba49b5bb1302746723dbc57320981
new file mode 100644
index 0000000..3efda68
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c784ad2e205ba49b5bb1302746723dbc57320981
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c84da54dacf04445b50448a70fb0ecdd08e9234a b/test/core/end2end/fuzzers/client_fuzzer_corpus/c84da54dacf04445b50448a70fb0ecdd08e9234a
new file mode 100644
index 0000000..fd3d2fc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c84da54dacf04445b50448a70fb0ecdd08e9234a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c8cb20176e427d2e108187924f570ef1df6d440c b/test/core/end2end/fuzzers/client_fuzzer_corpus/c8cb20176e427d2e108187924f570ef1df6d440c
new file mode 100644
index 0000000..88d1c1b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c8cb20176e427d2e108187924f570ef1df6d440c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c916ea9c6901c1e77af764773bd2843baa2ebdc6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c916ea9c6901c1e77af764773bd2843baa2ebdc6
new file mode 100644
index 0000000..0c1b623
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c916ea9c6901c1e77af764773bd2843baa2ebdc6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c97ebf43d8a5ce5cdb8e93a5d0362239c284ab4d b/test/core/end2end/fuzzers/client_fuzzer_corpus/c97ebf43d8a5ce5cdb8e93a5d0362239c284ab4d
new file mode 100644
index 0000000..16e805e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c97ebf43d8a5ce5cdb8e93a5d0362239c284ab4d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ca0db313bf949ba3f87a5254646a7a7dc8a7f89d b/test/core/end2end/fuzzers/client_fuzzer_corpus/ca0db313bf949ba3f87a5254646a7a7dc8a7f89d
new file mode 100644
index 0000000..daf5a83
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ca0db313bf949ba3f87a5254646a7a7dc8a7f89d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cc4197d2381a75b674fe4944b8c690fe69a0b3b1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/cc4197d2381a75b674fe4944b8c690fe69a0b3b1
new file mode 100644
index 0000000..3ab9cef
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cc4197d2381a75b674fe4944b8c690fe69a0b3b1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cceb4c620c02337138e489383db0d4f4e2c7a722 b/test/core/end2end/fuzzers/client_fuzzer_corpus/cceb4c620c02337138e489383db0d4f4e2c7a722
new file mode 100644
index 0000000..44b7482
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cceb4c620c02337138e489383db0d4f4e2c7a722
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cd4be18b1ae872c40580edc4fe8cbdf1fe2a3881 b/test/core/end2end/fuzzers/client_fuzzer_corpus/cd4be18b1ae872c40580edc4fe8cbdf1fe2a3881
new file mode 100644
index 0000000..70f2517
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cd4be18b1ae872c40580edc4fe8cbdf1fe2a3881
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cd76ed6aff7e074b0cfdcc6305ec4e453d8304bb b/test/core/end2end/fuzzers/client_fuzzer_corpus/cd76ed6aff7e074b0cfdcc6305ec4e453d8304bb
new file mode 100644
index 0000000..5c03120
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cd76ed6aff7e074b0cfdcc6305ec4e453d8304bb
@@ -0,0 +1 @@
+!‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ce990633c0f2b2a2ddb66144ed942d4bc9bcd8fb b/test/core/end2end/fuzzers/client_fuzzer_corpus/ce990633c0f2b2a2ddb66144ed942d4bc9bcd8fb
new file mode 100644
index 0000000..a2bab7f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ce990633c0f2b2a2ddb66144ed942d4bc9bcd8fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ceb297908903ba0fc24982ad4e6010e79dfbdd5e b/test/core/end2end/fuzzers/client_fuzzer_corpus/ceb297908903ba0fc24982ad4e6010e79dfbdd5e
new file mode 100644
index 0000000..5ba2cd2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ceb297908903ba0fc24982ad4e6010e79dfbdd5e
@@ -0,0 +1,2 @@
+!mm!N!mm!m)m!‘‘N!‘‘Nð‘N<N)‘
+‘a‘‘‘‘NNN•‘‘!‘m!)‘‘'NN‘‘•‘!‘Nm!N‘NNNN‘NNN'‘)‘‘N‘NN*
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cedd54df6d34491dbf7843c2621d6818418aca02 b/test/core/end2end/fuzzers/client_fuzzer_corpus/cedd54df6d34491dbf7843c2621d6818418aca02
new file mode 100644
index 0000000..dbbeff5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cedd54df6d34491dbf7843c2621d6818418aca02
@@ -0,0 +1,2 @@
+!mm!N!mm!m)m!‘‘N!‘‘Nð‘NN)‘
+‘a‘‘‘‘NNN•‘‘!‘m!)‘‘‘N'N‘•‘!‘mNN!‘NNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cf75632ee185df2cbbbe148e2e1ad5410f11d361 b/test/core/end2end/fuzzers/client_fuzzer_corpus/cf75632ee185df2cbbbe148e2e1ad5410f11d361
new file mode 100644
index 0000000..383ec54
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cf75632ee185df2cbbbe148e2e1ad5410f11d361
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cfa40fccc5ea4304e83ca26f4e567765c2c08627 b/test/core/end2end/fuzzers/client_fuzzer_corpus/cfa40fccc5ea4304e83ca26f4e567765c2c08627
new file mode 100644
index 0000000..82c7e33
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cfa40fccc5ea4304e83ca26f4e567765c2c08627
@@ -0,0 +1 @@
+!mã!ÿÿÿ£ÿÿÿÿÿƒ
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-12b69708d452b3cefe2da4a708a1030a661d37fc b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-12b69708d452b3cefe2da4a708a1030a661d37fc
new file mode 100644
index 0000000..21b2ccc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-12b69708d452b3cefe2da4a708a1030a661d37fc
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-3bd02c98286bfa7be8e13c5500ddb587bba74fbb b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-3bd02c98286bfa7be8e13c5500ddb587bba74fbb
new file mode 100644
index 0000000..a1d58be
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-3bd02c98286bfa7be8e13c5500ddb587bba74fbb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-53e93a1906d8442d058500e7107929cdd3e84ff8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-53e93a1906d8442d058500e7107929cdd3e84ff8
new file mode 100644
index 0000000..ac446e5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-53e93a1906d8442d058500e7107929cdd3e84ff8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-570c79624a2e4d36be107745d2b25e74464553af b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-570c79624a2e4d36be107745d2b25e74464553af
new file mode 100644
index 0000000..815841b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-570c79624a2e4d36be107745d2b25e74464553af
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-8e546795782dffa5d5f5e94c9510aac178fcee39 b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-8e546795782dffa5d5f5e94c9510aac178fcee39
new file mode 100644
index 0000000..53d6fd7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-8e546795782dffa5d5f5e94c9510aac178fcee39
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d5af12c391b7bf0ce63ee3dc656ee4410fe496eb b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d5af12c391b7bf0ce63ee3dc656ee4410fe496eb
new file mode 100644
index 0000000..b2b8838
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d5af12c391b7bf0ce63ee3dc656ee4410fe496eb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d92bb454bbbd415175df541661e3696453ce3e43 b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d92bb454bbbd415175df541661e3696453ce3e43
new file mode 100644
index 0000000..8580a04
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d92bb454bbbd415175df541661e3696453ce3e43
@@ -0,0 +1 @@
+!)‘!:‘O
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-e470e9fd09a5c9ef303813a40361c897650289fd b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-e470e9fd09a5c9ef303813a40361c897650289fd
new file mode 100644
index 0000000..23873dd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-e470e9fd09a5c9ef303813a40361c897650289fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d194592e6f471dd487ca2625e6c3da7802ea372f b/test/core/end2end/fuzzers/client_fuzzer_corpus/d194592e6f471dd487ca2625e6c3da7802ea372f
new file mode 100644
index 0000000..03bd5b7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d194592e6f471dd487ca2625e6c3da7802ea372f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d1b1863b478e1ea71eafac9e03256080c8f0d1c5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d1b1863b478e1ea71eafac9e03256080c8f0d1c5
new file mode 100644
index 0000000..11718eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d1b1863b478e1ea71eafac9e03256080c8f0d1c5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d24d1b9d754391fd0b11b0456a2e8c6050cadee6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d24d1b9d754391fd0b11b0456a2e8c6050cadee6
new file mode 100644
index 0000000..a8aa7e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d24d1b9d754391fd0b11b0456a2e8c6050cadee6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d250e525e8ff2ae4a9bddb2e478a90a1242155f0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d250e525e8ff2ae4a9bddb2e478a90a1242155f0
new file mode 100644
index 0000000..6fb6f86
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d250e525e8ff2ae4a9bddb2e478a90a1242155f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d257c41db22b60cd937de16b9d90a44b9fa8e426 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d257c41db22b60cd937de16b9d90a44b9fa8e426
new file mode 100644
index 0000000..975530c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d257c41db22b60cd937de16b9d90a44b9fa8e426
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d2df8e95436cf98ef2189191a75a3d9c78b1be6c b/test/core/end2end/fuzzers/client_fuzzer_corpus/d2df8e95436cf98ef2189191a75a3d9c78b1be6c
new file mode 100644
index 0000000..1e257a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d2df8e95436cf98ef2189191a75a3d9c78b1be6c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d3386702918881101368cdba2c4967e86ff3a7b9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d3386702918881101368cdba2c4967e86ff3a7b9
new file mode 100644
index 0000000..db3533a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d3386702918881101368cdba2c4967e86ff3a7b9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d363f288f48fba8fde401978b7e764295735645e b/test/core/end2end/fuzzers/client_fuzzer_corpus/d363f288f48fba8fde401978b7e764295735645e
new file mode 100644
index 0000000..e9f4e90
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d363f288f48fba8fde401978b7e764295735645e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d36e015b1e14ecb9559d67bb09c2851699f0aa35 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d36e015b1e14ecb9559d67bb09c2851699f0aa35
new file mode 100644
index 0000000..7e123c5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d36e015b1e14ecb9559d67bb09c2851699f0aa35
@@ -0,0 +1 @@
+!mmmmN!½
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d49450b97f489f0dea74a9f83c71abeba1066d3c b/test/core/end2end/fuzzers/client_fuzzer_corpus/d49450b97f489f0dea74a9f83c71abeba1066d3c
new file mode 100644
index 0000000..0403081
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d49450b97f489f0dea74a9f83c71abeba1066d3c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d4a72650e8218ec551fef6560ddd136d52828a4e b/test/core/end2end/fuzzers/client_fuzzer_corpus/d4a72650e8218ec551fef6560ddd136d52828a4e
new file mode 100644
index 0000000..a67ab58
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d4a72650e8218ec551fef6560ddd136d52828a4e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d60469c0b5b385f20d55aa5cca55bc2c801f3b95 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d60469c0b5b385f20d55aa5cca55bc2c801f3b95
new file mode 100644
index 0000000..c186e49
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d60469c0b5b385f20d55aa5cca55bc2c801f3b95
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d70b2046ee62676b525490b70812c2157e5a3585 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d70b2046ee62676b525490b70812c2157e5a3585
new file mode 100644
index 0000000..8c5596a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d70b2046ee62676b525490b70812c2157e5a3585
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d727b7edb460c549d7b12b90f581048c9f4747e5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d727b7edb460c549d7b12b90f581048c9f4747e5
new file mode 100644
index 0000000..ce30807
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d727b7edb460c549d7b12b90f581048c9f4747e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d89026894e6c5f8b5c88dec12950f56c4b6924ba b/test/core/end2end/fuzzers/client_fuzzer_corpus/d89026894e6c5f8b5c88dec12950f56c4b6924ba
new file mode 100644
index 0000000..1c6f6e2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d89026894e6c5f8b5c88dec12950f56c4b6924ba
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d90c312791129dee8c5f85cb3308323d0c39b70d b/test/core/end2end/fuzzers/client_fuzzer_corpus/d90c312791129dee8c5f85cb3308323d0c39b70d
new file mode 100644
index 0000000..9ac4841
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d90c312791129dee8c5f85cb3308323d0c39b70d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d91281daad9b821294db204dfc244b2d0d5496e4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d91281daad9b821294db204dfc244b2d0d5496e4
new file mode 100644
index 0000000..b802985
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d91281daad9b821294db204dfc244b2d0d5496e4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/da322a6b88da87babb52d1527fe54cb4ac214b32 b/test/core/end2end/fuzzers/client_fuzzer_corpus/da322a6b88da87babb52d1527fe54cb4ac214b32
new file mode 100644
index 0000000..5325844
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/da322a6b88da87babb52d1527fe54cb4ac214b32
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/da4d300d0a8e6f803ec053e3e7689c4b91eaef90 b/test/core/end2end/fuzzers/client_fuzzer_corpus/da4d300d0a8e6f803ec053e3e7689c4b91eaef90
new file mode 100644
index 0000000..3341147
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/da4d300d0a8e6f803ec053e3e7689c4b91eaef90
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/da538941f1613c627523cb1be71eb220d1ca2579 b/test/core/end2end/fuzzers/client_fuzzer_corpus/da538941f1613c627523cb1be71eb220d1ca2579
new file mode 100644
index 0000000..3d6e58c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/da538941f1613c627523cb1be71eb220d1ca2579
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/da8d4c7f02dbeaa543c159b3a4e527059978a429 b/test/core/end2end/fuzzers/client_fuzzer_corpus/da8d4c7f02dbeaa543c159b3a4e527059978a429
new file mode 100644
index 0000000..07a2e53
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/da8d4c7f02dbeaa543c159b3a4e527059978a429
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/data_frame.bin b/test/core/end2end/fuzzers/client_fuzzer_corpus/data_frame.bin
new file mode 100644
index 0000000..a99061c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/data_frame.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/dc4a248fa4c903ce3a571dd18aea575019445740 b/test/core/end2end/fuzzers/client_fuzzer_corpus/dc4a248fa4c903ce3a571dd18aea575019445740
new file mode 100644
index 0000000..2ff2c5f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/dc4a248fa4c903ce3a571dd18aea575019445740
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/dc7ebba06558484af10b5aafd01ec4fd59276b12 b/test/core/end2end/fuzzers/client_fuzzer_corpus/dc7ebba06558484af10b5aafd01ec4fd59276b12
new file mode 100644
index 0000000..d06ecaa
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/dc7ebba06558484af10b5aafd01ec4fd59276b12
@@ -0,0 +1 @@
+!‘‘!‘N‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/dc815fd6d5e817898238481472f359bc50b510c4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/dc815fd6d5e817898238481472f359bc50b510c4
new file mode 100644
index 0000000..0bee6ac
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/dc815fd6d5e817898238481472f359bc50b510c4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/dccd1fd6d3394f5f68c87950ed7356a2e9ef0f6f b/test/core/end2end/fuzzers/client_fuzzer_corpus/dccd1fd6d3394f5f68c87950ed7356a2e9ef0f6f
new file mode 100644
index 0000000..9d01cd1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/dccd1fd6d3394f5f68c87950ed7356a2e9ef0f6f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/dd662353bad317cee7d16191a39e094bfa4898f2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/dd662353bad317cee7d16191a39e094bfa4898f2
new file mode 100644
index 0000000..2683cbb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/dd662353bad317cee7d16191a39e094bfa4898f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/df684493457bc8d87dec2ca0825f7b43978fecfd b/test/core/end2end/fuzzers/client_fuzzer_corpus/df684493457bc8d87dec2ca0825f7b43978fecfd
new file mode 100644
index 0000000..6cc31a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/df684493457bc8d87dec2ca0825f7b43978fecfd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e0d1ee5e2e169dcae87f790f5c27e84a3453cedb b/test/core/end2end/fuzzers/client_fuzzer_corpus/e0d1ee5e2e169dcae87f790f5c27e84a3453cedb
new file mode 100644
index 0000000..0be99ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e0d1ee5e2e169dcae87f790f5c27e84a3453cedb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e18cab69ad5cc17c88f8b56ca9929ca8af3eed30 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e18cab69ad5cc17c88f8b56ca9929ca8af3eed30
new file mode 100644
index 0000000..acce397
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e18cab69ad5cc17c88f8b56ca9929ca8af3eed30
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e1bd70aa5c802cd4462ff4833c09ed432ce4c9fa b/test/core/end2end/fuzzers/client_fuzzer_corpus/e1bd70aa5c802cd4462ff4833c09ed432ce4c9fa
new file mode 100644
index 0000000..b00ba83
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e1bd70aa5c802cd4462ff4833c09ed432ce4c9fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e1f2e203d39ab2509d4a67f7a44265b1e6364334 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e1f2e203d39ab2509d4a67f7a44265b1e6364334
new file mode 100644
index 0000000..5d1b4ec
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e1f2e203d39ab2509d4a67f7a44265b1e6364334
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e262f378a3d27bc519d472ce3650bdffcd48a055 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e262f378a3d27bc519d472ce3650bdffcd48a055
new file mode 100644
index 0000000..f2e303e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e262f378a3d27bc519d472ce3650bdffcd48a055
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e309e21c69e4b96ab37f675f4e87a52453512ef8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e309e21c69e4b96ab37f675f4e87a52453512ef8
new file mode 100644
index 0000000..3e856ee
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e309e21c69e4b96ab37f675f4e87a52453512ef8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e30c4ef6423bd4d872792fbd6954ff8e47d31a97 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e30c4ef6423bd4d872792fbd6954ff8e47d31a97
new file mode 100644
index 0000000..8abefd8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e30c4ef6423bd4d872792fbd6954ff8e47d31a97
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e3422e8f5d63a9ef180aab552353955c7aba90b0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e3422e8f5d63a9ef180aab552353955c7aba90b0
new file mode 100644
index 0000000..56efea5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e3422e8f5d63a9ef180aab552353955c7aba90b0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e40b0fa5d814be8f2081ca2c8e0a4090d4893831 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e40b0fa5d814be8f2081ca2c8e0a4090d4893831
new file mode 100644
index 0000000..887a303
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e40b0fa5d814be8f2081ca2c8e0a4090d4893831
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e442f9fd63bc5345de1c14803d4ca4bb6f1152cf b/test/core/end2end/fuzzers/client_fuzzer_corpus/e442f9fd63bc5345de1c14803d4ca4bb6f1152cf
new file mode 100644
index 0000000..4a6060c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e442f9fd63bc5345de1c14803d4ca4bb6f1152cf
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e4c0e27cfd3690b8255a8214d6dd055385d1d24e b/test/core/end2end/fuzzers/client_fuzzer_corpus/e4c0e27cfd3690b8255a8214d6dd055385d1d24e
new file mode 100644
index 0000000..3b67734
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e4c0e27cfd3690b8255a8214d6dd055385d1d24e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e4dc0a111e77dc495c5db07df5e2917adb674697 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e4dc0a111e77dc495c5db07df5e2917adb674697
new file mode 100644
index 0000000..e4fd8c6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e4dc0a111e77dc495c5db07df5e2917adb674697
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e5a7c086208248a15ee6fa5195fc4ce22469de15 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5a7c086208248a15ee6fa5195fc4ce22469de15
new file mode 100644
index 0000000..00dd612
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5a7c086208248a15ee6fa5195fc4ce22469de15
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e5ac3394971400b6636d029aec7ec665a94ecf29 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5ac3394971400b6636d029aec7ec665a94ecf29
new file mode 100644
index 0000000..6a0cc0c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5ac3394971400b6636d029aec7ec665a94ecf29
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e61f728210ce72ed8b2c066bd1b1ecf9e6824b77 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e61f728210ce72ed8b2c066bd1b1ecf9e6824b77
new file mode 100644
index 0000000..5b33b9b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e61f728210ce72ed8b2c066bd1b1ecf9e6824b77
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e6a08259a7d47601eab5c0249cb6547024e002c7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e6a08259a7d47601eab5c0249cb6547024e002c7
new file mode 100644
index 0000000..fd26981
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e6a08259a7d47601eab5c0249cb6547024e002c7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e6b3c920b47e00055226d49b9f715c5d4353e3e5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e6b3c920b47e00055226d49b9f715c5d4353e3e5
new file mode 100644
index 0000000..427937b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e6b3c920b47e00055226d49b9f715c5d4353e3e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e6f5cc0702a5f38b9e7339849e1dd2e4001e547d b/test/core/end2end/fuzzers/client_fuzzer_corpus/e6f5cc0702a5f38b9e7339849e1dd2e4001e547d
new file mode 100644
index 0000000..680f2d8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e6f5cc0702a5f38b9e7339849e1dd2e4001e547d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e7c26599fb2e2b031346ff1ba09294fd758f7abe b/test/core/end2end/fuzzers/client_fuzzer_corpus/e7c26599fb2e2b031346ff1ba09294fd758f7abe
new file mode 100644
index 0000000..fc1dec3
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e7c26599fb2e2b031346ff1ba09294fd758f7abe
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e8323c817d18f0c920d3cf53be41a9bc0fd64b76 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e8323c817d18f0c920d3cf53be41a9bc0fd64b76
new file mode 100644
index 0000000..5055202
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e8323c817d18f0c920d3cf53be41a9bc0fd64b76
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e969affd8af10a1b87dc63afd3b29cce3e58fbb2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e969affd8af10a1b87dc63afd3b29cce3e58fbb2
new file mode 100644
index 0000000..aa51bd5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e969affd8af10a1b87dc63afd3b29cce3e58fbb2
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e9f7f7f258c72222397a960652c01d2a37e2afe3 b/test/core/end2end/fuzzers/client_fuzzer_corpus/e9f7f7f258c72222397a960652c01d2a37e2afe3
new file mode 100644
index 0000000..87986b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e9f7f7f258c72222397a960652c01d2a37e2afe3
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/eb969b9ab1b0d6b5d197795223ba7a091ebd8460 b/test/core/end2end/fuzzers/client_fuzzer_corpus/eb969b9ab1b0d6b5d197795223ba7a091ebd8460
new file mode 100644
index 0000000..5074097
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/eb969b9ab1b0d6b5d197795223ba7a091ebd8460
@@ -0,0 +1 @@
+!mm!mmN•‘‘!‘m!‘NN'‘)*‘‘•‘‘!‘m!‘NNN‘NNN'‘)‘‘N‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ebb0786acc21c6185356eae9a62490a03fddd1f2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ebb0786acc21c6185356eae9a62490a03fddd1f2
new file mode 100644
index 0000000..9374102
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ebb0786acc21c6185356eae9a62490a03fddd1f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ec180175f0edea0a6c3eea2ae719b006bc029ff8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ec180175f0edea0a6c3eea2ae719b006bc029ff8
new file mode 100644
index 0000000..8655cae
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ec180175f0edea0a6c3eea2ae719b006bc029ff8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ed6358fbe6721c9ac01a6f4cab4d2df377eb1f11 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ed6358fbe6721c9ac01a6f4cab4d2df377eb1f11
new file mode 100644
index 0000000..1c4e252
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ed6358fbe6721c9ac01a6f4cab4d2df377eb1f11
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ee436743977b8e31feec22a91b1ce23dee96665e b/test/core/end2end/fuzzers/client_fuzzer_corpus/ee436743977b8e31feec22a91b1ce23dee96665e
new file mode 100644
index 0000000..94abe36
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ee436743977b8e31feec22a91b1ce23dee96665e
@@ -0,0 +1 @@
+!mã!ÿÿÿÿÿÿÿÿŒ
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ef1984d6146670122c7a7246374bca460e7284e5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ef1984d6146670122c7a7246374bca460e7284e5
new file mode 100644
index 0000000..6af61ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ef1984d6146670122c7a7246374bca460e7284e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/eff9ad9144a2953fadc019fe72eb1cc3447c33fb b/test/core/end2end/fuzzers/client_fuzzer_corpus/eff9ad9144a2953fadc019fe72eb1cc3447c33fb
new file mode 100644
index 0000000..6fd26ca
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/eff9ad9144a2953fadc019fe72eb1cc3447c33fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/empty b/test/core/end2end/fuzzers/client_fuzzer_corpus/empty
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/empty
@@ -0,0 +1 @@
+
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f03120d1a8376638e071735bf4746454b6ede389 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f03120d1a8376638e071735bf4746454b6ede389
new file mode 100644
index 0000000..b5e68ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f03120d1a8376638e071735bf4746454b6ede389
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f09410ab7bc19ee1ff206f94e8eec2931faef15f b/test/core/end2end/fuzzers/client_fuzzer_corpus/f09410ab7bc19ee1ff206f94e8eec2931faef15f
new file mode 100644
index 0000000..beaf36d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f09410ab7bc19ee1ff206f94e8eec2931faef15f
@@ -0,0 +1 @@
+m!‘‘NN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f1b9b6803e41beabb1a762d511fc148116e09e78 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f1b9b6803e41beabb1a762d511fc148116e09e78
new file mode 100644
index 0000000..0552e13
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f1b9b6803e41beabb1a762d511fc148116e09e78
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f24f925945aaf5e8b5ee470935e5aa7f847e7a72 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f24f925945aaf5e8b5ee470935e5aa7f847e7a72
new file mode 100644
index 0000000..065f15b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f24f925945aaf5e8b5ee470935e5aa7f847e7a72
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f41f9319bda14ef21b925c46945b30728503dfaf b/test/core/end2end/fuzzers/client_fuzzer_corpus/f41f9319bda14ef21b925c46945b30728503dfaf
new file mode 100644
index 0000000..52ef5bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f41f9319bda14ef21b925c46945b30728503dfaf
@@ -0,0 +1,2 @@

+‘a‘‘‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f4499e3d4bf60ae3ae929c485a13ea4dc2713369 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f4499e3d4bf60ae3ae929c485a13ea4dc2713369
new file mode 100644
index 0000000..0a9bf7c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f4499e3d4bf60ae3ae929c485a13ea4dc2713369
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f5b1eab444efb2664a295d4e6d087eb209c0c480 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f5b1eab444efb2664a295d4e6d087eb209c0c480
new file mode 100644
index 0000000..fe4cef0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f5b1eab444efb2664a295d4e6d087eb209c0c480
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f66305230042fa83fcd1b98c469d90ffef3ff6da b/test/core/end2end/fuzzers/client_fuzzer_corpus/f66305230042fa83fcd1b98c469d90ffef3ff6da
new file mode 100644
index 0000000..107dd45
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f66305230042fa83fcd1b98c469d90ffef3ff6da
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f6af3f46aacee395877d7f7909f8e412a6538efb b/test/core/end2end/fuzzers/client_fuzzer_corpus/f6af3f46aacee395877d7f7909f8e412a6538efb
new file mode 100644
index 0000000..3dbba7f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f6af3f46aacee395877d7f7909f8e412a6538efb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f74143e8160754e40eb4d21a182c970210707979 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f74143e8160754e40eb4d21a182c970210707979
new file mode 100644
index 0000000..de22f65
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f74143e8160754e40eb4d21a182c970210707979
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f7812b2aca4d12ffbdac67bcacc41b34524de6cb b/test/core/end2end/fuzzers/client_fuzzer_corpus/f7812b2aca4d12ffbdac67bcacc41b34524de6cb
new file mode 100644
index 0000000..828e42d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f7812b2aca4d12ffbdac67bcacc41b34524de6cb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f8467d9574de94b9bb904f75a6a7e2405c36f105 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f8467d9574de94b9bb904f75a6a7e2405c36f105
new file mode 100644
index 0000000..a8a8292
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f8467d9574de94b9bb904f75a6a7e2405c36f105
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f84f5d6188cf099465f0b70337b87ad8aa8efb78 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f84f5d6188cf099465f0b70337b87ad8aa8efb78
new file mode 100644
index 0000000..bc36c65
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f84f5d6188cf099465f0b70337b87ad8aa8efb78
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f8fb1348ec3ceeb75c2a03df6a2ead0de6f4127a b/test/core/end2end/fuzzers/client_fuzzer_corpus/f8fb1348ec3ceeb75c2a03df6a2ead0de6f4127a
new file mode 100644
index 0000000..82c6055
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f8fb1348ec3ceeb75c2a03df6a2ead0de6f4127a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f91f76fa45a23adfed48a10ec9512cf16bfb6636 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f91f76fa45a23adfed48a10ec9512cf16bfb6636
new file mode 100644
index 0000000..1c50bd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f91f76fa45a23adfed48a10ec9512cf16bfb6636
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f96843fdf2d6fdd661c26201d96ae7bec72c6c3d b/test/core/end2end/fuzzers/client_fuzzer_corpus/f96843fdf2d6fdd661c26201d96ae7bec72c6c3d
new file mode 100644
index 0000000..58c1734
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f96843fdf2d6fdd661c26201d96ae7bec72c6c3d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f9940356ee9b212849fbdf0d818b17af1a4f3c6c b/test/core/end2end/fuzzers/client_fuzzer_corpus/f9940356ee9b212849fbdf0d818b17af1a4f3c6c
new file mode 100644
index 0000000..0c2d2bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f9940356ee9b212849fbdf0d818b17af1a4f3c6c
@@ -0,0 +1 @@
+!mm‘•N!‘')‘ð‘NNN
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f9c875c00b7327df5bf21c3e051b55b0d2ed3cc8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f9c875c00b7327df5bf21c3e051b55b0d2ed3cc8
new file mode 100644
index 0000000..b89a2b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f9c875c00b7327df5bf21c3e051b55b0d2ed3cc8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fb340fff42a4d7ebf6b82adb9345655ffeeb05d9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/fb340fff42a4d7ebf6b82adb9345655ffeeb05d9
new file mode 100644
index 0000000..b978a69
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fb340fff42a4d7ebf6b82adb9345655ffeeb05d9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fc3ef8b3cb43e4d2721b252e7fb578d83ed6605f b/test/core/end2end/fuzzers/client_fuzzer_corpus/fc3ef8b3cb43e4d2721b252e7fb578d83ed6605f
new file mode 100644
index 0000000..3cf35b7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fc3ef8b3cb43e4d2721b252e7fb578d83ed6605f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fcc557c9844892675be823fac8788eb694a3a118 b/test/core/end2end/fuzzers/client_fuzzer_corpus/fcc557c9844892675be823fac8788eb694a3a118
new file mode 100644
index 0000000..f219f24
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fcc557c9844892675be823fac8788eb694a3a118
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fda07f0de15cac77ccc54ec221d81cdade189bfd b/test/core/end2end/fuzzers/client_fuzzer_corpus/fda07f0de15cac77ccc54ec221d81cdade189bfd
new file mode 100644
index 0000000..39b2594
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fda07f0de15cac77ccc54ec221d81cdade189bfd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fdb553b8d82e68270a7345b048772bf8367b1224 b/test/core/end2end/fuzzers/client_fuzzer_corpus/fdb553b8d82e68270a7345b048772bf8367b1224
new file mode 100644
index 0000000..4e4338b
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fdb553b8d82e68270a7345b048772bf8367b1224
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fe1390762579b5c335bbdea73e251b95b979c3c9 b/test/core/end2end/fuzzers/client_fuzzer_corpus/fe1390762579b5c335bbdea73e251b95b979c3c9
new file mode 100644
index 0000000..7fe5a73
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fe1390762579b5c335bbdea73e251b95b979c3c9
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fecccfc70b1cf1a524b9f28a9ba2c153c8e14d0e b/test/core/end2end/fuzzers/client_fuzzer_corpus/fecccfc70b1cf1a524b9f28a9ba2c153c8e14d0e
new file mode 100644
index 0000000..4378c8e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fecccfc70b1cf1a524b9f28a9ba2c153c8e14d0e
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/fef80aa34c31700ac8e53bede4a97131176ceef0 b/test/core/end2end/fuzzers/client_fuzzer_corpus/fef80aa34c31700ac8e53bede4a97131176ceef0
new file mode 100644
index 0000000..db02dd6
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/fef80aa34c31700ac8e53bede4a97131176ceef0
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/hdr_frame.bin b/test/core/end2end/fuzzers/client_fuzzer_corpus/hdr_frame.bin
new file mode 100644
index 0000000..a569bd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/hdr_frame.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/settings_frame_1.bin b/test/core/end2end/fuzzers/client_fuzzer_corpus/settings_frame_1.bin
new file mode 100644
index 0000000..49b1bbb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/settings_frame_1.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary
new file mode 100644
index 0000000..b081368
--- /dev/null
+++ b/test/core/end2end/fuzzers/hpack.dictionary
@@ -0,0 +1,170 @@
+# hpack fuzzing dictionary
+"\x010"
+"\x011"
+"\x012"
+"\x03200"
+"\x03204"
+"\x03206"
+"\x03304"
+"\x03400"
+"\x03404"
+"\x03500"
+"\x06accept"
+"\x0Eaccept-charset"
+"\x0Faccept-encoding"
+"\x0Faccept-language"
+"\x0Daccept-ranges"
+"\x1Baccess-control-allow-origin"
+"\x03age"
+"\x05allow"
+"\x10application/grpc"
+"\x0A:authority"
+"\x0Dauthorization"
+"\x0Dcache-control"
+"\x0Acensus-bin"
+"\x11census-binary-bin"
+"\x13content-disposition"
+"\x10content-encoding"
+"\x10content-language"
+"\x0Econtent-length"
+"\x10content-location"
+"\x0Dcontent-range"
+"\x0Ccontent-type"
+"\x06cookie"
+"\x04date"
+"\x07deflate"
+"\x0Cdeflate,gzip"
+"\x00"
+"\x04etag"
+"\x06expect"
+"\x07expires"
+"\x04from"
+"\x03GET"
+"\x04grpc"
+"\x14grpc-accept-encoding"
+"\x0Dgrpc-encoding"
+"\x1Egrpc-internal-encoding-request"
+"\x0Cgrpc-message"
+"\x0Bgrpc-status"
+"\x0Cgrpc-timeout"
+"\x04gzip"
+"\x0Dgzip, deflate"
+"\x04host"
+"\x04http"
+"\x05https"
+"\x08identity"
+"\x10identity,deflate"
+"\x15identity,deflate,gzip"
+"\x0Didentity,gzip"
+"\x08if-match"
+"\x11if-modified-since"
+"\x0Dif-none-match"
+"\x08if-range"
+"\x13if-unmodified-since"
+"\x0Dlast-modified"
+"\x04link"
+"\x08location"
+"\x0Cmax-forwards"
+"\x07:method"
+"\x05:path"
+"\x04POST"
+"\x12proxy-authenticate"
+"\x13proxy-authorization"
+"\x03PUT"
+"\x05range"
+"\x07referer"
+"\x07refresh"
+"\x0Bretry-after"
+"\x07:scheme"
+"\x06server"
+"\x0Aset-cookie"
+"\x01/"
+"\x0B/index.html"
+"\x07:status"
+"\x19strict-transport-security"
+"\x02te"
+"\x08trailers"
+"\x11transfer-encoding"
+"\x0Auser-agent"
+"\x04vary"
+"\x03via"
+"\x10www-authenticate"
+"\x00\x0Eaccept-charset\x00"
+"\x00\x06accept\x00"
+"\x00\x0Faccept-encoding\x00"
+"\x00\x0Faccept-encoding\x0Dgzip, deflate"
+"\x00\x0Faccept-language\x00"
+"\x00\x0Daccept-ranges\x00"
+"\x00\x1Baccess-control-allow-origin\x00"
+"\x00\x03age\x00"
+"\x00\x05allow\x00"
+"\x00\x0A:authority\x00"
+"\x00\x0Dauthorization\x00"
+"\x00\x0Dcache-control\x00"
+"\x00\x13content-disposition\x00"
+"\x00\x10content-encoding\x00"
+"\x00\x10content-language\x00"
+"\x00\x0Econtent-length\x00"
+"\x00\x10content-location\x00"
+"\x00\x0Dcontent-range\x00"
+"\x00\x0Ccontent-type\x10application/grpc"
+"\x00\x0Ccontent-type\x00"
+"\x00\x06cookie\x00"
+"\x00\x04date\x00"
+"\x00\x04etag\x00"
+"\x00\x06expect\x00"
+"\x00\x07expires\x00"
+"\x00\x04from\x00"
+"\x00\x14grpc-accept-encoding\x07deflate"
+"\x00\x14grpc-accept-encoding\x0Cdeflate,gzip"
+"\x00\x14grpc-accept-encoding\x04gzip"
+"\x00\x14grpc-accept-encoding\x08identity"
+"\x00\x14grpc-accept-encoding\x10identity,deflate"
+"\x00\x14grpc-accept-encoding\x15identity,deflate,gzip"
+"\x00\x14grpc-accept-encoding\x0Didentity,gzip"
+"\x00\x0Dgrpc-encoding\x07deflate"
+"\x00\x0Dgrpc-encoding\x04gzip"
+"\x00\x0Dgrpc-encoding\x08identity"
+"\x00\x0Bgrpc-status\x010"
+"\x00\x0Bgrpc-status\x011"
+"\x00\x0Bgrpc-status\x012"
+"\x00\x04host\x00"
+"\x00\x08if-match\x00"
+"\x00\x11if-modified-since\x00"
+"\x00\x0Dif-none-match\x00"
+"\x00\x08if-range\x00"
+"\x00\x13if-unmodified-since\x00"
+"\x00\x0Dlast-modified\x00"
+"\x00\x04link\x00"
+"\x00\x08location\x00"
+"\x00\x0Cmax-forwards\x00"
+"\x00\x07:method\x03GET"
+"\x00\x07:method\x04POST"
+"\x00\x07:method\x03PUT"
+"\x00\x05:path\x01/"
+"\x00\x05:path\x0B/index.html"
+"\x00\x12proxy-authenticate\x00"
+"\x00\x13proxy-authorization\x00"
+"\x00\x05range\x00"
+"\x00\x07referer\x00"
+"\x00\x07refresh\x00"
+"\x00\x0Bretry-after\x00"
+"\x00\x07:scheme\x04grpc"
+"\x00\x07:scheme\x04http"
+"\x00\x07:scheme\x05https"
+"\x00\x06server\x00"
+"\x00\x0Aset-cookie\x00"
+"\x00\x07:status\x03200"
+"\x00\x07:status\x03204"
+"\x00\x07:status\x03206"
+"\x00\x07:status\x03304"
+"\x00\x07:status\x03400"
+"\x00\x07:status\x03404"
+"\x00\x07:status\x03500"
+"\x00\x19strict-transport-security\x00"
+"\x00\x02te\x08trailers"
+"\x00\x11transfer-encoding\x00"
+"\x00\x0Auser-agent\x00"
+"\x00\x04vary\x00"
+"\x00\x03via\x00"
+"\x00\x10www-authenticate\x00"
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
new file mode 100644
index 0000000..4027371
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -0,0 +1,127 @@
+/*
+ *
+ * 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 <grpc/grpc.h>
+
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/surface/server.h"
+#include "test/core/util/memory_counters.h"
+#include "test/core/util/mock_endpoint.h"
+
+static const bool squelch = true;
+
+static void discard_write(gpr_slice slice) {}
+
+static void *tag(int n) { return (void *)(uintptr_t)n; }
+static int detag(void *p) { return (int)(uintptr_t)p; }
+
+static void dont_log(gpr_log_func_args *args) {}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  grpc_test_only_set_metadata_hash_seed(0);
+  struct grpc_memory_counters counters;
+  if (squelch) gpr_set_log_function(dont_log);
+  grpc_memory_counters_init();
+  grpc_init();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  grpc_endpoint *mock_endpoint = grpc_mock_endpoint_create(discard_write);
+  grpc_mock_endpoint_put_read(
+      &exec_ctx, mock_endpoint,
+      gpr_slice_from_copied_buffer((const char *)data, size));
+
+  grpc_server *server = grpc_server_create(NULL, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+  grpc_server_register_completion_queue(server, cq, NULL);
+  // TODO(ctiller): add registered methods (one for POST, one for PUT)
+  // void *registered_method =
+  //    grpc_server_register_method(server, "/reg", NULL, 0);
+  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_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0);
+
+  grpc_call *call1 = NULL;
+  grpc_call_details call_details1;
+  grpc_metadata_array request_metadata1;
+  grpc_call_details_init(&call_details1);
+  grpc_metadata_array_init(&request_metadata1);
+  int requested_calls = 0;
+
+  grpc_server_request_call(server, &call1, &call_details1, &request_metadata1,
+                           cq, cq, tag(1));
+  requested_calls++;
+
+  grpc_event ev;
+  while (1) {
+    grpc_exec_ctx_flush(&exec_ctx);
+    ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
+    switch (ev.type) {
+      case GRPC_QUEUE_TIMEOUT:
+        goto done;
+      case GRPC_QUEUE_SHUTDOWN:
+        break;
+      case GRPC_OP_COMPLETE:
+        switch (detag(ev.tag)) {
+          case 1:
+            requested_calls--;
+            // TODO(ctiller): keep reading that call!
+            break;
+        }
+    }
+  }
+
+done:
+  if (call1 != NULL) grpc_call_destroy(call1);
+  grpc_call_details_destroy(&call_details1);
+  grpc_metadata_array_destroy(&request_metadata1);
+  grpc_server_shutdown_and_notify(server, cq, tag(0xdead));
+  grpc_server_cancel_all_calls(server);
+  for (int i = 0; i <= requested_calls; i++) {
+    ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
+    GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+  }
+  grpc_completion_queue_shutdown(cq);
+  for (int i = 0; i <= requested_calls; i++) {
+    ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
+    GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN);
+  }
+  grpc_server_destroy(server);
+  grpc_completion_queue_destroy(cq);
+  grpc_shutdown();
+  counters = grpc_memory_counters_snapshot();
+  grpc_memory_counters_destroy();
+  GPR_ASSERT(counters.total_size_relative == 0);
+  return 0;
+}
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/01c008fa.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/01c008fa.bin
new file mode 100644
index 0000000..2f670cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/01c008fa.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/021ec59f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/021ec59f.bin
new file mode 100644
index 0000000..b4896fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/021ec59f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/02918e4ad9e8928845f232c0cb043057add3c9a9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/02918e4ad9e8928845f232c0cb043057add3c9a9
new file mode 100644
index 0000000..5f53b70
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/02918e4ad9e8928845f232c0cb043057add3c9a9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0336e1ff71939de9e2007fdb4aba891e35a37488 b/test/core/end2end/fuzzers/server_fuzzer_corpus/0336e1ff71939de9e2007fdb4aba891e35a37488
new file mode 100644
index 0000000..c1d8fa1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0336e1ff71939de9e2007fdb4aba891e35a37488
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/033dd2f6.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/033dd2f6.bin
new file mode 100644
index 0000000..732d846
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/033dd2f6.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0384345c.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/0384345c.bin
new file mode 100644
index 0000000..00c4956
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0384345c.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/03b9be1fa172dff5d1543be079b9c64fa2c9a278 b/test/core/end2end/fuzzers/server_fuzzer_corpus/03b9be1fa172dff5d1543be079b9c64fa2c9a278
new file mode 100644
index 0000000..94a877e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/03b9be1fa172dff5d1543be079b9c64fa2c9a278
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/05c3a0390d0f52d241728926fa901599a47e4606 b/test/core/end2end/fuzzers/server_fuzzer_corpus/05c3a0390d0f52d241728926fa901599a47e4606
new file mode 100644
index 0000000..4c657a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/05c3a0390d0f52d241728926fa901599a47e4606
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/05efe6d81ce606557691432634e81f61e68b0b81 b/test/core/end2end/fuzzers/server_fuzzer_corpus/05efe6d81ce606557691432634e81f61e68b0b81
new file mode 100644
index 0000000..fd00271
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/05efe6d81ce606557691432634e81f61e68b0b81
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/06bd2f82fefb9943787d63ea359f9b77072380c2 b/test/core/end2end/fuzzers/server_fuzzer_corpus/06bd2f82fefb9943787d63ea359f9b77072380c2
new file mode 100644
index 0000000..c3408cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/06bd2f82fefb9943787d63ea359f9b77072380c2
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0766afc7c27c06ea18d896083470d587a380de3c b/test/core/end2end/fuzzers/server_fuzzer_corpus/0766afc7c27c06ea18d896083470d587a380de3c
new file mode 100644
index 0000000..dbe2ade
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0766afc7c27c06ea18d896083470d587a380de3c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/07ad7e0ea2aaecba37f2429a64e946fc6e2556f1 b/test/core/end2end/fuzzers/server_fuzzer_corpus/07ad7e0ea2aaecba37f2429a64e946fc6e2556f1
new file mode 100644
index 0000000..c400e76
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/07ad7e0ea2aaecba37f2429a64e946fc6e2556f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/07c96c06eddbed5a3ce050436bc805f6821cbc9b b/test/core/end2end/fuzzers/server_fuzzer_corpus/07c96c06eddbed5a3ce050436bc805f6821cbc9b
new file mode 100644
index 0000000..7d5fb0b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/07c96c06eddbed5a3ce050436bc805f6821cbc9b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/081e56ce6f6b1c57adb806fbc5baa9f93f87513a b/test/core/end2end/fuzzers/server_fuzzer_corpus/081e56ce6f6b1c57adb806fbc5baa9f93f87513a
new file mode 100644
index 0000000..5c01671
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/081e56ce6f6b1c57adb806fbc5baa9f93f87513a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/08492d3d0994005206d1d3213b8747d1026ae1eb b/test/core/end2end/fuzzers/server_fuzzer_corpus/08492d3d0994005206d1d3213b8747d1026ae1eb
new file mode 100644
index 0000000..0910f93
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/08492d3d0994005206d1d3213b8747d1026ae1eb
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/09938e3256d06a8e168eb038d8a58b8462f7f697 b/test/core/end2end/fuzzers/server_fuzzer_corpus/09938e3256d06a8e168eb038d8a58b8462f7f697
new file mode 100644
index 0000000..0c1be25
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/09938e3256d06a8e168eb038d8a58b8462f7f697
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0aa599e20761777c2cb9b41cd89e5c2e18f82d9e b/test/core/end2end/fuzzers/server_fuzzer_corpus/0aa599e20761777c2cb9b41cd89e5c2e18f82d9e
new file mode 100644
index 0000000..efbfeaf
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0aa599e20761777c2cb9b41cd89e5c2e18f82d9e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0aa7b949.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/0aa7b949.bin
new file mode 100644
index 0000000..0e22a45
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0aa7b949.bin
@@ -0,0 +1 @@
+PRI * HTTP/2X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0abd533e.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/0abd533e.bin
new file mode 100644
index 0000000..112188c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0abd533e.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0b275a7f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/0b275a7f.bin
new file mode 100644
index 0000000..853ca7c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0b275a7f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0c413d2b361b2221585026d42f3046ff4135d2ff b/test/core/end2end/fuzzers/server_fuzzer_corpus/0c413d2b361b2221585026d42f3046ff4135d2ff
new file mode 100644
index 0000000..34bee24
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0c413d2b361b2221585026d42f3046ff4135d2ff
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0d10bb63.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/0d10bb63.bin
new file mode 100644
index 0000000..50bb312
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0d10bb63.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0e349b8762703d080b3a696600e21d64c23a2ed3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/0e349b8762703d080b3a696600e21d64c23a2ed3
new file mode 100644
index 0000000..c57226e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0e349b8762703d080b3a696600e21d64c23a2ed3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0f700e05.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/0f700e05.bin
new file mode 100644
index 0000000..f861853
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0f700e05.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0ff4d220.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/0ff4d220.bin
new file mode 100644
index 0000000..fc79411
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0ff4d220.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/10724098.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/10724098.bin
new file mode 100644
index 0000000..9d1a39d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/10724098.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/108e270a272e312fc97ec23004b80fdc7bad3906 b/test/core/end2end/fuzzers/server_fuzzer_corpus/108e270a272e312fc97ec23004b80fdc7bad3906
new file mode 100644
index 0000000..2d703cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/108e270a272e312fc97ec23004b80fdc7bad3906
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/11516d58.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/11516d58.bin
new file mode 100644
index 0000000..7edd81d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/11516d58.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/11cda3f70be4b507ea936bca93af9ce5aaab3be7 b/test/core/end2end/fuzzers/server_fuzzer_corpus/11cda3f70be4b507ea936bca93af9ce5aaab3be7
new file mode 100644
index 0000000..62cbd41
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/11cda3f70be4b507ea936bca93af9ce5aaab3be7
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/13501419f349b7855d2e94060bd08b28923d1f37 b/test/core/end2end/fuzzers/server_fuzzer_corpus/13501419f349b7855d2e94060bd08b28923d1f37
new file mode 100644
index 0000000..34906e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/13501419f349b7855d2e94060bd08b28923d1f37
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1421a8e9f045ac65a0f6938fae93fece1060c41d b/test/core/end2end/fuzzers/server_fuzzer_corpus/1421a8e9f045ac65a0f6938fae93fece1060c41d
new file mode 100644
index 0000000..ce7a5ed
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1421a8e9f045ac65a0f6938fae93fece1060c41d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/146b7d66ad932c4b623eec8004e286d3705697d3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/146b7d66ad932c4b623eec8004e286d3705697d3
new file mode 100644
index 0000000..e6a8541
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/146b7d66ad932c4b623eec8004e286d3705697d3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/14f9a0cda0d64590430218aaf6dedd9be2a3533f b/test/core/end2end/fuzzers/server_fuzzer_corpus/14f9a0cda0d64590430218aaf6dedd9be2a3533f
new file mode 100644
index 0000000..7f448c2
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/14f9a0cda0d64590430218aaf6dedd9be2a3533f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/15ae78a8543a4794a27e6c79b0d34540322b97fd b/test/core/end2end/fuzzers/server_fuzzer_corpus/15ae78a8543a4794a27e6c79b0d34540322b97fd
new file mode 100644
index 0000000..602f456
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/15ae78a8543a4794a27e6c79b0d34540322b97fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/15afdcf2cadb93f56dbe36233d8cd7ea9d2bd6fe b/test/core/end2end/fuzzers/server_fuzzer_corpus/15afdcf2cadb93f56dbe36233d8cd7ea9d2bd6fe
new file mode 100644
index 0000000..b63ef6b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/15afdcf2cadb93f56dbe36233d8cd7ea9d2bd6fe
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1650b19093c56a1e86ee192bd9cd8d2266a9e353 b/test/core/end2end/fuzzers/server_fuzzer_corpus/1650b19093c56a1e86ee192bd9cd8d2266a9e353
new file mode 100644
index 0000000..1aab198
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1650b19093c56a1e86ee192bd9cd8d2266a9e353
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/16753235697083ecc45c117287f1d8ce6ad1ad1a b/test/core/end2end/fuzzers/server_fuzzer_corpus/16753235697083ecc45c117287f1d8ce6ad1ad1a
new file mode 100644
index 0000000..0e4097e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/16753235697083ecc45c117287f1d8ce6ad1ad1a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/17d7c718ec2597353a5dd2c78d6717a3d6aabfae b/test/core/end2end/fuzzers/server_fuzzer_corpus/17d7c718ec2597353a5dd2c78d6717a3d6aabfae
new file mode 100644
index 0000000..8f5786f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/17d7c718ec2597353a5dd2c78d6717a3d6aabfae
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/18d8d274aa7c163fd6d0084d5c25c8623e10c541 b/test/core/end2end/fuzzers/server_fuzzer_corpus/18d8d274aa7c163fd6d0084d5c25c8623e10c541
new file mode 100644
index 0000000..6c44d1a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/18d8d274aa7c163fd6d0084d5c25c8623e10c541
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/18f00b5f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/18f00b5f.bin
new file mode 100644
index 0000000..a41cbd4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/18f00b5f.bin
@@ -0,0 +1 @@
+PRI * HTTX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1939a9021aba59ea2e49d3d0909e6fdf86ac3f9e b/test/core/end2end/fuzzers/server_fuzzer_corpus/1939a9021aba59ea2e49d3d0909e6fdf86ac3f9e
new file mode 100644
index 0000000..e5acc97
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1939a9021aba59ea2e49d3d0909e6fdf86ac3f9e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1a69d5fc.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/1a69d5fc.bin
new file mode 100644
index 0000000..db1c0d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1a69d5fc.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1aa6897b6eebb8c68c972cc5025b39c7e60c17fe b/test/core/end2end/fuzzers/server_fuzzer_corpus/1aa6897b6eebb8c68c972cc5025b39c7e60c17fe
new file mode 100644
index 0000000..699279d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1aa6897b6eebb8c68c972cc5025b39c7e60c17fe
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1cf17783de9e662f3720847f2d83d86dcdcab500 b/test/core/end2end/fuzzers/server_fuzzer_corpus/1cf17783de9e662f3720847f2d83d86dcdcab500
new file mode 100644
index 0000000..21a3a65
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1cf17783de9e662f3720847f2d83d86dcdcab500
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1cfdde7a.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/1cfdde7a.bin
new file mode 100644
index 0000000..61a954d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1cfdde7a.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1d614f3d6b826f844178a77094bedb534748a362 b/test/core/end2end/fuzzers/server_fuzzer_corpus/1d614f3d6b826f844178a77094bedb534748a362
new file mode 100644
index 0000000..ece6c2f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1d614f3d6b826f844178a77094bedb534748a362
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1e92aaa5.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/1e92aaa5.bin
new file mode 100644
index 0000000..02796cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1e92aaa5.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1ea5651f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/1ea5651f.bin
new file mode 100644
index 0000000..782f21d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1ea5651f.bin
@@ -0,0 +1 @@
+PRI * X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1f992057.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/1f992057.bin
new file mode 100644
index 0000000..c60d1eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1f992057.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/20fd12d3670571283dc0c5dbb3fc139a8e943790 b/test/core/end2end/fuzzers/server_fuzzer_corpus/20fd12d3670571283dc0c5dbb3fc139a8e943790
new file mode 100644
index 0000000..1bf164c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/20fd12d3670571283dc0c5dbb3fc139a8e943790
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/21475569.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/21475569.bin
new file mode 100644
index 0000000..06aecff
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/21475569.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/218c1b123428a07622570947e9b7cdb48c310ca5 b/test/core/end2end/fuzzers/server_fuzzer_corpus/218c1b123428a07622570947e9b7cdb48c310ca5
new file mode 100644
index 0000000..d7ec737
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/218c1b123428a07622570947e9b7cdb48c310ca5
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/21a2dcda.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/21a2dcda.bin
new file mode 100644
index 0000000..92b918f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/21a2dcda.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/22ad891a.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/22ad891a.bin
new file mode 100644
index 0000000..edd095a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/22ad891a.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2463aea879c5ab49f8409d0e5c062c7e086b034b b/test/core/end2end/fuzzers/server_fuzzer_corpus/2463aea879c5ab49f8409d0e5c062c7e086b034b
new file mode 100644
index 0000000..aecaacd
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2463aea879c5ab49f8409d0e5c062c7e086b034b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/24ed80095e58199c52997f174046272f61ce4a8d b/test/core/end2end/fuzzers/server_fuzzer_corpus/24ed80095e58199c52997f174046272f61ce4a8d
new file mode 100644
index 0000000..a2f7fad
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/24ed80095e58199c52997f174046272f61ce4a8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/25ab638f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/25ab638f.bin
new file mode 100644
index 0000000..af5a22a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/25ab638f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/26048c58bd5f2a94843f6fd1e4ab0be04b232636 b/test/core/end2end/fuzzers/server_fuzzer_corpus/26048c58bd5f2a94843f6fd1e4ab0be04b232636
new file mode 100644
index 0000000..e87be99
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/26048c58bd5f2a94843f6fd1e4ab0be04b232636
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/26870785fd0564f552af4e0ca418738a85b21086 b/test/core/end2end/fuzzers/server_fuzzer_corpus/26870785fd0564f552af4e0ca418738a85b21086
new file mode 100644
index 0000000..2e53646
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/26870785fd0564f552af4e0ca418738a85b21086
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2701d1669c2996c097a74c5255d569615357b916 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2701d1669c2996c097a74c5255d569615357b916
new file mode 100644
index 0000000..ec7d792
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2701d1669c2996c097a74c5255d569615357b916
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/27ac2ae2.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/27ac2ae2.bin
new file mode 100644
index 0000000..0daef3f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/27ac2ae2.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2814d70c.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/2814d70c.bin
new file mode 100644
index 0000000..500c070
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2814d70c.bin
@@ -0,0 +1 @@
+X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/282b6585.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/282b6585.bin
new file mode 100644
index 0000000..a2cabf6
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/282b6585.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2a688fd507072e1cfa2e3bc58652a7cd82dface3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2a688fd507072e1cfa2e3bc58652a7cd82dface3
new file mode 100644
index 0000000..682ed1f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2a688fd507072e1cfa2e3bc58652a7cd82dface3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2abe64b96e5e72adcf2dcc43444a69d0fb664b66 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2abe64b96e5e72adcf2dcc43444a69d0fb664b66
new file mode 100644
index 0000000..a5e92ec
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2abe64b96e5e72adcf2dcc43444a69d0fb664b66
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2ad6cedd32cd646ba8e25226c7c13a107c1d6447 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2ad6cedd32cd646ba8e25226c7c13a107c1d6447
new file mode 100644
index 0000000..da6f569
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2ad6cedd32cd646ba8e25226c7c13a107c1d6447
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2b14c6e618ec95754ea7e24fe6bc5a3a97df6897 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2b14c6e618ec95754ea7e24fe6bc5a3a97df6897
new file mode 100644
index 0000000..3c79631
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2b14c6e618ec95754ea7e24fe6bc5a3a97df6897
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2b40aa21723c7e67e92e74a3083df008461d591c b/test/core/end2end/fuzzers/server_fuzzer_corpus/2b40aa21723c7e67e92e74a3083df008461d591c
new file mode 100644
index 0000000..f7e2877
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2b40aa21723c7e67e92e74a3083df008461d591c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2bf69fe6b40734cc3f0abdd765757809b14b0b88 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2bf69fe6b40734cc3f0abdd765757809b14b0b88
new file mode 100644
index 0000000..391e893
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2bf69fe6b40734cc3f0abdd765757809b14b0b88
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2c6660ba.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/2c6660ba.bin
new file mode 100644
index 0000000..5f96b34
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2c6660ba.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2cc6d1f3ee8933518e91b8410781fa6e105b3a15 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2cc6d1f3ee8933518e91b8410781fa6e105b3a15
new file mode 100644
index 0000000..da23fe1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2cc6d1f3ee8933518e91b8410781fa6e105b3a15
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2e4805c3.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/2e4805c3.bin
new file mode 100644
index 0000000..2041099
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2e4805c3.bin
@@ -0,0 +1,3 @@
+PRI * HTTP/2.0

+

+SX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2f20e2decd09b6f211a5469c67efbada355e6c04 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2f20e2decd09b6f211a5469c67efbada355e6c04
new file mode 100644
index 0000000..19ce52c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2f20e2decd09b6f211a5469c67efbada355e6c04
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2f3b1cd6780fe475f76f17e9e36541963d993165 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2f3b1cd6780fe475f76f17e9e36541963d993165
new file mode 100644
index 0000000..bf0334b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2f3b1cd6780fe475f76f17e9e36541963d993165
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/2fb017cd4c34f4af183d03c4a219d2bb36ee2dd6 b/test/core/end2end/fuzzers/server_fuzzer_corpus/2fb017cd4c34f4af183d03c4a219d2bb36ee2dd6
new file mode 100644
index 0000000..df31fcf
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/2fb017cd4c34f4af183d03c4a219d2bb36ee2dd6
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/30bba77d0f420c4f454011476f3c94e31c50c161 b/test/core/end2end/fuzzers/server_fuzzer_corpus/30bba77d0f420c4f454011476f3c94e31c50c161
new file mode 100644
index 0000000..f172eb7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/30bba77d0f420c4f454011476f3c94e31c50c161
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3224e6cd.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/3224e6cd.bin
new file mode 100644
index 0000000..b1bfc23
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3224e6cd.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/326ec4d5.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/326ec4d5.bin
new file mode 100644
index 0000000..98c7665
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/326ec4d5.bin
@@ -0,0 +1 @@
+PRIX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3292129aa7f6eba86b70fff64408f18fff895c12 b/test/core/end2end/fuzzers/server_fuzzer_corpus/3292129aa7f6eba86b70fff64408f18fff895c12
new file mode 100644
index 0000000..6e3f0e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3292129aa7f6eba86b70fff64408f18fff895c12
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/32b11997.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/32b11997.bin
new file mode 100644
index 0000000..f19bc29
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/32b11997.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/32cecacca27b249bd764f852168036c5f962bd16 b/test/core/end2end/fuzzers/server_fuzzer_corpus/32cecacca27b249bd764f852168036c5f962bd16
new file mode 100644
index 0000000..38d8c2a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/32cecacca27b249bd764f852168036c5f962bd16
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/330ad4b6.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/330ad4b6.bin
new file mode 100644
index 0000000..d4b63ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/330ad4b6.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/33b4cf1ac251f0ba0c014005ef8207afe1dea623 b/test/core/end2end/fuzzers/server_fuzzer_corpus/33b4cf1ac251f0ba0c014005ef8207afe1dea623
new file mode 100644
index 0000000..4b297d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/33b4cf1ac251f0ba0c014005ef8207afe1dea623
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/33e2ecd5c9bbc1f1dcab29d00195e0ab6d04642d b/test/core/end2end/fuzzers/server_fuzzer_corpus/33e2ecd5c9bbc1f1dcab29d00195e0ab6d04642d
new file mode 100644
index 0000000..cc2058d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/33e2ecd5c9bbc1f1dcab29d00195e0ab6d04642d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/340b032d39e2b212828a2bd1a97e2b6b81dcd41b b/test/core/end2end/fuzzers/server_fuzzer_corpus/340b032d39e2b212828a2bd1a97e2b6b81dcd41b
new file mode 100644
index 0000000..d4240cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/340b032d39e2b212828a2bd1a97e2b6b81dcd41b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/34bba9e4.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/34bba9e4.bin
new file mode 100644
index 0000000..1c77a38
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/34bba9e4.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/374262a5acf9cde1f480e7b7254c788e1936a4de b/test/core/end2end/fuzzers/server_fuzzer_corpus/374262a5acf9cde1f480e7b7254c788e1936a4de
new file mode 100644
index 0000000..229f071
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/374262a5acf9cde1f480e7b7254c788e1936a4de
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/37ec9df8.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/37ec9df8.bin
new file mode 100644
index 0000000..5400eb5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/37ec9df8.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/38df7e63181cbd045e5af9dbee463360c8254618 b/test/core/end2end/fuzzers/server_fuzzer_corpus/38df7e63181cbd045e5af9dbee463360c8254618
new file mode 100644
index 0000000..c46dc83
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/38df7e63181cbd045e5af9dbee463360c8254618
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/39ea47bb.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/39ea47bb.bin
new file mode 100644
index 0000000..13997e0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/39ea47bb.bin
@@ -0,0 +1 @@
+PRI * HTTP/2.X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3aa82376296ab5a33f2921d7705b75b78b683c2d b/test/core/end2end/fuzzers/server_fuzzer_corpus/3aa82376296ab5a33f2921d7705b75b78b683c2d
new file mode 100644
index 0000000..112fbd1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3aa82376296ab5a33f2921d7705b75b78b683c2d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3ca5da2f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/3ca5da2f.bin
new file mode 100644
index 0000000..5b46240
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3ca5da2f.bin
@@ -0,0 +1,3 @@
+PRI * HTTP/2.0

+

+SMX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3d7ef8c7b05f26e914c479dedb1bef5e378d2d94 b/test/core/end2end/fuzzers/server_fuzzer_corpus/3d7ef8c7b05f26e914c479dedb1bef5e378d2d94
new file mode 100644
index 0000000..fb9af0d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3d7ef8c7b05f26e914c479dedb1bef5e378d2d94
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3dc665f93db294b9ccb8fcec94bcc2a91f3a04e7 b/test/core/end2end/fuzzers/server_fuzzer_corpus/3dc665f93db294b9ccb8fcec94bcc2a91f3a04e7
new file mode 100644
index 0000000..efde0d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3dc665f93db294b9ccb8fcec94bcc2a91f3a04e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3de41f3f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/3de41f3f.bin
new file mode 100644
index 0000000..262ed24
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3de41f3f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3e2077a4fd2def7b11e618d46245d0aa85824317 b/test/core/end2end/fuzzers/server_fuzzer_corpus/3e2077a4fd2def7b11e618d46245d0aa85824317
new file mode 100644
index 0000000..69263de
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3e2077a4fd2def7b11e618d46245d0aa85824317
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3e3ae35a.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/3e3ae35a.bin
new file mode 100644
index 0000000..49c7897
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3e3ae35a.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3e787760.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/3e787760.bin
new file mode 100644
index 0000000..3b8a1ed
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3e787760.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3f3069cf26f761366f947e025f7049254d555e7f b/test/core/end2end/fuzzers/server_fuzzer_corpus/3f3069cf26f761366f947e025f7049254d555e7f
new file mode 100644
index 0000000..cd907fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3f3069cf26f761366f947e025f7049254d555e7f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/407607d2.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/407607d2.bin
new file mode 100644
index 0000000..8e48939
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/407607d2.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/40af8d589c76d7912bec06c2ae1f2466065018e7 b/test/core/end2end/fuzzers/server_fuzzer_corpus/40af8d589c76d7912bec06c2ae1f2466065018e7
new file mode 100644
index 0000000..c72af8a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/40af8d589c76d7912bec06c2ae1f2466065018e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/418f392319c44d06a018ce4c62569d527829177a b/test/core/end2end/fuzzers/server_fuzzer_corpus/418f392319c44d06a018ce4c62569d527829177a
new file mode 100644
index 0000000..2d72c37
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/418f392319c44d06a018ce4c62569d527829177a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/41b31ef0.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/41b31ef0.bin
new file mode 100644
index 0000000..7469434
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/41b31ef0.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/422708b4.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/422708b4.bin
new file mode 100644
index 0000000..111a2b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/422708b4.bin
@@ -0,0 +1 @@
+PRI * HTTP/X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/422fa704.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/422fa704.bin
new file mode 100644
index 0000000..bfdd460
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/422fa704.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4271fbb36e03cee79b21a4a5a65f37ceef58a8cd b/test/core/end2end/fuzzers/server_fuzzer_corpus/4271fbb36e03cee79b21a4a5a65f37ceef58a8cd
new file mode 100644
index 0000000..a2ee89d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4271fbb36e03cee79b21a4a5a65f37ceef58a8cd
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/42b0afca.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/42b0afca.bin
new file mode 100644
index 0000000..e01fec2
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/42b0afca.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/43fc6abab9840be5ee614211f17395b5966f6070 b/test/core/end2end/fuzzers/server_fuzzer_corpus/43fc6abab9840be5ee614211f17395b5966f6070
new file mode 100644
index 0000000..2c7f585
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/43fc6abab9840be5ee614211f17395b5966f6070
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/44516839d35af9ccaf8a2c62f3ce6a723482445e b/test/core/end2end/fuzzers/server_fuzzer_corpus/44516839d35af9ccaf8a2c62f3ce6a723482445e
new file mode 100644
index 0000000..890f934
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/44516839d35af9ccaf8a2c62f3ce6a723482445e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/44f342a6.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/44f342a6.bin
new file mode 100644
index 0000000..1e7e47b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/44f342a6.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4558ddeb.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/4558ddeb.bin
new file mode 100644
index 0000000..7b9f09f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4558ddeb.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/459c0bf6.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/459c0bf6.bin
new file mode 100644
index 0000000..fcb842e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/459c0bf6.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/468cf8bf3e31e1013c7c6d2288baac47ff90aa63 b/test/core/end2end/fuzzers/server_fuzzer_corpus/468cf8bf3e31e1013c7c6d2288baac47ff90aa63
new file mode 100644
index 0000000..71cf9ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/468cf8bf3e31e1013c7c6d2288baac47ff90aa63
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4aa883d0.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/4aa883d0.bin
new file mode 100644
index 0000000..2657149
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4aa883d0.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4b7bcb4ae6c0222a1a24d1fb1a5d96519750ca5e b/test/core/end2end/fuzzers/server_fuzzer_corpus/4b7bcb4ae6c0222a1a24d1fb1a5d96519750ca5e
new file mode 100644
index 0000000..f6168fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4b7bcb4ae6c0222a1a24d1fb1a5d96519750ca5e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4c412cc1a775cea041fa270483d610afb72f463b b/test/core/end2end/fuzzers/server_fuzzer_corpus/4c412cc1a775cea041fa270483d610afb72f463b
new file mode 100644
index 0000000..5ef77a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4c412cc1a775cea041fa270483d610afb72f463b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4d55d5ae.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/4d55d5ae.bin
new file mode 100644
index 0000000..7e5544c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4d55d5ae.bin
@@ -0,0 +1 @@
+PRI *X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4db3d4075ed27f2a2311f85dd1d6df028cc5d083 b/test/core/end2end/fuzzers/server_fuzzer_corpus/4db3d4075ed27f2a2311f85dd1d6df028cc5d083
new file mode 100644
index 0000000..a084359
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4db3d4075ed27f2a2311f85dd1d6df028cc5d083
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4eb269c3.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/4eb269c3.bin
new file mode 100644
index 0000000..cf6e9d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4eb269c3.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4ecfe1be695df0d2489dddb52da8bcdeb6ed779d b/test/core/end2end/fuzzers/server_fuzzer_corpus/4ecfe1be695df0d2489dddb52da8bcdeb6ed779d
new file mode 100644
index 0000000..91eb6a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4ecfe1be695df0d2489dddb52da8bcdeb6ed779d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4f97bd97ab5dc6b4c0f62f8459be8a9593dc83b3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/4f97bd97ab5dc6b4c0f62f8459be8a9593dc83b3
new file mode 100644
index 0000000..bb5688e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4f97bd97ab5dc6b4c0f62f8459be8a9593dc83b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/4ff50e49865768323f94116bd98d2314455273cc b/test/core/end2end/fuzzers/server_fuzzer_corpus/4ff50e49865768323f94116bd98d2314455273cc
new file mode 100644
index 0000000..01cd4a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/4ff50e49865768323f94116bd98d2314455273cc
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/508def44e4d60f237f18a40d7058e58a752a74e1 b/test/core/end2end/fuzzers/server_fuzzer_corpus/508def44e4d60f237f18a40d7058e58a752a74e1
new file mode 100644
index 0000000..ab378be
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/508def44e4d60f237f18a40d7058e58a752a74e1
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/51a1abd1.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/51a1abd1.bin
new file mode 100644
index 0000000..dbf6a08
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/51a1abd1.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/52b5478161de7b2eba0f7bfbc29aea985c8d9ee7 b/test/core/end2end/fuzzers/server_fuzzer_corpus/52b5478161de7b2eba0f7bfbc29aea985c8d9ee7
new file mode 100644
index 0000000..943d162
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/52b5478161de7b2eba0f7bfbc29aea985c8d9ee7
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/52ecfedca3b2b26e6999b6afc846f3dbd5d35130 b/test/core/end2end/fuzzers/server_fuzzer_corpus/52ecfedca3b2b26e6999b6afc846f3dbd5d35130
new file mode 100644
index 0000000..58d0378
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/52ecfedca3b2b26e6999b6afc846f3dbd5d35130
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/53d18398c0d484de00afd8d583fe802d55d4da44 b/test/core/end2end/fuzzers/server_fuzzer_corpus/53d18398c0d484de00afd8d583fe802d55d4da44
new file mode 100644
index 0000000..e337a1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/53d18398c0d484de00afd8d583fe802d55d4da44
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/53de507f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/53de507f.bin
new file mode 100644
index 0000000..a659525
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/53de507f.bin
@@ -0,0 +1,5 @@
+PRI * HTTP/2.0

+

+SM

+

+
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/540ada69.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/540ada69.bin
new file mode 100644
index 0000000..18f0a36
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/540ada69.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5413b531fe06923ddf2c9e3eb958769374bc2445 b/test/core/end2end/fuzzers/server_fuzzer_corpus/5413b531fe06923ddf2c9e3eb958769374bc2445
new file mode 100644
index 0000000..cf83d57
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5413b531fe06923ddf2c9e3eb958769374bc2445
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5429f0da.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/5429f0da.bin
new file mode 100644
index 0000000..001c62c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5429f0da.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5435005f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/5435005f.bin
new file mode 100644
index 0000000..999a656
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5435005f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/546367bfdd2b9464fbfe5d74f55d8cd220accbab b/test/core/end2end/fuzzers/server_fuzzer_corpus/546367bfdd2b9464fbfe5d74f55d8cd220accbab
new file mode 100644
index 0000000..d2711d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/546367bfdd2b9464fbfe5d74f55d8cd220accbab
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/54d0fc6c.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/54d0fc6c.bin
new file mode 100644
index 0000000..24b882d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/54d0fc6c.bin
@@ -0,0 +1,4 @@
+PRI * HTTP/2.0

+

+SM

+X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/55af20415ead0ddd417f37fa91a4c767b749ee34 b/test/core/end2end/fuzzers/server_fuzzer_corpus/55af20415ead0ddd417f37fa91a4c767b749ee34
new file mode 100644
index 0000000..adbf92f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/55af20415ead0ddd417f37fa91a4c767b749ee34
@@ -0,0 +1 @@
+PR
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/55f6fb1a.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/55f6fb1a.bin
new file mode 100644
index 0000000..0963601
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/55f6fb1a.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5780565e.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/5780565e.bin
new file mode 100644
index 0000000..53057ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5780565e.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/57918260.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/57918260.bin
new file mode 100644
index 0000000..2f68d68
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/57918260.bin
@@ -0,0 +1 @@
+PRI * HTTPX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5841d898d2cd804f2d6373538e341dfba8a4dfab b/test/core/end2end/fuzzers/server_fuzzer_corpus/5841d898d2cd804f2d6373538e341dfba8a4dfab
new file mode 100644
index 0000000..e17f047
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5841d898d2cd804f2d6373538e341dfba8a4dfab
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/58b88a24.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/58b88a24.bin
new file mode 100644
index 0000000..696be2b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/58b88a24.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/597fdab5.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/597fdab5.bin
new file mode 100644
index 0000000..465b569
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/597fdab5.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/59ce7091c00075943d79e857c01ad1af5f38c78e b/test/core/end2end/fuzzers/server_fuzzer_corpus/59ce7091c00075943d79e857c01ad1af5f38c78e
new file mode 100644
index 0000000..848f8ed
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/59ce7091c00075943d79e857c01ad1af5f38c78e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/59d0b24d1acd01c749fb4bd6802a5f4dd003ce75 b/test/core/end2end/fuzzers/server_fuzzer_corpus/59d0b24d1acd01c749fb4bd6802a5f4dd003ce75
new file mode 100644
index 0000000..bdf76d5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/59d0b24d1acd01c749fb4bd6802a5f4dd003ce75
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/59dcfde4.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/59dcfde4.bin
new file mode 100644
index 0000000..e90e9a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/59dcfde4.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5ac92c4a7fb476393f8275fe4b79a2b13e3bcad9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/5ac92c4a7fb476393f8275fe4b79a2b13e3bcad9
new file mode 100644
index 0000000..fa9842c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5ac92c4a7fb476393f8275fe4b79a2b13e3bcad9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5d43ac923d7607a16e3d7bf8b838f52622871251 b/test/core/end2end/fuzzers/server_fuzzer_corpus/5d43ac923d7607a16e3d7bf8b838f52622871251
new file mode 100644
index 0000000..afaeca4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5d43ac923d7607a16e3d7bf8b838f52622871251
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5d817877.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/5d817877.bin
new file mode 100644
index 0000000..8c2ec2a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5d817877.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5e2508e15c79fbe9c2e6c1a393b490356a17efbc b/test/core/end2end/fuzzers/server_fuzzer_corpus/5e2508e15c79fbe9c2e6c1a393b490356a17efbc
new file mode 100644
index 0000000..c455479
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5e2508e15c79fbe9c2e6c1a393b490356a17efbc
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5f758756.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/5f758756.bin
new file mode 100644
index 0000000..47f2d2b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5f758756.bin
@@ -0,0 +1,2 @@
+PRI * HTTP/2.0

+X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/5f820fa8d44229219d0b7c4724e3e40a2ace97f4 b/test/core/end2end/fuzzers/server_fuzzer_corpus/5f820fa8d44229219d0b7c4724e3e40a2ace97f4
new file mode 100644
index 0000000..9026c10
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/5f820fa8d44229219d0b7c4724e3e40a2ace97f4
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/61e798bdd49b339983fea4ccfe18efe44afbd69b b/test/core/end2end/fuzzers/server_fuzzer_corpus/61e798bdd49b339983fea4ccfe18efe44afbd69b
new file mode 100644
index 0000000..7179868
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/61e798bdd49b339983fea4ccfe18efe44afbd69b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/62d05f336176a10a2c339c04d818f23b6e9a2637 b/test/core/end2end/fuzzers/server_fuzzer_corpus/62d05f336176a10a2c339c04d818f23b6e9a2637
new file mode 100644
index 0000000..ab8ec8f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/62d05f336176a10a2c339c04d818f23b6e9a2637
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6499e2db.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/6499e2db.bin
new file mode 100644
index 0000000..9187c94
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6499e2db.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/64cdbb31d5eda779d07885fa7881812db7800c05 b/test/core/end2end/fuzzers/server_fuzzer_corpus/64cdbb31d5eda779d07885fa7881812db7800c05
new file mode 100644
index 0000000..1cacb86
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/64cdbb31d5eda779d07885fa7881812db7800c05
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/65077d2946cfb822cf92c9dfc44517a34589f277 b/test/core/end2end/fuzzers/server_fuzzer_corpus/65077d2946cfb822cf92c9dfc44517a34589f277
new file mode 100644
index 0000000..094c4e7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/65077d2946cfb822cf92c9dfc44517a34589f277
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/65099066.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/65099066.bin
new file mode 100644
index 0000000..bf5806d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/65099066.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/652bfdce.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/652bfdce.bin
new file mode 100644
index 0000000..49d0f7f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/652bfdce.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/65d5ae42e6acb429459a1e1a5fb35f09c0f95de2 b/test/core/end2end/fuzzers/server_fuzzer_corpus/65d5ae42e6acb429459a1e1a5fb35f09c0f95de2
new file mode 100644
index 0000000..b56d59e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/65d5ae42e6acb429459a1e1a5fb35f09c0f95de2
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/65fd6cb3058ee0baae854cc7859b7c0c1e1c1166 b/test/core/end2end/fuzzers/server_fuzzer_corpus/65fd6cb3058ee0baae854cc7859b7c0c1e1c1166
new file mode 100644
index 0000000..34c9103
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/65fd6cb3058ee0baae854cc7859b7c0c1e1c1166
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6652f7be83a876214affc3f230040757f7db4ea8 b/test/core/end2end/fuzzers/server_fuzzer_corpus/6652f7be83a876214affc3f230040757f7db4ea8
new file mode 100644
index 0000000..c552bf8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6652f7be83a876214affc3f230040757f7db4ea8
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/67b04816.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/67b04816.bin
new file mode 100644
index 0000000..5387e6e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/67b04816.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/67ebf074c7f928c4fe32fef44e5c958cf441c93c b/test/core/end2end/fuzzers/server_fuzzer_corpus/67ebf074c7f928c4fe32fef44e5c958cf441c93c
new file mode 100644
index 0000000..59e952e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/67ebf074c7f928c4fe32fef44e5c958cf441c93c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/68f564fd8064233897ff704b5955b33a2e29293a b/test/core/end2end/fuzzers/server_fuzzer_corpus/68f564fd8064233897ff704b5955b33a2e29293a
new file mode 100644
index 0000000..291e9c4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/68f564fd8064233897ff704b5955b33a2e29293a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/69891e9f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/69891e9f.bin
new file mode 100644
index 0000000..0ba2abc
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/69891e9f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6c5bb78b51cf5006c92258292de19550985c00ba b/test/core/end2end/fuzzers/server_fuzzer_corpus/6c5bb78b51cf5006c92258292de19550985c00ba
new file mode 100644
index 0000000..d1af281
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6c5bb78b51cf5006c92258292de19550985c00ba
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6dc4455c.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/6dc4455c.bin
new file mode 100644
index 0000000..7ce8938
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6dc4455c.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6e050e98.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/6e050e98.bin
new file mode 100644
index 0000000..0fbf1ca
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6e050e98.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6f3bd9f33ca05bebe3811f7b3ae6ed112e1e45b9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/6f3bd9f33ca05bebe3811f7b3ae6ed112e1e45b9
new file mode 100644
index 0000000..4069f67
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6f3bd9f33ca05bebe3811f7b3ae6ed112e1e45b9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6f9d75e1af7ae7010d32872da888a582a25fddb4 b/test/core/end2end/fuzzers/server_fuzzer_corpus/6f9d75e1af7ae7010d32872da888a582a25fddb4
new file mode 100644
index 0000000..313d3b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6f9d75e1af7ae7010d32872da888a582a25fddb4
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/70ebe7f32c63ca8940017eb83e6db4d8b39ee03c b/test/core/end2end/fuzzers/server_fuzzer_corpus/70ebe7f32c63ca8940017eb83e6db4d8b39ee03c
new file mode 100644
index 0000000..0cd6faa
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/70ebe7f32c63ca8940017eb83e6db4d8b39ee03c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/712300b98afdb5f0d15c657c13cea76841164b13 b/test/core/end2end/fuzzers/server_fuzzer_corpus/712300b98afdb5f0d15c657c13cea76841164b13
new file mode 100644
index 0000000..179133d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/712300b98afdb5f0d15c657c13cea76841164b13
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/71ab07577909ca4b766f8ea0c6b8ec2bc395fc66 b/test/core/end2end/fuzzers/server_fuzzer_corpus/71ab07577909ca4b766f8ea0c6b8ec2bc395fc66
new file mode 100644
index 0000000..8705aec
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/71ab07577909ca4b766f8ea0c6b8ec2bc395fc66
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/72296cf9e1052ced4b60e2053aba9f1a569144e9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/72296cf9e1052ced4b60e2053aba9f1a569144e9
new file mode 100644
index 0000000..861524b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/72296cf9e1052ced4b60e2053aba9f1a569144e9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/7342b3febb07521e39abdf4ee976d16199d51239 b/test/core/end2end/fuzzers/server_fuzzer_corpus/7342b3febb07521e39abdf4ee976d16199d51239
new file mode 100644
index 0000000..8d69e99
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/7342b3febb07521e39abdf4ee976d16199d51239
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/746715fe.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/746715fe.bin
new file mode 100644
index 0000000..8ede09c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/746715fe.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/76294f12a5974e9f87d8f092d0df5429cf6c0466 b/test/core/end2end/fuzzers/server_fuzzer_corpus/76294f12a5974e9f87d8f092d0df5429cf6c0466
new file mode 100644
index 0000000..80206a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/76294f12a5974e9f87d8f092d0df5429cf6c0466
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/769f5d079151d1b5cab388c47a74f3c297c18d58 b/test/core/end2end/fuzzers/server_fuzzer_corpus/769f5d079151d1b5cab388c47a74f3c297c18d58
new file mode 100644
index 0000000..9b79b6e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/769f5d079151d1b5cab388c47a74f3c297c18d58
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/7839f12a8410a73d66e191cb5183d36d09a375e8 b/test/core/end2end/fuzzers/server_fuzzer_corpus/7839f12a8410a73d66e191cb5183d36d09a375e8
new file mode 100644
index 0000000..b03b904
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/7839f12a8410a73d66e191cb5183d36d09a375e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/7b453adcb9c4bf31dbc448ff32c2bc90ebcbdf0f b/test/core/end2end/fuzzers/server_fuzzer_corpus/7b453adcb9c4bf31dbc448ff32c2bc90ebcbdf0f
new file mode 100644
index 0000000..effab96
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/7b453adcb9c4bf31dbc448ff32c2bc90ebcbdf0f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/7ddfac7d7845b424bf670070781ca6ff8586c63b b/test/core/end2end/fuzzers/server_fuzzer_corpus/7ddfac7d7845b424bf670070781ca6ff8586c63b
new file mode 100644
index 0000000..027cb69
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/7ddfac7d7845b424bf670070781ca6ff8586c63b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/7f15bbce.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/7f15bbce.bin
new file mode 100644
index 0000000..eb23e5a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/7f15bbce.bin
@@ -0,0 +1 @@
+PRI * HX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/7ffd05db.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/7ffd05db.bin
new file mode 100644
index 0000000..ed01ab2
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/7ffd05db.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8164d3c4af043c47cfd6966873bccd2353d072bf b/test/core/end2end/fuzzers/server_fuzzer_corpus/8164d3c4af043c47cfd6966873bccd2353d072bf
new file mode 100644
index 0000000..a60e270
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8164d3c4af043c47cfd6966873bccd2353d072bf
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/81fb19dfcb3c3a18fd9e7c177356479503e75e6f b/test/core/end2end/fuzzers/server_fuzzer_corpus/81fb19dfcb3c3a18fd9e7c177356479503e75e6f
new file mode 100644
index 0000000..3834be4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/81fb19dfcb3c3a18fd9e7c177356479503e75e6f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/82dda42ddde662192ebaa96788945b7673bb486b b/test/core/end2end/fuzzers/server_fuzzer_corpus/82dda42ddde662192ebaa96788945b7673bb486b
new file mode 100644
index 0000000..4b6e82f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/82dda42ddde662192ebaa96788945b7673bb486b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8338ebee.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/8338ebee.bin
new file mode 100644
index 0000000..7e6c62c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8338ebee.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/84a3c6cf853ff318ae163231ce295171a59d5871 b/test/core/end2end/fuzzers/server_fuzzer_corpus/84a3c6cf853ff318ae163231ce295171a59d5871
new file mode 100644
index 0000000..d177938
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/84a3c6cf853ff318ae163231ce295171a59d5871
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/86a19d13cc65790696299c819cac17b14e337647 b/test/core/end2end/fuzzers/server_fuzzer_corpus/86a19d13cc65790696299c819cac17b14e337647
new file mode 100644
index 0000000..25ecc53
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/86a19d13cc65790696299c819cac17b14e337647
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/86e6dbf2.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/86e6dbf2.bin
new file mode 100644
index 0000000..b773567
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/86e6dbf2.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/88017b0894db1e6f4e3a6640ffe2876d31a54723 b/test/core/end2end/fuzzers/server_fuzzer_corpus/88017b0894db1e6f4e3a6640ffe2876d31a54723
new file mode 100644
index 0000000..2c2e8f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/88017b0894db1e6f4e3a6640ffe2876d31a54723
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8846918f967dd6513040c6d382fcd68ff7099873 b/test/core/end2end/fuzzers/server_fuzzer_corpus/8846918f967dd6513040c6d382fcd68ff7099873
new file mode 100644
index 0000000..b0cb61d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8846918f967dd6513040c6d382fcd68ff7099873
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/885fe25a0b441ef46ab176b88771c133e530cb73 b/test/core/end2end/fuzzers/server_fuzzer_corpus/885fe25a0b441ef46ab176b88771c133e530cb73
new file mode 100644
index 0000000..97896d1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/885fe25a0b441ef46ab176b88771c133e530cb73
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/88e1329b.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/88e1329b.bin
new file mode 100644
index 0000000..7464d0e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/88e1329b.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8b186384.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/8b186384.bin
new file mode 100644
index 0000000..cb04b30
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8b186384.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8c04817a75fddd71f13779f2ad5b994f45c333a2 b/test/core/end2end/fuzzers/server_fuzzer_corpus/8c04817a75fddd71f13779f2ad5b994f45c333a2
new file mode 100644
index 0000000..97eb4e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8c04817a75fddd71f13779f2ad5b994f45c333a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8c72c3f35e9b9fd168ad9024c953a703f33ae3c1 b/test/core/end2end/fuzzers/server_fuzzer_corpus/8c72c3f35e9b9fd168ad9024c953a703f33ae3c1
new file mode 100644
index 0000000..8323a67
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8c72c3f35e9b9fd168ad9024c953a703f33ae3c1
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8c760938a2a72fa92b27e00e05005e2e4c429359 b/test/core/end2end/fuzzers/server_fuzzer_corpus/8c760938a2a72fa92b27e00e05005e2e4c429359
new file mode 100644
index 0000000..3accdc0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8c760938a2a72fa92b27e00e05005e2e4c429359
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8da521d9.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/8da521d9.bin
new file mode 100644
index 0000000..122486a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8da521d9.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8de81717.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/8de81717.bin
new file mode 100644
index 0000000..b16f546
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8de81717.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/8ec00f45afb097066f47d0bad256a8b856b1efe8 b/test/core/end2end/fuzzers/server_fuzzer_corpus/8ec00f45afb097066f47d0bad256a8b856b1efe8
new file mode 100644
index 0000000..6561c1c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/8ec00f45afb097066f47d0bad256a8b856b1efe8
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/90224b8e.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/90224b8e.bin
new file mode 100644
index 0000000..f660601
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/90224b8e.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/90240c7c.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/90240c7c.bin
new file mode 100644
index 0000000..365bf2d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/90240c7c.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9099ac4e83f6460c80b5557c87f653e4c65aa091 b/test/core/end2end/fuzzers/server_fuzzer_corpus/9099ac4e83f6460c80b5557c87f653e4c65aa091
new file mode 100644
index 0000000..4136f9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9099ac4e83f6460c80b5557c87f653e4c65aa091
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/914ed07570b6441365a3636d05850f7316c7f2a8 b/test/core/end2end/fuzzers/server_fuzzer_corpus/914ed07570b6441365a3636d05850f7316c7f2a8
new file mode 100644
index 0000000..5af7800
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/914ed07570b6441365a3636d05850f7316c7f2a8
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/916b825da0ffc46fdb6120b1044e98ae158fce70 b/test/core/end2end/fuzzers/server_fuzzer_corpus/916b825da0ffc46fdb6120b1044e98ae158fce70
new file mode 100644
index 0000000..dc54a58
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/916b825da0ffc46fdb6120b1044e98ae158fce70
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin
new file mode 100644
index 0000000..dc2c3a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/93c3ffcb7e3bcb5ed7e37a5b3dfb97b43ca42718 b/test/core/end2end/fuzzers/server_fuzzer_corpus/93c3ffcb7e3bcb5ed7e37a5b3dfb97b43ca42718
new file mode 100644
index 0000000..00329ed
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/93c3ffcb7e3bcb5ed7e37a5b3dfb97b43ca42718
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9540d3ad3fa75bfb95c0d57cefd737611c7069a5 b/test/core/end2end/fuzzers/server_fuzzer_corpus/9540d3ad3fa75bfb95c0d57cefd737611c7069a5
new file mode 100644
index 0000000..fc338c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9540d3ad3fa75bfb95c0d57cefd737611c7069a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/954337ef.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/954337ef.bin
new file mode 100644
index 0000000..782e59d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/954337ef.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/95d25ba2e190fafa2b3ca1e1c467b9ef64868962 b/test/core/end2end/fuzzers/server_fuzzer_corpus/95d25ba2e190fafa2b3ca1e1c467b9ef64868962
new file mode 100644
index 0000000..ee35bc7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/95d25ba2e190fafa2b3ca1e1c467b9ef64868962
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9764015f89a0b7a59f3b5359b0a037b38d6e39d7 b/test/core/end2end/fuzzers/server_fuzzer_corpus/9764015f89a0b7a59f3b5359b0a037b38d6e39d7
new file mode 100644
index 0000000..9b4a436
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9764015f89a0b7a59f3b5359b0a037b38d6e39d7
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/97aed4bd.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/97aed4bd.bin
new file mode 100644
index 0000000..dbe2507
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/97aed4bd.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/986c9ca7db83b2cddbae2a0db2dca87f52277074 b/test/core/end2end/fuzzers/server_fuzzer_corpus/986c9ca7db83b2cddbae2a0db2dca87f52277074
new file mode 100644
index 0000000..6ba1635
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/986c9ca7db83b2cddbae2a0db2dca87f52277074
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9953eb28aa1ed661612a4710a9d16a15de4ae353 b/test/core/end2end/fuzzers/server_fuzzer_corpus/9953eb28aa1ed661612a4710a9d16a15de4ae353
new file mode 100644
index 0000000..837c3e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9953eb28aa1ed661612a4710a9d16a15de4ae353
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9a176b6f7e0dc5f681a1788d8954f76fabd08cad b/test/core/end2end/fuzzers/server_fuzzer_corpus/9a176b6f7e0dc5f681a1788d8954f76fabd08cad
new file mode 100644
index 0000000..ef52cd7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9a176b6f7e0dc5f681a1788d8954f76fabd08cad
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9a6963b0d0fcb0e91a31748c47c6f0e1e842fea9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/9a6963b0d0fcb0e91a31748c47c6f0e1e842fea9
new file mode 100644
index 0000000..e8fef7f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9a6963b0d0fcb0e91a31748c47c6f0e1e842fea9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9bf7553a.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/9bf7553a.bin
new file mode 100644
index 0000000..e612aec
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9bf7553a.bin
@@ -0,0 +1 @@
+PRX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/9d2d18fce18c790035d8f67ed798703bdda0a949 b/test/core/end2end/fuzzers/server_fuzzer_corpus/9d2d18fce18c790035d8f67ed798703bdda0a949
new file mode 100644
index 0000000..3799081
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/9d2d18fce18c790035d8f67ed798703bdda0a949
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a112d484b70e778835fcd478fd651828720791e5 b/test/core/end2end/fuzzers/server_fuzzer_corpus/a112d484b70e778835fcd478fd651828720791e5
new file mode 100644
index 0000000..47c71a3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a112d484b70e778835fcd478fd651828720791e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a24bf2dc.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/a24bf2dc.bin
new file mode 100644
index 0000000..1e5b421
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a24bf2dc.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a32be0653ccc65463445b4aaf24a7a1164d5c642 b/test/core/end2end/fuzzers/server_fuzzer_corpus/a32be0653ccc65463445b4aaf24a7a1164d5c642
new file mode 100644
index 0000000..a4c4bf3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a32be0653ccc65463445b4aaf24a7a1164d5c642
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a357658d.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/a357658d.bin
new file mode 100644
index 0000000..255103f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a357658d.bin
@@ -0,0 +1 @@
+PX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a3a2b1af.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/a3a2b1af.bin
new file mode 100644
index 0000000..23086f5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a3a2b1af.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a5348197.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/a5348197.bin
new file mode 100644
index 0000000..d8a73f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a5348197.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a5b529754606b96a8c801615ac12a1f6ee5c3f54 b/test/core/end2end/fuzzers/server_fuzzer_corpus/a5b529754606b96a8c801615ac12a1f6ee5c3f54
new file mode 100644
index 0000000..9179e76
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a5b529754606b96a8c801615ac12a1f6ee5c3f54
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a5cc3762cb2b2cac316c60ddee794016057fb4ff b/test/core/end2end/fuzzers/server_fuzzer_corpus/a5cc3762cb2b2cac316c60ddee794016057fb4ff
new file mode 100644
index 0000000..c9105a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a5cc3762cb2b2cac316c60ddee794016057fb4ff
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a7e64803.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/a7e64803.bin
new file mode 100644
index 0000000..e406166
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a7e64803.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a8d229374635fa6f2a75ca1669892e1bc244e719 b/test/core/end2end/fuzzers/server_fuzzer_corpus/a8d229374635fa6f2a75ca1669892e1bc244e719
new file mode 100644
index 0000000..f40ea15
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a8d229374635fa6f2a75ca1669892e1bc244e719
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a8f2345b2c949e9e32a434c99accf771f405eb65 b/test/core/end2end/fuzzers/server_fuzzer_corpus/a8f2345b2c949e9e32a434c99accf771f405eb65
new file mode 100644
index 0000000..a5d1315
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a8f2345b2c949e9e32a434c99accf771f405eb65
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a9463428cdc47d37efb6e3c5633d1e5e78911f16 b/test/core/end2end/fuzzers/server_fuzzer_corpus/a9463428cdc47d37efb6e3c5633d1e5e78911f16
new file mode 100644
index 0000000..5cb8323
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a9463428cdc47d37efb6e3c5633d1e5e78911f16
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a9966f7181d08f6a9ff8158736ad77a285d743a6 b/test/core/end2end/fuzzers/server_fuzzer_corpus/a9966f7181d08f6a9ff8158736ad77a285d743a6
new file mode 100644
index 0000000..f692fa1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a9966f7181d08f6a9ff8158736ad77a285d743a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a9e22d93.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/a9e22d93.bin
new file mode 100644
index 0000000..f3ef55b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a9e22d93.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/aa3c8974.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/aa3c8974.bin
new file mode 100644
index 0000000..9998126
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/aa3c8974.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/aa825693.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/aa825693.bin
new file mode 100644
index 0000000..4a68f21
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/aa825693.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/aa8729d7.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/aa8729d7.bin
new file mode 100644
index 0000000..2f4e478
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/aa8729d7.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/aaafca90a7f59184f3d768a1d6f9093e8f737b8a b/test/core/end2end/fuzzers/server_fuzzer_corpus/aaafca90a7f59184f3d768a1d6f9093e8f737b8a
new file mode 100644
index 0000000..315e850
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/aaafca90a7f59184f3d768a1d6f9093e8f737b8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ad810f7f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/ad810f7f.bin
new file mode 100644
index 0000000..7761e52
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ad810f7f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/aedefcd9bd7fc10b7bf60372da54c43e953523bd b/test/core/end2end/fuzzers/server_fuzzer_corpus/aedefcd9bd7fc10b7bf60372da54c43e953523bd
new file mode 100644
index 0000000..f93d485
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/aedefcd9bd7fc10b7bf60372da54c43e953523bd
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/aefcbc29f2caea5038cda4dbc927cdadd9b844c4 b/test/core/end2end/fuzzers/server_fuzzer_corpus/aefcbc29f2caea5038cda4dbc927cdadd9b844c4
new file mode 100644
index 0000000..a95b626
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/aefcbc29f2caea5038cda4dbc927cdadd9b844c4
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b06ce623.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/b06ce623.bin
new file mode 100644
index 0000000..63a9a8c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b06ce623.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b1128694.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/b1128694.bin
new file mode 100644
index 0000000..82aa699
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b1128694.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b220d23a13d98d4815b1f7a3e4fe7dd8672b1c83 b/test/core/end2end/fuzzers/server_fuzzer_corpus/b220d23a13d98d4815b1f7a3e4fe7dd8672b1c83
new file mode 100644
index 0000000..dffb607
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b220d23a13d98d4815b1f7a3e4fe7dd8672b1c83
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b28959dd.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/b28959dd.bin
new file mode 100644
index 0000000..4252278
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b28959dd.bin
@@ -0,0 +1 @@
+PRI * HTTP/2.0X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b431df13.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/b431df13.bin
new file mode 100644
index 0000000..a1a1842
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b431df13.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b5acaa52.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/b5acaa52.bin
new file mode 100644
index 0000000..ea99ae7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b5acaa52.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b7ce4a4f6eea20c0b83d9f7fa8406a0730ee0040 b/test/core/end2end/fuzzers/server_fuzzer_corpus/b7ce4a4f6eea20c0b83d9f7fa8406a0730ee0040
new file mode 100644
index 0000000..cca0014
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b7ce4a4f6eea20c0b83d9f7fa8406a0730ee0040
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b829143b.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/b829143b.bin
new file mode 100644
index 0000000..b3e88f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b829143b.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b887097732b9c30719f6c7ea7a7cbac531512a31 b/test/core/end2end/fuzzers/server_fuzzer_corpus/b887097732b9c30719f6c7ea7a7cbac531512a31
new file mode 100644
index 0000000..3cee5d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b887097732b9c30719f6c7ea7a7cbac531512a31
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b924c842.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/b924c842.bin
new file mode 100644
index 0000000..05f8de1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b924c842.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/bad4f467.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/bad4f467.bin
new file mode 100644
index 0000000..068e1ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/bad4f467.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/bc9545cebdcb3af82406a5f0c1b286d28f9d4f5a b/test/core/end2end/fuzzers/server_fuzzer_corpus/bc9545cebdcb3af82406a5f0c1b286d28f9d4f5a
new file mode 100644
index 0000000..4d02fcc
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/bc9545cebdcb3af82406a5f0c1b286d28f9d4f5a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/bd63e44a3b004e7ed471c2367c3efae2c58a676d b/test/core/end2end/fuzzers/server_fuzzer_corpus/bd63e44a3b004e7ed471c2367c3efae2c58a676d
new file mode 100644
index 0000000..e66fdcb
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/bd63e44a3b004e7ed471c2367c3efae2c58a676d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/be9b6e78.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/be9b6e78.bin
new file mode 100644
index 0000000..27e9ebc
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/be9b6e78.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/bf5e21c32becb5839deeb81e9174cf6478a25473 b/test/core/end2end/fuzzers/server_fuzzer_corpus/bf5e21c32becb5839deeb81e9174cf6478a25473
new file mode 100644
index 0000000..c26cef3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/bf5e21c32becb5839deeb81e9174cf6478a25473
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/bfb55acd5b66521eb5bd8ce6b57b3b6895883675 b/test/core/end2end/fuzzers/server_fuzzer_corpus/bfb55acd5b66521eb5bd8ce6b57b3b6895883675
new file mode 100644
index 0000000..94fb6a9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/bfb55acd5b66521eb5bd8ce6b57b3b6895883675
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/bfcbffa9.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/bfcbffa9.bin
new file mode 100644
index 0000000..a571ff3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/bfcbffa9.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c004455e9d60bc2fff094e79cd0b38507023e018 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c004455e9d60bc2fff094e79cd0b38507023e018
new file mode 100644
index 0000000..41ddff9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c004455e9d60bc2fff094e79cd0b38507023e018
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c039ac9a5a570f8fd9064df9320890b885edf9c3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c039ac9a5a570f8fd9064df9320890b885edf9c3
new file mode 100644
index 0000000..dbc9405
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c039ac9a5a570f8fd9064df9320890b885edf9c3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c1188b44.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/c1188b44.bin
new file mode 100644
index 0000000..bbc80e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c1188b44.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c12835aa9f3513d3f7179ee4f9976292713f7cb9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c12835aa9f3513d3f7179ee4f9976292713f7cb9
new file mode 100644
index 0000000..e61533a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c12835aa9f3513d3f7179ee4f9976292713f7cb9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c13188118af1634061b6a3947b81618891aeb6a3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c13188118af1634061b6a3947b81618891aeb6a3
new file mode 100644
index 0000000..a423a7b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c13188118af1634061b6a3947b81618891aeb6a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c35968bf.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/c35968bf.bin
new file mode 100644
index 0000000..1d4b516
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c35968bf.bin
@@ -0,0 +1 @@
+PRI X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c43d97f2.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/c43d97f2.bin
new file mode 100644
index 0000000..6295958
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c43d97f2.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c4534867.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/c4534867.bin
new file mode 100644
index 0000000..40fb374
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c4534867.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c4a71cdd29759b51f9cc54175ad69c44b4ab6eb6 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c4a71cdd29759b51f9cc54175ad69c44b4ab6eb6
new file mode 100644
index 0000000..3c47fb3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c4a71cdd29759b51f9cc54175ad69c44b4ab6eb6
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c559f565.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/c559f565.bin
new file mode 100644
index 0000000..28429cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c559f565.bin
@@ -0,0 +1,3 @@
+PRI * HTTP/2.0

+

+X
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c56fada76f5c198232201a608072a1a63e3d3785 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c56fada76f5c198232201a608072a1a63e3d3785
new file mode 100644
index 0000000..f7092e5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c56fada76f5c198232201a608072a1a63e3d3785
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c5ff50ae447ac7a0c8fb3363b2458824d405e64c b/test/core/end2end/fuzzers/server_fuzzer_corpus/c5ff50ae447ac7a0c8fb3363b2458824d405e64c
new file mode 100644
index 0000000..ccebb36
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c5ff50ae447ac7a0c8fb3363b2458824d405e64c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c66e84d1.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/c66e84d1.bin
new file mode 100644
index 0000000..1cc73ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c66e84d1.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c6a1d2cc8935808b6e317a69baec1c3cb87cac94 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c6a1d2cc8935808b6e317a69baec1c3cb87cac94
new file mode 100644
index 0000000..23ae452
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c6a1d2cc8935808b6e317a69baec1c3cb87cac94
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c7c44b98faa21c8f0645a818a65b60d956d15952 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c7c44b98faa21c8f0645a818a65b60d956d15952
new file mode 100644
index 0000000..6c36033
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c7c44b98faa21c8f0645a818a65b60d956d15952
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c8073f5f41970fab4738215e42ec97a4383855e5 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c8073f5f41970fab4738215e42ec97a4383855e5
new file mode 100644
index 0000000..8a6e432
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c8073f5f41970fab4738215e42ec97a4383855e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c81dec02.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/c81dec02.bin
new file mode 100644
index 0000000..746cd72
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c81dec02.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c8812dc8a1ab1592a2d7b71300e1a0a5da6a6382 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c8812dc8a1ab1592a2d7b71300e1a0a5da6a6382
new file mode 100644
index 0000000..59f3bd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c8812dc8a1ab1592a2d7b71300e1a0a5da6a6382
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ca843c66c4c4807ccb1615b472c79bc459e5c6cb b/test/core/end2end/fuzzers/server_fuzzer_corpus/ca843c66c4c4807ccb1615b472c79bc459e5c6cb
new file mode 100644
index 0000000..e8fa525
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ca843c66c4c4807ccb1615b472c79bc459e5c6cb
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/cbb04be69714f81f5cd09e36e8ea4e69ea73d618 b/test/core/end2end/fuzzers/server_fuzzer_corpus/cbb04be69714f81f5cd09e36e8ea4e69ea73d618
new file mode 100644
index 0000000..5622aca
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/cbb04be69714f81f5cd09e36e8ea4e69ea73d618
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/cc97ece92b72cc2a4d045e16c0e2f2021bc014f8 b/test/core/end2end/fuzzers/server_fuzzer_corpus/cc97ece92b72cc2a4d045e16c0e2f2021bc014f8
new file mode 100644
index 0000000..76e26ec
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/cc97ece92b72cc2a4d045e16c0e2f2021bc014f8
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/cca29902.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/cca29902.bin
new file mode 100644
index 0000000..60f208f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/cca29902.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/cdba6c45.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/cdba6c45.bin
new file mode 100644
index 0000000..e2e324c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/cdba6c45.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-0f4b135c0242669ce425d2662168e9440f8a628d b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-0f4b135c0242669ce425d2662168e9440f8a628d
new file mode 100644
index 0000000..9c2ae72
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-0f4b135c0242669ce425d2662168e9440f8a628d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-239cc27a23827ea53b60ccbaee0ecc64dad2bff0 b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-239cc27a23827ea53b60ccbaee0ecc64dad2bff0
new file mode 100644
index 0000000..0bfd764
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-239cc27a23827ea53b60ccbaee0ecc64dad2bff0
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-41ab0e868e84612275f77118f9e832bc94ff45c5 b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-41ab0e868e84612275f77118f9e832bc94ff45c5
new file mode 100644
index 0000000..87bfefb
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-41ab0e868e84612275f77118f9e832bc94ff45c5
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7af5da2a8da23d197d9336e32da72c9ff64c15b3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7af5da2a8da23d197d9336e32da72c9ff64c15b3
new file mode 100644
index 0000000..f713daa
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7af5da2a8da23d197d9336e32da72c9ff64c15b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7e121dd3be057176369bea160d873040b32a03dc b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7e121dd3be057176369bea160d873040b32a03dc
new file mode 100644
index 0000000..9491b01
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7e121dd3be057176369bea160d873040b32a03dc
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-e34b0a9a428001cb4094a9ebca76329f578811a4 b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-e34b0a9a428001cb4094a9ebca76329f578811a4
new file mode 100644
index 0000000..adbbcec
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-e34b0a9a428001cb4094a9ebca76329f578811a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d0f7eebc.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/d0f7eebc.bin
new file mode 100644
index 0000000..0edc3bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d0f7eebc.bin
@@ -0,0 +1 @@
+PRI * HTX
\ No newline at end of file
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d2031009d3783fcf083963fa30bb493f7f935541 b/test/core/end2end/fuzzers/server_fuzzer_corpus/d2031009d3783fcf083963fa30bb493f7f935541
new file mode 100644
index 0000000..953d5e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d2031009d3783fcf083963fa30bb493f7f935541
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d28155c6c92642c61dfb097f7b2eb1d6ced272c0 b/test/core/end2end/fuzzers/server_fuzzer_corpus/d28155c6c92642c61dfb097f7b2eb1d6ced272c0
new file mode 100644
index 0000000..13dc155
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d28155c6c92642c61dfb097f7b2eb1d6ced272c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d6979f0f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/d6979f0f.bin
new file mode 100644
index 0000000..8ed84f9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d6979f0f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d8a1d141a9e3876b71c7decbe6e3affccf6de397 b/test/core/end2end/fuzzers/server_fuzzer_corpus/d8a1d141a9e3876b71c7decbe6e3affccf6de397
new file mode 100644
index 0000000..ba3b0cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d8a1d141a9e3876b71c7decbe6e3affccf6de397
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d9074e68.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/d9074e68.bin
new file mode 100644
index 0000000..b7cd2f7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d9074e68.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d95556cac07e720909aaf2ac09d876106420463f b/test/core/end2end/fuzzers/server_fuzzer_corpus/d95556cac07e720909aaf2ac09d876106420463f
new file mode 100644
index 0000000..e3d74d0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d95556cac07e720909aaf2ac09d876106420463f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d96da249094db51ea92b1413907abfd27a4f2426 b/test/core/end2end/fuzzers/server_fuzzer_corpus/d96da249094db51ea92b1413907abfd27a4f2426
new file mode 100644
index 0000000..9b3c751
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d96da249094db51ea92b1413907abfd27a4f2426
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/da7e44a9.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/da7e44a9.bin
new file mode 100644
index 0000000..cc57d19
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/da7e44a9.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/dab172ff.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/dab172ff.bin
new file mode 100644
index 0000000..c1fec49
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/dab172ff.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/dad922e2daf84cf039f50cf8636eaa9dbd01ff83 b/test/core/end2end/fuzzers/server_fuzzer_corpus/dad922e2daf84cf039f50cf8636eaa9dbd01ff83
new file mode 100644
index 0000000..2a1e236
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/dad922e2daf84cf039f50cf8636eaa9dbd01ff83
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/db33559d4afb4c32e68525c000fde16a4c3300f5 b/test/core/end2end/fuzzers/server_fuzzer_corpus/db33559d4afb4c32e68525c000fde16a4c3300f5
new file mode 100644
index 0000000..fb1e78c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/db33559d4afb4c32e68525c000fde16a4c3300f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/dcabac1ef8b197ef39b188bcf5dc470f9749e903 b/test/core/end2end/fuzzers/server_fuzzer_corpus/dcabac1ef8b197ef39b188bcf5dc470f9749e903
new file mode 100644
index 0000000..ec70c9c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/dcabac1ef8b197ef39b188bcf5dc470f9749e903
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/df5d3cf5f05eab65ef9d385e263780ae73c42b19 b/test/core/end2end/fuzzers/server_fuzzer_corpus/df5d3cf5f05eab65ef9d385e263780ae73c42b19
new file mode 100644
index 0000000..3312090
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/df5d3cf5f05eab65ef9d385e263780ae73c42b19
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e0d9a9a7.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/e0d9a9a7.bin
new file mode 100644
index 0000000..3d32ffc
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e0d9a9a7.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e2652fbb.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/e2652fbb.bin
new file mode 100644
index 0000000..946cfe2
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e2652fbb.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e2c954e1.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/e2c954e1.bin
new file mode 100644
index 0000000..759683f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e2c954e1.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e3bab014.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/e3bab014.bin
new file mode 100644
index 0000000..d9ae95a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e3bab014.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e7ad0c4b7d0f289c90a3988309e9e03b78f7eea3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/e7ad0c4b7d0f289c90a3988309e9e03b78f7eea3
new file mode 100644
index 0000000..a4fd83a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e7ad0c4b7d0f289c90a3988309e9e03b78f7eea3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e9bbe2fe47b7b9c2683e7f17f4a33625c6ffbd8c b/test/core/end2end/fuzzers/server_fuzzer_corpus/e9bbe2fe47b7b9c2683e7f17f4a33625c6ffbd8c
new file mode 100644
index 0000000..1972fa4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e9bbe2fe47b7b9c2683e7f17f4a33625c6ffbd8c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e9d96662.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/e9d96662.bin
new file mode 100644
index 0000000..672f079
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e9d96662.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/eb66106b.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/eb66106b.bin
new file mode 100644
index 0000000..32c355b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/eb66106b.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/eba8472a.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/eba8472a.bin
new file mode 100644
index 0000000..24d97fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/eba8472a.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ed8da77f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/ed8da77f.bin
new file mode 100644
index 0000000..a78a2ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ed8da77f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ee64e1ba4897bfd7c6baa1fb72d4c5f83b5654e4 b/test/core/end2end/fuzzers/server_fuzzer_corpus/ee64e1ba4897bfd7c6baa1fb72d4c5f83b5654e4
new file mode 100644
index 0000000..52f26cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ee64e1ba4897bfd7c6baa1fb72d4c5f83b5654e4
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f0387dfdd6b8c925d958113e669ec4a1897034b4 b/test/core/end2end/fuzzers/server_fuzzer_corpus/f0387dfdd6b8c925d958113e669ec4a1897034b4
new file mode 100644
index 0000000..6c65103
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f0387dfdd6b8c925d958113e669ec4a1897034b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f1121b952e75463cc71137683dc2528f9cbc19b7 b/test/core/end2end/fuzzers/server_fuzzer_corpus/f1121b952e75463cc71137683dc2528f9cbc19b7
new file mode 100644
index 0000000..6d2a60d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f1121b952e75463cc71137683dc2528f9cbc19b7
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f3220426.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/f3220426.bin
new file mode 100644
index 0000000..eac62a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f3220426.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f3d084cf20b92a5f026fe7cc6e5af49bde28693d b/test/core/end2end/fuzzers/server_fuzzer_corpus/f3d084cf20b92a5f026fe7cc6e5af49bde28693d
new file mode 100644
index 0000000..589225e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f3d084cf20b92a5f026fe7cc6e5af49bde28693d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f4024b01.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/f4024b01.bin
new file mode 100644
index 0000000..7097b7e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f4024b01.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f541d27e.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/f541d27e.bin
new file mode 100644
index 0000000..50be7f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f541d27e.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f5424a9d7bd14317b6de7b15587df28bfde8362d b/test/core/end2end/fuzzers/server_fuzzer_corpus/f5424a9d7bd14317b6de7b15587df28bfde8362d
new file mode 100644
index 0000000..ddfb3e4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f5424a9d7bd14317b6de7b15587df28bfde8362d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f5c877c4.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/f5c877c4.bin
new file mode 100644
index 0000000..35cf822
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f5c877c4.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f5f0615030439dda162e8862b6bbd09f81f14d81 b/test/core/end2end/fuzzers/server_fuzzer_corpus/f5f0615030439dda162e8862b6bbd09f81f14d81
new file mode 100644
index 0000000..9b44f75
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f5f0615030439dda162e8862b6bbd09f81f14d81
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f74b9428.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/f74b9428.bin
new file mode 100644
index 0000000..fd41223
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f74b9428.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f7bf0d7bb0dd6e1866ccef9fafc3cb295db2f07f b/test/core/end2end/fuzzers/server_fuzzer_corpus/f7bf0d7bb0dd6e1866ccef9fafc3cb295db2f07f
new file mode 100644
index 0000000..cb892bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f7bf0d7bb0dd6e1866ccef9fafc3cb295db2f07f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f826100f.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/f826100f.bin
new file mode 100644
index 0000000..a072e28
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f826100f.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f88ffb7f3066f2706cfcd9be077595e07834cc15 b/test/core/end2end/fuzzers/server_fuzzer_corpus/f88ffb7f3066f2706cfcd9be077595e07834cc15
new file mode 100644
index 0000000..d17e017
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f88ffb7f3066f2706cfcd9be077595e07834cc15
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/f8b46e92c7ceb4c2f2cdcb3452a6d8c58768eaa2 b/test/core/end2end/fuzzers/server_fuzzer_corpus/f8b46e92c7ceb4c2f2cdcb3452a6d8c58768eaa2
new file mode 100644
index 0000000..db89ca1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/f8b46e92c7ceb4c2f2cdcb3452a6d8c58768eaa2
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fa36b4280d9e28edd81c5e4d192d1a5c2765e5e4 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fa36b4280d9e28edd81c5e4d192d1a5c2765e5e4
new file mode 100644
index 0000000..6fe7633
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fa36b4280d9e28edd81c5e4d192d1a5c2765e5e4
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fb3b0d80.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/fb3b0d80.bin
new file mode 100644
index 0000000..b403188
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fb3b0d80.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fb84edfa9e8cbddba26a7184e7fdc219bde556c0 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fb84edfa9e8cbddba26a7184e7fdc219bde556c0
new file mode 100644
index 0000000..f5de9d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fb84edfa9e8cbddba26a7184e7fdc219bde556c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fd14bea45ecaf13af0053900edb2f17b71a0bf09 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fd14bea45ecaf13af0053900edb2f17b71a0bf09
new file mode 100644
index 0000000..fc84812
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fd14bea45ecaf13af0053900edb2f17b71a0bf09
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fd26e0a6.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/fd26e0a6.bin
new file mode 100644
index 0000000..999ed6b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fd26e0a6.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fd943e69304dffebf47e1e40b0849e12abeee287 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fd943e69304dffebf47e1e40b0849e12abeee287
new file mode 100644
index 0000000..25ecfe1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fd943e69304dffebf47e1e40b0849e12abeee287
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fdf67df81857577361d319e76559c5e85a257b07 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fdf67df81857577361d319e76559c5e85a257b07
new file mode 100644
index 0000000..a465680
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fdf67df81857577361d319e76559c5e85a257b07
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fe1957b9bc7c6bf9d8b6089c422d72a0f444da6e b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe1957b9bc7c6bf9d8b6089c422d72a0f444da6e
new file mode 100644
index 0000000..5c73a94
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe1957b9bc7c6bf9d8b6089c422d72a0f444da6e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fe66893c.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe66893c.bin
new file mode 100644
index 0000000..3a954cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe66893c.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fe69ddfa5827dd560bb0b5d4da7d982273f17ef9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe69ddfa5827dd560bb0b5d4da7d982273f17ef9
new file mode 100644
index 0000000..c20a0c8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe69ddfa5827dd560bb0b5d4da7d982273f17ef9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ff227015.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/ff227015.bin
new file mode 100644
index 0000000..c9d6bf0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ff227015.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ff898c08.bin b/test/core/end2end/fuzzers/server_fuzzer_corpus/ff898c08.bin
new file mode 100644
index 0000000..ff0f909
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ff898c08.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-082763e16153cb6b8f3f5308cd060e822f475e5a b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-082763e16153cb6b8f3f5308cd060e822f475e5a
new file mode 100644
index 0000000..561f98c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-082763e16153cb6b8f3f5308cd060e822f475e5a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-13501419f349b7855d2e94060bd08b28923d1f37 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-13501419f349b7855d2e94060bd08b28923d1f37
new file mode 100644
index 0000000..34906e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-13501419f349b7855d2e94060bd08b28923d1f37
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-14862768a1fe076896fd37e2543ddd23192a9e3c b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-14862768a1fe076896fd37e2543ddd23192a9e3c
new file mode 100644
index 0000000..c9f22b2
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-14862768a1fe076896fd37e2543ddd23192a9e3c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1a3ebf8f8bb0b5a0109a5ef44734cc64170377f9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1a3ebf8f8bb0b5a0109a5ef44734cc64170377f9
new file mode 100644
index 0000000..9fe5d9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1a3ebf8f8bb0b5a0109a5ef44734cc64170377f9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1ae0ed17a042aab8a3c3199c83a809b0243d1424 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1ae0ed17a042aab8a3c3199c83a809b0243d1424
new file mode 100644
index 0000000..8ab8cbe
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1ae0ed17a042aab8a3c3199c83a809b0243d1424
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1b6c4b5c1949adae3efd5e3264bb32a40eea524e b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1b6c4b5c1949adae3efd5e3264bb32a40eea524e
new file mode 100644
index 0000000..8831098
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1b6c4b5c1949adae3efd5e3264bb32a40eea524e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-3991c873ba814d0cd03a67d25fff0c8fe8713aca b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-3991c873ba814d0cd03a67d25fff0c8fe8713aca
new file mode 100644
index 0000000..fbc7a0b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-3991c873ba814d0cd03a67d25fff0c8fe8713aca
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-4c6da955e4c101b81a62b2f8e934d94a62ae534b b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-4c6da955e4c101b81a62b2f8e934d94a62ae534b
new file mode 100644
index 0000000..6aac3e4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-4c6da955e4c101b81a62b2f8e934d94a62ae534b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-58f116dfba8d428a01ca596174fca63f4ac523f0 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-58f116dfba8d428a01ca596174fca63f4ac523f0
new file mode 100644
index 0000000..b0c854c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-58f116dfba8d428a01ca596174fca63f4ac523f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-59f6edc7cf4aeed49b4dc024052db4846d5d7fc8 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-59f6edc7cf4aeed49b4dc024052db4846d5d7fc8
new file mode 100644
index 0000000..e01687e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-59f6edc7cf4aeed49b4dc024052db4846d5d7fc8
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-63ebf780ee6c2003eba622686a4bf94c503ad96e b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-63ebf780ee6c2003eba622686a4bf94c503ad96e
new file mode 100644
index 0000000..071391b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-63ebf780ee6c2003eba622686a4bf94c503ad96e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-68ed2d33c9d32f73343c097303c3d5a6a3467c83 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-68ed2d33c9d32f73343c097303c3d5a6a3467c83
new file mode 100644
index 0000000..a5ed8e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-68ed2d33c9d32f73343c097303c3d5a6a3467c83
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6d37c5e6d7efee56319b1316725fdc5aee5a52c3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6d37c5e6d7efee56319b1316725fdc5aee5a52c3
new file mode 100644
index 0000000..96c97df
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6d37c5e6d7efee56319b1316725fdc5aee5a52c3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6e980a9d12c392175b5f66683e608626ae983276 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6e980a9d12c392175b5f66683e608626ae983276
new file mode 100644
index 0000000..f0489f8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6e980a9d12c392175b5f66683e608626ae983276
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7233d53f94386b0339b2c2b01ef2d348f5862f1f b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7233d53f94386b0339b2c2b01ef2d348f5862f1f
new file mode 100644
index 0000000..49dda96
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7233d53f94386b0339b2c2b01ef2d348f5862f1f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7281d9eaed0d20b0b6b5e7709c57e78fefe9c315 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7281d9eaed0d20b0b6b5e7709c57e78fefe9c315
new file mode 100644
index 0000000..44c3397
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7281d9eaed0d20b0b6b5e7709c57e78fefe9c315
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-73e0a41066bc09c8e3fbd0dd7628445bcdaabb4a b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-73e0a41066bc09c8e3fbd0dd7628445bcdaabb4a
new file mode 100644
index 0000000..d745d21
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-73e0a41066bc09c8e3fbd0dd7628445bcdaabb4a
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-93cd6b3f9786ee107a0e2d135b40d13f96e652ed b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-93cd6b3f9786ee107a0e2d135b40d13f96e652ed
new file mode 100644
index 0000000..bb4bbbb
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-93cd6b3f9786ee107a0e2d135b40d13f96e652ed
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9a176b6f7e0dc5f681a1788d8954f76fabd08cad b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9a176b6f7e0dc5f681a1788d8954f76fabd08cad
new file mode 100644
index 0000000..ef52cd7
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9a176b6f7e0dc5f681a1788d8954f76fabd08cad
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9de2e92150e54982d4e502b18f374f8cd8fd453b b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9de2e92150e54982d4e502b18f374f8cd8fd453b
new file mode 100644
index 0000000..e7aa007
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9de2e92150e54982d4e502b18f374f8cd8fd453b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a61a28cf78149518466b87e5463ec5c771dc504e b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a61a28cf78149518466b87e5463ec5c771dc504e
new file mode 100644
index 0000000..2933607
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a61a28cf78149518466b87e5463ec5c771dc504e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-aa23c18f6badd88a7bec65e8b04f7801ba624ec6 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-aa23c18f6badd88a7bec65e8b04f7801ba624ec6
new file mode 100644
index 0000000..3d7f426
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-aa23c18f6badd88a7bec65e8b04f7801ba624ec6
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ba2b1fde90cc70d9abae22c4c4cb051aae8aa148 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ba2b1fde90cc70d9abae22c4c4cb051aae8aa148
new file mode 100644
index 0000000..cd2506a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ba2b1fde90cc70d9abae22c4c4cb051aae8aa148
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bda43d420a3e5d5228a5f5130207a1f11fc1c81f b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bda43d420a3e5d5228a5f5130207a1f11fc1c81f
new file mode 100644
index 0000000..37b9287
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bda43d420a3e5d5228a5f5130207a1f11fc1c81f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c05c239719a7beeca2c126b7e5ef7251fa615b54 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c05c239719a7beeca2c126b7e5ef7251fa615b54
new file mode 100644
index 0000000..2d2a93d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c05c239719a7beeca2c126b7e5ef7251fa615b54
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c151762e5f37e233142059c1b269ce55434cf6a6 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c151762e5f37e233142059c1b269ce55434cf6a6
new file mode 100644
index 0000000..9d35a1b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c151762e5f37e233142059c1b269ce55434cf6a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-cacd0e0c5f7d4169085735400100da4d36397185 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-cacd0e0c5f7d4169085735400100da4d36397185
new file mode 100644
index 0000000..16489d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-cacd0e0c5f7d4169085735400100da4d36397185
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3c3cba3897fafec97665411ea1f94a89bb4de7b b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3c3cba3897fafec97665411ea1f94a89bb4de7b
new file mode 100644
index 0000000..30ff86f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3c3cba3897fafec97665411ea1f94a89bb4de7b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3fcd80cd6f1bb05f5e5084ebb2ee801067863fb b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3fcd80cd6f1bb05f5e5084ebb2ee801067863fb
new file mode 100644
index 0000000..f9db611
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3fcd80cd6f1bb05f5e5084ebb2ee801067863fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ddfe613d8791b2d377e14fbdffb18b84a89d49b6 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ddfe613d8791b2d377e14fbdffb18b84a89d49b6
new file mode 100644
index 0000000..93bc416
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ddfe613d8791b2d377e14fbdffb18b84a89d49b6
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f67be653815f6c2c10eea55c8009e1167ac9c20b b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f67be653815f6c2c10eea55c8009e1167ac9c20b
new file mode 100644
index 0000000..f8ae9f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f67be653815f6c2c10eea55c8009e1167ac9c20b
Binary files differ
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index fa32601..cffe599 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -53,12 +53,8 @@
     'h2_census': default_unsecure_fixture_options,
     'h2_fakesec': default_secure_fixture_options._replace(ci_mac=False),
     'h2_full': default_unsecure_fixture_options,
-    'h2_full+poll': default_unsecure_fixture_options._replace(
-        platforms=['linux']),
     'h2_full+pipe': default_unsecure_fixture_options._replace(
         platforms=['linux']),
-    'h2_full+poll+pipe': default_unsecure_fixture_options._replace(
-        platforms=['linux']),
     'h2_full+trace': default_unsecure_fixture_options._replace(tracing=True),
     'h2_oauth2': default_secure_fixture_options._replace(ci_mac=False),
     'h2_proxy': default_unsecure_fixture_options._replace(includes_proxy=True,
@@ -69,11 +65,9 @@
     'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace(
         ci_mac=False, tracing=True),
     'h2_ssl': default_secure_fixture_options,
-    'h2_ssl+poll': default_secure_fixture_options._replace(platforms=['linux']),
+    'h2_ssl_cert': default_secure_fixture_options,
     'h2_ssl_proxy': default_secure_fixture_options._replace(includes_proxy=True,
                                                             ci_mac=False),
-    'h2_uchannel': default_unsecure_fixture_options._replace(fullstack=False),
-    'h2_uds+poll': uds_fixture_options._replace(platforms=['linux']),
     'h2_uds': uds_fixture_options,
 }
 
@@ -101,10 +95,12 @@
                                                   needs_dns=True),
     'disappearing_server': connectivity_test_options,
     'empty_batch': default_test_options,
+    'filter_causes_close': default_test_options,
     'graceful_server_shutdown': default_test_options._replace(cpu_cost=LOWCPU),
     'hpack_size': default_test_options._replace(proxyable=False,
                                                 traceable=False),
     'high_initial_seqno': default_test_options,
+    'idempotent_request': default_test_options,
     'invoke_large_request': default_test_options,
     'large_metadata': default_test_options,
     'max_concurrent_streams': default_test_options._replace(proxyable=False),
diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c
new file mode 100644
index 0000000..5f8c264
--- /dev/null
+++ b/test/core/end2end/goaway_server_test.c
@@ -0,0 +1,301 @@
+/*
+ *
+ * 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 <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <string.h>
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "test/core/end2end/cq_verifier.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+static void *tag(intptr_t i) { return (void *)i; }
+
+static gpr_mu g_mu;
+static int g_resolve_port = -1;
+static grpc_resolved_addresses *(*iomgr_resolve_address)(
+    const char *name, const char *default_port);
+
+static void set_resolve_port(int port) {
+  gpr_mu_lock(&g_mu);
+  g_resolve_port = port;
+  gpr_mu_unlock(&g_mu);
+}
+
+static grpc_resolved_addresses *my_resolve_address(const char *name,
+                                                   const char *addr) {
+  if (0 != strcmp(name, "test")) {
+    return iomgr_resolve_address(name, addr);
+  }
+
+  gpr_mu_lock(&g_mu);
+  if (g_resolve_port < 0) {
+    gpr_mu_unlock(&g_mu);
+    return NULL;
+  } else {
+    grpc_resolved_addresses *addrs = gpr_malloc(sizeof(*addrs));
+    addrs->naddrs = 1;
+    addrs->addrs = gpr_malloc(sizeof(*addrs->addrs));
+    memset(addrs->addrs, 0, sizeof(*addrs->addrs));
+    struct sockaddr_in *sa = (struct sockaddr_in *)addrs->addrs[0].addr;
+    sa->sin_family = AF_INET;
+    sa->sin_addr.s_addr = htonl(0x7f000001);
+    sa->sin_port = htons((uint16_t)g_resolve_port);
+    addrs->addrs[0].len = sizeof(*sa);
+    gpr_mu_unlock(&g_mu);
+    return addrs;
+  }
+}
+
+int main(int argc, char **argv) {
+  grpc_completion_queue *cq;
+  cq_verifier *cqv;
+  grpc_op ops[6];
+  grpc_op *op;
+
+  grpc_test_init(argc, argv);
+
+  gpr_mu_init(&g_mu);
+  iomgr_resolve_address = grpc_blocking_resolve_address;
+  grpc_blocking_resolve_address = my_resolve_address;
+  grpc_init();
+
+  int was_cancelled1;
+  int was_cancelled2;
+
+  grpc_metadata_array trailing_metadata_recv1;
+  grpc_metadata_array request_metadata1;
+  grpc_call_details request_details1;
+  grpc_status_code status1;
+  char *details1 = NULL;
+  size_t details_capacity1 = 0;
+  grpc_metadata_array_init(&trailing_metadata_recv1);
+  grpc_metadata_array_init(&request_metadata1);
+  grpc_call_details_init(&request_details1);
+
+  grpc_metadata_array trailing_metadata_recv2;
+  grpc_metadata_array request_metadata2;
+  grpc_call_details request_details2;
+  grpc_status_code status2;
+  char *details2 = NULL;
+  size_t details_capacity2 = 0;
+  grpc_metadata_array_init(&trailing_metadata_recv2);
+  grpc_metadata_array_init(&request_metadata2);
+  grpc_call_details_init(&request_details2);
+
+  cq = grpc_completion_queue_create(NULL);
+  cqv = cq_verifier_create(cq);
+
+  /* reserve two ports */
+  int port1 = grpc_pick_unused_port_or_die();
+  int port2 = grpc_pick_unused_port_or_die();
+
+  char *addr;
+
+  /* create a channel that picks first amongst the servers */
+  grpc_channel *chan = grpc_insecure_channel_create("test", NULL, NULL);
+  /* and an initial call to them */
+  grpc_call *call1 = grpc_channel_create_call(
+      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "127.0.0.1",
+      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
+  /* send initial metadata to probe connectivity */
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call1, ops,
+                                                   (size_t)(op - ops),
+                                                   tag(0x101), NULL));
+  /* and receive status to probe termination */
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
+  op->data.recv_status_on_client.status = &status1;
+  op->data.recv_status_on_client.status_details = &details1;
+  op->data.recv_status_on_client.status_details_capacity = &details_capacity1;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call1, ops,
+                                                   (size_t)(op - ops),
+                                                   tag(0x102), NULL));
+
+  /* bring a server up on the first port */
+  grpc_server *server1 = grpc_server_create(NULL, NULL);
+  gpr_asprintf(&addr, "127.0.0.1:%d", port1);
+  grpc_server_add_insecure_http2_port(server1, addr);
+  grpc_server_register_completion_queue(server1, cq, NULL);
+  gpr_free(addr);
+  grpc_server_start(server1);
+
+  /* request a call to the server */
+  grpc_call *server_call1;
+  GPR_ASSERT(GRPC_CALL_OK ==
+             grpc_server_request_call(server1, &server_call1, &request_details1,
+                                      &request_metadata1, cq, cq, tag(0x301)));
+
+  set_resolve_port(port1);
+
+  /* first call should now start */
+  cq_expect_completion(cqv, tag(0x101), 1);
+  cq_expect_completion(cqv, tag(0x301), 1);
+  cq_verify(cqv);
+
+  GPR_ASSERT(GRPC_CHANNEL_READY ==
+             grpc_channel_check_connectivity_state(chan, 0));
+  grpc_channel_watch_connectivity_state(chan, GRPC_CHANNEL_READY,
+                                        gpr_inf_future(GPR_CLOCK_REALTIME), cq,
+                                        tag(0x9999));
+
+  /* listen for close on the server call to probe for finishing */
+  op = ops;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled1;
+  op->flags = 0;
+  op++;
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(server_call1, ops,
+                                                   (size_t)(op - ops),
+                                                   tag(0x302), NULL));
+
+  /* shutdown first server:
+   * we should see a connectivity change and then nothing */
+  set_resolve_port(-1);
+  grpc_server_shutdown_and_notify(server1, cq, tag(0xdead1));
+  cq_expect_completion(cqv, tag(0x9999), 1);
+  cq_verify(cqv);
+  cq_verify_empty(cqv);
+
+  /* and a new call: should go through to server2 when we start it */
+  grpc_call *call2 = grpc_channel_create_call(
+      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "127.0.0.1",
+      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
+  /* send initial metadata to probe connectivity */
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call2, ops,
+                                                   (size_t)(op - ops),
+                                                   tag(0x201), NULL));
+  /* and receive status to probe termination */
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
+  op->data.recv_status_on_client.status = &status2;
+  op->data.recv_status_on_client.status_details = &details2;
+  op->data.recv_status_on_client.status_details_capacity = &details_capacity2;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call2, ops,
+                                                   (size_t)(op - ops),
+                                                   tag(0x202), NULL));
+
+  /* and bring up second server */
+  set_resolve_port(port2);
+  grpc_server *server2 = grpc_server_create(NULL, NULL);
+  gpr_asprintf(&addr, "127.0.0.1:%d", port2);
+  grpc_server_add_insecure_http2_port(server2, addr);
+  grpc_server_register_completion_queue(server2, cq, NULL);
+  gpr_free(addr);
+  grpc_server_start(server2);
+
+  /* request a call to the server */
+  grpc_call *server_call2;
+  GPR_ASSERT(GRPC_CALL_OK ==
+             grpc_server_request_call(server2, &server_call2, &request_details2,
+                                      &request_metadata2, cq, cq, tag(0x401)));
+
+  /* second call should now start */
+  cq_expect_completion(cqv, tag(0x201), 1);
+  cq_expect_completion(cqv, tag(0x401), 1);
+  cq_verify(cqv);
+
+  /* listen for close on the server call to probe for finishing */
+  op = ops;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled2;
+  op->flags = 0;
+  op++;
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(server_call2, ops,
+                                                   (size_t)(op - ops),
+                                                   tag(0x402), NULL));
+
+  /* shutdown second server: we should see nothing */
+  grpc_server_shutdown_and_notify(server2, cq, tag(0xdead2));
+  cq_verify_empty(cqv);
+
+  grpc_call_cancel(call1, NULL);
+  grpc_call_cancel(call2, NULL);
+
+  /* now everything else should finish */
+  cq_expect_completion(cqv, tag(0x102), 1);
+  cq_expect_completion(cqv, tag(0x202), 1);
+  cq_expect_completion(cqv, tag(0x302), 1);
+  cq_expect_completion(cqv, tag(0x402), 1);
+  cq_expect_completion(cqv, tag(0xdead1), 1);
+  cq_expect_completion(cqv, tag(0xdead2), 1);
+  cq_verify(cqv);
+
+  grpc_call_destroy(call1);
+  grpc_call_destroy(call2);
+  grpc_call_destroy(server_call1);
+  grpc_call_destroy(server_call2);
+  grpc_server_destroy(server1);
+  grpc_server_destroy(server2);
+  grpc_channel_destroy(chan);
+
+  grpc_metadata_array_destroy(&trailing_metadata_recv1);
+  grpc_metadata_array_destroy(&request_metadata1);
+  grpc_call_details_destroy(&request_details1);
+  gpr_free(details1);
+  grpc_metadata_array_destroy(&trailing_metadata_recv2);
+  grpc_metadata_array_destroy(&request_metadata2);
+  grpc_call_details_destroy(&request_details2);
+  gpr_free(details2);
+
+  cq_verifier_destroy(cqv);
+  grpc_completion_queue_destroy(cq);
+
+  grpc_shutdown();
+  gpr_mu_destroy(&g_mu);
+
+  return 0;
+}
diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c
index 2fa1a0a..cf42e92 100644
--- a/test/core/end2end/invalid_call_argument_test.c
+++ b/test/core/end2end/invalid_call_argument_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,7 @@
 static struct test_state g_state;
 
 static void prepare_test(int is_client) {
-  int port;
+  int port = grpc_pick_unused_port_or_die();
   char *server_hostport;
   grpc_op *op;
   g_state.is_client = is_client;
@@ -85,7 +85,6 @@
   } else {
     g_state.server = grpc_server_create(NULL, NULL);
     grpc_server_register_completion_queue(g_state.server, g_state.cq, NULL);
-    port = grpc_pick_unused_port_or_die();
     gpr_join_host_port(&server_hostport, "0.0.0.0", port);
     grpc_server_add_insecure_http2_port(g_state.server, server_hostport);
     grpc_server_start(g_state.server);
@@ -131,15 +130,16 @@
     grpc_server_shutdown_and_notify(g_state.server, g_state.cq, tag(1000));
     GPR_ASSERT(grpc_completion_queue_pluck(g_state.cq, tag(1000),
                                            GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                           NULL).type == GRPC_OP_COMPLETE);
+                                           NULL)
+                   .type == GRPC_OP_COMPLETE);
     grpc_server_destroy(g_state.server);
     grpc_call_details_destroy(&g_state.call_details);
     grpc_metadata_array_destroy(&g_state.server_initial_metadata_recv);
   }
   grpc_completion_queue_shutdown(g_state.cq);
   while (grpc_completion_queue_next(g_state.cq,
-                                    gpr_inf_future(GPR_CLOCK_REALTIME),
-                                    NULL).type != GRPC_QUEUE_SHUTDOWN)
+                                    gpr_inf_future(GPR_CLOCK_REALTIME), NULL)
+             .type != GRPC_QUEUE_SHUTDOWN)
     ;
   grpc_completion_queue_destroy(g_state.cq);
 }
diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c
index 5c971ea..7a5cd23 100644
--- a/test/core/end2end/no_server_test.c
+++ b/test/core/end2end/no_server_test.c
@@ -88,8 +88,9 @@
   GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
 
   grpc_completion_queue_shutdown(cq);
-  while (grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
-                                    NULL).type != GRPC_QUEUE_SHUTDOWN)
+  while (
+      grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL)
+          .type != GRPC_QUEUE_SHUTDOWN)
     ;
   grpc_completion_queue_destroy(cq);
   grpc_call_destroy(call);
diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c
index 1458738..3cb9b3d 100644
--- a/test/core/end2end/tests/bad_hostname.c
+++ b/test/core/end2end/tests/bad_hostname.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -152,7 +152,7 @@
   cq_expect_completion(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
+  GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
 
   gpr_free(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
@@ -179,3 +179,5 @@
     test_invoke_simple_request(config);
   }
 }
+
+void bad_hostname_pre_init(void) {}
diff --git a/test/core/end2end/tests/binary_metadata.c b/test/core/end2end/tests/binary_metadata.c
index 4eccd16..994c3bf 100644
--- a/test/core/end2end/tests/binary_metadata.c
+++ b/test/core/end2end/tests/binary_metadata.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -287,3 +287,5 @@
 void binary_metadata(grpc_end2end_test_config config) {
   test_request_response_with_metadata_and_payload(config);
 }
+
+void binary_metadata_pre_init(void) {}
diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c
index c9d4251..b555bea 100644
--- a/test/core/end2end/tests/call_creds.c
+++ b/test/core/end2end/tests/call_creds.c
@@ -36,15 +36,15 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <grpc/grpc_security.h>
 #include <grpc/byte_buffer.h>
+#include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
-#include "src/core/security/credentials.h"
-#include "src/core/support/string.h"
 
 static const char iam_token[] = "token";
 static const char iam_selector[] = "selector";
@@ -93,9 +93,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -475,3 +475,5 @@
     test_request_with_server_rejecting_client_creds(config);
   }
 }
+
+void call_creds_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c
index 4646bf7..fc2a64a 100644
--- a/test/core/end2end/tests/cancel_after_accept.c
+++ b/test/core/end2end/tests/cancel_after_accept.c
@@ -76,9 +76,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -233,3 +233,5 @@
     test_cancel_after_accept(config, cancellation_modes[i]);
   }
 }
+
+void cancel_after_accept_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c
index 364598a..3bafa8c 100644
--- a/test/core/end2end/tests/cancel_after_client_done.c
+++ b/test/core/end2end/tests/cancel_after_client_done.c
@@ -76,9 +76,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -237,3 +237,5 @@
     test_cancel_after_accept_and_writes_closed(config, cancellation_modes[i]);
   }
 }
+
+void cancel_after_client_done_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c
index ec0b0de..fc2751a 100644
--- a/test/core/end2end/tests/cancel_after_invoke.c
+++ b/test/core/end2end/tests/cancel_after_invoke.c
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -199,3 +199,5 @@
     }
   }
 }
+
+void cancel_after_invoke_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c
index 7b432fe..33005db 100644
--- a/test/core/end2end/tests/cancel_before_invoke.c
+++ b/test/core/end2end/tests/cancel_before_invoke.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -194,3 +194,5 @@
     test_cancel_before_invoke(config, i);
   }
 }
+
+void cancel_before_invoke_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c
index 214ab2b..0c893b5 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.c
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.c
@@ -76,9 +76,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -127,3 +127,5 @@
     test_cancel_in_a_vacuum(config, cancellation_modes[i]);
   }
 }
+
+void cancel_in_a_vacuum_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index 1541ca0..c3ee4a6 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -182,3 +182,5 @@
     test_invoke_simple_request(config, i);
   }
 }
+
+void cancel_with_status_pre_init(void) {}
diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c
index 33b1d8f..589bc31 100644
--- a/test/core/end2end/tests/compressed_payload.c
+++ b/test/core/end2end/tests/compressed_payload.c
@@ -43,10 +43,10 @@
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/surface/call_test_only.h"
 #include "test/core/end2end/cq_verifier.h"
-#include "src/core/channel/channel_args.h"
-#include "src/core/channel/compress_filter.h"
-#include "src/core/surface/call_test_only.h"
 
 enum { TIMEOUT = 200000 };
 
@@ -80,9 +80,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -336,3 +336,5 @@
   test_invoke_request_with_compressed_payload(config);
   test_invoke_request_with_compressed_payload_md_override(config);
 }
+
+void compressed_payload_pre_init(void) {}
diff --git a/test/core/end2end/tests/connectivity.c b/test/core/end2end/tests/connectivity.c
index 975c620..5775976 100644
--- a/test/core/end2end/tests/connectivity.c
+++ b/test/core/end2end/tests/connectivity.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -172,3 +172,5 @@
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION);
   test_connectivity(config);
 }
+
+void connectivity_pre_init(void) {}
diff --git a/test/core/end2end/tests/default_host.c b/test/core/end2end/tests/default_host.c
index dc33034..44384a7 100644
--- a/test/core/end2end/tests/default_host.c
+++ b/test/core/end2end/tests/default_host.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -232,3 +232,5 @@
     return;
   test_invoke_simple_request(config);
 }
+
+void default_host_pre_init(void) {}
diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c
index 5b2bbaf..03d1ded 100644
--- a/test/core/end2end/tests/disappearing_server.c
+++ b/test/core/end2end/tests/disappearing_server.c
@@ -213,3 +213,5 @@
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION);
   disappearing_server_test(config);
 }
+
+void disappearing_server_pre_init(void) {}
diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c
index 24320c0..c05b919 100644
--- a/test/core/end2end/tests/empty_batch.c
+++ b/test/core/end2end/tests/empty_batch.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -132,3 +132,5 @@
 void empty_batch(grpc_end2end_test_config config) {
   test_invoke_empty_body(config);
 }
+
+void empty_batch_pre_init(void) {}
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
new file mode 100644
index 0000000..9f9ee85
--- /dev/null
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -0,0 +1,286 @@
+/*
+ *
+ * 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 "test/core/end2end/end2end_tests.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "test/core/end2end/cq_verifier.h"
+
+enum { TIMEOUT = 200000 };
+
+static bool g_enable_filter = false;
+
+static void *tag(intptr_t t) { return (void *)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char *test_name,
+                                            grpc_channel_args *client_args,
+                                            grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_server(&f, server_args);
+  config.init_client(&f, client_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_time(int n) {
+  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+}
+
+static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
+
+static void drain_cq(grpc_completion_queue *cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture *f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = NULL;
+}
+
+static void end_test(grpc_end2end_test_fixture *f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+}
+
+/* Simple request via a server filter that always closes the stream.*/
+static void test_request(grpc_end2end_test_config config) {
+  grpc_call *c;
+  grpc_call *s;
+  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 = five_seconds_time();
+  grpc_end2end_test_fixture f =
+      begin_test(config, "filter_causes_close", NULL, NULL);
+  cq_verifier *cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op *op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_byte_buffer *request_payload_recv = NULL;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  char *details = NULL;
+  size_t details_capacity = 0;
+
+  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               "/foo", "foo.test.google.fr", deadline, NULL);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->data.send_initial_metadata.metadata = NULL;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_MESSAGE;
+  op->data.send_message = request_payload;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(101));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  cq_expect_completion(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
+  GPR_ASSERT(0 == strcmp(details, "Random failure that's not preventable."));
+
+  gpr_free(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_destroy(c);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_byte_buffer_destroy(request_payload);
+  grpc_byte_buffer_destroy(request_payload_recv);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+/*******************************************************************************
+ * Test filter - always closes incoming requests
+ */
+
+typedef struct { grpc_closure *recv_im_ready; } call_data;
+
+typedef struct { uint8_t unused; } channel_data;
+
+static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+  grpc_call_element *elem = arg;
+  call_data *calld = elem->call_data;
+  if (success) {
+    // close the stream with an error.
+    gpr_slice message =
+        gpr_slice_from_copied_string("Random failure that's not preventable.");
+    grpc_transport_stream_op op;
+    memset(&op, 0, sizeof(op));
+    grpc_transport_stream_op_add_close(&op, GRPC_STATUS_PERMISSION_DENIED,
+                                       &message);
+    grpc_call_next_op(exec_ctx, elem, &op);
+  }
+  calld->recv_im_ready->cb(exec_ctx, calld->recv_im_ready->cb_arg, false);
+}
+
+static void start_transport_stream_op(grpc_exec_ctx *exec_ctx,
+                                      grpc_call_element *elem,
+                                      grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+  if (op->recv_initial_metadata != NULL) {
+    calld->recv_im_ready = op->recv_initial_metadata_ready;
+    op->recv_initial_metadata_ready = grpc_closure_create(recv_im_ready, elem);
+  }
+  grpc_call_next_op(exec_ctx, elem, op);
+}
+
+static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                           grpc_call_element_args *args) {}
+
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_call_element *elem) {}
+
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {}
+
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {}
+
+static const grpc_channel_filter test_filter = {
+    start_transport_stream_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "filter_causes_close"};
+
+/*******************************************************************************
+ * Registration
+ */
+
+static bool maybe_add_filter(grpc_channel_stack_builder *builder, void *arg) {
+  if (g_enable_filter) {
+    return grpc_channel_stack_builder_prepend_filter(builder, &test_filter,
+                                                     NULL, NULL);
+  } else {
+    return true;
+  }
+}
+
+static void init_plugin(void) {
+  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, 0, maybe_add_filter,
+                                   NULL);
+}
+
+static void destroy_plugin(void) {}
+
+void filter_causes_close(grpc_end2end_test_config config) {
+  g_enable_filter = true;
+  test_request(config);
+  g_enable_filter = false;
+}
+
+void filter_causes_close_pre_init(void) {
+  grpc_register_plugin(init_plugin, destroy_plugin);
+}
diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c
index cc6a9d4..26198f3 100644
--- a/test/core/end2end/tests/graceful_server_shutdown.c
+++ b/test/core/end2end/tests/graceful_server_shutdown.c
@@ -210,3 +210,5 @@
 void graceful_server_shutdown(grpc_end2end_test_config config) {
   test_early_server_shutdown_finishes_inflight_calls(config);
 }
+
+void graceful_server_shutdown_pre_init(void) {}
diff --git a/test/core/end2end/tests/high_initial_seqno.c b/test/core/end2end/tests/high_initial_seqno.c
index 8d16ef5..374606d 100644
--- a/test/core/end2end/tests/high_initial_seqno.c
+++ b/test/core/end2end/tests/high_initial_seqno.c
@@ -44,7 +44,7 @@
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/support/string.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -79,9 +79,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -237,3 +237,5 @@
     test_invoke_10_simple_requests(config, 2147483645);
   }
 }
+
+void high_initial_seqno_pre_init(void) {}
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
index fd4fe34..07d5d38 100644
--- a/test/core/end2end/tests/hpack_size.c
+++ b/test/core/end2end/tests/hpack_size.c
@@ -44,7 +44,7 @@
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/support/string.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 static void *tag(intptr_t t) { return (void *)t; }
@@ -262,9 +262,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -444,3 +444,5 @@
     }
   }
 }
+
+void hpack_size_pre_init(void) {}
diff --git a/test/core/end2end/tests/idempotent_request.c b/test/core/end2end/tests/idempotent_request.c
new file mode 100644
index 0000000..e53f3b2
--- /dev/null
+++ b/test/core/end2end/tests/idempotent_request.c
@@ -0,0 +1,250 @@
+/*
+ *
+ * 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 "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
+#include "test/core/end2end/cq_verifier.h"
+
+enum { TIMEOUT = 200000 };
+
+static void *tag(intptr_t t) { return (void *)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char *test_name,
+                                            grpc_channel_args *client_args,
+                                            grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_server(&f, server_args);
+  config.init_client(&f, client_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_time(int n) {
+  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+}
+
+static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
+
+static void drain_cq(grpc_completion_queue *cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture *f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = NULL;
+}
+
+static void end_test(grpc_end2end_test_fixture *f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+}
+
+static void simple_request_body(grpc_end2end_test_fixture f) {
+  grpc_call *c;
+  grpc_call *s;
+  gpr_timespec deadline = five_seconds_time();
+  cq_verifier *cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op *op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  char *details = NULL;
+  size_t details_capacity = 0;
+  int was_cancelled = 2;
+  char *peer;
+
+  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               "/foo", "foo.test.google.fr:1234", deadline,
+                               NULL);
+  GPR_ASSERT(c);
+
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != NULL);
+  gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer);
+  gpr_free(peer);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(101));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  cq_expect_completion(cqv, tag(101), 1);
+  cq_verify(cqv);
+
+  peer = grpc_call_get_peer(s);
+  GPR_ASSERT(peer != NULL);
+  gpr_log(GPR_DEBUG, "server_peer=%s", peer);
+  gpr_free(peer);
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != NULL);
+  gpr_log(GPR_DEBUG, "client_peer=%s", peer);
+  gpr_free(peer);
+
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  op->data.send_status_from_server.status_details = "xyz";
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  cq_expect_completion(cqv, tag(102), 1);
+  cq_expect_completion(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
+  GPR_ASSERT(0 == strcmp(details, "xyz"));
+  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
+  GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags);
+  GPR_ASSERT(was_cancelled == 1);
+
+  gpr_free(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_destroy(c);
+  grpc_call_destroy(s);
+
+  cq_verifier_destroy(cqv);
+}
+
+static void test_invoke_simple_request(grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f;
+
+  f = begin_test(config, "test_invoke_simple_request", NULL, NULL);
+  simple_request_body(f);
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_invoke_10_simple_requests(grpc_end2end_test_config config) {
+  int i;
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_invoke_10_simple_requests", NULL, NULL);
+  for (i = 0; i < 10; i++) {
+    simple_request_body(f);
+    gpr_log(GPR_INFO, "Passed simple request %d", i);
+  }
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+void idempotent_request(grpc_end2end_test_config config) {
+  int i;
+  for (i = 0; i < 10; i++) {
+    test_invoke_simple_request(config);
+  }
+  test_invoke_10_simple_requests(config);
+}
+
+void idempotent_request_pre_init(void) {}
diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c
index f0b0198..6410305 100644
--- a/test/core/end2end/tests/invoke_large_request.c
+++ b/test/core/end2end/tests/invoke_large_request.c
@@ -73,9 +73,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -254,3 +254,5 @@
 void invoke_large_request(grpc_end2end_test_config config) {
   test_invoke_large_request(config);
 }
+
+void invoke_large_request_pre_init(void) {}
diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c
index 1b41e89..0e5d6b4 100644
--- a/test/core/end2end/tests/large_metadata.c
+++ b/test/core/end2end/tests/large_metadata.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -245,3 +245,5 @@
 void large_metadata(grpc_end2end_test_config config) {
   test_request_with_large_metadata(config);
 }
+
+void large_metadata_pre_init(void) {}
diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c
index d6b2a06..1bb5307 100644
--- a/test/core/end2end/tests/max_concurrent_streams.c
+++ b/test/core/end2end/tests/max_concurrent_streams.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -436,3 +436,5 @@
 void max_concurrent_streams(grpc_end2end_test_config config) {
   test_max_concurrent_streams(config);
 }
+
+void max_concurrent_streams_pre_init(void) {}
diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c
index 59ab7f4..b5dbc13 100644
--- a/test/core/end2end/tests/max_message_length.c
+++ b/test/core/end2end/tests/max_message_length.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -221,3 +221,5 @@
 void max_message_length(grpc_end2end_test_config config) {
   test_max_message_length(config);
 }
+
+void max_message_length_pre_init(void) {}
diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c
index 2109310..03e57a9 100644
--- a/test/core/end2end/tests/negative_deadline.c
+++ b/test/core/end2end/tests/negative_deadline.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -179,3 +179,5 @@
     test_invoke_simple_request(config, i);
   }
 }
+
+void negative_deadline_pre_init(void) {}
diff --git a/test/core/end2end/tests/no_op.c b/test/core/end2end/tests/no_op.c
index 4bc1d63..284be7a 100644
--- a/test/core/end2end/tests/no_op.c
+++ b/test/core/end2end/tests/no_op.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -104,3 +104,5 @@
 }
 
 void no_op(grpc_end2end_test_config config) { test_no_op(config); }
+
+void no_op_pre_init(void) {}
diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c
index bc220cb..bdfb135 100644
--- a/test/core/end2end/tests/payload.c
+++ b/test/core/end2end/tests/payload.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -268,3 +268,5 @@
   test_invoke_request_response_with_payload(config);
   test_invoke_10_request_response_with_payload(config);
 }
+
+void payload_pre_init(void) {}
diff --git a/test/core/end2end/tests/ping.c b/test/core/end2end/tests/ping.c
index f85df63..d49bec9 100644
--- a/test/core/end2end/tests/ping.c
+++ b/test/core/end2end/tests/ping.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -95,3 +95,5 @@
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION);
   test_ping(config);
 }
+
+void ping_pre_init(void) {}
diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c
index 8351f50..15e1c6e 100644
--- a/test/core/end2end/tests/ping_pong_streaming.c
+++ b/test/core/end2end/tests/ping_pong_streaming.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -275,3 +275,5 @@
     test_pingpong_streaming(config, i);
   }
 }
+
+void ping_pong_streaming_pre_init(void) {}
diff --git a/test/core/end2end/tests/registered_call.c b/test/core/end2end/tests/registered_call.c
index d9d2b19..3c4edba 100644
--- a/test/core/end2end/tests/registered_call.c
+++ b/test/core/end2end/tests/registered_call.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -231,3 +231,5 @@
   test_invoke_simple_request(config);
   test_invoke_10_simple_requests(config);
 }
+
+void registered_call_pre_init(void) {}
diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c
index 340aba6..779895b 100644
--- a/test/core/end2end/tests/request_with_flags.c
+++ b/test/core/end2end/tests/request_with_flags.c
@@ -41,7 +41,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
-#include "src/core/transport/byte_stream.h"
+#include "src/core/lib/transport/byte_stream.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -76,9 +76,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -214,3 +214,5 @@
     }
   }
 }
+
+void request_with_flags_pre_init(void) {}
diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c
index 1aced6a..7706404 100644
--- a/test/core/end2end/tests/request_with_payload.c
+++ b/test/core/end2end/tests/request_with_payload.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -232,3 +232,5 @@
 void request_with_payload(grpc_end2end_test_config config) {
   test_invoke_request_with_payload(config);
 }
+
+void request_with_payload_pre_init(void) {}
diff --git a/test/core/end2end/tests/server_finishes_request.c b/test/core/end2end/tests/server_finishes_request.c
index 6bca8d4..a4f5319 100644
--- a/test/core/end2end/tests/server_finishes_request.c
+++ b/test/core/end2end/tests/server_finishes_request.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -210,3 +210,5 @@
 void server_finishes_request(grpc_end2end_test_config config) {
   test_invoke_simple_request(config);
 }
+
+void server_finishes_request_pre_init(void) {}
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c
index b56ba46..80287cd 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.c
+++ b/test/core/end2end/tests/shutdown_finishes_calls.c
@@ -192,3 +192,5 @@
 void shutdown_finishes_calls(grpc_end2end_test_config config) {
   test_early_server_shutdown_finishes_inflight_calls(config);
 }
+
+void shutdown_finishes_calls_pre_init(void) {}
diff --git a/test/core/end2end/tests/shutdown_finishes_tags.c b/test/core/end2end/tests/shutdown_finishes_tags.c
index 4a060de..b1f3c94 100644
--- a/test/core/end2end/tests/shutdown_finishes_tags.c
+++ b/test/core/end2end/tests/shutdown_finishes_tags.c
@@ -119,3 +119,5 @@
 void shutdown_finishes_tags(grpc_end2end_test_config config) {
   test_early_server_shutdown_finishes_tags(config);
 }
+
+void shutdown_finishes_tags_pre_init(void) {}
diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c
index 0afef75..400b3a0 100644
--- a/test/core/end2end/tests/simple_delayed_request.c
+++ b/test/core/end2end/tests/simple_delayed_request.c
@@ -63,9 +63,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -120,7 +120,7 @@
   op = ops;
   op->op = GRPC_OP_SEND_INITIAL_METADATA;
   op->data.send_initial_metadata.count = 0;
-  op->flags = 0;
+  op->flags = GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY;
   op->reserved = NULL;
   op++;
   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
@@ -221,3 +221,5 @@
   test_simple_delayed_request_short(config);
   test_simple_delayed_request_long(config);
 }
+
+void simple_delayed_request_pre_init(void) {}
diff --git a/test/core/end2end/tests/simple_metadata.c b/test/core/end2end/tests/simple_metadata.c
index c5084a5..707b3c9 100644
--- a/test/core/end2end/tests/simple_metadata.c
+++ b/test/core/end2end/tests/simple_metadata.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -263,3 +263,5 @@
 void simple_metadata(grpc_end2end_test_config config) {
   test_request_response_with_metadata_and_payload(config);
 }
+
+void simple_metadata_pre_init(void) {}
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index 3720cd1..4210842 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -36,13 +36,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
 enum { TIMEOUT = 200000 };
@@ -77,9 +77,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -203,6 +203,7 @@
   GPR_ASSERT(0 == strcmp(details, "xyz"));
   GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
   GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
+  GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
   gpr_free(details);
@@ -245,3 +246,5 @@
   }
   test_invoke_10_simple_requests(config);
 }
+
+void simple_request_pre_init(void) {}
diff --git a/test/core/end2end/tests/trailing_metadata.c b/test/core/end2end/tests/trailing_metadata.c
index 78525e9..4dd8c12 100644
--- a/test/core/end2end/tests/trailing_metadata.c
+++ b/test/core/end2end/tests/trailing_metadata.c
@@ -75,9 +75,9 @@
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }
@@ -268,3 +268,5 @@
 void trailing_metadata(grpc_end2end_test_config config) {
   test_request_response_with_metadata_and_payload(config);
 }
+
+void trailing_metadata_pre_init(void) {}
diff --git a/test/core/fling/client.c b/test/core/fling/client.c
index b36aef3..8156227 100644
--- a/test/core/fling/client.c
+++ b/test/core/fling/client.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
-#include "src/core/profiling/timers.h"
+#include "src/core/lib/profiling/timers.h"
 #include "test/core/util/grpc_profiler.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/fling/fling_stream_test.c b/test/core/fling/fling_stream_test.c
index 78a7337..7e4daaa 100644
--- a/test/core/fling/fling_stream_test.c
+++ b/test/core/fling/fling_stream_test.c
@@ -35,19 +35,19 @@
 #define _POSIX_SOURCE
 #endif
 
-#include <unistd.h>
 #include <assert.h>
-#include <stdio.h>
-#include <string.h>
 #include <signal.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
-#include "src/core/support/string.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/string_util.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/util/port.h"
 
 int main(int argc, char **argv) {
diff --git a/test/core/fling/fling_test.c b/test/core/fling/fling_test.c
index cf43ecf..6663ad3 100644
--- a/test/core/fling/fling_test.c
+++ b/test/core/fling/fling_test.c
@@ -31,14 +31,14 @@
  *
  */
 
-#include <string.h>
 #include <stdio.h>
+#include <string.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/subprocess.h>
-#include "src/core/support/string.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/util/port.h"
 
 int main(int argc, char **argv) {
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index 42be20e..fd446f1 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -49,7 +49,7 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
-#include "src/core/profiling/timers.h"
+#include "src/core/lib/profiling/timers.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/grpc_profiler.h"
 #include "test/core/util/port.h"
diff --git a/test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427 b/test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
new file mode 100644
index 0000000..3d6face
--- /dev/null
+++ b/test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
@@ -0,0 +1,2 @@
+HTTP/1.1 …200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba b/test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
new file mode 100644
index 0000000..5cbaf2e
--- /dev/null
+++ b/test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
@@ -0,0 +1,2 @@
+HTTP/1.1 8) pMKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97 b/test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97
new file mode 100644
index 0000000..8831f07
--- /dev/null
+++ b/test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97
@@ -0,0 +1,2 @@
+HTTP/1.1 80) OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34 b/test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
new file mode 100644
index 0000000..10967d9
--- /dev/null
+++ b/test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
@@ -0,0 +1,2 @@
+„HTT/21. 200 HT!TP/1OKH.1HTTP 200 OKH

+tHT//1T0P.1y 2001.
\ No newline at end of file
diff --git a/test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d b/test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d
new file mode 100644
index 0000000..c79e456
--- /dev/null
+++ b/test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d
Binary files differ
diff --git a/test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf b/test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
new file mode 100644
index 0000000..7b979b5
--- /dev/null
+++ b/test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OKH

+tHTTP/01.021  Oes,H

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4 b/test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4
new file mode 100644
index 0000000..67382b4
--- /dev/null
+++ b/test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OKHHTTP‰/1.200 OKH

+

+tHTHTTP/0 20T:tes/01.
\ No newline at end of file
diff --git a/test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55 b/test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
new file mode 100644
index 0000000..deb8265
--- /dev/null
+++ b/test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
@@ -0,0 +1,3 @@
+JHTT/21. 2è0 HTTP/1.1 200 OKHHTTP‰/1.200 OKH

+

+tHTHTHTJHTTPT
\ No newline at end of file
diff --git a/test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f b/test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f
new file mode 100644
index 0000000..9f2e0e4
--- /dev/null
+++ b/test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f
@@ -0,0 +1,2 @@
+JHTT/21. 200œHTT/0OKH.1 HTTP/200 OKH

+tH1.T
\ No newline at end of file
diff --git a/test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f b/test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
new file mode 100644
index 0000000..4db04b2
--- /dev/null
+++ b/test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
Binary files differ
diff --git a/test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9 b/test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9
new file mode 100644
index 0000000..cee70bf
--- /dev/null
+++ b/test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9
@@ -0,0 +1,2 @@
+JHTT¹21. 200HTT/0OKH1 HTTP/100 OKH

+tH1.T
\ No newline at end of file
diff --git a/test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc b/test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc
new file mode 100644
index 0000000..e76b00e
--- /dev/null
+++ b/test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc
@@ -0,0 +1,2 @@
+GET / HTTHTTP/1.1 200 OKH

+t10H
\ No newline at end of file
diff --git a/test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305 b/test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305
new file mode 100644
index 0000000..7435f52
--- /dev/null
+++ b/test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305
Binary files differ
diff --git a/test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2 b/test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
new file mode 100644
index 0000000..cce8ded
--- /dev/null
+++ b/test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
@@ -0,0 +1,2 @@
+HTTP/1*9y 200 OKm

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b b/test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
new file mode 100644
index 0000000..57efa3c
--- /dev/null
+++ b/test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
@@ -0,0 +1,4 @@
+JHTT/21. 200 HTTP/0OKH.1 200 OKH

+tHTTP/01.021  Oes,H

+t

+t
\ No newline at end of file
diff --git a/test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece b/test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
new file mode 100644
index 0000000..8df43e4
--- /dev/null
+++ b/test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
@@ -0,0 +1,2 @@
+HTTP/1.9y 200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf b/test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
new file mode 100644
index 0000000..4efa386
--- /dev/null
+++ b/test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
Binary files differ
diff --git a/test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d b/test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
new file mode 100644
index 0000000..f85f1df
--- /dev/null
+++ b/test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
Binary files differ
diff --git a/test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76 b/test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76
new file mode 100644
index 0000000..fefa451
--- /dev/null
+++ b/test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76
@@ -0,0 +1,2 @@
+HTTP/1.1 000 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac b/test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
new file mode 100644
index 0000000..b967b57
--- /dev/null
+++ b/test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OKH

+tHTTP/01.021 : Oes,H

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b b/test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b
new file mode 100644
index 0000000..8af9007
--- /dev/null
+++ b/test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b
@@ -0,0 +1,2 @@
+@TTP/1.1y 002ÿOKH

+ves
\ No newline at end of file
diff --git a/test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046 b/test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
new file mode 100644
index 0000000..7d20266
--- /dev/null
+++ b/test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
@@ -0,0 +1,2 @@
+HTTP/1.1y 200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9 b/test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
new file mode 100644
index 0000000..5996b9a
--- /dev/null
+++ b/test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
Binary files differ
diff --git a/test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa b/test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa
new file mode 100644
index 0000000..c59c4d2
--- /dev/null
+++ b/test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa
@@ -0,0 +1,2 @@
+HTTP/01.021  O,H

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5 b/test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
new file mode 100644
index 0000000..8ac7ceb
--- /dev/null
+++ b/test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
@@ -0,0 +1,2 @@
+ITTP/11 …20O HK

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55 b/test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
new file mode 100644
index 0000000..49d1c8f
--- /dev/null
+++ b/test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
@@ -0,0 +1,2 @@
+HTTP/1.1 200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d b/test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d
new file mode 100644
index 0000000..5f2c4df
--- /dev/null
+++ b/test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OKH

+	 HTDP/01.021 : Oes,H

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff b/test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff
new file mode 100644
index 0000000..6313cd9
--- /dev/null
+++ b/test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff
@@ -0,0 +1,4 @@
+JHTT/21. 200 HTTP/1OKH.1 200 OKH

+tHTTP/01.021  Oes,H

+t

+t
\ No newline at end of file
diff --git a/test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104 b/test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
new file mode 100644
index 0000000..fee5512
--- /dev/null
+++ b/test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
@@ -0,0 +1,2 @@
+JÏHTTP‰/1.200:OKHHTã/21. 2è0 HTTP/

+1.1 200 OKHHTtTP‰
\ No newline at end of file
diff --git a/test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee b/test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
new file mode 100644
index 0000000..bd7e239
--- /dev/null
+++ b/test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
Binary files differ
diff --git a/test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5 b/test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
new file mode 100644
index 0000000..9a15ab0
--- /dev/null
+++ b/test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
@@ -0,0 +1,2 @@
+HTTP/1. 200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0 b/test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
new file mode 100644
index 0000000..480708e
--- /dev/null
+++ b/test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
@@ -0,0 +1,2 @@
+@TTP/1.1y 00'JHTTP/1.1 +00ÿOïH HTTP/

+ve1.1 200s
\ No newline at end of file
diff --git a/test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e b/test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
new file mode 100644
index 0000000..0ed0dfa
--- /dev/null
+++ b/test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
Binary files differ
diff --git a/test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2 b/test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2
new file mode 100644
index 0000000..1f14f69
--- /dev/null
+++ b/test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2
@@ -0,0 +1,3 @@
+HTT
+/1.1 201 OKH

+des
\ No newline at end of file
diff --git a/test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337 b/test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337
new file mode 100644
index 0000000..8fc481d
--- /dev/null
+++ b/test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337
@@ -0,0 +1,5 @@
+JHTTP/1.GET / HTTP/1.0
+1 200 OKH

+
+
+t
\ No newline at end of file
diff --git a/test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6 b/test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6
new file mode 100644
index 0000000..d4223cc
--- /dev/null
+++ b/test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6
@@ -0,0 +1,2 @@
+HTTP/1.1 8p) )MKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9 b/test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
new file mode 100644
index 0000000..99e2c48
--- /dev/null
+++ b/test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
@@ -0,0 +1,4 @@
+HTTP/1.1 200 OKH

+tHTHTTP/1. 20TP/01.020(: Oes,H0 OKH

+

+tteses
\ No newline at end of file
diff --git a/test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c b/test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
new file mode 100644
index 0000000..776253d
--- /dev/null
+++ b/test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
Binary files differ
diff --git a/test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548 b/test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548
new file mode 100644
index 0000000..b1927fb
--- /dev/null
+++ b/test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548
@@ -0,0 +1,3 @@
+HTHHTT`TT
+/1.1 201 P*/OKH

+des1.1 2T
\ No newline at end of file
diff --git a/test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1 b/test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1
new file mode 100644
index 0000000..0eb2c0d
--- /dev/null
+++ b/test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1
@@ -0,0 +1,2 @@
+@TTP/1.1y 002ÿOKH

+ves
\ No newline at end of file
diff --git a/test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8 b/test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
new file mode 100644
index 0000000..f93b9a0
--- /dev/null
+++ b/test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
@@ -0,0 +1,3 @@
+„HTT/21. 200 HTTP/1.1 HT!TP/1OKH.1HTTP 200 OKH

+tHT/:/80 OKH

+1
\ No newline at end of file
diff --git a/test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1 b/test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
new file mode 100644
index 0000000..4ea07dc
--- /dev/null
+++ b/test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
@@ -0,0 +1,5 @@
+JHTTP/1>GET / HTTP/2.0
+1 200 OKH

+
+
+t
\ No newline at end of file
diff --git a/test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85 b/test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
new file mode 100644
index 0000000..2e95bac
--- /dev/null
+++ b/test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
@@ -0,0 +1,3 @@
+„HTT/21. 200 HTTP/1.1 HT!TP/1OKH.1HTTP 200 OKH

+tHT//80) OKH

+1
\ No newline at end of file
diff --git a/test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441 b/test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
new file mode 100644
index 0000000..837449d
--- /dev/null
+++ b/test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
@@ -0,0 +1,2 @@
+HTTP/1.1 80î OH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0 b/test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
new file mode 100644
index 0000000..6075d0a
--- /dev/null
+++ b/test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
Binary files differ
diff --git a/test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47 b/test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
new file mode 100644
index 0000000..10905be
--- /dev/null
+++ b/test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
@@ -0,0 +1,2 @@
+JHTTP/1.1 200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940 b/test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940
new file mode 100644
index 0000000..4539d9f
--- /dev/null
+++ b/test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940
@@ -0,0 +1,4 @@
+JHTT/21. 200 HTTP/2OKH.1 200 OKH

+tHTTP/01.021  Oes,H

+t

+t
\ No newline at end of file
diff --git a/test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8 b/test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
new file mode 100644
index 0000000..2704e4f
--- /dev/null
+++ b/test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
@@ -0,0 +1,2 @@
+HTTP/1.1 767) OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2 b/test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
new file mode 100644
index 0000000..f5cbbc6
--- /dev/null
+++ b/test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
@@ -0,0 +1,3 @@
+HJHTHHTT`TT
+/1.1 201 P*HHTT/T1/OKH

+des1.1 2.1T 20T1
\ No newline at end of file
diff --git a/test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70 b/test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
new file mode 100644
index 0000000..f6ea09c
--- /dev/null
+++ b/test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
@@ -0,0 +1,3 @@
+JHTT/21. 200 HTTPHTTP/1.1 80î OH/1OKH.0 200 OKH

+tHTTP/0

+te
\ No newline at end of file
diff --git a/test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa b/test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
new file mode 100644
index 0000000..e241a0c
--- /dev/null
+++ b/test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
Binary files differ
diff --git a/test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453 b/test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
new file mode 100644
index 0000000..be33d81
--- /dev/null
+++ b/test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OKH

+ HTTP/01.021 : Oes,H

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629 b/test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
new file mode 100644
index 0000000..e81a59f
--- /dev/null
+++ b/test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
@@ -0,0 +1,2 @@
+ÏHTTP‰/1.200:OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4 b/test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4
new file mode 100644
index 0000000..ccf9187
--- /dev/null
+++ b/test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4
@@ -0,0 +1,2 @@
+HTTP‰/1.200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b b/test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
new file mode 100644
index 0000000..b6fc095
--- /dev/null
+++ b/test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
@@ -0,0 +1,3 @@
+JHTT/21. 200 HTTRHTTP/1.1 0î OL/1OKH.0 200 OKH

+tHTTP/0

+te
\ No newline at end of file
diff --git a/test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089 b/test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089
new file mode 100644
index 0000000..98b5f62
--- /dev/null
+++ b/test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089
@@ -0,0 +1,2 @@
+TTHP‰/1.200 OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb b/test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
new file mode 100644
index 0000000..78b36c9
--- /dev/null
+++ b/test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
@@ -0,0 +1,2 @@
+ITHTTTPHT/12 …2S HTKP/1.1 767) OKH

+tes
\ No newline at end of file
diff --git a/test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066 b/test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
new file mode 100644
index 0000000..06f1a3b
--- /dev/null
+++ b/test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
@@ -0,0 +1 @@
+HH
\ No newline at end of file
diff --git a/test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b b/test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
new file mode 100644
index 0000000..eb63d31
--- /dev/null
+++ b/test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
Binary files differ
diff --git a/test/core/http/corpus/request1.txt b/test/core/http/corpus/request1.txt
new file mode 100644
index 0000000..16a750f
--- /dev/null
+++ b/test/core/http/corpus/request1.txt
@@ -0,0 +1,3 @@
+GET / HTTP/1.0
+
+
diff --git a/test/core/http/corpus/request2.txt b/test/core/http/corpus/request2.txt
new file mode 100644
index 0000000..897a284
--- /dev/null
+++ b/test/core/http/corpus/request2.txt
@@ -0,0 +1,3 @@
+GET / HTTP/1.0
+Content-Length: 128
+
diff --git a/test/core/http/corpus/request3.txt b/test/core/http/corpus/request3.txt
new file mode 100644
index 0000000..aaa75bb
--- /dev/null
+++ b/test/core/http/corpus/request3.txt
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Content-Length: 128
+
diff --git a/test/core/http/corpus/request4.txt b/test/core/http/corpus/request4.txt
new file mode 100644
index 0000000..593f6fa
--- /dev/null
+++ b/test/core/http/corpus/request4.txt
@@ -0,0 +1,3 @@
+GET /foo.bar HTTP/1.1
+Content-Length: 128
+
diff --git a/test/core/http/corpus/request5.txt b/test/core/http/corpus/request5.txt
new file mode 100644
index 0000000..19fb244
--- /dev/null
+++ b/test/core/http/corpus/request5.txt
@@ -0,0 +1,3 @@
+POST / HTTP/1.0
+
+asdlfkjadsfl;akdjsfasdf
diff --git a/test/core/http/corpus/response1.txt b/test/core/http/corpus/response1.txt
new file mode 100644
index 0000000..a171399
--- /dev/null
+++ b/test/core/http/corpus/response1.txt
@@ -0,0 +1,4 @@
+HTTP/1.1 200 OK
+test: hello
+
+abcd
diff --git a/test/core/http/corpus/response2.txt b/test/core/http/corpus/response2.txt
new file mode 100644
index 0000000..1b86449
--- /dev/null
+++ b/test/core/http/corpus/response2.txt
@@ -0,0 +1,4 @@
+HTTP/0.9 200 OK
+test: hello
+
+abcd
diff --git a/test/core/http/corpus/response3.txt b/test/core/http/corpus/response3.txt
new file mode 100644
index 0000000..9e5b046
--- /dev/null
+++ b/test/core/http/corpus/response3.txt
@@ -0,0 +1,5 @@
+HTTP/0.9 200 OK
+test: hello
+content-length: 102384398
+
+abcd
diff --git a/test/core/http/corpus/response4.txt b/test/core/http/corpus/response4.txt
new file mode 100644
index 0000000..b237b01
--- /dev/null
+++ b/test/core/http/corpus/response4.txt
@@ -0,0 +1,2 @@
+HTTP/1.1 404 Not Found
+
diff --git a/test/core/http/corpus/response5.txt b/test/core/http/corpus/response5.txt
new file mode 100644
index 0000000..2630595
--- /dev/null
+++ b/test/core/http/corpus/response5.txt
@@ -0,0 +1,5 @@
+HTTP/0.9 200 OK
+test: hello
+content-length: 4
+
+abcd
diff --git a/test/core/http/corpus/response6.txt b/test/core/http/corpus/response6.txt
new file mode 100644
index 0000000..797b6ee
--- /dev/null
+++ b/test/core/http/corpus/response6.txt
@@ -0,0 +1,5 @@
+HTTP/0.9 200 OK
+test: hello
+content-length: 6
+
+abcd
diff --git a/test/core/http/corpus/toolong.txt b/test/core/http/corpus/toolong.txt
new file mode 100644
index 0000000..9a9d5e2
--- /dev/null
+++ b/test/core/http/corpus/toolong.txt
@@ -0,0 +1,2 @@
+GET / HTTP/1.1
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
diff --git a/test/core/http/format_request_test.c b/test/core/http/format_request_test.c
new file mode 100644
index 0000000..0d21e12
--- /dev/null
+++ b/test/core/http/format_request_test.c
@@ -0,0 +1,164 @@
+/*
+ *
+ * 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/http/format_request.h"
+
+#include <string.h>
+
+#include <grpc/support/log.h>
+#include "test/core/util/test_config.h"
+
+static void test_format_get_request(void) {
+  grpc_http_header hdr = {"x-yz", "abc"};
+  grpc_httpcli_request req;
+  gpr_slice slice;
+
+  memset(&req, 0, sizeof(req));
+  req.host = "example.com";
+  req.http.path = "/index.html";
+  req.http.hdr_count = 1;
+  req.http.hdrs = &hdr;
+
+  slice = grpc_httpcli_format_get_request(&req);
+
+  GPR_ASSERT(0 == gpr_slice_str_cmp(slice,
+                                    "GET /index.html HTTP/1.0\r\n"
+                                    "Host: example.com\r\n"
+                                    "Connection: close\r\n"
+                                    "User-Agent: " GRPC_HTTPCLI_USER_AGENT
+                                    "\r\n"
+                                    "x-yz: abc\r\n"
+                                    "\r\n"));
+
+  gpr_slice_unref(slice);
+}
+
+static void test_format_post_request(void) {
+  grpc_http_header hdr = {"x-yz", "abc"};
+  grpc_httpcli_request req;
+  gpr_slice slice;
+  char body_bytes[] = "fake body";
+  size_t body_len = 9;
+
+  memset(&req, 0, sizeof(req));
+  req.host = "example.com";
+  req.http.path = "/index.html";
+  req.http.hdr_count = 1;
+  req.http.hdrs = &hdr;
+
+  slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len);
+
+  GPR_ASSERT(0 == gpr_slice_str_cmp(slice,
+                                    "POST /index.html HTTP/1.0\r\n"
+                                    "Host: example.com\r\n"
+                                    "Connection: close\r\n"
+                                    "User-Agent: " GRPC_HTTPCLI_USER_AGENT
+                                    "\r\n"
+                                    "x-yz: abc\r\n"
+                                    "Content-Type: text/plain\r\n"
+                                    "Content-Length: 9\r\n"
+                                    "\r\n"
+                                    "fake body"));
+
+  gpr_slice_unref(slice);
+}
+
+static void test_format_post_request_no_body(void) {
+  grpc_http_header hdr = {"x-yz", "abc"};
+  grpc_httpcli_request req;
+  gpr_slice slice;
+
+  memset(&req, 0, sizeof(req));
+  req.host = "example.com";
+  req.http.path = "/index.html";
+  req.http.hdr_count = 1;
+  req.http.hdrs = &hdr;
+
+  slice = grpc_httpcli_format_post_request(&req, NULL, 0);
+
+  GPR_ASSERT(0 == gpr_slice_str_cmp(slice,
+                                    "POST /index.html HTTP/1.0\r\n"
+                                    "Host: example.com\r\n"
+                                    "Connection: close\r\n"
+                                    "User-Agent: " GRPC_HTTPCLI_USER_AGENT
+                                    "\r\n"
+                                    "x-yz: abc\r\n"
+                                    "\r\n"));
+
+  gpr_slice_unref(slice);
+}
+
+static void test_format_post_request_content_type_override(void) {
+  grpc_http_header hdrs[2];
+  grpc_httpcli_request req;
+  gpr_slice slice;
+  char body_bytes[] = "fake%20body";
+  size_t body_len = 11;
+
+  hdrs[0].key = "x-yz";
+  hdrs[0].value = "abc";
+  hdrs[1].key = "Content-Type";
+  hdrs[1].value = "application/x-www-form-urlencoded";
+  memset(&req, 0, sizeof(req));
+  req.host = "example.com";
+  req.http.path = "/index.html";
+  req.http.hdr_count = 2;
+  req.http.hdrs = hdrs;
+
+  slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len);
+
+  GPR_ASSERT(0 == gpr_slice_str_cmp(
+                      slice,
+                      "POST /index.html HTTP/1.0\r\n"
+                      "Host: example.com\r\n"
+                      "Connection: close\r\n"
+                      "User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n"
+                      "x-yz: abc\r\n"
+                      "Content-Type: application/x-www-form-urlencoded\r\n"
+                      "Content-Length: 11\r\n"
+                      "\r\n"
+                      "fake%20body"));
+
+  gpr_slice_unref(slice);
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+
+  test_format_get_request();
+  test_format_post_request();
+  test_format_post_request_no_body();
+  test_format_post_request_content_type_override();
+
+  return 0;
+}
diff --git a/test/core/http/fuzzer.c b/test/core/http/fuzzer.c
new file mode 100644
index 0000000..7e4f4eb
--- /dev/null
+++ b/test/core/http/fuzzer.c
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/lib/http/parser.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  grpc_http_parser parser;
+  grpc_http_parser_init(&parser);
+  gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
+  grpc_http_parser_parse(&parser, slice);
+  grpc_http_parser_eof(&parser);
+  gpr_slice_unref(slice);
+  grpc_http_parser_destroy(&parser);
+  return 0;
+}
diff --git a/test/core/http/httpcli_test.c b/test/core/http/httpcli_test.c
new file mode 100644
index 0000000..d3a68d0
--- /dev/null
+++ b/test/core/http/httpcli_test.c
@@ -0,0 +1,200 @@
+/*
+ *
+ * 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/http/httpcli.h"
+
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/subprocess.h>
+#include <grpc/support/sync.h>
+#include "src/core/lib/iomgr/iomgr.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+static int g_done = 0;
+static grpc_httpcli_context g_context;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
+
+static gpr_timespec n_seconds_time(int seconds) {
+  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
+}
+
+static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
+                      const grpc_httpcli_response *response) {
+  const char *expect =
+      "<html><head><title>Hello world!</title></head>"
+      "<body><p>This is a test</p></body></html>";
+  GPR_ASSERT(arg == (void *)42);
+  GPR_ASSERT(response);
+  GPR_ASSERT(response->status == 200);
+  GPR_ASSERT(response->body_length == strlen(expect));
+  GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
+  gpr_mu_lock(g_mu);
+  g_done = 1;
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
+}
+
+static void test_get(int port) {
+  grpc_httpcli_request req;
+  char *host;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  g_done = 0;
+  gpr_log(GPR_INFO, "test_get");
+
+  gpr_asprintf(&host, "localhost:%d", port);
+  gpr_log(GPR_INFO, "requesting from %s", host);
+
+  memset(&req, 0, sizeof(req));
+  req.host = host;
+  req.http.path = "/get";
+  req.handshaker = &grpc_httpcli_plaintext;
+
+  grpc_httpcli_get(&exec_ctx, &g_context, g_pollset, &req, n_seconds_time(15),
+                   on_finish, (void *)42);
+  gpr_mu_lock(g_mu);
+  while (!g_done) {
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    gpr_mu_unlock(g_mu);
+    grpc_exec_ctx_finish(&exec_ctx);
+    gpr_mu_lock(g_mu);
+  }
+  gpr_mu_unlock(g_mu);
+  gpr_free(host);
+}
+
+static void test_post(int port) {
+  grpc_httpcli_request req;
+  char *host;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  g_done = 0;
+  gpr_log(GPR_INFO, "test_post");
+
+  gpr_asprintf(&host, "localhost:%d", port);
+  gpr_log(GPR_INFO, "posting to %s", host);
+
+  memset(&req, 0, sizeof(req));
+  req.host = host;
+  req.http.path = "/post";
+  req.handshaker = &grpc_httpcli_plaintext;
+
+  grpc_httpcli_post(&exec_ctx, &g_context, g_pollset, &req, "hello", 5,
+                    n_seconds_time(15), on_finish, (void *)42);
+  gpr_mu_lock(g_mu);
+  while (!g_done) {
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    gpr_mu_unlock(g_mu);
+    grpc_exec_ctx_finish(&exec_ctx);
+    gpr_mu_lock(g_mu);
+  }
+  gpr_mu_unlock(g_mu);
+  gpr_free(host);
+}
+
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+  grpc_pollset_destroy(p);
+}
+
+int main(int argc, char **argv) {
+  grpc_closure destroyed;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  gpr_subprocess *server;
+  char *me = argv[0];
+  char *lslash = strrchr(me, '/');
+  char *args[4];
+  int port = grpc_pick_unused_port_or_die();
+  int arg_shift = 0;
+  /* figure out where we are */
+  char *root;
+  if (lslash) {
+    root = gpr_malloc((size_t)(lslash - me + 1));
+    memcpy(root, me, (size_t)(lslash - me));
+    root[lslash - me] = 0;
+  } else {
+    root = gpr_strdup(".");
+  }
+
+  GPR_ASSERT(argc <= 2);
+  if (argc == 2) {
+    args[0] = gpr_strdup(argv[1]);
+  } else {
+    arg_shift = 1;
+    gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root);
+    gpr_asprintf(&args[1], "%s/../../test/core/http/test_server.py", root);
+  }
+
+  /* start the server */
+  args[1 + arg_shift] = "--port";
+  gpr_asprintf(&args[2 + arg_shift], "%d", port);
+  server = gpr_subprocess_create(3 + arg_shift, (const char **)args);
+  GPR_ASSERT(server);
+  gpr_free(args[0]);
+  if (arg_shift) gpr_free(args[1]);
+  gpr_free(args[2 + arg_shift]);
+  gpr_free(root);
+
+  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                               gpr_time_from_seconds(5, GPR_TIMESPAN)));
+
+  grpc_test_init(argc, argv);
+  grpc_init();
+  grpc_httpcli_context_init(&g_context);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
+
+  test_get(port);
+  test_post(port);
+
+  grpc_httpcli_context_destroy(&g_context);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_shutdown();
+
+  gpr_free(g_pollset);
+
+  gpr_subprocess_destroy(server);
+
+  return 0;
+}
diff --git a/test/core/http/httpscli_test.c b/test/core/http/httpscli_test.c
new file mode 100644
index 0000000..d807336
--- /dev/null
+++ b/test/core/http/httpscli_test.c
@@ -0,0 +1,203 @@
+/*
+ *
+ * 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/http/httpcli.h"
+
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/subprocess.h>
+#include <grpc/support/sync.h>
+#include "src/core/lib/iomgr/iomgr.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+static int g_done = 0;
+static grpc_httpcli_context g_context;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
+
+static gpr_timespec n_seconds_time(int seconds) {
+  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
+}
+
+static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
+                      const grpc_httpcli_response *response) {
+  const char *expect =
+      "<html><head><title>Hello world!</title></head>"
+      "<body><p>This is a test</p></body></html>";
+  GPR_ASSERT(arg == (void *)42);
+  GPR_ASSERT(response);
+  GPR_ASSERT(response->status == 200);
+  GPR_ASSERT(response->body_length == strlen(expect));
+  GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
+  gpr_mu_lock(g_mu);
+  g_done = 1;
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
+}
+
+static void test_get(int port) {
+  grpc_httpcli_request req;
+  char *host;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  g_done = 0;
+  gpr_log(GPR_INFO, "test_get");
+
+  gpr_asprintf(&host, "localhost:%d", port);
+  gpr_log(GPR_INFO, "requesting from %s", host);
+
+  memset(&req, 0, sizeof(req));
+  req.host = host;
+  req.ssl_host_override = "foo.test.google.fr";
+  req.http.path = "/get";
+  req.handshaker = &grpc_httpcli_ssl;
+
+  grpc_httpcli_get(&exec_ctx, &g_context, g_pollset, &req, n_seconds_time(15),
+                   on_finish, (void *)42);
+  gpr_mu_lock(g_mu);
+  while (!g_done) {
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    gpr_mu_unlock(g_mu);
+    grpc_exec_ctx_finish(&exec_ctx);
+    gpr_mu_lock(g_mu);
+  }
+  gpr_mu_unlock(g_mu);
+  gpr_free(host);
+}
+
+static void test_post(int port) {
+  grpc_httpcli_request req;
+  char *host;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  g_done = 0;
+  gpr_log(GPR_INFO, "test_post");
+
+  gpr_asprintf(&host, "localhost:%d", port);
+  gpr_log(GPR_INFO, "posting to %s", host);
+
+  memset(&req, 0, sizeof(req));
+  req.host = host;
+  req.ssl_host_override = "foo.test.google.fr";
+  req.http.path = "/post";
+  req.handshaker = &grpc_httpcli_ssl;
+
+  grpc_httpcli_post(&exec_ctx, &g_context, g_pollset, &req, "hello", 5,
+                    n_seconds_time(15), on_finish, (void *)42);
+  gpr_mu_lock(g_mu);
+  while (!g_done) {
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    gpr_mu_unlock(g_mu);
+    grpc_exec_ctx_finish(&exec_ctx);
+    gpr_mu_lock(g_mu);
+  }
+  gpr_mu_unlock(g_mu);
+  gpr_free(host);
+}
+
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+  grpc_pollset_destroy(p);
+}
+
+int main(int argc, char **argv) {
+  grpc_closure destroyed;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  gpr_subprocess *server;
+  char *me = argv[0];
+  char *lslash = strrchr(me, '/');
+  char *args[5];
+  int port = grpc_pick_unused_port_or_die();
+  int arg_shift = 0;
+  /* figure out where we are */
+  char *root;
+  if (lslash) {
+    root = gpr_malloc((size_t)(lslash - me + 1));
+    memcpy(root, me, (size_t)(lslash - me));
+    root[lslash - me] = 0;
+  } else {
+    root = gpr_strdup(".");
+  }
+
+  GPR_ASSERT(argc <= 2);
+  if (argc == 2) {
+    args[0] = gpr_strdup(argv[1]);
+  } else {
+    arg_shift = 1;
+    gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root);
+    gpr_asprintf(&args[1], "%s/../../test/core/http/test_server.py", root);
+  }
+
+  /* start the server */
+  args[1 + arg_shift] = "--port";
+  gpr_asprintf(&args[2 + arg_shift], "%d", port);
+  args[3 + arg_shift] = "--ssl";
+  server = gpr_subprocess_create(4 + arg_shift, (const char **)args);
+  GPR_ASSERT(server);
+  gpr_free(args[0]);
+  if (arg_shift) gpr_free(args[1]);
+  gpr_free(args[2 + arg_shift]);
+  gpr_free(root);
+
+  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                               gpr_time_from_seconds(5, GPR_TIMESPAN)));
+
+  grpc_test_init(argc, argv);
+  grpc_init();
+  grpc_httpcli_context_init(&g_context);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
+
+  test_get(port);
+  test_post(port);
+
+  grpc_httpcli_context_destroy(&g_context);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_shutdown();
+
+  gpr_free(g_pollset);
+
+  gpr_subprocess_destroy(server);
+
+  return 0;
+}
diff --git a/test/core/http/parser_test.c b/test/core/http/parser_test.c
new file mode 100644
index 0000000..7fdf60c
--- /dev/null
+++ b/test/core/http/parser_test.c
@@ -0,0 +1,306 @@
+/*
+ *
+ * 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/http/parser.h"
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+#include "test/core/util/slice_splitter.h"
+#include "test/core/util/test_config.h"
+
+static void test_request_succeeds(grpc_slice_split_mode split_mode,
+                                  char *request, char *expect_method,
+                                  grpc_http_version expect_version,
+                                  char *expect_path, char *expect_body, ...) {
+  grpc_http_parser parser;
+  gpr_slice input_slice = gpr_slice_from_copied_string(request);
+  size_t num_slices;
+  size_t i;
+  gpr_slice *slices;
+  va_list args;
+
+  grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
+  gpr_slice_unref(input_slice);
+
+  grpc_http_parser_init(&parser);
+
+  for (i = 0; i < num_slices; i++) {
+    GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]));
+    gpr_slice_unref(slices[i]);
+  }
+  GPR_ASSERT(grpc_http_parser_eof(&parser));
+
+  GPR_ASSERT(GRPC_HTTP_REQUEST == parser.type);
+  GPR_ASSERT(0 == strcmp(expect_method, parser.http.request.method));
+  GPR_ASSERT(0 == strcmp(expect_path, parser.http.request.path));
+  GPR_ASSERT(expect_version == parser.http.request.version);
+
+  if (expect_body != NULL) {
+    GPR_ASSERT(strlen(expect_body) == parser.http.request.body_length);
+    GPR_ASSERT(0 == memcmp(expect_body, parser.http.request.body,
+                           parser.http.request.body_length));
+  } else {
+    GPR_ASSERT(parser.http.request.body_length == 0);
+  }
+
+  va_start(args, expect_body);
+  i = 0;
+  for (;;) {
+    char *expect_key;
+    char *expect_value;
+    expect_key = va_arg(args, char *);
+    if (!expect_key) break;
+    GPR_ASSERT(i < parser.http.request.hdr_count);
+    expect_value = va_arg(args, char *);
+    GPR_ASSERT(expect_value);
+    GPR_ASSERT(0 == strcmp(expect_key, parser.http.request.hdrs[i].key));
+    GPR_ASSERT(0 == strcmp(expect_value, parser.http.request.hdrs[i].value));
+    i++;
+  }
+  va_end(args);
+  GPR_ASSERT(i == parser.http.request.hdr_count);
+
+  grpc_http_parser_destroy(&parser);
+  gpr_free(slices);
+}
+
+static void test_succeeds(grpc_slice_split_mode split_mode, char *response,
+                          int expect_status, char *expect_body, ...) {
+  grpc_http_parser parser;
+  gpr_slice input_slice = gpr_slice_from_copied_string(response);
+  size_t num_slices;
+  size_t i;
+  gpr_slice *slices;
+  va_list args;
+
+  grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
+  gpr_slice_unref(input_slice);
+
+  grpc_http_parser_init(&parser);
+
+  for (i = 0; i < num_slices; i++) {
+    GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]));
+    gpr_slice_unref(slices[i]);
+  }
+  GPR_ASSERT(grpc_http_parser_eof(&parser));
+
+  GPR_ASSERT(GRPC_HTTP_RESPONSE == parser.type);
+  GPR_ASSERT(expect_status == parser.http.response.status);
+  if (expect_body != NULL) {
+    GPR_ASSERT(strlen(expect_body) == parser.http.response.body_length);
+    GPR_ASSERT(0 == memcmp(expect_body, parser.http.response.body,
+                           parser.http.response.body_length));
+  } else {
+    GPR_ASSERT(parser.http.response.body_length == 0);
+  }
+
+  va_start(args, expect_body);
+  i = 0;
+  for (;;) {
+    char *expect_key;
+    char *expect_value;
+    expect_key = va_arg(args, char *);
+    if (!expect_key) break;
+    GPR_ASSERT(i < parser.http.response.hdr_count);
+    expect_value = va_arg(args, char *);
+    GPR_ASSERT(expect_value);
+    GPR_ASSERT(0 == strcmp(expect_key, parser.http.response.hdrs[i].key));
+    GPR_ASSERT(0 == strcmp(expect_value, parser.http.response.hdrs[i].value));
+    i++;
+  }
+  va_end(args);
+  GPR_ASSERT(i == parser.http.response.hdr_count);
+
+  grpc_http_parser_destroy(&parser);
+  gpr_free(slices);
+}
+
+static void test_fails(grpc_slice_split_mode split_mode, char *response) {
+  grpc_http_parser parser;
+  gpr_slice input_slice = gpr_slice_from_copied_string(response);
+  size_t num_slices;
+  size_t i;
+  gpr_slice *slices;
+  int done = 0;
+
+  grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
+  gpr_slice_unref(input_slice);
+
+  grpc_http_parser_init(&parser);
+
+  for (i = 0; i < num_slices; i++) {
+    if (!done && !grpc_http_parser_parse(&parser, slices[i])) {
+      done = 1;
+    }
+    gpr_slice_unref(slices[i]);
+  }
+  if (!done && !grpc_http_parser_eof(&parser)) {
+    done = 1;
+  }
+  GPR_ASSERT(done);
+
+  grpc_http_parser_destroy(&parser);
+  gpr_free(slices);
+}
+
+static const uint8_t failed_test1[] = {
+    0x9e, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x4a,
+    0x48, 0x54, 0x54, 0x30, 0x32, 0x16, 0xa,  0x2f, 0x48, 0x20,
+    0x31, 0x2e, 0x31, 0x20, 0x32, 0x30, 0x31, 0x54, 0x54, 0xb9,
+    0x32, 0x31, 0x2e, 0x20, 0x32, 0x30, 0x20,
+};
+
+typedef struct {
+  const char *name;
+  const uint8_t *data;
+  size_t length;
+} failed_test;
+
+#define FAILED_TEST(name) \
+  { #name, name, sizeof(name) }
+
+failed_test failed_tests[] = {
+    FAILED_TEST(failed_test1),
+};
+
+static void test_doesnt_crash(failed_test t) {
+  gpr_log(GPR_DEBUG, "Run previously failed test: %s", t.name);
+  grpc_http_parser p;
+  grpc_http_parser_init(&p);
+  gpr_slice slice =
+      gpr_slice_from_copied_buffer((const char *)t.data, t.length);
+  grpc_http_parser_parse(&p, slice);
+  gpr_slice_unref(slice);
+  grpc_http_parser_destroy(&p);
+}
+
+int main(int argc, char **argv) {
+  size_t i;
+  const grpc_slice_split_mode split_modes[] = {GRPC_SLICE_SPLIT_IDENTITY,
+                                               GRPC_SLICE_SPLIT_ONE_BYTE};
+  char *tmp1, *tmp2;
+
+  grpc_test_init(argc, argv);
+
+  for (i = 0; i < GPR_ARRAY_SIZE(failed_tests); i++) {
+    test_doesnt_crash(failed_tests[i]);
+  }
+
+  for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) {
+    test_succeeds(split_modes[i],
+                  "HTTP/1.0 200 OK\r\n"
+                  "xyz: abc\r\n"
+                  "\r\n"
+                  "hello world!",
+                  200, "hello world!", "xyz", "abc", NULL);
+    test_succeeds(split_modes[i],
+                  "HTTP/1.0 404 Not Found\r\n"
+                  "\r\n",
+                  404, NULL, NULL);
+    test_succeeds(split_modes[i],
+                  "HTTP/1.1 200 OK\r\n"
+                  "xyz: abc\r\n"
+                  "\r\n"
+                  "hello world!",
+                  200, "hello world!", "xyz", "abc", NULL);
+    test_succeeds(split_modes[i],
+                  "HTTP/1.1 200 OK\n"
+                  "\n"
+                  "abc",
+                  200, "abc", NULL);
+    test_request_succeeds(split_modes[i],
+                          "GET / HTTP/1.0\r\n"
+                          "\r\n",
+                          "GET", GRPC_HTTP_HTTP10, "/", NULL, NULL);
+    test_request_succeeds(split_modes[i],
+                          "GET / HTTP/1.0\r\n"
+                          "\r\n"
+                          "xyz",
+                          "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL);
+    test_request_succeeds(split_modes[i],
+                          "GET / HTTP/1.1\r\n"
+                          "\r\n"
+                          "xyz",
+                          "GET", GRPC_HTTP_HTTP11, "/", "xyz", NULL);
+    test_request_succeeds(split_modes[i],
+                          "GET / HTTP/2.0\r\n"
+                          "\r\n"
+                          "xyz",
+                          "GET", GRPC_HTTP_HTTP20, "/", "xyz", NULL);
+    test_request_succeeds(split_modes[i],
+                          "GET / HTTP/1.0\r\n"
+                          "xyz: abc\r\n"
+                          "\r\n"
+                          "xyz",
+                          "GET", GRPC_HTTP_HTTP10, "/", "xyz", "xyz", "abc",
+                          NULL);
+    test_request_succeeds(split_modes[i],
+                          "GET / HTTP/1.0\n"
+                          "\n"
+                          "xyz",
+                          "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL);
+    test_fails(split_modes[i], "HTTP/1.0\r\n");
+    test_fails(split_modes[i], "HTTP/1.2\r\n");
+    test_fails(split_modes[i], "HTTP/1.0 000 XYX\r\n");
+    test_fails(split_modes[i], "HTTP/1.0 200 OK\n");
+    test_fails(split_modes[i], "HTTP/1.0 200 OK\r\n");
+    test_fails(split_modes[i], "HTTP/1.0 200 OK\r\nFoo x\r\n");
+    test_fails(split_modes[i],
+               "HTTP/1.0 200 OK\r\n"
+               "xyz: abc\r\n"
+               "  def\r\n"
+               "\r\n"
+               "hello world!");
+    test_fails(split_modes[i], "GET\r\n");
+    test_fails(split_modes[i], "GET /\r\n");
+    test_fails(split_modes[i], "GET / HTTP/0.0\r\n");
+    test_fails(split_modes[i], "GET / ____/1.0\r\n");
+    test_fails(split_modes[i], "GET / HTTP/1.2\r\n");
+    test_fails(split_modes[i], "GET / HTTP/1.0\n");
+
+    tmp1 = gpr_malloc(2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
+    memset(tmp1, 'a', 2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1);
+    tmp1[2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1] = 0;
+    gpr_asprintf(&tmp2, "HTTP/1.0 200 OK\r\nxyz: %s\r\n\r\n", tmp1);
+    test_fails(split_modes[i], tmp2);
+    gpr_free(tmp1);
+    gpr_free(tmp2);
+  }
+
+  return 0;
+}
diff --git a/test/core/http/test_server.py b/test/core/http/test_server.py
new file mode 100755
index 0000000..86c2fe9
--- /dev/null
+++ b/test/core/http/test_server.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python2.7
+# 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.
+
+"""Server for httpcli_test"""
+
+import argparse
+import BaseHTTPServer
+import os
+import ssl
+import sys
+
+_PEM = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/lib/tsi/test_creds/server1.pem'))
+_KEY = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/lib/tsi/test_creds/server1.key'))
+print _PEM
+open(_PEM).close()
+
+argp = argparse.ArgumentParser(description='Server for httpcli_test')
+argp.add_argument('-p', '--port', default=10080, type=int)
+argp.add_argument('-s', '--ssl', default=False, action='store_true')
+args = argp.parse_args()
+
+print 'server running on port %d' % args.port
+
+class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
+	def good(self):
+		self.send_response(200)
+		self.send_header('Content-Type', 'text/html')
+		self.end_headers()
+		self.wfile.write('<html><head><title>Hello world!</title></head>')
+		self.wfile.write('<body><p>This is a test</p></body></html>')
+
+	def do_GET(self):
+		if self.path == '/get':
+			self.good()
+
+	def do_POST(self):
+		content = self.rfile.read(int(self.headers.getheader('content-length')))
+		if self.path == '/post' and content == 'hello':
+			self.good()
+
+httpd = BaseHTTPServer.HTTPServer(('localhost', args.port), Handler)
+if args.ssl:
+	httpd.socket = ssl.wrap_socket(httpd.socket, certfile=_PEM, keyfile=_KEY, server_side=True)
+httpd.serve_forever()
diff --git a/test/core/httpcli/format_request_test.c b/test/core/httpcli/format_request_test.c
deleted file mode 100644
index da85004..0000000
--- a/test/core/httpcli/format_request_test.c
+++ /dev/null
@@ -1,165 +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/httpcli/format_request.h"
-
-#include <string.h>
-
-#include <grpc/support/log.h>
-#include "test/core/util/test_config.h"
-
-static void test_format_get_request(void) {
-  grpc_httpcli_header hdr = {"x-yz", "abc"};
-  grpc_httpcli_request req;
-  gpr_slice slice;
-
-  memset(&req, 0, sizeof(req));
-  req.host = "example.com";
-  req.path = "/index.html";
-  req.hdr_count = 1;
-  req.hdrs = &hdr;
-
-  slice = grpc_httpcli_format_get_request(&req);
-
-  GPR_ASSERT(0 == gpr_slice_str_cmp(slice,
-                                    "GET /index.html HTTP/1.0\r\n"
-                                    "Host: example.com\r\n"
-                                    "Connection: close\r\n"
-                                    "User-Agent: " GRPC_HTTPCLI_USER_AGENT
-                                    "\r\n"
-                                    "x-yz: abc\r\n"
-                                    "\r\n"));
-
-  gpr_slice_unref(slice);
-}
-
-static void test_format_post_request(void) {
-  grpc_httpcli_header hdr = {"x-yz", "abc"};
-  grpc_httpcli_request req;
-  gpr_slice slice;
-  char body_bytes[] = "fake body";
-  size_t body_len = 9;
-
-  memset(&req, 0, sizeof(req));
-  req.host = "example.com";
-  req.path = "/index.html";
-  req.hdr_count = 1;
-  req.hdrs = &hdr;
-
-  slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len);
-
-  GPR_ASSERT(0 == gpr_slice_str_cmp(slice,
-                                    "POST /index.html HTTP/1.0\r\n"
-                                    "Host: example.com\r\n"
-                                    "Connection: close\r\n"
-                                    "User-Agent: " GRPC_HTTPCLI_USER_AGENT
-                                    "\r\n"
-                                    "x-yz: abc\r\n"
-                                    "Content-Type: text/plain\r\n"
-                                    "Content-Length: 9\r\n"
-                                    "\r\n"
-                                    "fake body"));
-
-  gpr_slice_unref(slice);
-}
-
-static void test_format_post_request_no_body(void) {
-  grpc_httpcli_header hdr = {"x-yz", "abc"};
-  grpc_httpcli_request req;
-  gpr_slice slice;
-
-  memset(&req, 0, sizeof(req));
-  req.host = "example.com";
-  req.path = "/index.html";
-  req.hdr_count = 1;
-  req.hdrs = &hdr;
-
-  slice = grpc_httpcli_format_post_request(&req, NULL, 0);
-
-  GPR_ASSERT(0 == gpr_slice_str_cmp(slice,
-                                    "POST /index.html HTTP/1.0\r\n"
-                                    "Host: example.com\r\n"
-                                    "Connection: close\r\n"
-                                    "User-Agent: " GRPC_HTTPCLI_USER_AGENT
-                                    "\r\n"
-                                    "x-yz: abc\r\n"
-                                    "\r\n"));
-
-  gpr_slice_unref(slice);
-}
-
-static void test_format_post_request_content_type_override(void) {
-  grpc_httpcli_header hdrs[2];
-  grpc_httpcli_request req;
-  gpr_slice slice;
-  char body_bytes[] = "fake%20body";
-  size_t body_len = 11;
-
-  hdrs[0].key = "x-yz";
-  hdrs[0].value = "abc";
-  hdrs[1].key = "Content-Type";
-  hdrs[1].value = "application/x-www-form-urlencoded";
-  memset(&req, 0, sizeof(req));
-  req.host = "example.com";
-  req.path = "/index.html";
-  req.hdr_count = 2;
-  req.hdrs = hdrs;
-
-  slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len);
-
-  GPR_ASSERT(0 == gpr_slice_str_cmp(
-                      slice,
-                      "POST /index.html HTTP/1.0\r\n"
-                      "Host: example.com\r\n"
-                      "Connection: close\r\n"
-                      "User-Agent: " GRPC_HTTPCLI_USER_AGENT
-                      "\r\n"
-                      "x-yz: abc\r\n"
-                      "Content-Type: application/x-www-form-urlencoded\r\n"
-                      "Content-Length: 11\r\n"
-                      "\r\n"
-                      "fake%20body"));
-
-  gpr_slice_unref(slice);
-}
-
-int main(int argc, char **argv) {
-  grpc_test_init(argc, argv);
-
-  test_format_get_request();
-  test_format_post_request();
-  test_format_post_request_no_body();
-  test_format_post_request_content_type_override();
-
-  return 0;
-}
diff --git a/test/core/httpcli/httpcli_test.c b/test/core/httpcli/httpcli_test.c
deleted file mode 100644
index fbc5d4a..0000000
--- a/test/core/httpcli/httpcli_test.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- *
- * 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/httpcli/httpcli.h"
-
-#include <string.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/subprocess.h>
-#include <grpc/support/sync.h>
-#include "src/core/iomgr/iomgr.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-static int g_done = 0;
-static grpc_httpcli_context g_context;
-static gpr_mu *g_mu;
-static grpc_pollset *g_pollset;
-
-static gpr_timespec n_seconds_time(int seconds) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
-}
-
-static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
-                      const grpc_httpcli_response *response) {
-  const char *expect =
-      "<html><head><title>Hello world!</title></head>"
-      "<body><p>This is a test</p></body></html>";
-  GPR_ASSERT(arg == (void *)42);
-  GPR_ASSERT(response);
-  GPR_ASSERT(response->status == 200);
-  GPR_ASSERT(response->body_length == strlen(expect));
-  GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
-  gpr_mu_lock(g_mu);
-  g_done = 1;
-  grpc_pollset_kick(g_pollset, NULL);
-  gpr_mu_unlock(g_mu);
-}
-
-static void test_get(int port) {
-  grpc_httpcli_request req;
-  char *host;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  g_done = 0;
-  gpr_log(GPR_INFO, "test_get");
-
-  gpr_asprintf(&host, "localhost:%d", port);
-  gpr_log(GPR_INFO, "requesting from %s", host);
-
-  memset(&req, 0, sizeof(req));
-  req.host = host;
-  req.path = "/get";
-  req.handshaker = &grpc_httpcli_plaintext;
-
-  grpc_httpcli_get(&exec_ctx, &g_context, g_pollset, &req, n_seconds_time(15),
-                   on_finish, (void *)42);
-  gpr_mu_lock(g_mu);
-  while (!g_done) {
-    grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(g_mu);
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(g_mu);
-  }
-  gpr_mu_unlock(g_mu);
-  gpr_free(host);
-}
-
-static void test_post(int port) {
-  grpc_httpcli_request req;
-  char *host;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  g_done = 0;
-  gpr_log(GPR_INFO, "test_post");
-
-  gpr_asprintf(&host, "localhost:%d", port);
-  gpr_log(GPR_INFO, "posting to %s", host);
-
-  memset(&req, 0, sizeof(req));
-  req.host = host;
-  req.path = "/post";
-  req.handshaker = &grpc_httpcli_plaintext;
-
-  grpc_httpcli_post(&exec_ctx, &g_context, g_pollset, &req, "hello", 5,
-                    n_seconds_time(15), on_finish, (void *)42);
-  gpr_mu_lock(g_mu);
-  while (!g_done) {
-    grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(g_mu);
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(g_mu);
-  }
-  gpr_mu_unlock(g_mu);
-  gpr_free(host);
-}
-
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
-  grpc_pollset_destroy(p);
-}
-
-int main(int argc, char **argv) {
-  grpc_closure destroyed;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  gpr_subprocess *server;
-  char *me = argv[0];
-  char *lslash = strrchr(me, '/');
-  char *args[4];
-  int port = grpc_pick_unused_port_or_die();
-  int arg_shift = 0;
-  /* figure out where we are */
-  char *root;
-  if (lslash) {
-    root = gpr_malloc((size_t)(lslash - me + 1));
-    memcpy(root, me, (size_t)(lslash - me));
-    root[lslash - me] = 0;
-  } else {
-    root = gpr_strdup(".");
-  }
-
-  GPR_ASSERT(argc <= 2);
-  if (argc == 2) {
-    args[0] = gpr_strdup(argv[1]);
-  } else {
-    arg_shift = 1;
-    gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root);
-    gpr_asprintf(&args[1], "%s/../../test/core/httpcli/test_server.py", root);
-  }
-
-  /* start the server */
-  args[1 + arg_shift] = "--port";
-  gpr_asprintf(&args[2 + arg_shift], "%d", port);
-  server = gpr_subprocess_create(3 + arg_shift, (const char **)args);
-  GPR_ASSERT(server);
-  gpr_free(args[0]);
-  if (arg_shift) gpr_free(args[1]);
-  gpr_free(args[2 + arg_shift]);
-  gpr_free(root);
-
-  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                               gpr_time_from_seconds(5, GPR_TIMESPAN)));
-
-  grpc_test_init(argc, argv);
-  grpc_init();
-  grpc_httpcli_context_init(&g_context);
-  g_pollset = gpr_malloc(grpc_pollset_size());
-  grpc_pollset_init(g_pollset, &g_mu);
-
-  test_get(port);
-  test_post(port);
-
-  grpc_httpcli_context_destroy(&g_context);
-  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
-
-  gpr_free(g_pollset);
-
-  gpr_subprocess_destroy(server);
-
-  return 0;
-}
diff --git a/test/core/httpcli/httpscli_test.c b/test/core/httpcli/httpscli_test.c
deleted file mode 100644
index 04c57db..0000000
--- a/test/core/httpcli/httpscli_test.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *
- * 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/httpcli/httpcli.h"
-
-#include <string.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/subprocess.h>
-#include <grpc/support/sync.h>
-#include "src/core/iomgr/iomgr.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-static int g_done = 0;
-static grpc_httpcli_context g_context;
-static gpr_mu *g_mu;
-static grpc_pollset *g_pollset;
-
-static gpr_timespec n_seconds_time(int seconds) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
-}
-
-static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
-                      const grpc_httpcli_response *response) {
-  const char *expect =
-      "<html><head><title>Hello world!</title></head>"
-      "<body><p>This is a test</p></body></html>";
-  GPR_ASSERT(arg == (void *)42);
-  GPR_ASSERT(response);
-  GPR_ASSERT(response->status == 200);
-  GPR_ASSERT(response->body_length == strlen(expect));
-  GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
-  gpr_mu_lock(g_mu);
-  g_done = 1;
-  grpc_pollset_kick(g_pollset, NULL);
-  gpr_mu_unlock(g_mu);
-}
-
-static void test_get(int port) {
-  grpc_httpcli_request req;
-  char *host;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  g_done = 0;
-  gpr_log(GPR_INFO, "test_get");
-
-  gpr_asprintf(&host, "localhost:%d", port);
-  gpr_log(GPR_INFO, "requesting from %s", host);
-
-  memset(&req, 0, sizeof(req));
-  req.host = host;
-  req.ssl_host_override = "foo.test.google.fr";
-  req.path = "/get";
-  req.handshaker = &grpc_httpcli_ssl;
-
-  grpc_httpcli_get(&exec_ctx, &g_context, g_pollset, &req, n_seconds_time(15),
-                   on_finish, (void *)42);
-  gpr_mu_lock(g_mu);
-  while (!g_done) {
-    grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(g_mu);
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(g_mu);
-  }
-  gpr_mu_unlock(g_mu);
-  gpr_free(host);
-}
-
-static void test_post(int port) {
-  grpc_httpcli_request req;
-  char *host;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  g_done = 0;
-  gpr_log(GPR_INFO, "test_post");
-
-  gpr_asprintf(&host, "localhost:%d", port);
-  gpr_log(GPR_INFO, "posting to %s", host);
-
-  memset(&req, 0, sizeof(req));
-  req.host = host;
-  req.ssl_host_override = "foo.test.google.fr";
-  req.path = "/post";
-  req.handshaker = &grpc_httpcli_ssl;
-
-  grpc_httpcli_post(&exec_ctx, &g_context, g_pollset, &req, "hello", 5,
-                    n_seconds_time(15), on_finish, (void *)42);
-  gpr_mu_lock(g_mu);
-  while (!g_done) {
-    grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(g_mu);
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(g_mu);
-  }
-  gpr_mu_unlock(g_mu);
-  gpr_free(host);
-}
-
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
-  grpc_pollset_destroy(p);
-}
-
-int main(int argc, char **argv) {
-  grpc_closure destroyed;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  gpr_subprocess *server;
-  char *me = argv[0];
-  char *lslash = strrchr(me, '/');
-  char *args[5];
-  int port = grpc_pick_unused_port_or_die();
-  int arg_shift = 0;
-  /* figure out where we are */
-  char *root;
-  if (lslash) {
-    root = gpr_malloc((size_t)(lslash - me + 1));
-    memcpy(root, me, (size_t)(lslash - me));
-    root[lslash - me] = 0;
-  } else {
-    root = gpr_strdup(".");
-  }
-
-  GPR_ASSERT(argc <= 2);
-  if (argc == 2) {
-    args[0] = gpr_strdup(argv[1]);
-  } else {
-    arg_shift = 1;
-    gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root);
-    gpr_asprintf(&args[1], "%s/../../test/core/httpcli/test_server.py", root);
-  }
-
-  /* start the server */
-  args[1 + arg_shift] = "--port";
-  gpr_asprintf(&args[2 + arg_shift], "%d", port);
-  args[3 + arg_shift] = "--ssl";
-  server = gpr_subprocess_create(4 + arg_shift, (const char **)args);
-  GPR_ASSERT(server);
-  gpr_free(args[0]);
-  if (arg_shift) gpr_free(args[1]);
-  gpr_free(args[2 + arg_shift]);
-  gpr_free(root);
-
-  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                               gpr_time_from_seconds(5, GPR_TIMESPAN)));
-
-  grpc_test_init(argc, argv);
-  grpc_init();
-  grpc_httpcli_context_init(&g_context);
-  g_pollset = gpr_malloc(grpc_pollset_size());
-  grpc_pollset_init(g_pollset, &g_mu);
-
-  test_get(port);
-  test_post(port);
-
-  grpc_httpcli_context_destroy(&g_context);
-  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
-
-  gpr_free(g_pollset);
-
-  gpr_subprocess_destroy(server);
-
-  return 0;
-}
diff --git a/test/core/httpcli/parser_test.c b/test/core/httpcli/parser_test.c
deleted file mode 100644
index a26ddd2..0000000
--- a/test/core/httpcli/parser_test.c
+++ /dev/null
@@ -1,171 +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/httpcli/parser.h"
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-#include "test/core/util/slice_splitter.h"
-#include "test/core/util/test_config.h"
-
-static void test_succeeds(grpc_slice_split_mode split_mode, char *response,
-                          int expect_status, char *expect_body, ...) {
-  grpc_httpcli_parser parser;
-  gpr_slice input_slice = gpr_slice_from_copied_string(response);
-  size_t num_slices;
-  size_t i;
-  gpr_slice *slices;
-  va_list args;
-
-  grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
-  gpr_slice_unref(input_slice);
-
-  grpc_httpcli_parser_init(&parser);
-
-  for (i = 0; i < num_slices; i++) {
-    GPR_ASSERT(grpc_httpcli_parser_parse(&parser, slices[i]));
-    gpr_slice_unref(slices[i]);
-  }
-  GPR_ASSERT(grpc_httpcli_parser_eof(&parser));
-
-  GPR_ASSERT(expect_status == parser.r.status);
-  if (expect_body != NULL) {
-    GPR_ASSERT(strlen(expect_body) == parser.r.body_length);
-    GPR_ASSERT(0 == memcmp(expect_body, parser.r.body, parser.r.body_length));
-  } else {
-    GPR_ASSERT(parser.r.body_length == 0);
-  }
-
-  va_start(args, expect_body);
-  i = 0;
-  for (;;) {
-    char *expect_key;
-    char *expect_value;
-    expect_key = va_arg(args, char *);
-    if (!expect_key) break;
-    GPR_ASSERT(i < parser.r.hdr_count);
-    expect_value = va_arg(args, char *);
-    GPR_ASSERT(expect_value);
-    GPR_ASSERT(0 == strcmp(expect_key, parser.r.hdrs[i].key));
-    GPR_ASSERT(0 == strcmp(expect_value, parser.r.hdrs[i].value));
-    i++;
-  }
-  va_end(args);
-  GPR_ASSERT(i == parser.r.hdr_count);
-
-  grpc_httpcli_parser_destroy(&parser);
-  gpr_free(slices);
-}
-
-static void test_fails(grpc_slice_split_mode split_mode, char *response) {
-  grpc_httpcli_parser parser;
-  gpr_slice input_slice = gpr_slice_from_copied_string(response);
-  size_t num_slices;
-  size_t i;
-  gpr_slice *slices;
-  int done = 0;
-
-  grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
-  gpr_slice_unref(input_slice);
-
-  grpc_httpcli_parser_init(&parser);
-
-  for (i = 0; i < num_slices; i++) {
-    if (!done && !grpc_httpcli_parser_parse(&parser, slices[i])) {
-      done = 1;
-    }
-    gpr_slice_unref(slices[i]);
-  }
-  if (!done && !grpc_httpcli_parser_eof(&parser)) {
-    done = 1;
-  }
-  GPR_ASSERT(done);
-
-  grpc_httpcli_parser_destroy(&parser);
-  gpr_free(slices);
-}
-
-int main(int argc, char **argv) {
-  size_t i;
-  const grpc_slice_split_mode split_modes[] = {GRPC_SLICE_SPLIT_IDENTITY,
-                                               GRPC_SLICE_SPLIT_ONE_BYTE};
-  char *tmp1, *tmp2;
-
-  grpc_test_init(argc, argv);
-
-  for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) {
-    test_succeeds(split_modes[i],
-                  "HTTP/1.0 200 OK\r\n"
-                  "xyz: abc\r\n"
-                  "\r\n"
-                  "hello world!",
-                  200, "hello world!", "xyz", "abc", NULL);
-    test_succeeds(split_modes[i],
-                  "HTTP/1.0 404 Not Found\r\n"
-                  "\r\n",
-                  404, NULL, NULL);
-    test_succeeds(split_modes[i],
-                  "HTTP/1.1 200 OK\r\n"
-                  "xyz: abc\r\n"
-                  "\r\n"
-                  "hello world!",
-                  200, "hello world!", "xyz", "abc", NULL);
-    test_fails(split_modes[i], "HTTP/1.0\r\n");
-    test_fails(split_modes[i], "HTTP/1.2\r\n");
-    test_fails(split_modes[i], "HTTP/1.0 000 XYX\r\n");
-    test_fails(split_modes[i], "HTTP/1.0 200 OK\n");
-    test_fails(split_modes[i], "HTTP/1.0 200 OK\r\n");
-    test_fails(split_modes[i], "HTTP/1.0 200 OK\r\nFoo x\r\n");
-    test_fails(split_modes[i],
-               "HTTP/1.0 200 OK\r\n"
-               "xyz: abc\r\n"
-               "  def\r\n"
-               "\r\n"
-               "hello world!");
-
-    tmp1 = gpr_malloc(2 * GRPC_HTTPCLI_MAX_HEADER_LENGTH);
-    memset(tmp1, 'a', 2 * GRPC_HTTPCLI_MAX_HEADER_LENGTH - 1);
-    tmp1[2 * GRPC_HTTPCLI_MAX_HEADER_LENGTH - 1] = 0;
-    gpr_asprintf(&tmp2, "HTTP/1.0 200 OK\r\nxyz: %s\r\n\r\n", tmp1);
-    test_fails(split_modes[i], tmp2);
-    gpr_free(tmp1);
-    gpr_free(tmp2);
-  }
-
-  return 0;
-}
diff --git a/test/core/httpcli/test_server.py b/test/core/httpcli/test_server.py
deleted file mode 100755
index dbbf5ce..0000000
--- a/test/core/httpcli/test_server.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python2.7
-# 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.
-
-"""Server for httpcli_test"""
-
-import argparse
-import BaseHTTPServer
-import os
-import ssl
-import sys
-
-_PEM = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.pem'))
-_KEY = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.key'))
-print _PEM
-open(_PEM).close()
-
-argp = argparse.ArgumentParser(description='Server for httpcli_test')
-argp.add_argument('-p', '--port', default=10080, type=int)
-argp.add_argument('-s', '--ssl', default=False, action='store_true')
-args = argp.parse_args()
-
-print 'server running on port %d' % args.port
-
-class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
-	def good(self):
-		self.send_response(200)
-		self.send_header('Content-Type', 'text/html')
-		self.end_headers()
-		self.wfile.write('<html><head><title>Hello world!</title></head>')
-		self.wfile.write('<body><p>This is a test</p></body></html>')
-
-	def do_GET(self):
-		if self.path == '/get':
-			self.good()
-
-	def do_POST(self):
-		content = self.rfile.read(int(self.headers.getheader('content-length')))
-		if self.path == '/post' and content == 'hello':
-			self.good()
-
-httpd = BaseHTTPServer.HTTPServer(('localhost', args.port), Handler)
-if args.ssl:
-	httpd.socket = ssl.wrap_socket(httpd.socket, certfile=_PEM, keyfile=_KEY, server_side=True)
-httpd.serve_forever()
diff --git a/test/core/internal_api_canaries/iomgr.c b/test/core/internal_api_canaries/iomgr.c
new file mode 100644
index 0000000..f87a80c
--- /dev/null
+++ b/test/core/internal_api_canaries/iomgr.c
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/executor.h"
+
+/*******************************************************************************
+ * NOTE: If this test fails to compile, then the api changes are likely to cause
+ *       merge failures downstream. Please pay special attention to reviewing
+ *       these changes, and solicit help as appropriate when merging downstream.
+ *
+ * This test is NOT expected to be run directly.
+ ******************************************************************************/
+
+static void test_code(void) {
+  /* iomgr.h */
+  grpc_iomgr_init();
+  grpc_iomgr_shutdown();
+
+  /* closure.h */
+  grpc_closure closure;
+  closure.cb = NULL;
+  closure.cb_arg = NULL;
+  closure.final_data = 0;
+
+  grpc_closure_list closure_list = GRPC_CLOSURE_LIST_INIT;
+  closure_list.head = NULL;
+  closure_list.tail = NULL;
+
+  grpc_closure_init(&closure, NULL, NULL);
+
+  grpc_closure_create(NULL, NULL);
+
+  grpc_closure_list_move(NULL, NULL);
+  grpc_closure_list_add(NULL, NULL, true);
+  bool x = grpc_closure_list_empty(closure_list);
+  grpc_closure_next(&closure);
+
+  /* exec_ctx.h */
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_exec_ctx_flush(&exec_ctx);
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_exec_ctx_enqueue(&exec_ctx, &closure, x, NULL);
+  grpc_exec_ctx_enqueue_list(&exec_ctx, &closure_list, NULL);
+
+  /* endpoint.h */
+  grpc_endpoint endpoint;
+  grpc_endpoint_vtable vtable = {
+      grpc_endpoint_read,           grpc_endpoint_write,
+      grpc_endpoint_add_to_pollset, grpc_endpoint_add_to_pollset_set,
+      grpc_endpoint_shutdown,       grpc_endpoint_destroy,
+      grpc_endpoint_get_peer};
+  endpoint.vtable = &vtable;
+
+  grpc_endpoint_read(&exec_ctx, &endpoint, NULL, NULL);
+  grpc_endpoint_get_peer(&endpoint);
+  grpc_endpoint_write(&exec_ctx, &endpoint, NULL, NULL);
+  grpc_endpoint_shutdown(&exec_ctx, &endpoint);
+  grpc_endpoint_destroy(&exec_ctx, &endpoint);
+  grpc_endpoint_add_to_pollset(&exec_ctx, &endpoint, NULL);
+  grpc_endpoint_add_to_pollset_set(&exec_ctx, &endpoint, NULL);
+
+  /* executor.h */
+  grpc_executor_init();
+  grpc_executor_enqueue(&closure, x);
+  grpc_executor_shutdown();
+
+  /* pollset.h */
+  grpc_pollset_size();
+  grpc_pollset_init(NULL, NULL);
+  grpc_pollset_shutdown(NULL, NULL, NULL);
+  grpc_pollset_reset(NULL);
+  grpc_pollset_destroy(NULL);
+  grpc_pollset_work(NULL, NULL, NULL, gpr_now(GPR_CLOCK_REALTIME),
+                    gpr_now(GPR_CLOCK_MONOTONIC));
+  grpc_pollset_kick(NULL, NULL);
+}
+
+int main(void) {
+  if (false) test_code();
+  return 0;
+}
diff --git a/test/core/internal_api_canaries/support.c b/test/core/internal_api_canaries/support.c
new file mode 100644
index 0000000..c51cbf2
--- /dev/null
+++ b/test/core/internal_api_canaries/support.c
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/*******************************************************************************
+ * NOTE: If this test fails to compile, then the api changes are likely to cause
+ *       merge failures downstream. Please pay special attention to reviewing
+ *       these changes, and solicit help as appropriate when merging downstream.
+ *
+ * This test is NOT expected to be run directly.
+ ******************************************************************************/
+
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/support/tmpfile.h"
+
+static void test_code(void) {
+  /* env.h */
+  gpr_set_env("abc", gpr_getenv("xyz"));
+  /* load_file.h */
+  gpr_load_file("abc", 1, NULL);
+  /* tmpfile.h */
+  fclose(gpr_tmpfile("foo", NULL));
+}
+
+int main(void) {
+  if (false) test_code();
+  return 0;
+}
diff --git a/test/core/internal_api_canaries/transport.c b/test/core/internal_api_canaries/transport.c
new file mode 100644
index 0000000..0617865
--- /dev/null
+++ b/test/core/internal_api_canaries/transport.c
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/*******************************************************************************
+ * NOTE: If this test fails to compile, then the api changes are likely to cause
+ *       merge failures downstream. Please pay special attention to reviewing
+ *       these changes, and solicit help as appropriate when merging downstream.
+ *
+ * This test is NOT expected to be run directly.
+ ******************************************************************************/
+
+#include "src/core/lib/transport/transport.h"
+#include "src/core/lib/transport/transport_impl.h"
+
+static void test_code(void) {
+  /* transport_impl.h */
+  grpc_transport transport;
+  grpc_transport_vtable vtable = {12345,
+                                  grpc_transport_init_stream,
+                                  grpc_transport_set_pollset,
+                                  grpc_transport_perform_stream_op,
+                                  grpc_transport_perform_op,
+                                  grpc_transport_destroy_stream,
+                                  grpc_transport_destroy,
+                                  grpc_transport_get_peer};
+  transport.vtable = &vtable;
+
+  /* transport.h */
+  GRPC_STREAM_REF_INIT(NULL, 0, NULL, NULL, "xyz");
+  GPR_ASSERT(0 == grpc_transport_stream_size(NULL));
+  GPR_ASSERT(grpc_transport_init_stream(&transport, NULL, NULL, NULL, NULL));
+  grpc_transport_set_pollset(&transport, NULL, NULL, NULL);
+  grpc_transport_destroy_stream(&transport, NULL, NULL);
+  grpc_transport_stream_op_finish_with_failure(NULL, NULL);
+  grpc_transport_stream_op_add_cancellation(NULL, GRPC_STATUS_UNAVAILABLE);
+  grpc_transport_stream_op_add_close(NULL, GRPC_STATUS_UNAVAILABLE,
+                                     grpc_transport_op_string(NULL));
+  grpc_transport_perform_stream_op(&transport, NULL, NULL, NULL);
+  grpc_transport_perform_op(&transport, NULL, NULL);
+  grpc_transport_ping(&transport, NULL);
+  grpc_transport_goaway(&transport, GRPC_STATUS_UNAVAILABLE,
+                        gpr_slice_malloc(0));
+  grpc_transport_close(&transport);
+  grpc_transport_destroy(&transport, NULL);
+  GPR_ASSERT("xyz" == grpc_transport_get_peer(&transport, NULL));
+}
+
+int main(void) {
+  if (false) test_code();
+  return 0;
+}
diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c
index c3a9108..0df94a8 100644
--- a/test/core/iomgr/endpoint_pair_test.c
+++ b/test/core/iomgr/endpoint_pair_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,14 +31,12 @@
  *
  */
 
-#include "src/core/iomgr/tcp_posix.h"
-
+#include "src/core/lib/iomgr/endpoint_pair.h"
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
-#include "src/core/iomgr/endpoint_pair.h"
 #include "test/core/iomgr/endpoint_tests.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c
index f689e4b..52082c3 100644
--- a/test/core/iomgr/endpoint_tests.c
+++ b/test/core/iomgr/endpoint_tests.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,7 @@
 static gpr_slice *allocate_blocks(size_t num_bytes, size_t slice_size,
                                   size_t *num_blocks, uint8_t *current_data) {
   size_t nslices = num_bytes / slice_size + (num_bytes % slice_size ? 1 : 0);
-  gpr_slice *slices = malloc(sizeof(gpr_slice) * nslices);
+  gpr_slice *slices = gpr_malloc(sizeof(gpr_slice) * nslices);
   size_t num_bytes_left = num_bytes;
   size_t i;
   size_t j;
@@ -164,7 +164,7 @@
       gpr_slice_buffer_addn(&state->outgoing, slices, nslices);
       grpc_endpoint_write(exec_ctx, state->write_ep, &state->outgoing,
                           &state->done_write);
-      free(slices);
+      gpr_free(slices);
       return;
     }
   }
diff --git a/test/core/iomgr/endpoint_tests.h b/test/core/iomgr/endpoint_tests.h
index 8ea47e3..586010c 100644
--- a/test/core/iomgr/endpoint_tests.h
+++ b/test/core/iomgr/endpoint_tests.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@
 
 #include <sys/types.h>
 
-#include "src/core/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/endpoint.h"
 
 typedef struct grpc_endpoint_test_config grpc_endpoint_test_config;
 typedef struct grpc_endpoint_test_fixture grpc_endpoint_test_fixture;
diff --git a/test/core/iomgr/fd_conservation_posix_test.c b/test/core/iomgr/fd_conservation_posix_test.c
index 401bf70..bbb3f46 100644
--- a/test/core/iomgr/fd_conservation_posix_test.c
+++ b/test/core/iomgr/fd_conservation_posix_test.c
@@ -35,9 +35,9 @@
 
 #include <grpc/support/log.h>
 
+#include "src/core/lib/iomgr/endpoint_pair.h"
+#include "src/core/lib/iomgr/iomgr.h"
 #include "test/core/util/test_config.h"
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/iomgr/iomgr.h"
 
 int main(int argc, char **argv) {
   int i;
diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c
index 99689eb..f97f337 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/fd_posix.h"
+#include "src/core/lib/iomgr/ev_posix.h"
 
 #include <ctype.h>
 #include <errno.h>
@@ -50,7 +50,8 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
-#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/iomgr.h"
 #include "test/core/util/test_config.h"
 
 static gpr_mu *g_mu;
@@ -134,7 +135,7 @@
 static void session_read_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */
                             bool success) {
   session *se = arg;
-  int fd = se->em_fd->fd;
+  int fd = grpc_fd_wrapped_fd(se->em_fd);
 
   ssize_t read_once = 0;
   ssize_t read_total = 0;
@@ -204,7 +205,7 @@
     return;
   }
 
-  fd = accept(listen_em_fd->fd, (struct sockaddr *)&ss, &slen);
+  fd = accept(grpc_fd_wrapped_fd(listen_em_fd), (struct sockaddr *)&ss, &slen);
   GPR_ASSERT(fd >= 0);
   GPR_ASSERT(fd < FD_SETSIZE);
   flags = fcntl(fd, F_GETFL, 0);
@@ -306,7 +307,7 @@
 static void client_session_write(grpc_exec_ctx *exec_ctx, void *arg, /*client */
                                  bool success) {
   client *cl = arg;
-  int fd = cl->em_fd->fd;
+  int fd = grpc_fd_wrapped_fd(cl->em_fd);
   ssize_t write_once = 0;
 
   if (!success) {
diff --git a/test/core/iomgr/resolve_address_test.c b/test/core/iomgr/resolve_address_test.c
index 56ce091..c3ede18 100644
--- a/test/core/iomgr/resolve_address_test.c
+++ b/test/core/iomgr/resolve_address_test.c
@@ -31,11 +31,11 @@
  *
  */
 
-#include "src/core/iomgr/resolve_address.h"
-#include "src/core/iomgr/executor.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
+#include "src/core/lib/iomgr/executor.h"
 #include "test/core/util/test_config.h"
 
 static gpr_timespec test_deadline(void) {
@@ -59,28 +59,36 @@
 static void test_localhost(void) {
   gpr_event ev;
   gpr_event_init(&ev);
-  grpc_resolve_address("localhost:1", NULL, must_succeed, &ev);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_resolve_address(&exec_ctx, "localhost:1", NULL, must_succeed, &ev);
+  grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
 }
 
 static void test_default_port(void) {
   gpr_event ev;
   gpr_event_init(&ev);
-  grpc_resolve_address("localhost", "1", must_succeed, &ev);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_resolve_address(&exec_ctx, "localhost", "1", must_succeed, &ev);
+  grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
 }
 
 static void test_missing_default_port(void) {
   gpr_event ev;
   gpr_event_init(&ev);
-  grpc_resolve_address("localhost", NULL, must_fail, &ev);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_resolve_address(&exec_ctx, "localhost", NULL, must_fail, &ev);
+  grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
 }
 
 static void test_ipv6_with_port(void) {
   gpr_event ev;
   gpr_event_init(&ev);
-  grpc_resolve_address("[2001:db8::1]:1", NULL, must_succeed, &ev);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_resolve_address(&exec_ctx, "[2001:db8::1]:1", NULL, must_succeed, &ev);
+  grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
 }
 
@@ -92,7 +100,9 @@
   for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
     gpr_event ev;
     gpr_event_init(&ev);
-    grpc_resolve_address(kCases[i], "80", must_succeed, &ev);
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_resolve_address(&exec_ctx, kCases[i], "80", must_succeed, &ev);
+    grpc_exec_ctx_finish(&exec_ctx);
     GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
   }
 }
@@ -105,7 +115,9 @@
   for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
     gpr_event ev;
     gpr_event_init(&ev);
-    grpc_resolve_address(kCases[i], NULL, must_fail, &ev);
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_resolve_address(&exec_ctx, kCases[i], NULL, must_fail, &ev);
+    grpc_exec_ctx_finish(&exec_ctx);
     GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
   }
 }
@@ -118,7 +130,9 @@
   for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
     gpr_event ev;
     gpr_event_init(&ev);
-    grpc_resolve_address(kCases[i], "1", must_fail, &ev);
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_resolve_address(&exec_ctx, kCases[i], "1", must_fail, &ev);
+    grpc_exec_ctx_finish(&exec_ctx);
     GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
   }
 }
diff --git a/test/core/iomgr/sockaddr_utils_test.c b/test/core/iomgr/sockaddr_utils_test.c
index a7b57c1..a330314 100644
--- a/test/core/iomgr/sockaddr_utils_test.c
+++ b/test/core/iomgr/sockaddr_utils_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
 
 #include <errno.h>
 #include <string.h>
diff --git a/test/core/iomgr/socket_utils_test.c b/test/core/iomgr/socket_utils_test.c
index 58c3fbc..85c027a 100644
--- a/test/core/iomgr/socket_utils_test.c
+++ b/test/core/iomgr/socket_utils_test.c
@@ -32,7 +32,7 @@
  */
 
 #include <grpc/support/port_platform.h>
-#include "src/core/iomgr/socket_utils_posix.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
 
 #include <errno.h>
 #include <string.h>
diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c
index 746dfd8..22dc936 100644
--- a/test/core/iomgr/tcp_client_posix_test.c
+++ b/test/core/iomgr/tcp_client_posix_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/tcp_client.h"
+#include "src/core/lib/iomgr/tcp_client.h"
 
 #include <errno.h>
 #include <netinet/in.h>
@@ -44,9 +44,10 @@
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/socket_utils_posix.h"
-#include "src/core/iomgr/timer.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/pollset_set.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/iomgr/timer.h"
 #include "test/core/util/test_config.h"
 
 static grpc_pollset_set *g_pollset_set;
diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c
index 4351642..7a98fa0 100644
--- a/test/core/iomgr/tcp_posix_test.c
+++ b/test/core/iomgr/tcp_posix_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/tcp_posix.h"
+#include "src/core/lib/iomgr/tcp_posix.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -97,7 +97,7 @@
 static size_t fill_socket_partial(int fd, size_t bytes) {
   ssize_t write_bytes;
   size_t total_bytes = 0;
-  unsigned char *buf = malloc(bytes);
+  unsigned char *buf = gpr_malloc(bytes);
   unsigned i;
   for (i = 0; i < bytes; ++i) {
     buf[i] = (uint8_t)(i % 256);
@@ -292,7 +292,7 @@
 }
 
 void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) {
-  unsigned char *buf = malloc(read_size);
+  unsigned char *buf = gpr_malloc(read_size);
   ssize_t bytes_read;
   size_t bytes_left = num_bytes;
   int flags;
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index 7933468..266d239 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/tcp_server.h"
+#include "src/core/lib/iomgr/tcp_server.h"
 
 #include <errno.h>
 #include <netinet/in.h>
@@ -45,8 +45,8 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/iomgr/time_averaged_stats_test.c b/test/core/iomgr/time_averaged_stats_test.c
index cb006d1..72f8559 100644
--- a/test/core/iomgr/time_averaged_stats_test.c
+++ b/test/core/iomgr/time_averaged_stats_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/time_averaged_stats.h"
+#include "src/core/lib/iomgr/time_averaged_stats.h"
 
 #include <math.h>
 
diff --git a/test/core/iomgr/timer_heap_test.c b/test/core/iomgr/timer_heap_test.c
index dd23a99..d1cb004 100644
--- a/test/core/iomgr/timer_heap_test.c
+++ b/test/core/iomgr/timer_heap_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/timer_heap.h"
+#include "src/core/lib/iomgr/timer_heap.h"
 
 #include <stdlib.h>
 #include <string.h>
diff --git a/test/core/iomgr/timer_list_test.c b/test/core/iomgr/timer_list_test.c
index 7a21fdd..2e0f5c8 100644
--- a/test/core/iomgr/timer_list_test.c
+++ b/test/core/iomgr/timer_list_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/timer.h"
+#include "src/core/lib/iomgr/timer.h"
 
 #include <string.h>
 
@@ -81,9 +81,8 @@
   }
 
   GPR_ASSERT(!grpc_timer_check(
-                 &exec_ctx,
-                 gpr_time_add(start, gpr_time_from_millis(600, GPR_TIMESPAN)),
-                 NULL));
+      &exec_ctx, gpr_time_add(start, gpr_time_from_millis(600, GPR_TIMESPAN)),
+      NULL));
   grpc_exec_ctx_finish(&exec_ctx);
   for (i = 0; i < 30; i++) {
     GPR_ASSERT(cb_called[i][1] == (i < 10));
@@ -101,9 +100,8 @@
   }
 
   GPR_ASSERT(!grpc_timer_check(
-                 &exec_ctx,
-                 gpr_time_add(start, gpr_time_from_millis(1600, GPR_TIMESPAN)),
-                 NULL));
+      &exec_ctx, gpr_time_add(start, gpr_time_from_millis(1600, GPR_TIMESPAN)),
+      NULL));
   for (i = 0; i < 30; i++) {
     GPR_ASSERT(cb_called[i][1] == (i < 20));
     GPR_ASSERT(cb_called[i][0] == 0);
diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c
index 365b5c0..5248b61 100644
--- a/test/core/iomgr/udp_server_test.c
+++ b/test/core/iomgr/udp_server_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,25 +31,26 @@
  *
  */
 
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/pollset_posix.h"
-#include "src/core/iomgr/udp_server.h"
+#include "src/core/lib/iomgr/udp_server.h"
 #include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/iomgr.h"
 #include "test/core/util/test_config.h"
 
-#include <sys/socket.h>
 #include <netinet/in.h>
 #include <string.h>
+#include <sys/socket.h>
 #include <unistd.h>
 
 #ifdef GRPC_NEED_UDP
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x)
 
-static grpc_pollset g_pollset;
+static grpc_pollset *g_pollset;
 static gpr_mu *g_mu;
 static int g_number_of_reads = 0;
 static int g_number_of_bytes_read = 0;
@@ -60,12 +61,13 @@
   ssize_t byte_count;
 
   gpr_mu_lock(g_mu);
-  byte_count = recv(emfd->fd, read_buffer, sizeof(read_buffer), 0);
+  byte_count =
+      recv(grpc_fd_wrapped_fd(emfd), read_buffer, sizeof(read_buffer), 0);
 
   g_number_of_reads++;
   g_number_of_bytes_read += (int)byte_count;
 
-  grpc_pollset_kick(&g_pollset, NULL);
+  grpc_pollset_kick(g_pollset, NULL);
   gpr_mu_unlock(g_mu);
 }
 
@@ -142,7 +144,7 @@
   GPR_ASSERT(getsockname(svrfd, (struct sockaddr *)&addr, &addr_len) == 0);
   GPR_ASSERT(addr_len <= sizeof(addr));
 
-  pollsets[0] = &g_pollset;
+  pollsets[0] = g_pollset;
   grpc_udp_server_start(&exec_ctx, s, pollsets, 1, NULL);
 
   gpr_mu_lock(g_mu);
@@ -159,7 +161,7 @@
     while (g_number_of_reads == number_of_reads_before &&
            gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0) {
       grpc_pollset_worker *worker = NULL;
-      grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+      grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                         gpr_now(GPR_CLOCK_MONOTONIC), deadline);
       gpr_mu_unlock(g_mu);
       grpc_exec_ctx_finish(&exec_ctx);
@@ -185,7 +187,8 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  grpc_pollset_init(&g_pollset, &g_mu);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
 
   test_no_op();
   test_no_op_with_start();
@@ -194,9 +197,10 @@
   test_receive(1);
   test_receive(10);
 
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
+  gpr_free(g_pollset);
   grpc_iomgr_shutdown();
   return 0;
 }
diff --git a/test/core/iomgr/workqueue_test.c b/test/core/iomgr/workqueue_test.c
index 8a1faf6..874e696 100644
--- a/test/core/iomgr/workqueue_test.c
+++ b/test/core/iomgr/workqueue_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/iomgr/workqueue.h"
+#include "src/core/lib/iomgr/workqueue.h"
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
diff --git a/test/core/json/corpus/006d552e952c42b5340baaeb85c2cb80c81e78dd b/test/core/json/corpus/006d552e952c42b5340baaeb85c2cb80c81e78dd
new file mode 100644
index 0000000..762064c
--- /dev/null
+++ b/test/core/json/corpus/006d552e952c42b5340baaeb85c2cb80c81e78dd
@@ -0,0 +1 @@
+1e9
\ No newline at end of file
diff --git a/test/core/json/corpus/007eb985c44b6089a34995a7d9ebf349f1c2bf18 b/test/core/json/corpus/007eb985c44b6089a34995a7d9ebf349f1c2bf18
new file mode 100644
index 0000000..8affa52
--- /dev/null
+++ b/test/core/json/corpus/007eb985c44b6089a34995a7d9ebf349f1c2bf18
@@ -0,0 +1 @@
+{}3[
\ No newline at end of file
diff --git a/test/core/json/corpus/03b74a08f23734691512cb12d0b38d189a8df905 b/test/core/json/corpus/03b74a08f23734691512cb12d0b38d189a8df905
new file mode 100644
index 0000000..7ffe3f3
--- /dev/null
+++ b/test/core/json/corpus/03b74a08f23734691512cb12d0b38d189a8df905
@@ -0,0 +1 @@
+0.6991 
\ No newline at end of file
diff --git a/test/core/json/corpus/0495693af07325fb0d52eafd2d4c4d802c6457c6 b/test/core/json/corpus/0495693af07325fb0d52eafd2d4c4d802c6457c6
new file mode 100644
index 0000000..f7752ee
--- /dev/null
+++ b/test/core/json/corpus/0495693af07325fb0d52eafd2d4c4d802c6457c6
@@ -0,0 +1 @@
+0.83282
\ No newline at end of file
diff --git a/test/core/json/corpus/05454ab015cf74e9c3e8574d995517e05dd56751 b/test/core/json/corpus/05454ab015cf74e9c3e8574d995517e05dd56751
new file mode 100644
index 0000000..8377c55
--- /dev/null
+++ b/test/core/json/corpus/05454ab015cf74e9c3e8574d995517e05dd56751
@@ -0,0 +1 @@
+21.595»
\ No newline at end of file
diff --git a/test/core/json/corpus/0716d9708d321ffb6a00818614779e779925365c b/test/core/json/corpus/0716d9708d321ffb6a00818614779e779925365c
new file mode 100644
index 0000000..8e2afd3
--- /dev/null
+++ b/test/core/json/corpus/0716d9708d321ffb6a00818614779e779925365c
@@ -0,0 +1 @@
+17
\ No newline at end of file
diff --git a/test/core/json/corpus/0a9b3522a8e711e3bd53e2c2eb9d28b34a003acc b/test/core/json/corpus/0a9b3522a8e711e3bd53e2c2eb9d28b34a003acc
new file mode 100644
index 0000000..d249eb2
--- /dev/null
+++ b/test/core/json/corpus/0a9b3522a8e711e3bd53e2c2eb9d28b34a003acc
@@ -0,0 +1 @@
+[2.1e	"ˆÃ796;]3*
\ No newline at end of file
diff --git a/test/core/json/corpus/0ade7c2cf97f75d009975f4d720d1fa6c19f4897 b/test/core/json/corpus/0ade7c2cf97f75d009975f4d720d1fa6c19f4897
new file mode 100644
index 0000000..f11c82a
--- /dev/null
+++ b/test/core/json/corpus/0ade7c2cf97f75d009975f4d720d1fa6c19f4897
@@ -0,0 +1 @@
+9
\ No newline at end of file
diff --git a/test/core/json/corpus/0b1fcf0ac07e1e50cfe27316c7e1c8cc997f1318 b/test/core/json/corpus/0b1fcf0ac07e1e50cfe27316c7e1c8cc997f1318
new file mode 100644
index 0000000..b66d61b
--- /dev/null
+++ b/test/core/json/corpus/0b1fcf0ac07e1e50cfe27316c7e1c8cc997f1318
@@ -0,0 +1 @@
+{"'5E885,!\u065E{
\ No newline at end of file
diff --git a/test/core/json/corpus/0bc13548356d08009703d35e9c8d74397367bdfb b/test/core/json/corpus/0bc13548356d08009703d35e9c8d74397367bdfb
new file mode 100644
index 0000000..2c23914
--- /dev/null
+++ b/test/core/json/corpus/0bc13548356d08009703d35e9c8d74397367bdfb
@@ -0,0 +1 @@
+nu,*:
\ No newline at end of file
diff --git a/test/core/json/corpus/0ea9a160c57f2c705dce037196e360bf9be739c5 b/test/core/json/corpus/0ea9a160c57f2c705dce037196e360bf9be739c5
new file mode 100644
index 0000000..f92893d
--- /dev/null
+++ b/test/core/json/corpus/0ea9a160c57f2c705dce037196e360bf9be739c5
@@ -0,0 +1 @@
+f'
\ No newline at end of file
diff --git a/test/core/json/corpus/0f20d9c46991c0e97419e2cca07c7389f1d6bdf8 b/test/core/json/corpus/0f20d9c46991c0e97419e2cca07c7389f1d6bdf8
new file mode 100644
index 0000000..05a6fb2
--- /dev/null
+++ b/test/core/json/corpus/0f20d9c46991c0e97419e2cca07c7389f1d6bdf8
@@ -0,0 +1 @@
+1e	"ˆÃ9
\ No newline at end of file
diff --git a/test/core/json/corpus/0f2e2e6346f70c419300b661251754d50f7ca8ea b/test/core/json/corpus/0f2e2e6346f70c419300b661251754d50f7ca8ea
new file mode 100644
index 0000000..e429f50
--- /dev/null
+++ b/test/core/json/corpus/0f2e2e6346f70c419300b661251754d50f7ca8ea
@@ -0,0 +1 @@
+[2.1982
\ No newline at end of file
diff --git a/test/core/json/corpus/108b310facc1a193833fc2971fd83081f775ea0c b/test/core/json/corpus/108b310facc1a193833fc2971fd83081f775ea0c
new file mode 100644
index 0000000..45be455
--- /dev/null
+++ b/test/core/json/corpus/108b310facc1a193833fc2971fd83081f775ea0c
@@ -0,0 +1 @@
+false)
\ No newline at end of file
diff --git a/test/core/json/corpus/108e5bcd69b19ad0df743641085163b84f376fe8 b/test/core/json/corpus/108e5bcd69b19ad0df743641085163b84f376fe8
new file mode 100644
index 0000000..0973cbb
--- /dev/null
+++ b/test/core/json/corpus/108e5bcd69b19ad0df743641085163b84f376fe8
@@ -0,0 +1,2 @@
+[{
+"ˆÃ" "ˆÃ"
\ No newline at end of file
diff --git a/test/core/json/corpus/10e3ecd5624465020fdf0662a67e0f0885536cae b/test/core/json/corpus/10e3ecd5624465020fdf0662a67e0f0885536cae
new file mode 100644
index 0000000..5230607
--- /dev/null
+++ b/test/core/json/corpus/10e3ecd5624465020fdf0662a67e0f0885536cae
@@ -0,0 +1 @@
+{"":0,(!Ó'(\'!)
\ No newline at end of file
diff --git a/test/core/json/corpus/113c8c97cbb0a2b6176d75eaa9ac9baaa7ccddcc b/test/core/json/corpus/113c8c97cbb0a2b6176d75eaa9ac9baaa7ccddcc
new file mode 100644
index 0000000..8f04034
--- /dev/null
+++ b/test/core/json/corpus/113c8c97cbb0a2b6176d75eaa9ac9baaa7ccddcc
@@ -0,0 +1 @@
+1¹
\ No newline at end of file
diff --git a/test/core/json/corpus/11479d936dd006410a5946b6081a94d573bf8efd b/test/core/json/corpus/11479d936dd006410a5946b6081a94d573bf8efd
new file mode 100644
index 0000000..58cf749
--- /dev/null
+++ b/test/core/json/corpus/11479d936dd006410a5946b6081a94d573bf8efd
@@ -0,0 +1 @@
+tr¹82 'A\E57;)
\ No newline at end of file
diff --git a/test/core/json/corpus/11aa091189b78d1cc35c7ff4907ac16a73aba547 b/test/core/json/corpus/11aa091189b78d1cc35c7ff4907ac16a73aba547
new file mode 100644
index 0000000..cb88820
--- /dev/null
+++ b/test/core/json/corpus/11aa091189b78d1cc35c7ff4907ac16a73aba547
@@ -0,0 +1 @@
+[9281.2;
\ No newline at end of file
diff --git a/test/core/json/corpus/1227907b2ee5a9492a890beed55332e4560834c8 b/test/core/json/corpus/1227907b2ee5a9492a890beed55332e4560834c8
new file mode 100644
index 0000000..fd35270
--- /dev/null
+++ b/test/core/json/corpus/1227907b2ee5a9492a890beed55332e4560834c8
@@ -0,0 +1 @@
+2}5
\ No newline at end of file
diff --git a/test/core/json/corpus/134d65130947ec69cf8df8483424b45e99cf04e3 b/test/core/json/corpus/134d65130947ec69cf8df8483424b45e99cf04e3
new file mode 100644
index 0000000..522a9be
--- /dev/null
+++ b/test/core/json/corpus/134d65130947ec69cf8df8483424b45e99cf04e3
@@ -0,0 +1 @@
+0.2995 
\ No newline at end of file
diff --git a/test/core/json/corpus/13584505caa892d94982a968bbc4391ebcfe0d06 b/test/core/json/corpus/13584505caa892d94982a968bbc4391ebcfe0d06
new file mode 100644
index 0000000..9fb628a
--- /dev/null
+++ b/test/core/json/corpus/13584505caa892d94982a968bbc4391ebcfe0d06
@@ -0,0 +1 @@
+{"',!\uA>Š
\ No newline at end of file
diff --git a/test/core/json/corpus/137f554ee0f6b903acb81ab4e1f98c11fe92b008 b/test/core/json/corpus/137f554ee0f6b903acb81ab4e1f98c11fe92b008
new file mode 100644
index 0000000..98232c6
--- /dev/null
+++ b/test/core/json/corpus/137f554ee0f6b903acb81ab4e1f98c11fe92b008
@@ -0,0 +1 @@
+{
diff --git a/test/core/json/corpus/1401ea03ec78b8f20dc7be952555004d7147f0f5 b/test/core/json/corpus/1401ea03ec78b8f20dc7be952555004d7147f0f5
new file mode 100644
index 0000000..595fe02
--- /dev/null
+++ b/test/core/json/corpus/1401ea03ec78b8f20dc7be952555004d7147f0f5
@@ -0,0 +1 @@
+"ˆÃ{)ˆ!
\ No newline at end of file
diff --git a/test/core/json/corpus/141d45a59b073aeec4443cd7bcf20f7833ddbc95 b/test/core/json/corpus/141d45a59b073aeec4443cd7bcf20f7833ddbc95
new file mode 100644
index 0000000..e2e68e8
--- /dev/null
+++ b/test/core/json/corpus/141d45a59b073aeec4443cd7bcf20f7833ddbc95
@@ -0,0 +1 @@
+"'',!\u658E{128031:;):ˆ)!Ã5*¾?'ʳ³!!*!à):!*à::)!9:\udbD86'
\ No newline at end of file
diff --git a/test/core/json/corpus/15a8f2e7f94aa00b46f1b991416aa015dd633580 b/test/core/json/corpus/15a8f2e7f94aa00b46f1b991416aa015dd633580
new file mode 100644
index 0000000..7e613e8
--- /dev/null
+++ b/test/core/json/corpus/15a8f2e7f94aa00b46f1b991416aa015dd633580
@@ -0,0 +1 @@
+{"":21}
\ No newline at end of file
diff --git a/test/core/json/corpus/15c9c1284c27c8893559e15c9b2a50cbd5bbb56f b/test/core/json/corpus/15c9c1284c27c8893559e15c9b2a50cbd5bbb56f
new file mode 100644
index 0000000..21a9555
--- /dev/null
+++ b/test/core/json/corpus/15c9c1284c27c8893559e15c9b2a50cbd5bbb56f
@@ -0,0 +1 @@
+[2,"ˆÃ!{)!:",ˆÃ
\ No newline at end of file
diff --git a/test/core/json/corpus/15d1a6cda48ef569b368a0c4627435bc2c80a988 b/test/core/json/corpus/15d1a6cda48ef569b368a0c4627435bc2c80a988
new file mode 100644
index 0000000..8017a98
--- /dev/null
+++ b/test/core/json/corpus/15d1a6cda48ef569b368a0c4627435bc2c80a988
@@ -0,0 +1 @@
+	"ˆÃ "
\ No newline at end of file
diff --git a/test/core/json/corpus/17a29f2ac6df774585d7713091b299729738030c b/test/core/json/corpus/17a29f2ac6df774585d7713091b299729738030c
new file mode 100644
index 0000000..9402a603
--- /dev/null
+++ b/test/core/json/corpus/17a29f2ac6df774585d7713091b299729738030c
@@ -0,0 +1 @@
+[)
\ No newline at end of file
diff --git a/test/core/json/corpus/17b815f1f72cb64481bc40263e91ce063040f739 b/test/core/json/corpus/17b815f1f72cb64481bc40263e91ce063040f739
new file mode 100644
index 0000000..81b218e
--- /dev/null
+++ b/test/core/json/corpus/17b815f1f72cb64481bc40263e91ce063040f739
@@ -0,0 +1 @@
+[tr
\ No newline at end of file
diff --git a/test/core/json/corpus/182d57403d2c973a394055017d35b7621aa0aa05 b/test/core/json/corpus/182d57403d2c973a394055017d35b7621aa0aa05
new file mode 100644
index 0000000..f48f55e
--- /dev/null
+++ b/test/core/json/corpus/182d57403d2c973a394055017d35b7621aa0aa05
@@ -0,0 +1 @@
+null*:
\ No newline at end of file
diff --git a/test/core/json/corpus/190fbe2da448f6bdec0706c5301ad13363ae3ad9 b/test/core/json/corpus/190fbe2da448f6bdec0706c5301ad13363ae3ad9
new file mode 100644
index 0000000..37144c7
--- /dev/null
+++ b/test/core/json/corpus/190fbe2da448f6bdec0706c5301ad13363ae3ad9
@@ -0,0 +1 @@
+1e+2187560
\ No newline at end of file
diff --git a/test/core/json/corpus/1b045a24b8f1f1fd6e8234d5019952ee7713a8b7 b/test/core/json/corpus/1b045a24b8f1f1fd6e8234d5019952ee7713a8b7
new file mode 100644
index 0000000..04ac543
--- /dev/null
+++ b/test/core/json/corpus/1b045a24b8f1f1fd6e8234d5019952ee7713a8b7
@@ -0,0 +1 @@
+\5
\ No newline at end of file
diff --git a/test/core/json/corpus/1b6453892473a467d07372d45eb05abc2031647a b/test/core/json/corpus/1b6453892473a467d07372d45eb05abc2031647a
new file mode 100644
index 0000000..bf0d87a
--- /dev/null
+++ b/test/core/json/corpus/1b6453892473a467d07372d45eb05abc2031647a
@@ -0,0 +1 @@
+4
\ No newline at end of file
diff --git a/test/core/json/corpus/1c6463aa2dabcb4fadc8e5441d8b418535e768af b/test/core/json/corpus/1c6463aa2dabcb4fadc8e5441d8b418535e768af
new file mode 100644
index 0000000..7fa1b27
--- /dev/null
+++ b/test/core/json/corpus/1c6463aa2dabcb4fadc8e5441d8b418535e768af
@@ -0,0 +1 @@
+0{:ˆ)!Ã"*¾?'ʳ³!!*!à):!*à:::\udbD8ˆ)Ã!:{!`!?`¾¾!?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/1dea95b5050b766274ef80847505c0e4f47f3ebb b/test/core/json/corpus/1dea95b5050b766274ef80847505c0e4f47f3ebb
new file mode 100644
index 0000000..1237d77
--- /dev/null
+++ b/test/core/json/corpus/1dea95b5050b766274ef80847505c0e4f47f3ebb
@@ -0,0 +1 @@
+13e190560
\ No newline at end of file
diff --git a/test/core/json/corpus/1df0754d3e7970b3afe549b11ca128dcd0d4832b b/test/core/json/corpus/1df0754d3e7970b3afe549b11ca128dcd0d4832b
new file mode 100644
index 0000000..dd9df88
--- /dev/null
+++ b/test/core/json/corpus/1df0754d3e7970b3afe549b11ca128dcd0d4832b
@@ -0,0 +1 @@
+{"'5E885,!\u000E{
\ No newline at end of file
diff --git a/test/core/json/corpus/1dfe267b623b20cd97c6e8969d8b9148af9f4a2c b/test/core/json/corpus/1dfe267b623b20cd97c6e8969d8b9148af9f4a2c
new file mode 100644
index 0000000..7f010a2
--- /dev/null
+++ b/test/core/json/corpus/1dfe267b623b20cd97c6e8969d8b9148af9f4a2c
@@ -0,0 +1 @@
+6(0
\ No newline at end of file
diff --git a/test/core/json/corpus/1e5c2f367f02e47a8c160cda1cd9d91decbac441 b/test/core/json/corpus/1e5c2f367f02e47a8c160cda1cd9d91decbac441
new file mode 100644
index 0000000..8e2f0be
--- /dev/null
+++ b/test/core/json/corpus/1e5c2f367f02e47a8c160cda1cd9d91decbac441
@@ -0,0 +1 @@
+[
\ No newline at end of file
diff --git a/test/core/json/corpus/20efdba13ca7a3657d071b3d56997aa3b083068a b/test/core/json/corpus/20efdba13ca7a3657d071b3d56997aa3b083068a
new file mode 100644
index 0000000..5194be3
--- /dev/null
+++ b/test/core/json/corpus/20efdba13ca7a3657d071b3d56997aa3b083068a
@@ -0,0 +1 @@
+"ˆÃ{)!:*])Ã!:{"*¾?¾;?Xʳ³'!!Ê
\ No newline at end of file
diff --git a/test/core/json/corpus/215a956168f77421253e947c2436371d56aa7ea1 b/test/core/json/corpus/215a956168f77421253e947c2436371d56aa7ea1
new file mode 100644
index 0000000..a0aeede
--- /dev/null
+++ b/test/core/json/corpus/215a956168f77421253e947c2436371d56aa7ea1
@@ -0,0 +1 @@
+fa
\ No newline at end of file
diff --git a/test/core/json/corpus/2174b9ab6bf4f7c21fe1ed56957f1776ef611959 b/test/core/json/corpus/2174b9ab6bf4f7c21fe1ed56957f1776ef611959
new file mode 100644
index 0000000..ef32707
--- /dev/null
+++ b/test/core/json/corpus/2174b9ab6bf4f7c21fe1ed56957f1776ef611959
@@ -0,0 +1 @@
+13e5!01860
\ No newline at end of file
diff --git a/test/core/json/corpus/232f4bced4075545bb1469d5c2360f083ec7ec65 b/test/core/json/corpus/232f4bced4075545bb1469d5c2360f083ec7ec65
new file mode 100644
index 0000000..d4e4ebe
--- /dev/null
+++ b/test/core/json/corpus/232f4bced4075545bb1469d5c2360f083ec7ec65
@@ -0,0 +1 @@
+{"',!\u65E8850{2312;):ˆ)!Ã"*¾?'ʳ³!!*!à):!*à::8!9:\udbD86'
\ No newline at end of file
diff --git a/test/core/json/corpus/26aca41ee8f199e7c0c7cf31d979952571c53fc9 b/test/core/json/corpus/26aca41ee8f199e7c0c7cf31d979952571c53fc9
new file mode 100644
index 0000000..016fe56
--- /dev/null
+++ b/test/core/json/corpus/26aca41ee8f199e7c0c7cf31d979952571c53fc9
Binary files differ
diff --git a/test/core/json/corpus/27d84210636e9e83786be9e9b96b69f70b743b86 b/test/core/json/corpus/27d84210636e9e83786be9e9b96b69f70b743b86
new file mode 100644
index 0000000..701bd00
--- /dev/null
+++ b/test/core/json/corpus/27d84210636e9e83786be9e9b96b69f70b743b86
@@ -0,0 +1 @@
+{"',!\u'Š
\ No newline at end of file
diff --git a/test/core/json/corpus/27da426a5883662d19ea78f306d7a992be52f827 b/test/core/json/corpus/27da426a5883662d19ea78f306d7a992be52f827
new file mode 100644
index 0000000..2e7373e
--- /dev/null
+++ b/test/core/json/corpus/27da426a5883662d19ea78f306d7a992be52f827
@@ -0,0 +1,2 @@
+2

+P2÷
\ No newline at end of file
diff --git a/test/core/json/corpus/296dcda6f7e6979e68ddef7cbc1206a355084ad3 b/test/core/json/corpus/296dcda6f7e6979e68ddef7cbc1206a355084ad3
new file mode 100644
index 0000000..e510185
--- /dev/null
+++ b/test/core/json/corpus/296dcda6f7e6979e68ddef7cbc1206a355084ad3
@@ -0,0 +1 @@
+,ˆÃ""
\ No newline at end of file
diff --git a/test/core/json/corpus/29b08c03ca5a6851fa4604a984cb7ff44433a5a5 b/test/core/json/corpus/29b08c03ca5a6851fa4604a984cb7ff44433a5a5
new file mode 100644
index 0000000..60ec6c5
--- /dev/null
+++ b/test/core/json/corpus/29b08c03ca5a6851fa4604a984cb7ff44433a5a5
@@ -0,0 +1 @@
+3]5
\ No newline at end of file
diff --git a/test/core/json/corpus/2a3d964ec4527ad9f02129fcbf087b67a6ea6444 b/test/core/json/corpus/2a3d964ec4527ad9f02129fcbf087b67a6ea6444
new file mode 100644
index 0000000..e5e723f
--- /dev/null
+++ b/test/core/json/corpus/2a3d964ec4527ad9f02129fcbf087b67a6ea6444
@@ -0,0 +1 @@
+-w9'Á6
\ No newline at end of file
diff --git a/test/core/json/corpus/2b04974149815b143afb17af4388d751217e54ec b/test/core/json/corpus/2b04974149815b143afb17af4388d751217e54ec
new file mode 100644
index 0000000..880fb54
--- /dev/null
+++ b/test/core/json/corpus/2b04974149815b143afb17af4388d751217e54ec
@@ -0,0 +1 @@
+832E46;)
\ No newline at end of file
diff --git a/test/core/json/corpus/2b3b1ad952e3acb566e32a84e2d503acde13eb53 b/test/core/json/corpus/2b3b1ad952e3acb566e32a84e2d503acde13eb53
new file mode 100644
index 0000000..0f5e2da
--- /dev/null
+++ b/test/core/json/corpus/2b3b1ad952e3acb566e32a84e2d503acde13eb53
@@ -0,0 +1 @@
+31e8¤560
\ No newline at end of file
diff --git a/test/core/json/corpus/2cc301a6ed7f01e2cd339f02bd0fda20c227a17e b/test/core/json/corpus/2cc301a6ed7f01e2cd339f02bd0fda20c227a17e
new file mode 100644
index 0000000..f457fd8
--- /dev/null
+++ b/test/core/json/corpus/2cc301a6ed7f01e2cd339f02bd0fda20c227a17e
@@ -0,0 +1 @@
+825E132})
\ No newline at end of file
diff --git a/test/core/json/corpus/2d3d5b9275553430b4cfa68114099120ad7809ee b/test/core/json/corpus/2d3d5b9275553430b4cfa68114099120ad7809ee
new file mode 100644
index 0000000..7e7e3f7
--- /dev/null
+++ b/test/core/json/corpus/2d3d5b9275553430b4cfa68114099120ad7809ee
@@ -0,0 +1 @@
+[4*
\ No newline at end of file
diff --git a/test/core/json/corpus/2d5dbf403e0c12e2fe21b04ca3daff171c028ab7 b/test/core/json/corpus/2d5dbf403e0c12e2fe21b04ca3daff171c028ab7
new file mode 100644
index 0000000..42bbdf9
--- /dev/null
+++ b/test/core/json/corpus/2d5dbf403e0c12e2fe21b04ca3daff171c028ab7
@@ -0,0 +1 @@
+""919
\ No newline at end of file
diff --git a/test/core/json/corpus/2d7c769bed62004270034b976b1d940a5686106b b/test/core/json/corpus/2d7c769bed62004270034b976b1d940a5686106b
new file mode 100644
index 0000000..8a2b433
--- /dev/null
+++ b/test/core/json/corpus/2d7c769bed62004270034b976b1d940a5686106b
@@ -0,0 +1 @@
+{"',!\u65E8850{2312;):)ˆ!*?'¾Êѳ³!!ª!À):*!à::8!9:\udbD6\\'
\ No newline at end of file
diff --git a/test/core/json/corpus/2db120231eea12d9cdc6a00f30839b3cef2046be b/test/core/json/corpus/2db120231eea12d9cdc6a00f30839b3cef2046be
new file mode 100644
index 0000000..0cfb6e8
--- /dev/null
+++ b/test/core/json/corpus/2db120231eea12d9cdc6a00f30839b3cef2046be
@@ -0,0 +1 @@
+0.0 
\ No newline at end of file
diff --git a/test/core/json/corpus/2db610e1a230409a205cf22fbad3348a54cbe703 b/test/core/json/corpus/2db610e1a230409a205cf22fbad3348a54cbe703
new file mode 100644
index 0000000..3541d8d
--- /dev/null
+++ b/test/core/json/corpus/2db610e1a230409a205cf22fbad3348a54cbe703
@@ -0,0 +1 @@
+faå
\ No newline at end of file
diff --git a/test/core/json/corpus/2df1dd2e2f5d57e7d9d4e60a756a86e603573225 b/test/core/json/corpus/2df1dd2e2f5d57e7d9d4e60a756a86e603573225
new file mode 100644
index 0000000..390f409
--- /dev/null
+++ b/test/core/json/corpus/2df1dd2e2f5d57e7d9d4e60a756a86e603573225
@@ -0,0 +1 @@
+0.9!
\ No newline at end of file
diff --git a/test/core/json/corpus/2e32faacd3ea4461ec7aace297b4be6904d9a389 b/test/core/json/corpus/2e32faacd3ea4461ec7aace297b4be6904d9a389
new file mode 100644
index 0000000..83323c2
--- /dev/null
+++ b/test/core/json/corpus/2e32faacd3ea4461ec7aace297b4be6904d9a389
@@ -0,0 +1 @@
+[["ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\u1.y2db)8ˆÃ!‡:{!`!.7;?
\ No newline at end of file
diff --git a/test/core/json/corpus/2e756d91759d7e74f5b776c0d2a1935292f576d1 b/test/core/json/corpus/2e756d91759d7e74f5b776c0d2a1935292f576d1
new file mode 100644
index 0000000..037d9ce
--- /dev/null
+++ b/test/core/json/corpus/2e756d91759d7e74f5b776c0d2a1935292f576d1
@@ -0,0 +1 @@
+"ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à::d\r:8))ˆÃ![1.‡97:{
\ No newline at end of file
diff --git a/test/core/json/corpus/2f09b24f9f5fa0af2c29b604b4b0f97fa6163895 b/test/core/json/corpus/2f09b24f9f5fa0af2c29b604b4b0f97fa6163895
new file mode 100644
index 0000000..f7e8e7b
--- /dev/null
+++ b/test/core/json/corpus/2f09b24f9f5fa0af2c29b604b4b0f97fa6163895
@@ -0,0 +1 @@
+ 9Š
\ No newline at end of file
diff --git a/test/core/json/corpus/3027d901361162b38fcaf17f97ba7d9646e32495 b/test/core/json/corpus/3027d901361162b38fcaf17f97ba7d9646e32495
new file mode 100644
index 0000000..8372b41
--- /dev/null
+++ b/test/core/json/corpus/3027d901361162b38fcaf17f97ba7d9646e32495
Binary files differ
diff --git a/test/core/json/corpus/30d4467ecb771ece9ed6c78a46adc299072d9db9 b/test/core/json/corpus/30d4467ecb771ece9ed6c78a46adc299072d9db9
new file mode 100644
index 0000000..e396fba
--- /dev/null
+++ b/test/core/json/corpus/30d4467ecb771ece9ed6c78a46adc299072d9db9
@@ -0,0 +1 @@
+4.9!
\ No newline at end of file
diff --git a/test/core/json/corpus/311048bbf4c4bbabcde73607d7e76915cee9312e b/test/core/json/corpus/311048bbf4c4bbabcde73607d7e76915cee9312e
new file mode 100644
index 0000000..79453e9
--- /dev/null
+++ b/test/core/json/corpus/311048bbf4c4bbabcde73607d7e76915cee9312e
Binary files differ
diff --git a/test/core/json/corpus/323b48969d7bf9a50aacf0912f1b5cb02119e2ab b/test/core/json/corpus/323b48969d7bf9a50aacf0912f1b5cb02119e2ab
new file mode 100644
index 0000000..b558a9a
--- /dev/null
+++ b/test/core/json/corpus/323b48969d7bf9a50aacf0912f1b5cb02119e2ab
@@ -0,0 +1 @@
+"',!\u65E8850{2312;):ˆ)!Ã"*¾?'ʳ³!!*!à):!*à::)!9:\udbD86'
\ No newline at end of file
diff --git a/test/core/json/corpus/33400a242baeb5c46ddb1578c28b10d32a9c3cd3 b/test/core/json/corpus/33400a242baeb5c46ddb1578c28b10d32a9c3cd3
new file mode 100644
index 0000000..ffb93e3
--- /dev/null
+++ b/test/core/json/corpus/33400a242baeb5c46ddb1578c28b10d32a9c3cd3
@@ -0,0 +1 @@
+{"',!\ru65E8850{2312;):ˆ)!Ã"*¾{"',!u65E?'8Ê85
\ No newline at end of file
diff --git a/test/core/json/corpus/356a192b7913b04c54574d18c28d46e6395428ab b/test/core/json/corpus/356a192b7913b04c54574d18c28d46e6395428ab
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/test/core/json/corpus/356a192b7913b04c54574d18c28d46e6395428ab
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/test/core/json/corpus/35e995c107a71caeb833bb3b79f9f54781b33fa1 b/test/core/json/corpus/35e995c107a71caeb833bb3b79f9f54781b33fa1
new file mode 100644
index 0000000..e77a963
--- /dev/null
+++ b/test/core/json/corpus/35e995c107a71caeb833bb3b79f9f54781b33fa1
@@ -0,0 +1 @@
+73
\ No newline at end of file
diff --git a/test/core/json/corpus/373769c15c145472c8ec3bdde8fc84e85ec79211 b/test/core/json/corpus/373769c15c145472c8ec3bdde8fc84e85ec79211
new file mode 100644
index 0000000..7f34060
--- /dev/null
+++ b/test/core/json/corpus/373769c15c145472c8ec3bdde8fc84e85ec79211
Binary files differ
diff --git a/test/core/json/corpus/3795d911970a1fd8416b93649051b418948e3edf b/test/core/json/corpus/3795d911970a1fd8416b93649051b418948e3edf
new file mode 100644
index 0000000..1df36a5
--- /dev/null
+++ b/test/core/json/corpus/3795d911970a1fd8416b93649051b418948e3edf
@@ -0,0 +1 @@
+[[2.76;]3*
\ No newline at end of file
diff --git a/test/core/json/corpus/37d3333e1e2a384c3ba14a52682ca29f061d1ac7 b/test/core/json/corpus/37d3333e1e2a384c3ba14a52682ca29f061d1ac7
new file mode 100644
index 0000000..c37e132
--- /dev/null
+++ b/test/core/json/corpus/37d3333e1e2a384c3ba14a52682ca29f061d1ac7
@@ -0,0 +1 @@
+{"!(!\u'
\ No newline at end of file
diff --git a/test/core/json/corpus/38cd33bb390445e35b6514024b1317902cb7ba1b b/test/core/json/corpus/38cd33bb390445e35b6514024b1317902cb7ba1b
new file mode 100644
index 0000000..83312e5
--- /dev/null
+++ b/test/core/json/corpus/38cd33bb390445e35b6514024b1317902cb7ba1b
@@ -0,0 +1 @@
+"ˆÃ!{)!:",ˆÃ
\ No newline at end of file
diff --git a/test/core/json/corpus/3a90c688f44447a78efc111872b061a001f04d2b b/test/core/json/corpus/3a90c688f44447a78efc111872b061a001f04d2b
new file mode 100644
index 0000000..2b729e7
--- /dev/null
+++ b/test/core/json/corpus/3a90c688f44447a78efc111872b061a001f04d2b
@@ -0,0 +1 @@
+181e32560
\ No newline at end of file
diff --git a/test/core/json/corpus/3b1e7b56ad4465d126ea994d34d20dcecbb3a50a b/test/core/json/corpus/3b1e7b56ad4465d126ea994d34d20dcecbb3a50a
new file mode 100644
index 0000000..3029e04
--- /dev/null
+++ b/test/core/json/corpus/3b1e7b56ad4465d126ea994d34d20dcecbb3a50a
@@ -0,0 +1 @@
+5E882392);)
\ No newline at end of file
diff --git a/test/core/json/corpus/3c0a8d6c31edaca124714624eb64cb8ec0cbab13 b/test/core/json/corpus/3c0a8d6c31edaca124714624eb64cb8ec0cbab13
new file mode 100644
index 0000000..82db9e7
--- /dev/null
+++ b/test/core/json/corpus/3c0a8d6c31edaca124714624eb64cb8ec0cbab13
@@ -0,0 +1 @@
+{"*]:Ã!{)¾?'ʳ³!!*!à):!*à:::\udbD8ˆ)!{Ã:{!`!?`¾¾"(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/3cc0c9adcf3882f01409c70391c3cd30588ef34c b/test/core/json/corpus/3cc0c9adcf3882f01409c70391c3cd30588ef34c
new file mode 100644
index 0000000..7a63c8c
--- /dev/null
+++ b/test/core/json/corpus/3cc0c9adcf3882f01409c70391c3cd30588ef34c
@@ -0,0 +1 @@
+[{
\ No newline at end of file
diff --git a/test/core/json/corpus/3d0d9878b812ce4634962ba3dd755c0953550200 b/test/core/json/corpus/3d0d9878b812ce4634962ba3dd755c0953550200
new file mode 100644
index 0000000..8793f1e
--- /dev/null
+++ b/test/core/json/corpus/3d0d9878b812ce4634962ba3dd755c0953550200
@@ -0,0 +1 @@
+[tru[(0.193;]4*
\ No newline at end of file
diff --git a/test/core/json/corpus/3d4d5887a2fcdc5dd360b8a6f89dbce6500d8580 b/test/core/json/corpus/3d4d5887a2fcdc5dd360b8a6f89dbce6500d8580
new file mode 100644
index 0000000..c524697
--- /dev/null
+++ b/test/core/json/corpus/3d4d5887a2fcdc5dd360b8a6f89dbce6500d8580
@@ -0,0 +1 @@
+"'',!\u658E{128031:;):ˆ)!Ã5*¾?'ʳ³!!*!à):!*à::)!9:\udbD8 '
\ No newline at end of file
diff --git a/test/core/json/corpus/3efb5b7ff94c5b9d411c93da9a70e1cc547f4c59 b/test/core/json/corpus/3efb5b7ff94c5b9d411c93da9a70e1cc547f4c59
new file mode 100644
index 0000000..90a082d
--- /dev/null
+++ b/test/core/json/corpus/3efb5b7ff94c5b9d411c93da9a70e1cc547f4c59
@@ -0,0 +1 @@
+13e290560
\ No newline at end of file
diff --git a/test/core/json/corpus/421b7e8ea86e3c07474af16ab3ccef55d1857205 b/test/core/json/corpus/421b7e8ea86e3c07474af16ab3ccef55d1857205
new file mode 100644
index 0000000..1274714
--- /dev/null
+++ b/test/core/json/corpus/421b7e8ea86e3c07474af16ab3ccef55d1857205
@@ -0,0 +1,2 @@
+[2.1
+'{"ˆ"ÈÃ""
\ No newline at end of file
diff --git a/test/core/json/corpus/428d051e437dd260f2a2f7ed920d9734ca34dc90 b/test/core/json/corpus/428d051e437dd260f2a2f7ed920d9734ca34dc90
new file mode 100644
index 0000000..ad50d48
--- /dev/null
+++ b/test/core/json/corpus/428d051e437dd260f2a2f7ed920d9734ca34dc90
@@ -0,0 +1 @@
+[2.
\ No newline at end of file
diff --git a/test/core/json/corpus/42adc281578ffb1b8684b78b47aa40a16d10b6e7 b/test/core/json/corpus/42adc281578ffb1b8684b78b47aa40a16d10b6e7
new file mode 100644
index 0000000..59b1709
--- /dev/null
+++ b/test/core/json/corpus/42adc281578ffb1b8684b78b47aa40a16d10b6e7
@@ -0,0 +1 @@
+363,
\ No newline at end of file
diff --git a/test/core/json/corpus/43620ecd2e2fd58fe5650da2e9783f980f29ec07 b/test/core/json/corpus/43620ecd2e2fd58fe5650da2e9783f980f29ec07
new file mode 100644
index 0000000..f198034
--- /dev/null
+++ b/test/core/json/corpus/43620ecd2e2fd58fe5650da2e9783f980f29ec07
@@ -0,0 +1 @@
+13e109560
\ No newline at end of file
diff --git a/test/core/json/corpus/43b1ffcda49477adb1632822202631990ed3a269 b/test/core/json/corpus/43b1ffcda49477adb1632822202631990ed3a269
new file mode 100644
index 0000000..19db1d4
--- /dev/null
+++ b/test/core/json/corpus/43b1ffcda49477adb1632822202631990ed3a269
@@ -0,0 +1 @@
+1e+2,1ˆÃ"x
\ No newline at end of file
diff --git a/test/core/json/corpus/45279f85bf2f533a629073caf89403006279fab2 b/test/core/json/corpus/45279f85bf2f533a629073caf89403006279fab2
new file mode 100644
index 0000000..e6d3d7c
--- /dev/null
+++ b/test/core/json/corpus/45279f85bf2f533a629073caf89403006279fab2
@@ -0,0 +1,2 @@
+{
+620
\ No newline at end of file
diff --git a/test/core/json/corpus/455d9bb597f08bf698454157ecd86647b5dec4e0 b/test/core/json/corpus/455d9bb597f08bf698454157ecd86647b5dec4e0
new file mode 100644
index 0000000..0a601eb
--- /dev/null
+++ b/test/core/json/corpus/455d9bb597f08bf698454157ecd86647b5dec4e0
@@ -0,0 +1 @@
+0.3282
\ No newline at end of file
diff --git a/test/core/json/corpus/4561eb5c7e43cae048c06aaaad3d5f5218b376e9 b/test/core/json/corpus/4561eb5c7e43cae048c06aaaad3d5f5218b376e9
new file mode 100644
index 0000000..1fdd026
--- /dev/null
+++ b/test/core/json/corpus/4561eb5c7e43cae048c06aaaad3d5f5218b376e9
@@ -0,0 +1 @@
+fal0%)
\ No newline at end of file
diff --git a/test/core/json/corpus/46417b001eeb87c32b642499fd5e1690d5d88c7f b/test/core/json/corpus/46417b001eeb87c32b642499fd5e1690d5d88c7f
new file mode 100644
index 0000000..f084840
--- /dev/null
+++ b/test/core/json/corpus/46417b001eeb87c32b642499fd5e1690d5d88c7f
@@ -0,0 +1 @@
+825E}321)
\ No newline at end of file
diff --git a/test/core/json/corpus/468af040024e96e9878ef33cc52755c5e7f5cbd5 b/test/core/json/corpus/468af040024e96e9878ef33cc52755c5e7f5cbd5
new file mode 100644
index 0000000..c9ff1a1
--- /dev/null
+++ b/test/core/json/corpus/468af040024e96e9878ef33cc52755c5e7f5cbd5
@@ -0,0 +1 @@
+0.72479834e;0.Ü3ï993)
\ No newline at end of file
diff --git a/test/core/json/corpus/469e5ed2547e9e55a96e96eb832c615631e3b576 b/test/core/json/corpus/469e5ed2547e9e55a96e96eb832c615631e3b576
new file mode 100644
index 0000000..97e7caf
--- /dev/null
+++ b/test/core/json/corpus/469e5ed2547e9e55a96e96eb832c615631e3b576
@@ -0,0 +1 @@
+[])Ã!:{"*¾?'ʳ³!!*!à):!*à:::\udbD8ˆ){Ã!:{!`!?`¾¾"(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/472b07b9fcf2c2451e8781e944bf5f77cd8457c8 b/test/core/json/corpus/472b07b9fcf2c2451e8781e944bf5f77cd8457c8
new file mode 100644
index 0000000..b5045cc
--- /dev/null
+++ b/test/core/json/corpus/472b07b9fcf2c2451e8781e944bf5f77cd8457c8
@@ -0,0 +1 @@
+21
\ No newline at end of file
diff --git a/test/core/json/corpus/486da8aff04083c5e0fe112e733f2ae510e312a1 b/test/core/json/corpus/486da8aff04083c5e0fe112e733f2ae510e312a1
new file mode 100644
index 0000000..0afcc5f
--- /dev/null
+++ b/test/core/json/corpus/486da8aff04083c5e0fe112e733f2ae510e312a1
@@ -0,0 +1 @@
+tru¹82 'A\E60;)
\ No newline at end of file
diff --git a/test/core/json/corpus/488a5ed641e340ae51992e04ce6590bdec587218 b/test/core/json/corpus/488a5ed641e340ae51992e04ce6590bdec587218
new file mode 100644
index 0000000..f0b671b
--- /dev/null
+++ b/test/core/json/corpus/488a5ed641e340ae51992e04ce6590bdec587218
@@ -0,0 +1 @@
+0.1)¹
\ No newline at end of file
diff --git a/test/core/json/corpus/4a0a19218e082a343a1b17e5333409af9d98f0f5 b/test/core/json/corpus/4a0a19218e082a343a1b17e5333409af9d98f0f5
new file mode 100644
index 0000000..4d1ae35
--- /dev/null
+++ b/test/core/json/corpus/4a0a19218e082a343a1b17e5333409af9d98f0f5
@@ -0,0 +1 @@
+f
\ No newline at end of file
diff --git a/test/core/json/corpus/4a6644a1a3d5218f4bbd60220cab79c0b7bef45e b/test/core/json/corpus/4a6644a1a3d5218f4bbd60220cab79c0b7bef45e
new file mode 100644
index 0000000..90b4ca3
--- /dev/null
+++ b/test/core/json/corpus/4a6644a1a3d5218f4bbd60220cab79c0b7bef45e
@@ -0,0 +1 @@
+[21.82
\ No newline at end of file
diff --git a/test/core/json/corpus/4b39d4b8a9a04b9469e8fe4016322327fe540882 b/test/core/json/corpus/4b39d4b8a9a04b9469e8fe4016322327fe540882
new file mode 100644
index 0000000..a7c1d08
--- /dev/null
+++ b/test/core/json/corpus/4b39d4b8a9a04b9469e8fe4016322327fe540882
@@ -0,0 +1 @@
+3E8;4)
\ No newline at end of file
diff --git a/test/core/json/corpus/4bb0294e14946fb1f64213384097a676d3ef94f0 b/test/core/json/corpus/4bb0294e14946fb1f64213384097a676d3ef94f0
new file mode 100644
index 0000000..56e2dbc
--- /dev/null
+++ b/test/core/json/corpus/4bb0294e14946fb1f64213384097a676d3ef94f0
@@ -0,0 +1 @@
+363	
diff --git a/test/core/json/corpus/4cd66dfabbd964f8c6c4414b07cdb45dae692e19 b/test/core/json/corpus/4cd66dfabbd964f8c6c4414b07cdb45dae692e19
new file mode 100644
index 0000000..a46c9d2
--- /dev/null
+++ b/test/core/json/corpus/4cd66dfabbd964f8c6c4414b07cdb45dae692e19
@@ -0,0 +1 @@
+91
\ No newline at end of file
diff --git a/test/core/json/corpus/4d134bc072212ace2df385dae143139da74ec0ef b/test/core/json/corpus/4d134bc072212ace2df385dae143139da74ec0ef
new file mode 100644
index 0000000..cabf43b
--- /dev/null
+++ b/test/core/json/corpus/4d134bc072212ace2df385dae143139da74ec0ef
@@ -0,0 +1 @@
+24
\ No newline at end of file
diff --git a/test/core/json/corpus/4efa35221b2088e785048d0ff8fd99b03d5316fc b/test/core/json/corpus/4efa35221b2088e785048d0ff8fd99b03d5316fc
new file mode 100644
index 0000000..ecf2233
--- /dev/null
+++ b/test/core/json/corpus/4efa35221b2088e785048d0ff8fd99b03d5316fc
@@ -0,0 +1 @@
+0.)
\ No newline at end of file
diff --git a/test/core/json/corpus/4fa2a4a5a2f7dc4ddbdecae3ee85c787817b4cf8 b/test/core/json/corpus/4fa2a4a5a2f7dc4ddbdecae3ee85c787817b4cf8
new file mode 100644
index 0000000..17ef43e
--- /dev/null
+++ b/test/core/json/corpus/4fa2a4a5a2f7dc4ddbdecae3ee85c787817b4cf8
@@ -0,0 +1 @@
+813e128560
\ No newline at end of file
diff --git a/test/core/json/corpus/4fed4bf2dc6259d9de54e9fa7db4fd5a61f2535e b/test/core/json/corpus/4fed4bf2dc6259d9de54e9fa7db4fd5a61f2535e
new file mode 100644
index 0000000..e9cb940
--- /dev/null
+++ b/test/core/json/corpus/4fed4bf2dc6259d9de54e9fa7db4fd5a61f2535e
@@ -0,0 +1 @@
+2531E117t)*6
\ No newline at end of file
diff --git a/test/core/json/corpus/4ff800de0863adb5851fa26935159aa53b11cba7 b/test/core/json/corpus/4ff800de0863adb5851fa26935159aa53b11cba7
new file mode 100644
index 0000000..edd3d2b
--- /dev/null
+++ b/test/core/json/corpus/4ff800de0863adb5851fa26935159aa53b11cba7
@@ -0,0 +1 @@
+0.82510
\ No newline at end of file
diff --git a/test/core/json/corpus/4ff99a030518a132748c44bc1d836018e5b82cd0 b/test/core/json/corpus/4ff99a030518a132748c44bc1d836018e5b82cd0
new file mode 100644
index 0000000..bc59462
--- /dev/null
+++ b/test/core/json/corpus/4ff99a030518a132748c44bc1d836018e5b82cd0
@@ -0,0 +1 @@
+{"*]:Ã!{)¾?'Ê)“ :*!à):!*à:::\udb81\uDeA12])!{Ã:{!`!?
\ No newline at end of file
diff --git a/test/core/json/corpus/531c87b9772e54e3e183ef729f0a7d5a0d584f46 b/test/core/json/corpus/531c87b9772e54e3e183ef729f0a7d5a0d584f46
new file mode 100644
index 0000000..08f1be3
--- /dev/null
+++ b/test/core/json/corpus/531c87b9772e54e3e183ef729f0a7d5a0d584f46
@@ -0,0 +1 @@
+{"',!\u65E8850{2312;):ˆ)!*?'¾Ê³³!!ª!à):!*à::8!9:\udbD86'
\ No newline at end of file
diff --git a/test/core/json/corpus/534d66e7b0709d1e7692faae9e7f7299c92bba4b b/test/core/json/corpus/534d66e7b0709d1e7692faae9e7f7299c92bba4b
new file mode 100644
index 0000000..44b3fa0
--- /dev/null
+++ b/test/core/json/corpus/534d66e7b0709d1e7692faae9e7f7299c92bba4b
@@ -0,0 +1 @@
+[[2.193]4*
\ No newline at end of file
diff --git a/test/core/json/corpus/548775f9d7d13339dba3001f8238b84e9a457533 b/test/core/json/corpus/548775f9d7d13339dba3001f8238b84e9a457533
new file mode 100644
index 0000000..9fed6d1
--- /dev/null
+++ b/test/core/json/corpus/548775f9d7d13339dba3001f8238b84e9a457533
@@ -0,0 +1 @@
+[1.97;
\ No newline at end of file
diff --git a/test/core/json/corpus/54ec3b2d8a9b7a6d8204712eb1b90da703cf8a79 b/test/core/json/corpus/54ec3b2d8a9b7a6d8204712eb1b90da703cf8a79
new file mode 100644
index 0000000..25984e7
--- /dev/null
+++ b/test/core/json/corpus/54ec3b2d8a9b7a6d8204712eb1b90da703cf8a79
@@ -0,0 +1 @@
+"ˆÃ{)!:*¾;?Xʳ³!!*!à):!*à:::\udÃb)ˆ8!‡:{!`!*`¾¾!?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/552cfe1d8958e6d003ec8e883c4983dd67ef255e b/test/core/json/corpus/552cfe1d8958e6d003ec8e883c4983dd67ef255e
new file mode 100644
index 0000000..1b18370
--- /dev/null
+++ b/test/core/json/corpus/552cfe1d8958e6d003ec8e883c4983dd67ef255e
@@ -0,0 +1 @@
+nu#
\ No newline at end of file
diff --git a/test/core/json/corpus/55f0c61d096a08506076489ded3b868db4086770 b/test/core/json/corpus/55f0c61d096a08506076489ded3b868db4086770
new file mode 100644
index 0000000..d65b537
--- /dev/null
+++ b/test/core/json/corpus/55f0c61d096a08506076489ded3b868db4086770
@@ -0,0 +1 @@
+0.2]G)
\ No newline at end of file
diff --git a/test/core/json/corpus/56cd60743c2cee939f5f357905bd36ec9363f441 b/test/core/json/corpus/56cd60743c2cee939f5f357905bd36ec9363f441
new file mode 100644
index 0000000..8d53a05
--- /dev/null
+++ b/test/core/json/corpus/56cd60743c2cee939f5f357905bd36ec9363f441
@@ -0,0 +1 @@
+{"":21]
\ No newline at end of file
diff --git a/test/core/json/corpus/56e5f35e3d08b4e17e3558cacddf9e5ed13a0159 b/test/core/json/corpus/56e5f35e3d08b4e17e3558cacddf9e5ed13a0159
new file mode 100644
index 0000000..1960fad
--- /dev/null
+++ b/test/core/json/corpus/56e5f35e3d08b4e17e3558cacddf9e5ed13a0159
@@ -0,0 +1 @@
+[[[{"ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\u12198.y2db)8ˆÃ!3;!ȇ:!`!.7;?
\ No newline at end of file
diff --git a/test/core/json/corpus/580b03c49fba02bb8e399500eb66f2ff0482b22a b/test/core/json/corpus/580b03c49fba02bb8e399500eb66f2ff0482b22a
new file mode 100644
index 0000000..5c23e62
--- /dev/null
+++ b/test/core/json/corpus/580b03c49fba02bb8e399500eb66f2ff0482b22a
@@ -0,0 +1 @@
+2]G)y3
\ No newline at end of file
diff --git a/test/core/json/corpus/5852643fbbcf92b0181327b69b4874c6ba6fa9f4 b/test/core/json/corpus/5852643fbbcf92b0181327b69b4874c6ba6fa9f4
new file mode 100644
index 0000000..d72c7c7
--- /dev/null
+++ b/test/core/json/corpus/5852643fbbcf92b0181327b69b4874c6ba6fa9f4
@@ -0,0 +1 @@
+{"'!\u3@:Š
\ No newline at end of file
diff --git a/test/core/json/corpus/58f497e5efaf9f69080f9eef63b0b9dabcfdbc0d b/test/core/json/corpus/58f497e5efaf9f69080f9eef63b0b9dabcfdbc0d
new file mode 100644
index 0000000..3ed722a
--- /dev/null
+++ b/test/core/json/corpus/58f497e5efaf9f69080f9eef63b0b9dabcfdbc0d
Binary files differ
diff --git a/test/core/json/corpus/59129aacfb6cebbe2c52f30ef3424209f7252e82 b/test/core/json/corpus/59129aacfb6cebbe2c52f30ef3424209f7252e82
new file mode 100644
index 0000000..d1cbcfa
--- /dev/null
+++ b/test/core/json/corpus/59129aacfb6cebbe2c52f30ef3424209f7252e82
@@ -0,0 +1 @@
+66
\ No newline at end of file
diff --git a/test/core/json/corpus/598a287a3e56caae23ed63abc95d5f3457165eef b/test/core/json/corpus/598a287a3e56caae23ed63abc95d5f3457165eef
new file mode 100644
index 0000000..7d3db88
--- /dev/null
+++ b/test/core/json/corpus/598a287a3e56caae23ed63abc95d5f3457165eef
@@ -0,0 +1 @@
+81e6125380
\ No newline at end of file
diff --git a/test/core/json/corpus/5a37a26dd2482226f534f79d321d28e7a615ab72 b/test/core/json/corpus/5a37a26dd2482226f534f79d321d28e7a615ab72
new file mode 100644
index 0000000..c9b11ff
--- /dev/null
+++ b/test/core/json/corpus/5a37a26dd2482226f534f79d321d28e7a615ab72
@@ -0,0 +1 @@
+[0.959] 
\ No newline at end of file
diff --git a/test/core/json/corpus/5a710dcd4c78ca1a74ceb9fbfb011f7ac86a5f7b b/test/core/json/corpus/5a710dcd4c78ca1a74ceb9fbfb011f7ac86a5f7b
new file mode 100644
index 0000000..a1cd2e7
--- /dev/null
+++ b/test/core/json/corpus/5a710dcd4c78ca1a74ceb9fbfb011f7ac86a5f7b
@@ -0,0 +1 @@
+[[{}G3
\ No newline at end of file
diff --git a/test/core/json/corpus/5ae7b87f5377d5ffc16fd3f69b4a4aa7be8b1184 b/test/core/json/corpus/5ae7b87f5377d5ffc16fd3f69b4a4aa7be8b1184
new file mode 100644
index 0000000..a1c1118
--- /dev/null
+++ b/test/core/json/corpus/5ae7b87f5377d5ffc16fd3f69b4a4aa7be8b1184
@@ -0,0 +1,2 @@
+{
+"ˆ"ÈÃ""
\ No newline at end of file
diff --git a/test/core/json/corpus/5b3fe86d5a309a6ba745881bd220fe1100b271ce b/test/core/json/corpus/5b3fe86d5a309a6ba745881bd220fe1100b271ce
new file mode 100644
index 0000000..bd45ebf
--- /dev/null
+++ b/test/core/json/corpus/5b3fe86d5a309a6ba745881bd220fe1100b271ce
@@ -0,0 +1 @@
+true82 'ANE2(0;)
\ No newline at end of file
diff --git a/test/core/json/corpus/5c38b7da113ab4535dbc22777ce8a1480c1c9d1e b/test/core/json/corpus/5c38b7da113ab4535dbc22777ce8a1480c1c9d1e
new file mode 100644
index 0000000..a135742
--- /dev/null
+++ b/test/core/json/corpus/5c38b7da113ab4535dbc22777ce8a1480c1c9d1e
@@ -0,0 +1 @@
+{"'!'\u3B:Š
\ No newline at end of file
diff --git a/test/core/json/corpus/5ca6c45a8d2e11c782806df43e7668beb4aba8f5 b/test/core/json/corpus/5ca6c45a8d2e11c782806df43e7668beb4aba8f5
new file mode 100644
index 0000000..ef736fd
--- /dev/null
+++ b/test/core/json/corpus/5ca6c45a8d2e11c782806df43e7668beb4aba8f5
@@ -0,0 +1 @@
+nul
\ No newline at end of file
diff --git a/test/core/json/corpus/5da7b543313339f84fd52e96bacf3a73368a1d2c b/test/core/json/corpus/5da7b543313339f84fd52e96bacf3a73368a1d2c
new file mode 100644
index 0000000..0e44b3e
--- /dev/null
+++ b/test/core/json/corpus/5da7b543313339f84fd52e96bacf3a73368a1d2c
@@ -0,0 +1 @@
+])Ã!:{"*¾?'ʳ³!!*!à):!*à:::\udbD8ˆ)Ã!:{!`!?`¾¾!?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/5e12ae9117668bcc22832640cc626315940aeba8 b/test/core/json/corpus/5e12ae9117668bcc22832640cc626315940aeba8
new file mode 100644
index 0000000..c182018
--- /dev/null
+++ b/test/core/json/corpus/5e12ae9117668bcc22832640cc626315940aeba8
Binary files differ
diff --git a/test/core/json/corpus/5e397439a2680ed827c46704969c6711dabbda84 b/test/core/json/corpus/5e397439a2680ed827c46704969c6711dabbda84
new file mode 100644
index 0000000..3be1f86
--- /dev/null
+++ b/test/core/json/corpus/5e397439a2680ed827c46704969c6711dabbda84
@@ -0,0 +1 @@
+"!!\\''
\ No newline at end of file
diff --git a/test/core/json/corpus/5e629dfb8b7533c7c2d173d4c3d587c88112cc29 b/test/core/json/corpus/5e629dfb8b7533c7c2d173d4c3d587c88112cc29
new file mode 100644
index 0000000..08b9840
--- /dev/null
+++ b/test/core/json/corpus/5e629dfb8b7533c7c2d173d4c3d587c88112cc29
@@ -0,0 +1 @@
+1e2188560
\ No newline at end of file
diff --git a/test/core/json/corpus/5e785c7c26813577f3e30ef8f7e37ab2a9ffe39c b/test/core/json/corpus/5e785c7c26813577f3e30ef8f7e37ab2a9ffe39c
new file mode 100644
index 0000000..134ad52
--- /dev/null
+++ b/test/core/json/corpus/5e785c7c26813577f3e30ef8f7e37ab2a9ffe39c
@@ -0,0 +1 @@
+{"":0,}f'+G{)13(§!(''\!
\ No newline at end of file
diff --git a/test/core/json/corpus/5f3394f5058822cc044b92654837625897176480 b/test/core/json/corpus/5f3394f5058822cc044b92654837625897176480
new file mode 100644
index 0000000..fb460ce
--- /dev/null
+++ b/test/core/json/corpus/5f3394f5058822cc044b92654837625897176480
@@ -0,0 +1 @@
+813e1622427913e1099560
\ No newline at end of file
diff --git a/test/core/json/corpus/5fb9bcbbb30a377209eab0541d144e44e71508d7 b/test/core/json/corpus/5fb9bcbbb30a377209eab0541d144e44e71508d7
new file mode 100644
index 0000000..a83c813
--- /dev/null
+++ b/test/core/json/corpus/5fb9bcbbb30a377209eab0541d144e44e71508d7
@@ -0,0 +1 @@
+,0)
\ No newline at end of file
diff --git a/test/core/json/corpus/6008213a61d06b4382b223768530c3452968b7b3 b/test/core/json/corpus/6008213a61d06b4382b223768530c3452968b7b3
new file mode 100644
index 0000000..46f8135
--- /dev/null
+++ b/test/core/json/corpus/6008213a61d06b4382b223768530c3452968b7b3
@@ -0,0 +1 @@
+{"',!u65E8850{2312;):ˆ)!*?'¾Ê³³!ª!à):!*Àà::4!9:\udD86'
\ No newline at end of file
diff --git a/test/core/json/corpus/60ba4b2daa4ed4d070fec06687e249e0e6f9ee45 b/test/core/json/corpus/60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
new file mode 100644
index 0000000..81750b9
--- /dev/null
+++ b/test/core/json/corpus/60ba4b2daa4ed4d070fec06687e249e0e6f9ee45
@@ -0,0 +1 @@
+{
\ No newline at end of file
diff --git a/test/core/json/corpus/625ed64c30c8ab2f0b3bc75690f9faa4270f0041 b/test/core/json/corpus/625ed64c30c8ab2f0b3bc75690f9faa4270f0041
new file mode 100644
index 0000000..a9322d4
--- /dev/null
+++ b/test/core/json/corpus/625ed64c30c8ab2f0b3bc75690f9faa4270f0041
@@ -0,0 +1 @@
+"ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à::d\b:8))ˆÃ![1.‡97:{
\ No newline at end of file
diff --git a/test/core/json/corpus/6314c2b304d04dc0108a95d29a93515e85e2b0b0 b/test/core/json/corpus/6314c2b304d04dc0108a95d29a93515e85e2b0b0
new file mode 100644
index 0000000..5981d9b
--- /dev/null
+++ b/test/core/json/corpus/6314c2b304d04dc0108a95d29a93515e85e2b0b0
@@ -0,0 +1 @@
+{"*]:Ã!{)¾?'ʳ³ :*!à):!*à:::\udbD8\u)!{Ã:{!`!?`¾¾")(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/6462d8079d2ea921617e7d073b85cfab706800d3 b/test/core/json/corpus/6462d8079d2ea921617e7d073b85cfab706800d3
new file mode 100644
index 0000000..8ecd203
--- /dev/null
+++ b/test/core/json/corpus/6462d8079d2ea921617e7d073b85cfab706800d3
@@ -0,0 +1 @@
+null³
\ No newline at end of file
diff --git a/test/core/json/corpus/6474383282788e556aa86f57fc8650137ad264d0 b/test/core/json/corpus/6474383282788e556aa86f57fc8650137ad264d0
new file mode 100644
index 0000000..9210f64
--- /dev/null
+++ b/test/core/json/corpus/6474383282788e556aa86f57fc8650137ad264d0
@@ -0,0 +1 @@
+{"!!\/!!\'''
\ No newline at end of file
diff --git a/test/core/json/corpus/648c3f58ecc8fb4b8c779e6b11006ab5b1986dad b/test/core/json/corpus/648c3f58ecc8fb4b8c779e6b11006ab5b1986dad
new file mode 100644
index 0000000..dc9a929
--- /dev/null
+++ b/test/core/json/corpus/648c3f58ecc8fb4b8c779e6b11006ab5b1986dad
@@ -0,0 +1 @@
+21.498"
\ No newline at end of file
diff --git a/test/core/json/corpus/66328e03a2ccd5e54dab23b816182786e6f518b6 b/test/core/json/corpus/66328e03a2ccd5e54dab23b816182786e6f518b6
new file mode 100644
index 0000000..0d7016b
--- /dev/null
+++ b/test/core/json/corpus/66328e03a2ccd5e54dab23b816182786e6f518b6
@@ -0,0 +1 @@
+[{"ˆÃ\t5{)!:*
\ No newline at end of file
diff --git a/test/core/json/corpus/683e9045bc95e0cb5fc16ec64b118433475ba559 b/test/core/json/corpus/683e9045bc95e0cb5fc16ec64b118433475ba559
new file mode 100644
index 0000000..ab9ecdf
--- /dev/null
+++ b/test/core/json/corpus/683e9045bc95e0cb5fc16ec64b118433475ba559
Binary files differ
diff --git a/test/core/json/corpus/689f13680f4682303c8aa6828b67955959dc9669 b/test/core/json/corpus/689f13680f4682303c8aa6828b67955959dc9669
new file mode 100644
index 0000000..e49c890
--- /dev/null
+++ b/test/core/json/corpus/689f13680f4682303c8aa6828b67955959dc9669
@@ -0,0 +1 @@
+["*]:Ã!{)¾?'ʳ³!!*!à):!*à:::\udcD8ˆ){Ã!:{!`!?`¾¾"(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/68c6ba7f0602a5410d1fa3c5de24fe264436b993 b/test/core/json/corpus/68c6ba7f0602a5410d1fa3c5de24fe264436b993
new file mode 100644
index 0000000..05c556c
--- /dev/null
+++ b/test/core/json/corpus/68c6ba7f0602a5410d1fa3c5de24fe264436b993
@@ -0,0 +1 @@
+{},[
\ No newline at end of file
diff --git a/test/core/json/corpus/699cafde80b1e1777306f781186d1253f018ab23 b/test/core/json/corpus/699cafde80b1e1777306f781186d1253f018ab23
new file mode 100644
index 0000000..54a4e1e
--- /dev/null
+++ b/test/core/json/corpus/699cafde80b1e1777306f781186d1253f018ab23
@@ -0,0 +1 @@
+[2}5{
\ No newline at end of file
diff --git a/test/core/json/corpus/69ab053b59e235fd6af246c5180f15bd95295113 b/test/core/json/corpus/69ab053b59e235fd6af246c5180f15bd95295113
new file mode 100644
index 0000000..dc0f5a0
--- /dev/null
+++ b/test/core/json/corpus/69ab053b59e235fd6af246c5180f15bd95295113
Binary files differ
diff --git a/test/core/json/corpus/69afa12510b2e653b0af7c7030832647b2d63c37 b/test/core/json/corpus/69afa12510b2e653b0af7c7030832647b2d63c37
new file mode 100644
index 0000000..5cd5103
--- /dev/null
+++ b/test/core/json/corpus/69afa12510b2e653b0af7c7030832647b2d63c37
@@ -0,0 +1 @@
+"ˆÃ,"
\ No newline at end of file
diff --git a/test/core/json/corpus/6b75857f86be5c51b21a97f4a61e69e8bb6cd698 b/test/core/json/corpus/6b75857f86be5c51b21a97f4a61e69e8bb6cd698
new file mode 100644
index 0000000..890abf2
--- /dev/null
+++ b/test/core/json/corpus/6b75857f86be5c51b21a97f4a61e69e8bb6cd698
@@ -0,0 +1 @@
+310560
\ No newline at end of file
diff --git a/test/core/json/corpus/6c75e71ecde9f073a7bad89f4831c8cde0bc1830 b/test/core/json/corpus/6c75e71ecde9f073a7bad89f4831c8cde0bc1830
new file mode 100644
index 0000000..84d8fa5
--- /dev/null
+++ b/test/core/json/corpus/6c75e71ecde9f073a7bad89f4831c8cde0bc1830
@@ -0,0 +1 @@
+9	3'Á6
\ No newline at end of file
diff --git a/test/core/json/corpus/6ce5170dc4f2eee3b31a875b6a41f2444959f3dd b/test/core/json/corpus/6ce5170dc4f2eee3b31a875b6a41f2444959f3dd
new file mode 100644
index 0000000..c91aab3
--- /dev/null
+++ b/test/core/json/corpus/6ce5170dc4f2eee3b31a875b6a41f2444959f3dd
@@ -0,0 +1 @@
+0}54
\ No newline at end of file
diff --git a/test/core/json/corpus/6d2859436fbbee637f0a5981ca82e8f88a1d0d28 b/test/core/json/corpus/6d2859436fbbee637f0a5981ca82e8f88a1d0d28
new file mode 100644
index 0000000..12d7c03
--- /dev/null
+++ b/test/core/json/corpus/6d2859436fbbee637f0a5981ca82e8f88a1d0d28
@@ -0,0 +1 @@
+[tr[[0.193;]4*
\ No newline at end of file
diff --git a/test/core/json/corpus/6d63e39f56d1d537bab9c2830303cabab3cd9035 b/test/core/json/corpus/6d63e39f56d1d537bab9c2830303cabab3cd9035
new file mode 100644
index 0000000..6b51382
--- /dev/null
+++ b/test/core/json/corpus/6d63e39f56d1d537bab9c2830303cabab3cd9035
@@ -0,0 +1 @@
+{"":}+G{12§(!(''\!
\ No newline at end of file
diff --git a/test/core/json/corpus/6e05a0a240fe2974e14527bbe390d294564156e2 b/test/core/json/corpus/6e05a0a240fe2974e14527bbe390d294564156e2
new file mode 100644
index 0000000..82236fc
--- /dev/null
+++ b/test/core/json/corpus/6e05a0a240fe2974e14527bbe390d294564156e2
@@ -0,0 +1 @@
+[2.1981
\ No newline at end of file
diff --git a/test/core/json/corpus/6e6c9d301adb0f0ddffd79cdf3426a2de99bad48 b/test/core/json/corpus/6e6c9d301adb0f0ddffd79cdf3426a2de99bad48
new file mode 100644
index 0000000..363c669
--- /dev/null
+++ b/test/core/json/corpus/6e6c9d301adb0f0ddffd79cdf3426a2de99bad48
@@ -0,0 +1,2 @@
+{
+"ˆÃ"
\ No newline at end of file
diff --git a/test/core/json/corpus/6e989edf725ec64849377681ce02641c3d1870e8 b/test/core/json/corpus/6e989edf725ec64849377681ce02641c3d1870e8
new file mode 100644
index 0000000..45cb64d
--- /dev/null
+++ b/test/core/json/corpus/6e989edf725ec64849377681ce02641c3d1870e8
@@ -0,0 +1 @@
+2}G)y3
\ No newline at end of file
diff --git a/test/core/json/corpus/70142f66475ae2fb33722d8d4750f386ecfefe7b b/test/core/json/corpus/70142f66475ae2fb33722d8d4750f386ecfefe7b
new file mode 100644
index 0000000..415b19f
--- /dev/null
+++ b/test/core/json/corpus/70142f66475ae2fb33722d8d4750f386ecfefe7b
@@ -0,0 +1 @@
+2.0
\ No newline at end of file
diff --git a/test/core/json/corpus/719edbe667ce2729ac78a22dac29263c91144029 b/test/core/json/corpus/719edbe667ce2729ac78a22dac29263c91144029
new file mode 100644
index 0000000..fccbca3
--- /dev/null
+++ b/test/core/json/corpus/719edbe667ce2729ac78a22dac29263c91144029
Binary files differ
diff --git a/test/core/json/corpus/71f99ca2bda6ef2e15b965479a79587f9d794be0 b/test/core/json/corpus/71f99ca2bda6ef2e15b965479a79587f9d794be0
new file mode 100644
index 0000000..bad49bb
--- /dev/null
+++ b/test/core/json/corpus/71f99ca2bda6ef2e15b965479a79587f9d794be0
@@ -0,0 +1 @@
+834E;)
\ No newline at end of file
diff --git a/test/core/json/corpus/743e89b768af4bd591ea7228118550b1bfb8e7d1 b/test/core/json/corpus/743e89b768af4bd591ea7228118550b1bfb8e7d1
new file mode 100644
index 0000000..b232065
--- /dev/null
+++ b/test/core/json/corpus/743e89b768af4bd591ea7228118550b1bfb8e7d1
@@ -0,0 +1 @@
+{"":0}f'+G{)13(§!(''\!
\ No newline at end of file
diff --git a/test/core/json/corpus/7714a1a32872442a2eaff472685f3ea69451a732 b/test/core/json/corpus/7714a1a32872442a2eaff472685f3ea69451a732
new file mode 100644
index 0000000..03a8147
--- /dev/null
+++ b/test/core/json/corpus/7714a1a32872442a2eaff472685f3ea69451a732
@@ -0,0 +1 @@
+8324E685;)
\ No newline at end of file
diff --git a/test/core/json/corpus/7719a1c782a1ba91c031a682a0a2f8658209adbf b/test/core/json/corpus/7719a1c782a1ba91c031a682a0a2f8658209adbf
new file mode 100644
index 0000000..d99e90e
--- /dev/null
+++ b/test/core/json/corpus/7719a1c782a1ba91c031a682a0a2f8658209adbf
@@ -0,0 +1 @@
+29
\ No newline at end of file
diff --git a/test/core/json/corpus/775e8ffda1f5d340dba472d06dc7c8bf8159e379 b/test/core/json/corpus/775e8ffda1f5d340dba472d06dc7c8bf8159e379
new file mode 100644
index 0000000..6f56d40
--- /dev/null
+++ b/test/core/json/corpus/775e8ffda1f5d340dba472d06dc7c8bf8159e379
@@ -0,0 +1 @@
+{"":0},f'+G{)23(§!''!
\ No newline at end of file
diff --git a/test/core/json/corpus/77de68daecd823babbb58edb1c8e14d7106e83bb b/test/core/json/corpus/77de68daecd823babbb58edb1c8e14d7106e83bb
new file mode 100644
index 0000000..e440e5c
--- /dev/null
+++ b/test/core/json/corpus/77de68daecd823babbb58edb1c8e14d7106e83bb
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/test/core/json/corpus/7957dc9aac31e6a6783fb3a6ee073688fed6cf9d b/test/core/json/corpus/7957dc9aac31e6a6783fb3a6ee073688fed6cf9d
new file mode 100644
index 0000000..27410a6
--- /dev/null
+++ b/test/core/json/corpus/7957dc9aac31e6a6783fb3a6ee073688fed6cf9d
@@ -0,0 +1 @@
+fal[2.1982
\ No newline at end of file
diff --git a/test/core/json/corpus/7ae893cbbf9b11ff411640b80985ce618907559c b/test/core/json/corpus/7ae893cbbf9b11ff411640b80985ce618907559c
new file mode 100644
index 0000000..2306064
--- /dev/null
+++ b/test/core/json/corpus/7ae893cbbf9b11ff411640b80985ce618907559c
@@ -0,0 +1 @@
+[0.29]95 
\ No newline at end of file
diff --git a/test/core/json/corpus/7b20ac50954063e3ad00813acab4a98b2bfdb858 b/test/core/json/corpus/7b20ac50954063e3ad00813acab4a98b2bfdb858
new file mode 100644
index 0000000..0bfbc04
--- /dev/null
+++ b/test/core/json/corpus/7b20ac50954063e3ad00813acab4a98b2bfdb858
@@ -0,0 +1 @@
+[2.198
\ No newline at end of file
diff --git a/test/core/json/corpus/7b6273145fb090de1c6163586f884a1da4b5cfbf b/test/core/json/corpus/7b6273145fb090de1c6163586f884a1da4b5cfbf
new file mode 100644
index 0000000..7e75a57
--- /dev/null
+++ b/test/core/json/corpus/7b6273145fb090de1c6163586f884a1da4b5cfbf
Binary files differ
diff --git a/test/core/json/corpus/7cf84b5a78281e6c6b5a9884110f3dbc6a40e310 b/test/core/json/corpus/7cf84b5a78281e6c6b5a9884110f3dbc6a40e310
new file mode 100644
index 0000000..6409a85
--- /dev/null
+++ b/test/core/json/corpus/7cf84b5a78281e6c6b5a9884110f3dbc6a40e310
@@ -0,0 +1,2 @@
+{
+"ˆ[2":}5ˆÃ["}5""{
\ No newline at end of file
diff --git a/test/core/json/corpus/7ef13b83e6bde582d9000be043e729cd3221c150 b/test/core/json/corpus/7ef13b83e6bde582d9000be043e729cd3221c150
new file mode 100644
index 0000000..bb69053
--- /dev/null
+++ b/test/core/json/corpus/7ef13b83e6bde582d9000be043e729cd3221c150
@@ -0,0 +1 @@
+{"" \!'(\'!
\ No newline at end of file
diff --git a/test/core/json/corpus/82059e250904b478f65daa0e647c1647ba6d6a3d b/test/core/json/corpus/82059e250904b478f65daa0e647c1647ba6d6a3d
new file mode 100644
index 0000000..7912fa5
--- /dev/null
+++ b/test/core/json/corpus/82059e250904b478f65daa0e647c1647ba6d6a3d
@@ -0,0 +1 @@
+21.596»
\ No newline at end of file
diff --git a/test/core/json/corpus/8207fdf4bd302d6b6b1894990b353944a8716aa7 b/test/core/json/corpus/8207fdf4bd302d6b6b1894990b353944a8716aa7
new file mode 100644
index 0000000..bbc3e31
--- /dev/null
+++ b/test/core/json/corpus/8207fdf4bd302d6b6b1894990b353944a8716aa7
@@ -0,0 +1 @@
+{"*]:Ã!{)¾?'Ê)“ :*!à):!*à:::\udb81\uD83e12])!{Ã:{!`!?
\ No newline at end of file
diff --git a/test/core/json/corpus/831a49ad81b59025c241ac9e58bd88463fd798eb b/test/core/json/corpus/831a49ad81b59025c241ac9e58bd88463fd798eb
new file mode 100644
index 0000000..8d42875
--- /dev/null
+++ b/test/core/json/corpus/831a49ad81b59025c241ac9e58bd88463fd798eb
@@ -0,0 +1 @@
+5E8850{2312;):ˆ)!Ã"*¾?'ʳ³!!*!à):!*à::8!9:\udbD8ˆ)Ã!:{!`
\ No newline at end of file
diff --git a/test/core/json/corpus/84582c1dbe026475319df14c19967d1dd0bf751f b/test/core/json/corpus/84582c1dbe026475319df14c19967d1dd0bf751f
new file mode 100644
index 0000000..7f509bf
--- /dev/null
+++ b/test/core/json/corpus/84582c1dbe026475319df14c19967d1dd0bf751f
@@ -0,0 +1 @@
+560
\ No newline at end of file
diff --git a/test/core/json/corpus/860d4ad0b7c026d1fcf51932b5e46500be7860a6 b/test/core/json/corpus/860d4ad0b7c026d1fcf51932b5e46500be7860a6
new file mode 100644
index 0000000..6e1ec85
--- /dev/null
+++ b/test/core/json/corpus/860d4ad0b7c026d1fcf51932b5e46500be7860a6
@@ -0,0 +1,2 @@
+3
+)
\ No newline at end of file
diff --git a/test/core/json/corpus/865c7cf36a4f4499a6242e51b77b58b868a7447b b/test/core/json/corpus/865c7cf36a4f4499a6242e51b77b58b868a7447b
new file mode 100644
index 0000000..f78c7b5
--- /dev/null
+++ b/test/core/json/corpus/865c7cf36a4f4499a6242e51b77b58b868a7447b
@@ -0,0 +1 @@
+"9![\b
\ No newline at end of file
diff --git a/test/core/json/corpus/87a2b80f9272583517c0207af176fc40ea55022c b/test/core/json/corpus/87a2b80f9272583517c0207af176fc40ea55022c
new file mode 100644
index 0000000..1ba5237
--- /dev/null
+++ b/test/core/json/corpus/87a2b80f9272583517c0207af176fc40ea55022c
@@ -0,0 +1 @@
+0.
\ No newline at end of file
diff --git a/test/core/json/corpus/887309d048beef83ad3eabf2a79a64a389ab1c9f b/test/core/json/corpus/887309d048beef83ad3eabf2a79a64a389ab1c9f
new file mode 100644
index 0000000..978b4e8
--- /dev/null
+++ b/test/core/json/corpus/887309d048beef83ad3eabf2a79a64a389ab1c9f
@@ -0,0 +1 @@
+26
\ No newline at end of file
diff --git a/test/core/json/corpus/88d89860ccaf21e5f0f002303a2cd853ecbb2acb b/test/core/json/corpus/88d89860ccaf21e5f0f002303a2cd853ecbb2acb
new file mode 100644
index 0000000..7fffca8
--- /dev/null
+++ b/test/core/json/corpus/88d89860ccaf21e5f0f002303a2cd853ecbb2acb
@@ -0,0 +1 @@
+{"":{}+G'(!'(\'!
\ No newline at end of file
diff --git a/test/core/json/corpus/88f658400b1870ddf081fb03020c3098b0b1e083 b/test/core/json/corpus/88f658400b1870ddf081fb03020c3098b0b1e083
new file mode 100644
index 0000000..6c4c537
--- /dev/null
+++ b/test/core/json/corpus/88f658400b1870ddf081fb03020c3098b0b1e083
@@ -0,0 +1 @@
+[[])Ã!:{"*¾?'ʳ³!!*!à):!*à:::\udbD{8ˆ){Ã!:{!`!?`¾¾"(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/88f8b0984bb2f081918ad883c8f0ffacb5a8ff0a b/test/core/json/corpus/88f8b0984bb2f081918ad883c8f0ffacb5a8ff0a
new file mode 100644
index 0000000..e37941d
--- /dev/null
+++ b/test/core/json/corpus/88f8b0984bb2f081918ad883c8f0ffacb5a8ff0a
@@ -0,0 +1,2 @@
+2

\ No newline at end of file
diff --git a/test/core/json/corpus/89304953495f060c7abd3584d83cb1c8e6d6653b b/test/core/json/corpus/89304953495f060c7abd3584d83cb1c8e6d6653b
new file mode 100644
index 0000000..fa86cb3
--- /dev/null
+++ b/test/core/json/corpus/89304953495f060c7abd3584d83cb1c8e6d6653b
@@ -0,0 +1 @@
+[[["ˆÃ{)!:*¾;?'ʳ³!!*!à)])Ã!:{:!*à:::\"u12*1¾
\ No newline at end of file
diff --git a/test/core/json/corpus/8a5f6dc6873e3fd51fd866854d85258f8aa83a02 b/test/core/json/corpus/8a5f6dc6873e3fd51fd866854d85258f8aa83a02
new file mode 100644
index 0000000..057adde
--- /dev/null
+++ b/test/core/json/corpus/8a5f6dc6873e3fd51fd866854d85258f8aa83a02
@@ -0,0 +1,2 @@
+{
+"ˆ":ˆÃ""
\ No newline at end of file
diff --git a/test/core/json/corpus/8a87261277c15667e2957dd52c5db6757ebc8e88 b/test/core/json/corpus/8a87261277c15667e2957dd52c5db6757ebc8e88
new file mode 100644
index 0000000..9d7ee39
--- /dev/null
+++ b/test/core/json/corpus/8a87261277c15667e2957dd52c5db6757ebc8e88
@@ -0,0 +1 @@
+t"ˆÃ{)!:*¾;?Xʳ³!!*!à):!*à:::\
\ No newline at end of file
diff --git a/test/core/json/corpus/8aa61d8bd260942521bb1ba82cd4cce2324fdbee b/test/core/json/corpus/8aa61d8bd260942521bb1ba82cd4cce2324fdbee
new file mode 100644
index 0000000..9c93de0
--- /dev/null
+++ b/test/core/json/corpus/8aa61d8bd260942521bb1ba82cd4cce2324fdbee
@@ -0,0 +1 @@
+fal
\ No newline at end of file
diff --git a/test/core/json/corpus/8d8874439569824e371a0284460440175cdb8a27 b/test/core/json/corpus/8d8874439569824e371a0284460440175cdb8a27
new file mode 100644
index 0000000..ba964c2
--- /dev/null
+++ b/test/core/json/corpus/8d8874439569824e371a0284460440175cdb8a27
@@ -0,0 +1 @@
+5E882312;)
\ No newline at end of file
diff --git a/test/core/json/corpus/8d952ec2e33b2a6a1c7876898719a610f5546388 b/test/core/json/corpus/8d952ec2e33b2a6a1c7876898719a610f5546388
new file mode 100644
index 0000000..fb7475b
--- /dev/null
+++ b/test/core/json/corpus/8d952ec2e33b2a6a1c7876898719a610f5546388
@@ -0,0 +1 @@
+{"":0]f'+G{)13(§!(''\!
\ No newline at end of file
diff --git a/test/core/json/corpus/8e6fec8a05b24f221b6e94fdfe205e5bf7709a2c b/test/core/json/corpus/8e6fec8a05b24f221b6e94fdfe205e5bf7709a2c
new file mode 100644
index 0000000..2146b21
--- /dev/null
+++ b/test/core/json/corpus/8e6fec8a05b24f221b6e94fdfe205e5bf7709a2c
@@ -0,0 +1 @@
+[{"[])Ã!:{&*¾ˆÃ\f5{)!?'ʳ³!!*!à):!–à:::\ubD8:ˆ)kÃ!:{!`!?`¾¾"(*
\ No newline at end of file
diff --git a/test/core/json/corpus/8e7fda77644ff91578d25243fad51a3cd6d60860 b/test/core/json/corpus/8e7fda77644ff91578d25243fad51a3cd6d60860
new file mode 100644
index 0000000..538c0cc
--- /dev/null
+++ b/test/core/json/corpus/8e7fda77644ff91578d25243fad51a3cd6d60860
@@ -0,0 +1 @@
+[2.1982;
\ No newline at end of file
diff --git a/test/core/json/corpus/8ea6295ff82bb119acd44a91b463b19fedafb226 b/test/core/json/corpus/8ea6295ff82bb119acd44a91b463b19fedafb226
new file mode 100644
index 0000000..1acdc8e
--- /dev/null
+++ b/test/core/json/corpus/8ea6295ff82bb119acd44a91b463b19fedafb226
@@ -0,0 +1 @@
+[[2.6»7]3*
\ No newline at end of file
diff --git a/test/core/json/corpus/8ee51caaa2c2f4ee2e5b4b7ef5a89db7df1068d7 b/test/core/json/corpus/8ee51caaa2c2f4ee2e5b4b7ef5a89db7df1068d7
new file mode 100644
index 0000000..69226f7
--- /dev/null
+++ b/test/core/json/corpus/8ee51caaa2c2f4ee2e5b4b7ef5a89db7df1068d7
@@ -0,0 +1 @@
+92
\ No newline at end of file
diff --git a/test/core/json/corpus/8ef4dd9f2d0f9d770c937d9a43413d24df83f09b b/test/core/json/corpus/8ef4dd9f2d0f9d770c937d9a43413d24df83f09b
new file mode 100644
index 0000000..64adcb3
--- /dev/null
+++ b/test/core/json/corpus/8ef4dd9f2d0f9d770c937d9a43413d24df83f09b
@@ -0,0 +1 @@
+[{"ˆÃ\f5{)!:*]){
\ No newline at end of file
diff --git a/test/core/json/corpus/8efd86fb78a56a5145ed7739dcb00c78581c5375 b/test/core/json/corpus/8efd86fb78a56a5145ed7739dcb00c78581c5375
new file mode 100644
index 0000000..32f64f4
--- /dev/null
+++ b/test/core/json/corpus/8efd86fb78a56a5145ed7739dcb00c78581c5375
@@ -0,0 +1 @@
+t
\ No newline at end of file
diff --git a/test/core/json/corpus/8f0ba762c2fed0fc993feb91948902ac397b0919 b/test/core/json/corpus/8f0ba762c2fed0fc993feb91948902ac397b0919
new file mode 100644
index 0000000..cda6df2
--- /dev/null
+++ b/test/core/json/corpus/8f0ba762c2fed0fc993feb91948902ac397b0919
@@ -0,0 +1 @@
+["*:Ã!{)¾?'ʳ³!**!à):!*à:::\udbD8,ˆ
\ No newline at end of file
diff --git a/test/core/json/corpus/8fe81e450694cac1eb4c4a5c966ffbc56ade3513 b/test/core/json/corpus/8fe81e450694cac1eb4c4a5c966ffbc56ade3513
new file mode 100644
index 0000000..6b3c043
--- /dev/null
+++ b/test/core/json/corpus/8fe81e450694cac1eb4c4a5c966ffbc56ade3513
@@ -0,0 +1 @@
+0.2497Ü 
\ No newline at end of file
diff --git a/test/core/json/corpus/902ba3cda1883801594b6e1b452790cc53948fda b/test/core/json/corpus/902ba3cda1883801594b6e1b452790cc53948fda
new file mode 100644
index 0000000..c793025
--- /dev/null
+++ b/test/core/json/corpus/902ba3cda1883801594b6e1b452790cc53948fda
@@ -0,0 +1 @@
+7
\ No newline at end of file
diff --git a/test/core/json/corpus/910a1528b28ebc6ff2f2a4fedb013c86de4103e2 b/test/core/json/corpus/910a1528b28ebc6ff2f2a4fedb013c86de4103e2
new file mode 100644
index 0000000..1c5bc51
--- /dev/null
+++ b/test/core/json/corpus/910a1528b28ebc6ff2f2a4fedb013c86de4103e2
@@ -0,0 +1 @@
+8162E2517;)6
\ No newline at end of file
diff --git a/test/core/json/corpus/92049bf3d8a0ec93c2d1633631c0082e66ca69e7 b/test/core/json/corpus/92049bf3d8a0ec93c2d1633631c0082e66ca69e7
new file mode 100644
index 0000000..a4e01a7
--- /dev/null
+++ b/test/core/json/corpus/92049bf3d8a0ec93c2d1633631c0082e66ca69e7
@@ -0,0 +1,2 @@
+0

\ No newline at end of file
diff --git a/test/core/json/corpus/920a3c318f3127b9c30ab02a077555c7dfbb6edb b/test/core/json/corpus/920a3c318f3127b9c30ab02a077555c7dfbb6edb
new file mode 100644
index 0000000..2e7a62e
--- /dev/null
+++ b/test/core/json/corpus/920a3c318f3127b9c30ab02a077555c7dfbb6edb
@@ -0,0 +1 @@
+[[["ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\u12198.y2db)8ˆÃ!3;!‡:{!`!.7;?
\ No newline at end of file
diff --git a/test/core/json/corpus/925fc05dd661aeb4a776dcbc5df3dcb2cefaf0a6 b/test/core/json/corpus/925fc05dd661aeb4a776dcbc5df3dcb2cefaf0a6
new file mode 100644
index 0000000..22425f2
--- /dev/null
+++ b/test/core/json/corpus/925fc05dd661aeb4a776dcbc5df3dcb2cefaf0a6
@@ -0,0 +1 @@
+{}+G'
\ No newline at end of file
diff --git a/test/core/json/corpus/9367ba65affd5bf7aabf79c28e783cc5d93518e8 b/test/core/json/corpus/9367ba65affd5bf7aabf79c28e783cc5d93518e8
new file mode 100644
index 0000000..8e9c1aa
--- /dev/null
+++ b/test/core/json/corpus/9367ba65affd5bf7aabf79c28e783cc5d93518e8
@@ -0,0 +1 @@
+[2.11E02	"ˆÁ960
\ No newline at end of file
diff --git a/test/core/json/corpus/939f5049b1eefb91ccbd3fcecaed8cb21ea6b285 b/test/core/json/corpus/939f5049b1eefb91ccbd3fcecaed8cb21ea6b285
new file mode 100644
index 0000000..20dd34e
--- /dev/null
+++ b/test/core/json/corpus/939f5049b1eefb91ccbd3fcecaed8cb21ea6b285
@@ -0,0 +1 @@
+"!\'
\ No newline at end of file
diff --git a/test/core/json/corpus/9405c2b00eaa5526f71cc78914dbd3ecaf093b6e b/test/core/json/corpus/9405c2b00eaa5526f71cc78914dbd3ecaf093b6e
new file mode 100644
index 0000000..f996624
--- /dev/null
+++ b/test/core/json/corpus/9405c2b00eaa5526f71cc78914dbd3ecaf093b6e
@@ -0,0 +1 @@
+"9![\"
\ No newline at end of file
diff --git a/test/core/json/corpus/94d3598751569d2a5be258e59665cbbf0692dfbe b/test/core/json/corpus/94d3598751569d2a5be258e59665cbbf0692dfbe
new file mode 100644
index 0000000..e179cde
--- /dev/null
+++ b/test/core/json/corpus/94d3598751569d2a5be258e59665cbbf0692dfbe
@@ -0,0 +1 @@
+"',!\u65E8850{2312;):ˆ)!*?'¾Ê³0.³!!ª!À):*!à:;8!9:\udbD8\uDe250'
\ No newline at end of file
diff --git a/test/core/json/corpus/94f96d95d01e98fd2f04ce26c0913e5f9a882fb4 b/test/core/json/corpus/94f96d95d01e98fd2f04ce26c0913e5f9a882fb4
new file mode 100644
index 0000000..1de2ca8
--- /dev/null
+++ b/test/core/json/corpus/94f96d95d01e98fd2f04ce26c0913e5f9a882fb4
@@ -0,0 +1 @@
+58!9
\ No newline at end of file
diff --git a/test/core/json/corpus/95b54a84db75abab401d282fdb04440a879a9708 b/test/core/json/corpus/95b54a84db75abab401d282fdb04440a879a9708
new file mode 100644
index 0000000..5b41744
--- /dev/null
+++ b/test/core/json/corpus/95b54a84db75abab401d282fdb04440a879a9708
@@ -0,0 +1 @@
+{]3[
\ No newline at end of file
diff --git a/test/core/json/corpus/96189202e587ec951d5795da3e03062f2fb5d708 b/test/core/json/corpus/96189202e587ec951d5795da3e03062f2fb5d708
new file mode 100644
index 0000000..912fa7c
--- /dev/null
+++ b/test/core/json/corpus/96189202e587ec951d5795da3e03062f2fb5d708
@@ -0,0 +1 @@
+{"( \\!§('!
\ No newline at end of file
diff --git a/test/core/json/corpus/9711703428704ce2827a719eddb9d54be23a0cb7 b/test/core/json/corpus/9711703428704ce2827a719eddb9d54be23a0cb7
new file mode 100644
index 0000000..fdb93ea
--- /dev/null
+++ b/test/core/json/corpus/9711703428704ce2827a719eddb9d54be23a0cb7
@@ -0,0 +1 @@
+{"',!\u65E8850{2312;):ˆ)!*?'¾Ê³³!!ª!à):!*à::8!9:\udbD8,6'
\ No newline at end of file
diff --git a/test/core/json/corpus/9734597e96eebe99b2243121a51d178a338ec46f b/test/core/json/corpus/9734597e96eebe99b2243121a51d178a338ec46f
new file mode 100644
index 0000000..6903376
--- /dev/null
+++ b/test/core/json/corpus/9734597e96eebe99b2243121a51d178a338ec46f
@@ -0,0 +1 @@
+8162E-13;0.32)
\ No newline at end of file
diff --git a/test/core/json/corpus/9747c85a9510011bf87c23a80b029b9f2d04c37d b/test/core/json/corpus/9747c85a9510011bf87c23a80b029b9f2d04c37d
new file mode 100644
index 0000000..614c91b
--- /dev/null
+++ b/test/core/json/corpus/9747c85a9510011bf87c23a80b029b9f2d04c37d
@@ -0,0 +1 @@
+[0.3629,95 
\ No newline at end of file
diff --git a/test/core/json/corpus/97d170e1550eee4afc0af065b78cda302a97674c b/test/core/json/corpus/97d170e1550eee4afc0af065b78cda302a97674c
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/test/core/json/corpus/97d170e1550eee4afc0af065b78cda302a97674c
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/test/core/json/corpus/98e02e7fc96479e8d10ff2cc7610be772e2d6fba b/test/core/json/corpus/98e02e7fc96479e8d10ff2cc7610be772e2d6fba
new file mode 100644
index 0000000..6bc0fb8
--- /dev/null
+++ b/test/core/json/corpus/98e02e7fc96479e8d10ff2cc7610be772e2d6fba
@@ -0,0 +1 @@
+[[{"\/5nˆ[{+!:*
\ No newline at end of file
diff --git a/test/core/json/corpus/996156b191b619eff79b2fcbb7598518a09b06bc b/test/core/json/corpus/996156b191b619eff79b2fcbb7598518a09b06bc
new file mode 100644
index 0000000..c3f582e
--- /dev/null
+++ b/test/core/json/corpus/996156b191b619eff79b2fcbb7598518a09b06bc
@@ -0,0 +1 @@
+2.1498 
\ No newline at end of file
diff --git a/test/core/json/corpus/99667fcfa6d583a742fb5450527fc86dfb78ebbf b/test/core/json/corpus/99667fcfa6d583a742fb5450527fc86dfb78ebbf
new file mode 100644
index 0000000..861ae02
--- /dev/null
+++ b/test/core/json/corpus/99667fcfa6d583a742fb5450527fc86dfb78ebbf
@@ -0,0 +1 @@
+[{"ˆÃ{)!:*])Ã!:{"*¾?¾;?Xʳ³'!!Ê
\ No newline at end of file
diff --git a/test/core/json/corpus/9b1ead2dbeeb1a3e9a7bebcf6964c3cfbc7e8867 b/test/core/json/corpus/9b1ead2dbeeb1a3e9a7bebcf6964c3cfbc7e8867
new file mode 100644
index 0000000..d4f8951
--- /dev/null
+++ b/test/core/json/corpus/9b1ead2dbeeb1a3e9a7bebcf6964c3cfbc7e8867
@@ -0,0 +1 @@
+t \'
\ No newline at end of file
diff --git a/test/core/json/corpus/9b7669e201574bfb979d56110539a90da5aca2c0 b/test/core/json/corpus/9b7669e201574bfb979d56110539a90da5aca2c0
new file mode 100644
index 0000000..0cb3d49
--- /dev/null
+++ b/test/core/json/corpus/9b7669e201574bfb979d56110539a90da5aca2c0
@@ -0,0 +1 @@
+{""!!\'!!\'''
\ No newline at end of file
diff --git a/test/core/json/corpus/9c24b456af3cb51a1ff2780c2d9cbdd7d93f6c76 b/test/core/json/corpus/9c24b456af3cb51a1ff2780c2d9cbdd7d93f6c76
new file mode 100644
index 0000000..cbf048b
--- /dev/null
+++ b/test/core/json/corpus/9c24b456af3cb51a1ff2780c2d9cbdd7d93f6c76
@@ -0,0 +1 @@
+nuþ*:
\ No newline at end of file
diff --git a/test/core/json/corpus/9d0441f23ae7d5a3a5b1140497868ee6eeab656b b/test/core/json/corpus/9d0441f23ae7d5a3a5b1140497868ee6eeab656b
new file mode 100644
index 0000000..ed86228
--- /dev/null
+++ b/test/core/json/corpus/9d0441f23ae7d5a3a5b1140497868ee6eeab656b
@@ -0,0 +1,2 @@
+{
+"ˆÃ
\ No newline at end of file
diff --git a/test/core/json/corpus/9d890bd3139a8f9a44d435ff8edfbeb5b072ded0 b/test/core/json/corpus/9d890bd3139a8f9a44d435ff8edfbeb5b072ded0
new file mode 100644
index 0000000..468bde0
--- /dev/null
+++ b/test/core/json/corpus/9d890bd3139a8f9a44d435ff8edfbeb5b072ded0
Binary files differ
diff --git a/test/core/json/corpus/9e6a55b6b4563e652a23be9d623ca5055c356940 b/test/core/json/corpus/9e6a55b6b4563e652a23be9d623ca5055c356940
new file mode 100644
index 0000000..25bf17f
--- /dev/null
+++ b/test/core/json/corpus/9e6a55b6b4563e652a23be9d623ca5055c356940
@@ -0,0 +1 @@
+18
\ No newline at end of file
diff --git a/test/core/json/corpus/9ec88420ef0408642f6930996e35f5b9f18ec88c b/test/core/json/corpus/9ec88420ef0408642f6930996e35f5b9f18ec88c
new file mode 100644
index 0000000..852eeab
--- /dev/null
+++ b/test/core/json/corpus/9ec88420ef0408642f6930996e35f5b9f18ec88c
@@ -0,0 +1 @@
+"ˆÃ"
\ No newline at end of file
diff --git a/test/core/json/corpus/9edd067c569315d5e93b0d14c7eac9fa6d81d3cd b/test/core/json/corpus/9edd067c569315d5e93b0d14c7eac9fa6d81d3cd
new file mode 100644
index 0000000..86d0a11
--- /dev/null
+++ b/test/core/json/corpus/9edd067c569315d5e93b0d14c7eac9fa6d81d3cd
@@ -0,0 +1 @@
+[0.3629,]95 
\ No newline at end of file
diff --git a/test/core/json/corpus/9fbda4f714043d975389b536b4497c6d713452e5 b/test/core/json/corpus/9fbda4f714043d975389b536b4497c6d713452e5
new file mode 100644
index 0000000..c02cbb5
--- /dev/null
+++ b/test/core/json/corpus/9fbda4f714043d975389b536b4497c6d713452e5
@@ -0,0 +1 @@
+[2.4
\ No newline at end of file
diff --git a/test/core/json/corpus/9fc8cb8ab3b05e306e5e81d9d949e69f931244ea b/test/core/json/corpus/9fc8cb8ab3b05e306e5e81d9d949e69f931244ea
new file mode 100644
index 0000000..c85b1ce
--- /dev/null
+++ b/test/core/json/corpus/9fc8cb8ab3b05e306e5e81d9d949e69f931244ea
Binary files differ
diff --git a/test/core/json/corpus/a02b857f2eff73e8e188f35529dd91f8144b23b9 b/test/core/json/corpus/a02b857f2eff73e8e188f35529dd91f8144b23b9
new file mode 100644
index 0000000..3d9983a
--- /dev/null
+++ b/test/core/json/corpus/a02b857f2eff73e8e188f35529dd91f8144b23b9
@@ -0,0 +1 @@
+295
\ No newline at end of file
diff --git a/test/core/json/corpus/a060d5bfd1235cbbe4bcecf332fa3b03bc2282e3 b/test/core/json/corpus/a060d5bfd1235cbbe4bcecf332fa3b03bc2282e3
new file mode 100644
index 0000000..d6eb38c
--- /dev/null
+++ b/test/core/json/corpus/a060d5bfd1235cbbe4bcecf332fa3b03bc2282e3
@@ -0,0 +1 @@
+8324E7"!;\'
\ No newline at end of file
diff --git a/test/core/json/corpus/a0931fae1d43e7887c1cabde83fdfc52eaeedba8 b/test/core/json/corpus/a0931fae1d43e7887c1cabde83fdfc52eaeedba8
new file mode 100644
index 0000000..2950be2
--- /dev/null
+++ b/test/core/json/corpus/a0931fae1d43e7887c1cabde83fdfc52eaeedba8
@@ -0,0 +1 @@
+"',!\u65E8850{2312;):ˆ)!*?'¾Ê³³!!ª!À):*!à::8!9:\udbD8\u'
\ No newline at end of file
diff --git a/test/core/json/corpus/a0d4af29c6c223b48fe34d6a09b3a7466242f33c b/test/core/json/corpus/a0d4af29c6c223b48fe34d6a09b3a7466242f33c
new file mode 100644
index 0000000..db616e9
--- /dev/null
+++ b/test/core/json/corpus/a0d4af29c6c223b48fe34d6a09b3a7466242f33c
@@ -0,0 +1 @@
+{"":0],f'`+G{-22(§!''!
\ No newline at end of file
diff --git a/test/core/json/corpus/a1abe8a785030d475a7350438fd23a05c382c110 b/test/core/json/corpus/a1abe8a785030d475a7350438fd23a05c382c110
new file mode 100644
index 0000000..bb4e42e
--- /dev/null
+++ b/test/core/json/corpus/a1abe8a785030d475a7350438fd23a05c382c110
@@ -0,0 +1,2 @@
+[{
+"ˆÃ" :"ˆÃ!{)!:",}"ˆˆÃ;"
\ No newline at end of file
diff --git a/test/core/json/corpus/a1fb86293eac950c2b4f5182d9e4b5d9e0982ef6 b/test/core/json/corpus/a1fb86293eac950c2b4f5182d9e4b5d9e0982ef6
new file mode 100644
index 0000000..9ab1dd2
--- /dev/null
+++ b/test/core/json/corpus/a1fb86293eac950c2b4f5182d9e4b5d9e0982ef6
@@ -0,0 +1 @@
+1e+2,[2}1ˆ5{Ã"
\ No newline at end of file
diff --git a/test/core/json/corpus/a2d4e3d6f5ba43c9199d5d2011678f82cfd55afc b/test/core/json/corpus/a2d4e3d6f5ba43c9199d5d2011678f82cfd55afc
new file mode 100644
index 0000000..cfd2339
--- /dev/null
+++ b/test/core/json/corpus/a2d4e3d6f5ba43c9199d5d2011678f82cfd55afc
@@ -0,0 +1 @@
+[{"ˆ\\t5{)!:*
\ No newline at end of file
diff --git a/test/core/json/corpus/a39653cb3d97c58c44013197f4d7557577700177 b/test/core/json/corpus/a39653cb3d97c58c44013197f4d7557577700177
new file mode 100644
index 0000000..9e667cc
--- /dev/null
+++ b/test/core/json/corpus/a39653cb3d97c58c44013197f4d7557577700177
@@ -0,0 +1 @@
+[true[(0.193;]4*
\ No newline at end of file
diff --git a/test/core/json/corpus/a4c74ad56ae0e94e96101a8f2ce9b1e588df5e44 b/test/core/json/corpus/a4c74ad56ae0e94e96101a8f2ce9b1e588df5e44
new file mode 100644
index 0000000..079936b
--- /dev/null
+++ b/test/core/json/corpus/a4c74ad56ae0e94e96101a8f2ce9b1e588df5e44
@@ -0,0 +1 @@
+{])
\ No newline at end of file
diff --git a/test/core/json/corpus/a6b34b06b00e9226f2bd961483f9da81d8de99a8 b/test/core/json/corpus/a6b34b06b00e9226f2bd961483f9da81d8de99a8
new file mode 100644
index 0000000..56fbef6
--- /dev/null
+++ b/test/core/json/corpus/a6b34b06b00e9226f2bd961483f9da81d8de99a8
@@ -0,0 +1 @@
+{"*]:Ã!{)¾?'ʳ³ :!)à!*:*à:::\udbD8\\){!uÃ:{!`!?`¾¾")(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/a72c3b9cc71eb7f0e0e4dabcd2dcd2b997f21c07 b/test/core/json/corpus/a72c3b9cc71eb7f0e0e4dabcd2dcd2b997f21c07
new file mode 100644
index 0000000..30b2379
--- /dev/null
+++ b/test/core/json/corpus/a72c3b9cc71eb7f0e0e4dabcd2dcd2b997f21c07
@@ -0,0 +1 @@
+0.9 }G3
\ No newline at end of file
diff --git a/test/core/json/corpus/a749d24bac55bc19465acc92b12244c56ca0f20d b/test/core/json/corpus/a749d24bac55bc19465acc92b12244c56ca0f20d
new file mode 100644
index 0000000..0fc6abd
--- /dev/null
+++ b/test/core/json/corpus/a749d24bac55bc19465acc92b12244c56ca0f20d
@@ -0,0 +1 @@
+}G3
\ No newline at end of file
diff --git a/test/core/json/corpus/a78009ff8b3f4d722ee0eb84795e857e74a58aea b/test/core/json/corpus/a78009ff8b3f4d722ee0eb84795e857e74a58aea
new file mode 100644
index 0000000..6f1758e
--- /dev/null
+++ b/test/core/json/corpus/a78009ff8b3f4d722ee0eb84795e857e74a58aea
@@ -0,0 +1 @@
+3836278E344;2E;))
\ No newline at end of file
diff --git a/test/core/json/corpus/a7ae4b16677806d78d0016c276b6722eba8eef3c b/test/core/json/corpus/a7ae4b16677806d78d0016c276b6722eba8eef3c
new file mode 100644
index 0000000..a42916a
--- /dev/null
+++ b/test/core/json/corpus/a7ae4b16677806d78d0016c276b6722eba8eef3c
@@ -0,0 +1 @@
+0.724790.Ü32996  
\ No newline at end of file
diff --git a/test/core/json/corpus/a806f43dd48e35e75c27814c13a2a96c12449bd1 b/test/core/json/corpus/a806f43dd48e35e75c27814c13a2a96c12449bd1
new file mode 100644
index 0000000..91725db
--- /dev/null
+++ b/test/core/json/corpus/a806f43dd48e35e75c27814c13a2a96c12449bd1
@@ -0,0 +1 @@
+[2.1491
\ No newline at end of file
diff --git a/test/core/json/corpus/a90a858013f90d2a94e0d62a7156ffd6848bf238 b/test/core/json/corpus/a90a858013f90d2a94e0d62a7156ffd6848bf238
new file mode 100644
index 0000000..cf6637a
--- /dev/null
+++ b/test/core/json/corpus/a90a858013f90d2a94e0d62a7156ffd6848bf238
@@ -0,0 +1 @@
+[{"ˆÃ\n5{)!:*]){
\ No newline at end of file
diff --git a/test/core/json/corpus/a94bfbfe16d026b52d7f73cf78fdf7d6a6c5c58b b/test/core/json/corpus/a94bfbfe16d026b52d7f73cf78fdf7d6a6c5c58b
new file mode 100644
index 0000000..6678fba
--- /dev/null
+++ b/test/core/json/corpus/a94bfbfe16d026b52d7f73cf78fdf7d6a6c5c58b
Binary files differ
diff --git a/test/core/json/corpus/a9718f029d11a9335ef596cbd42794de5b0b18b5 b/test/core/json/corpus/a9718f029d11a9335ef596cbd42794de5b0b18b5
new file mode 100644
index 0000000..70a969b
--- /dev/null
+++ b/test/core/json/corpus/a9718f029d11a9335ef596cbd42794de5b0b18b5
@@ -0,0 +1 @@
+0.9 
\ No newline at end of file
diff --git a/test/core/json/corpus/aa6e08a488d1ed00aa51f20c2477fc89e7b0a852 b/test/core/json/corpus/aa6e08a488d1ed00aa51f20c2477fc89e7b0a852
new file mode 100644
index 0000000..9794ac1
--- /dev/null
+++ b/test/core/json/corpus/aa6e08a488d1ed00aa51f20c2477fc89e7b0a852
@@ -0,0 +1,2 @@
+[{
+"ˆÃ" :"ˆÃ"
\ No newline at end of file
diff --git a/test/core/json/corpus/aaa038513c192fec501e4e7302156872ce2fde37 b/test/core/json/corpus/aaa038513c192fec501e4e7302156872ce2fde37
new file mode 100644
index 0000000..3959c2e
--- /dev/null
+++ b/test/core/json/corpus/aaa038513c192fec501e4e7302156872ce2fde37
@@ -0,0 +1,2 @@
+-2:
+p}5
\ No newline at end of file
diff --git a/test/core/json/corpus/ac2686c095a5a1c92a1d4209a6c287778720c86d b/test/core/json/corpus/ac2686c095a5a1c92a1d4209a6c287778720c86d
new file mode 100644
index 0000000..f02f0b8
--- /dev/null
+++ b/test/core/json/corpus/ac2686c095a5a1c92a1d4209a6c287778720c86d
@@ -0,0 +1 @@
+[2.3
\ No newline at end of file
diff --git a/test/core/json/corpus/ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 b/test/core/json/corpus/ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
new file mode 100644
index 0000000..7813681
--- /dev/null
+++ b/test/core/json/corpus/ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
@@ -0,0 +1 @@
+5
\ No newline at end of file
diff --git a/test/core/json/corpus/ac9231da4082430afe8f4d40127814c613648d8e b/test/core/json/corpus/ac9231da4082430afe8f4d40127814c613648d8e
new file mode 100644
index 0000000..501a6bb
--- /dev/null
+++ b/test/core/json/corpus/ac9231da4082430afe8f4d40127814c613648d8e
@@ -0,0 +1 @@
+	
\ No newline at end of file
diff --git a/test/core/json/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc b/test/core/json/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/core/json/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
@@ -0,0 +1 @@
+
diff --git a/test/core/json/corpus/aff25e569bd8c93157e08cd18ebcd896438e34c9 b/test/core/json/corpus/aff25e569bd8c93157e08cd18ebcd896438e34c9
new file mode 100644
index 0000000..ca42430
--- /dev/null
+++ b/test/core/json/corpus/aff25e569bd8c93157e08cd18ebcd896438e34c9
@@ -0,0 +1 @@
+{"( \!'(\'!
\ No newline at end of file
diff --git a/test/core/json/corpus/affced8168ec801de89deac663f708f0c96cf1a4 b/test/core/json/corpus/affced8168ec801de89deac663f708f0c96cf1a4
new file mode 100644
index 0000000..3579fbd
--- /dev/null
+++ b/test/core/json/corpus/affced8168ec801de89deac663f708f0c96cf1a4
@@ -0,0 +1 @@
+t92 \'862E517;)
\ No newline at end of file
diff --git a/test/core/json/corpus/b015dfc2f62b640d7c25adab7b38c5fcb5cb64c8 b/test/core/json/corpus/b015dfc2f62b640d7c25adab7b38c5fcb5cb64c8
new file mode 100644
index 0000000..d5ffeff
--- /dev/null
+++ b/test/core/json/corpus/b015dfc2f62b640d7c25adab7b38c5fcb5cb64c8
@@ -0,0 +1 @@
+58E+³4y;0)ˆ	)!Ã
\ No newline at end of file
diff --git a/test/core/json/corpus/b021dd7cd98b63092685ea092df0dc01c8f63334 b/test/core/json/corpus/b021dd7cd98b63092685ea092df0dc01c8f63334
new file mode 100644
index 0000000..43789b2
--- /dev/null
+++ b/test/core/json/corpus/b021dd7cd98b63092685ea092df0dc01c8f63334
@@ -0,0 +1 @@
+{"*]:Ã!{)¾?'ʳ³ :*!à):!*à:::\udbD8\u813e12)!{Ã:{!`!?
\ No newline at end of file
diff --git a/test/core/json/corpus/b17485b8bdec8809b3819a83753ca893871df403 b/test/core/json/corpus/b17485b8bdec8809b3819a83753ca893871df403
new file mode 100644
index 0000000..375ad53
--- /dev/null
+++ b/test/core/json/corpus/b17485b8bdec8809b3819a83753ca893871df403
@@ -0,0 +1 @@
+0,Ó)
\ No newline at end of file
diff --git a/test/core/json/corpus/b32ef51eca9c6c658e6fb75fdf96bbba066404e7 b/test/core/json/corpus/b32ef51eca9c6c658e6fb75fdf96bbba066404e7
new file mode 100644
index 0000000..6283767
--- /dev/null
+++ b/test/core/json/corpus/b32ef51eca9c6c658e6fb75fdf96bbba066404e7
@@ -0,0 +1 @@
+fals%)
\ No newline at end of file
diff --git a/test/core/json/corpus/b3f0c7f6bb763af1be91d9e74eabfeb199dc1f1f b/test/core/json/corpus/b3f0c7f6bb763af1be91d9e74eabfeb199dc1f1f
new file mode 100644
index 0000000..dec2bf5
--- /dev/null
+++ b/test/core/json/corpus/b3f0c7f6bb763af1be91d9e74eabfeb199dc1f1f
@@ -0,0 +1 @@
+19
\ No newline at end of file
diff --git a/test/core/json/corpus/b45a1635ec526bcc890f9d735976704e516c5f19 b/test/core/json/corpus/b45a1635ec526bcc890f9d735976704e516c5f19
new file mode 100644
index 0000000..5df3969
--- /dev/null
+++ b/test/core/json/corpus/b45a1635ec526bcc890f9d735976704e516c5f19
@@ -0,0 +1 @@
+{"":(!'(\'!
\ No newline at end of file
diff --git a/test/core/json/corpus/b50ce51a7baa28cd298ebd05b4a3b9b70f9d4370 b/test/core/json/corpus/b50ce51a7baa28cd298ebd05b4a3b9b70f9d4370
new file mode 100644
index 0000000..cb9a114
--- /dev/null
+++ b/test/core/json/corpus/b50ce51a7baa28cd298ebd05b4a3b9b70f9d4370
@@ -0,0 +1 @@
+832834E4E;6;))
\ No newline at end of file
diff --git a/test/core/json/corpus/b5126721812b925426b30d283d2bb8b6969f230a b/test/core/json/corpus/b5126721812b925426b30d283d2bb8b6969f230a
new file mode 100644
index 0000000..fdd7734
--- /dev/null
+++ b/test/core/json/corpus/b5126721812b925426b30d283d2bb8b6969f230a
@@ -0,0 +1 @@
+5E9	3'Á8)232;)6
\ No newline at end of file
diff --git a/test/core/json/corpus/b57af943a3ee411bffeaa3872eec9c6fb01569a4 b/test/core/json/corpus/b57af943a3ee411bffeaa3872eec9c6fb01569a4
new file mode 100644
index 0000000..b6970dd
--- /dev/null
+++ b/test/core/json/corpus/b57af943a3ee411bffeaa3872eec9c6fb01569a4
Binary files differ
diff --git a/test/core/json/corpus/b5abf6fd22ed0f852781de35d043059d0f86f3cd b/test/core/json/corpus/b5abf6fd22ed0f852781de35d043059d0f86f3cd
new file mode 100644
index 0000000..7bf416f
--- /dev/null
+++ b/test/core/json/corpus/b5abf6fd22ed0f852781de35d043059d0f86f3cd
@@ -0,0 +1 @@
+0,f')
\ No newline at end of file
diff --git a/test/core/json/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c b/test/core/json/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
new file mode 100644
index 0000000..c227083
--- /dev/null
+++ b/test/core/json/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/test/core/json/corpus/b6f19238d2b04c5b86a17369093dafda34f332e7 b/test/core/json/corpus/b6f19238d2b04c5b86a17369093dafda34f332e7
new file mode 100644
index 0000000..fb1edb4
--- /dev/null
+++ b/test/core/json/corpus/b6f19238d2b04c5b86a17369093dafda34f332e7
@@ -0,0 +1,2 @@
+")
+è"ˆÃ{)!:*¾;!'ʳ³!!*!à):!*"ˆÃ{)!:*])à
\ No newline at end of file
diff --git a/test/core/json/corpus/b858cb282617fb0956d960215c8e84d1ccf909c6 b/test/core/json/corpus/b858cb282617fb0956d960215c8e84d1ccf909c6
new file mode 100644
index 0000000..0519ecb
--- /dev/null
+++ b/test/core/json/corpus/b858cb282617fb0956d960215c8e84d1ccf909c6
@@ -0,0 +1 @@
+ 
\ No newline at end of file
diff --git a/test/core/json/corpus/b9c38fad09c80db7781fefbe51039752de575ecc b/test/core/json/corpus/b9c38fad09c80db7781fefbe51039752de575ecc
new file mode 100644
index 0000000..c16d3bc
--- /dev/null
+++ b/test/core/json/corpus/b9c38fad09c80db7781fefbe51039752de575ecc
@@ -0,0 +1 @@
+3e45!01860
\ No newline at end of file
diff --git a/test/core/json/corpus/bb407c8992800444201dccfe744dac49c0295fde b/test/core/json/corpus/bb407c8992800444201dccfe744dac49c0295fde
new file mode 100644
index 0000000..7984a6f
--- /dev/null
+++ b/test/core/json/corpus/bb407c8992800444201dccfe744dac49c0295fde
@@ -0,0 +1 @@
+{"!(!\t'
\ No newline at end of file
diff --git a/test/core/json/corpus/bc335734f73502b92d2bd3587259ce915985f0ee b/test/core/json/corpus/bc335734f73502b92d2bd3587259ce915985f0ee
new file mode 100644
index 0000000..75ce6ce
--- /dev/null
+++ b/test/core/json/corpus/bc335734f73502b92d2bd3587259ce915985f0ee
@@ -0,0 +1 @@
+0.6995 
\ No newline at end of file
diff --git a/test/core/json/corpus/bd113c2c8a2328e3674c680c7cff829a6c8ab924 b/test/core/json/corpus/bd113c2c8a2328e3674c680c7cff829a6c8ab924
new file mode 100644
index 0000000..08894ee
--- /dev/null
+++ b/test/core/json/corpus/bd113c2c8a2328e3674c680c7cff829a6c8ab924
@@ -0,0 +1 @@
+[2.10;2;®
\ No newline at end of file
diff --git a/test/core/json/corpus/be051d58015d4af1977a5dfd14ef3fd070ecc9d2 b/test/core/json/corpus/be051d58015d4af1977a5dfd14ef3fd070ecc9d2
new file mode 100644
index 0000000..c56ae0e
--- /dev/null
+++ b/test/core/json/corpus/be051d58015d4af1977a5dfd14ef3fd070ecc9d2
@@ -0,0 +1 @@
+9!
\ No newline at end of file
diff --git a/test/core/json/corpus/be461a0cd1fda052a69c3fd94f8cf5f6f86afa34 b/test/core/json/corpus/be461a0cd1fda052a69c3fd94f8cf5f6f86afa34
new file mode 100644
index 0000000..3ca9062
--- /dev/null
+++ b/test/core/json/corpus/be461a0cd1fda052a69c3fd94f8cf5f6f86afa34
@@ -0,0 +1 @@
+84
\ No newline at end of file
diff --git a/test/core/json/corpus/bef524502f8dbbc45af717ece01ec88edd7f903b b/test/core/json/corpus/bef524502f8dbbc45af717ece01ec88edd7f903b
new file mode 100644
index 0000000..2a42b12
--- /dev/null
+++ b/test/core/json/corpus/bef524502f8dbbc45af717ece01ec88edd7f903b
@@ -0,0 +1 @@
+13e108560
\ No newline at end of file
diff --git a/test/core/json/corpus/bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f b/test/core/json/corpus/bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/test/core/json/corpus/bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/test/core/json/corpus/c0b6a90832b78ed5f6d129d3640c612540527c85 b/test/core/json/corpus/c0b6a90832b78ed5f6d129d3640c612540527c85
new file mode 100644
index 0000000..a03cfc1
--- /dev/null
+++ b/test/core/json/corpus/c0b6a90832b78ed5f6d129d3640c612540527c85
@@ -0,0 +1 @@
+{"'!\u3Â:Š
\ No newline at end of file
diff --git a/test/core/json/corpus/c18d315f0d35849b2aae4a47cab4608204b85d76 b/test/core/json/corpus/c18d315f0d35849b2aae4a47cab4608204b85d76
new file mode 100644
index 0000000..d082c57
--- /dev/null
+++ b/test/core/json/corpus/c18d315f0d35849b2aae4a47cab4608204b85d76
@@ -0,0 +1,2 @@
+[{")
+è"ˆÃ{)!:*¾;!'ʳ³!!*!à):!*"ˆÃ{)!:*])à
\ No newline at end of file
diff --git a/test/core/json/corpus/c257fd6bc9e5254a733378ab4ddd39629c4a3069 b/test/core/json/corpus/c257fd6bc9e5254a733378ab4ddd39629c4a3069
new file mode 100644
index 0000000..b040a5e
--- /dev/null
+++ b/test/core/json/corpus/c257fd6bc9e5254a733378ab4ddd39629c4a3069
@@ -0,0 +1 @@
+13e128560
\ No newline at end of file
diff --git a/test/core/json/corpus/c2bf7f49d8f2e13a60af4473b3b3451b65b3aa9a b/test/core/json/corpus/c2bf7f49d8f2e13a60af4473b3b3451b65b3aa9a
new file mode 100644
index 0000000..7f9e4a6
--- /dev/null
+++ b/test/core/json/corpus/c2bf7f49d8f2e13a60af4473b3b3451b65b3aa9a
@@ -0,0 +1 @@
+1e+2188560
\ No newline at end of file
diff --git a/test/core/json/corpus/c308517acf6f7088634d491a1608240f83a3ac95 b/test/core/json/corpus/c308517acf6f7088634d491a1608240f83a3ac95
new file mode 100644
index 0000000..cc56474
--- /dev/null
+++ b/test/core/json/corpus/c308517acf6f7088634d491a1608240f83a3ac95
@@ -0,0 +1 @@
+0.427Ü$
\ No newline at end of file
diff --git a/test/core/json/corpus/c3badd71ef8a51b97ce93cbfe99f6778048f2128 b/test/core/json/corpus/c3badd71ef8a51b97ce93cbfe99f6778048f2128
new file mode 100644
index 0000000..4d10e08
--- /dev/null
+++ b/test/core/json/corpus/c3badd71ef8a51b97ce93cbfe99f6778048f2128
@@ -0,0 +1 @@
+3(
\ No newline at end of file
diff --git a/test/core/json/corpus/c482a632702ae7f532d126e70149dda4fadc3cd7 b/test/core/json/corpus/c482a632702ae7f532d126e70149dda4fadc3cd7
new file mode 100644
index 0000000..e041368
--- /dev/null
+++ b/test/core/json/corpus/c482a632702ae7f532d126e70149dda4fadc3cd7
@@ -0,0 +1 @@
+0.2996 
\ No newline at end of file
diff --git a/test/core/json/corpus/c541bb86e55b98e083b141114066f9c17d853374 b/test/core/json/corpus/c541bb86e55b98e083b141114066f9c17d853374
new file mode 100644
index 0000000..8162989
--- /dev/null
+++ b/test/core/json/corpus/c541bb86e55b98e083b141114066f9c17d853374
@@ -0,0 +1 @@
+[[["ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\u06099.y2db)8ˆÃ!3;!‡:{!`!.7;?
\ No newline at end of file
diff --git a/test/core/json/corpus/c5b50b9015b6aaedd7eb1077b1204858f837b53c b/test/core/json/corpus/c5b50b9015b6aaedd7eb1077b1204858f837b53c
new file mode 100644
index 0000000..deb26ed
--- /dev/null
+++ b/test/core/json/corpus/c5b50b9015b6aaedd7eb1077b1204858f837b53c
@@ -0,0 +1 @@
+"',!\u65E8850{2312;):ˆ)!*?'¾Ê³0.³!!ª!À):*!à::8!9:\udbD8\u82510'
\ No newline at end of file
diff --git a/test/core/json/corpus/c62ef0dbd1350da9ea5a32e56672d385837643e7 b/test/core/json/corpus/c62ef0dbd1350da9ea5a32e56672d385837643e7
new file mode 100644
index 0000000..f7ac687
--- /dev/null
+++ b/test/core/json/corpus/c62ef0dbd1350da9ea5a32e56672d385837643e7
Binary files differ
diff --git a/test/core/json/corpus/c7a34d6d49e1da1ccd490350c2df3a168ed09ae8 b/test/core/json/corpus/c7a34d6d49e1da1ccd490350c2df3a168ed09ae8
new file mode 100644
index 0000000..1d06e43
--- /dev/null
+++ b/test/core/json/corpus/c7a34d6d49e1da1ccd490350c2df3a168ed09ae8
@@ -0,0 +1,3 @@
+{
+"ˆ[2":{}
+5‰Ã["
\ No newline at end of file
diff --git a/test/core/json/corpus/c88c4bec8d440c56d3ea7abce39276f0927dbe0a b/test/core/json/corpus/c88c4bec8d440c56d3ea7abce39276f0927dbe0a
new file mode 100644
index 0000000..9442128
--- /dev/null
+++ b/test/core/json/corpus/c88c4bec8d440c56d3ea7abce39276f0927dbe0a
@@ -0,0 +1 @@
+33(
\ No newline at end of file
diff --git a/test/core/json/corpus/c92f147bfc034003ac42ed9e62a16c84102ab417 b/test/core/json/corpus/c92f147bfc034003ac42ed9e62a16c84102ab417
new file mode 100644
index 0000000..3fae4b1
--- /dev/null
+++ b/test/core/json/corpus/c92f147bfc034003ac42ed9e62a16c84102ab417
@@ -0,0 +1 @@
+[[2.193,]4ˆÃ"*("
\ No newline at end of file
diff --git a/test/core/json/corpus/c96b0fe6034668edf37ef0f5f391d5107953dc06 b/test/core/json/corpus/c96b0fe6034668edf37ef0f5f391d5107953dc06
new file mode 100644
index 0000000..975bc39
--- /dev/null
+++ b/test/core/json/corpus/c96b0fe6034668edf37ef0f5f391d5107953dc06
@@ -0,0 +1 @@
+8162E517;)
\ No newline at end of file
diff --git a/test/core/json/corpus/cac74aa5d7aab7fce0253f00c1a025980c1f9b7a b/test/core/json/corpus/cac74aa5d7aab7fce0253f00c1a025980c1f9b7a
new file mode 100644
index 0000000..e2c8b2a
--- /dev/null
+++ b/test/core/json/corpus/cac74aa5d7aab7fce0253f00c1a025980c1f9b7a
@@ -0,0 +1 @@
+ \'
\ No newline at end of file
diff --git a/test/core/json/corpus/caea0a0e6d8708cf682eaa446c344da56a7d5515 b/test/core/json/corpus/caea0a0e6d8708cf682eaa446c344da56a7d5515
new file mode 100644
index 0000000..767d851
--- /dev/null
+++ b/test/core/json/corpus/caea0a0e6d8708cf682eaa446c344da56a7d5515
@@ -0,0 +1 @@
+"!2}G!\'')y3
\ No newline at end of file
diff --git a/test/core/json/corpus/cc8a3dd2678d4b400ad630f402012b894e841b05 b/test/core/json/corpus/cc8a3dd2678d4b400ad630f402012b894e841b05
new file mode 100644
index 0000000..f115f81
--- /dev/null
+++ b/test/core/json/corpus/cc8a3dd2678d4b400ad630f402012b894e841b05
@@ -0,0 +1 @@
+"9![\f
\ No newline at end of file
diff --git a/test/core/json/corpus/cd851bec7adad52f79777fb9347d5fd2f9486aa7 b/test/core/json/corpus/cd851bec7adad52f79777fb9347d5fd2f9486aa7
new file mode 100644
index 0000000..0f8b1eb
--- /dev/null
+++ b/test/core/json/corpus/cd851bec7adad52f79777fb9347d5fd2f9486aa7
@@ -0,0 +1 @@
+{"',!\u@':Š
\ No newline at end of file
diff --git a/test/core/json/corpus/ce3899b62ba3efe00eb31ddad2861ffe16a30d06 b/test/core/json/corpus/ce3899b62ba3efe00eb31ddad2861ffe16a30d06
new file mode 100644
index 0000000..91bd82a
--- /dev/null
+++ b/test/core/json/corpus/ce3899b62ba3efe00eb31ddad2861ffe16a30d06
@@ -0,0 +1 @@
+[[["ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\\06099.y2db)8ˆÃ!3;!‡:{!`!.7;?
\ No newline at end of file
diff --git a/test/core/json/corpus/ce8b76fdcdbf1c951afc2b115be9acc8a6358b32 b/test/core/json/corpus/ce8b76fdcdbf1c951afc2b115be9acc8a6358b32
new file mode 100644
index 0000000..8ecd07a
--- /dev/null
+++ b/test/core/json/corpus/ce8b76fdcdbf1c951afc2b115be9acc8a6358b32
@@ -0,0 +1 @@
+8324E512;)
\ No newline at end of file
diff --git a/test/core/json/corpus/cec87b67871fc7a59652bc3546fbbb68e4d31e28 b/test/core/json/corpus/cec87b67871fc7a59652bc3546fbbb68e4d31e28
new file mode 100644
index 0000000..56e1cf4
--- /dev/null
+++ b/test/core/json/corpus/cec87b67871fc7a59652bc3546fbbb68e4d31e28
@@ -0,0 +1,2 @@
+[{
+"ˆÃ" :"ˆÃ!{)!:","ˆˆÃÃ"
\ No newline at end of file
diff --git a/test/core/json/corpus/cf32406111908544e504c84731147f072cdf2fbd b/test/core/json/corpus/cf32406111908544e504c84731147f072cdf2fbd
new file mode 100644
index 0000000..a0d1ef1
--- /dev/null
+++ b/test/core/json/corpus/cf32406111908544e504c84731147f072cdf2fbd
@@ -0,0 +1 @@
+620
\ No newline at end of file
diff --git a/test/core/json/corpus/cf35dc76bf9a2052636c1ecc92942161830dcdc3 b/test/core/json/corpus/cf35dc76bf9a2052636c1ecc92942161830dcdc3
new file mode 100644
index 0000000..2401421
--- /dev/null
+++ b/test/core/json/corpus/cf35dc76bf9a2052636c1ecc92942161830dcdc3
@@ -0,0 +1 @@
+	3Á6
\ No newline at end of file
diff --git a/test/core/json/corpus/cf6a5e6bfe4f15b43e411dd2782e10f1670c9767 b/test/core/json/corpus/cf6a5e6bfe4f15b43e411dd2782e10f1670c9767
new file mode 100644
index 0000000..f4c0d10
--- /dev/null
+++ b/test/core/json/corpus/cf6a5e6bfe4f15b43e411dd2782e10f1670c9767
@@ -0,0 +1 @@
+30.5E8;!4;
\ No newline at end of file
diff --git a/test/core/json/corpus/cfc45616f5f0e7c25df91f6984ff5f6f1648beab b/test/core/json/corpus/cfc45616f5f0e7c25df91f6984ff5f6f1648beab
new file mode 100644
index 0000000..77db9a6
--- /dev/null
+++ b/test/core/json/corpus/cfc45616f5f0e7c25df91f6984ff5f6f1648beab
@@ -0,0 +1 @@
+{"',!\u65E8850{2312;):ˆ)!*?'¾Ê³³!!ª!À):*!à::8!9:\udbD8\6'
\ No newline at end of file
diff --git a/test/core/json/corpus/cff891e5858ae68d08ecc8470ca6a68c9438bfa3 b/test/core/json/corpus/cff891e5858ae68d08ecc8470ca6a68c9438bfa3
new file mode 100644
index 0000000..9ef39eb
--- /dev/null
+++ b/test/core/json/corpus/cff891e5858ae68d08ecc8470ca6a68c9438bfa3
@@ -0,0 +1 @@
+{"*]:Ë!{)¾?'ʳ³ !*!à):!*à:::\udbD8 !)!{Ã:{!`!?`¾¾"(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/cfff4e9d08cba81b663dd1999710008342851e19 b/test/core/json/corpus/cfff4e9d08cba81b663dd1999710008342851e19
new file mode 100644
index 0000000..eb4d5f1
--- /dev/null
+++ b/test/core/json/corpus/cfff4e9d08cba81b663dd1999710008342851e19
@@ -0,0 +1 @@
+nul*:
\ No newline at end of file
diff --git a/test/core/json/corpus/crash-f21867fe8b6df0b54c13e2e6e613dce871ecf0f0 b/test/core/json/corpus/crash-f21867fe8b6df0b54c13e2e6e613dce871ecf0f0
new file mode 100644
index 0000000..6d3bcfe
--- /dev/null
+++ b/test/core/json/corpus/crash-f21867fe8b6df0b54c13e2e6e613dce871ecf0f0
@@ -0,0 +1 @@
+ˆ)Ã!:{"*¾?'ʳ³!!*!à):!*à:::\udbD8ˆ)Ã!:{!`!?`¾¾!?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/d1db03c626fb16c3b9cd44cc38cf40ebd355a194 b/test/core/json/corpus/d1db03c626fb16c3b9cd44cc38cf40ebd355a194
new file mode 100644
index 0000000..f292b52
--- /dev/null
+++ b/test/core/json/corpus/d1db03c626fb16c3b9cd44cc38cf40ebd355a194
@@ -0,0 +1 @@
+8324E684;)
\ No newline at end of file
diff --git a/test/core/json/corpus/d85ca051da784c0441898c5affbf11a2ae8f56bc b/test/core/json/corpus/d85ca051da784c0441898c5affbf11a2ae8f56bc
new file mode 100644
index 0000000..921f250
--- /dev/null
+++ b/test/core/json/corpus/d85ca051da784c0441898c5affbf11a2ae8f56bc
@@ -0,0 +1 @@
+[[["ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\u0049.y2db)8ˆÃ!3;!‡7`!{:!.;?
\ No newline at end of file
diff --git a/test/core/json/corpus/da03f536ceaf609972aa2a699687cc6f73ac0dcd b/test/core/json/corpus/da03f536ceaf609972aa2a699687cc6f73ac0dcd
new file mode 100644
index 0000000..68efa7b
--- /dev/null
+++ b/test/core/json/corpus/da03f536ceaf609972aa2a699687cc6f73ac0dcd
@@ -0,0 +1 @@
+"7 
\ No newline at end of file
diff --git a/test/core/json/corpus/da4b9237bacccdf19c0760cab7aec4a8359010b0 b/test/core/json/corpus/da4b9237bacccdf19c0760cab7aec4a8359010b0
new file mode 100644
index 0000000..d8263ee
--- /dev/null
+++ b/test/core/json/corpus/da4b9237bacccdf19c0760cab7aec4a8359010b0
@@ -0,0 +1 @@
+2
\ No newline at end of file
diff --git a/test/core/json/corpus/dcc45e405208d7a2db33d0b5b9da2a2f1b034957 b/test/core/json/corpus/dcc45e405208d7a2db33d0b5b9da2a2f1b034957
new file mode 100644
index 0000000..2f58c32
--- /dev/null
+++ b/test/core/json/corpus/dcc45e405208d7a2db33d0b5b9da2a2f1b034957
@@ -0,0 +1 @@
+0.5!
\ No newline at end of file
diff --git a/test/core/json/corpus/dcc60d3aaa1fc4d00201a3512284fcb79b5b68ef b/test/core/json/corpus/dcc60d3aaa1fc4d00201a3512284fcb79b5b68ef
new file mode 100644
index 0000000..9e15a74
--- /dev/null
+++ b/test/core/json/corpus/dcc60d3aaa1fc4d00201a3512284fcb79b5b68ef
Binary files differ
diff --git a/test/core/json/corpus/dd0567ae57bf3cc85891a1ca988c2945d9186678 b/test/core/json/corpus/dd0567ae57bf3cc85891a1ca988c2945d9186678
new file mode 100644
index 0000000..0e05e02
--- /dev/null
+++ b/test/core/json/corpus/dd0567ae57bf3cc85891a1ca988c2945d9186678
@@ -0,0 +1 @@
+"',!\u65E8850{2312;):ˆ)!*?'¾Ê³0.³!!ª!À):*!à::8!9:\udbD8\uD8250'
\ No newline at end of file
diff --git a/test/core/json/corpus/dd890a5a32e9f0489c6c77695f2155041f00fc9a b/test/core/json/corpus/dd890a5a32e9f0489c6c77695f2155041f00fc9a
new file mode 100644
index 0000000..86d708f
--- /dev/null
+++ b/test/core/json/corpus/dd890a5a32e9f0489c6c77695f2155041f00fc9a
@@ -0,0 +1 @@
+{"!!\''
\ No newline at end of file
diff --git a/test/core/json/corpus/df88e2baf7b76ffb2e94b9da57fd8d137f44b1ef b/test/core/json/corpus/df88e2baf7b76ffb2e94b9da57fd8d137f44b1ef
new file mode 100644
index 0000000..3c61ef6
--- /dev/null
+++ b/test/core/json/corpus/df88e2baf7b76ffb2e94b9da57fd8d137f44b1ef
@@ -0,0 +1 @@
+"ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\)db)8ˆÃ!‡:{!`!?`¾¾!'?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/e00ee378c3f6e0b3cd89bd6e7517478d093f73dd b/test/core/json/corpus/e00ee378c3f6e0b3cd89bd6e7517478d093f73dd
new file mode 100644
index 0000000..fb9c6f8
--- /dev/null
+++ b/test/core/json/corpus/e00ee378c3f6e0b3cd89bd6e7517478d093f73dd
@@ -0,0 +1 @@
+834e;)
\ No newline at end of file
diff --git a/test/core/json/corpus/e0c124e90d068e2a70a3e148052869033453ec58 b/test/core/json/corpus/e0c124e90d068e2a70a3e148052869033453ec58
new file mode 100644
index 0000000..e05343f
--- /dev/null
+++ b/test/core/json/corpus/e0c124e90d068e2a70a3e148052869033453ec58
@@ -0,0 +1 @@
+27e7¤2:60
\ No newline at end of file
diff --git a/test/core/json/corpus/e0d87b1f3e54e5adc5c2205f9e14772822a25766 b/test/core/json/corpus/e0d87b1f3e54e5adc5c2205f9e14772822a25766
new file mode 100644
index 0000000..83c6ab5
--- /dev/null
+++ b/test/core/json/corpus/e0d87b1f3e54e5adc5c2205f9e14772822a25766
@@ -0,0 +1 @@
+[{"ˆÃ\5{)!:*]){
\ No newline at end of file
diff --git a/test/core/json/corpus/e1199df649697c570db5d6b2ea09d755eddd32b7 b/test/core/json/corpus/e1199df649697c570db5d6b2ea09d755eddd32b7
new file mode 100644
index 0000000..adac51f
--- /dev/null
+++ b/test/core/json/corpus/e1199df649697c570db5d6b2ea09d755eddd32b7
@@ -0,0 +1 @@
+[[0.193;]4*
\ No newline at end of file
diff --git a/test/core/json/corpus/e235f6f2a8b6a22117f1baa932fb6c69799e1136 b/test/core/json/corpus/e235f6f2a8b6a22117f1baa932fb6c69799e1136
new file mode 100644
index 0000000..f3f2d8c
--- /dev/null
+++ b/test/core/json/corpus/e235f6f2a8b6a22117f1baa932fb6c69799e1136
@@ -0,0 +1 @@
+[1.197;
\ No newline at end of file
diff --git a/test/core/json/corpus/e3a654055a867ae62d8e68fa2c410228ac55cb6d b/test/core/json/corpus/e3a654055a867ae62d8e68fa2c410228ac55cb6d
new file mode 100644
index 0000000..428fe54
--- /dev/null
+++ b/test/core/json/corpus/e3a654055a867ae62d8e68fa2c410228ac55cb6d
@@ -0,0 +1 @@
+"!!\''
\ No newline at end of file
diff --git a/test/core/json/corpus/e3c680aac46b9c46392e3b2c43ecdcc1547f2023 b/test/core/json/corpus/e3c680aac46b9c46392e3b2c43ecdcc1547f2023
new file mode 100644
index 0000000..53f048b
--- /dev/null
+++ b/test/core/json/corpus/e3c680aac46b9c46392e3b2c43ecdcc1547f2023
@@ -0,0 +1 @@
+[}G3
\ No newline at end of file
diff --git a/test/core/json/corpus/e3d134b35cc25a4861d90023c95988ec6103ddd5 b/test/core/json/corpus/e3d134b35cc25a4861d90023c95988ec6103ddd5
new file mode 100644
index 0000000..a9f28d4
--- /dev/null
+++ b/test/core/json/corpus/e3d134b35cc25a4861d90023c95988ec6103ddd5
@@ -0,0 +1 @@
+"ˆÃ{)!:*¾;!'ʳ³!!*!à):!*à::\udb)8ˆÃ!‡:{`!?`¾¾!?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/e3ff65de4b1622315c3b34b7a5e39bffb275489d b/test/core/json/corpus/e3ff65de4b1622315c3b34b7a5e39bffb275489d
new file mode 100644
index 0000000..d188dbf
--- /dev/null
+++ b/test/core/json/corpus/e3ff65de4b1622315c3b34b7a5e39bffb275489d
@@ -0,0 +1 @@
+[2.19
\ No newline at end of file
diff --git a/test/core/json/corpus/e4a4085cc31476f5de9047422851d8ccf86339df b/test/core/json/corpus/e4a4085cc31476f5de9047422851d8ccf86339df
new file mode 100644
index 0000000..e673b6d
--- /dev/null
+++ b/test/core/json/corpus/e4a4085cc31476f5de9047422851d8ccf86339df
@@ -0,0 +1 @@
+{"',!\u@':Š
\ No newline at end of file
diff --git a/test/core/json/corpus/e4e3c69da200af932c8a79fa055d7aeea28eb1d1 b/test/core/json/corpus/e4e3c69da200af932c8a79fa055d7aeea28eb1d1
new file mode 100644
index 0000000..fa71dbe
--- /dev/null
+++ b/test/core/json/corpus/e4e3c69da200af932c8a79fa055d7aeea28eb1d1
@@ -0,0 +1 @@
+[2."ˆÃ!{)!:",ˆÃ
\ No newline at end of file
diff --git a/test/core/json/corpus/e6c3dd630428fd54834172b8fd2735fed9416da4 b/test/core/json/corpus/e6c3dd630428fd54834172b8fd2735fed9416da4
new file mode 100644
index 0000000..2b82dfe
--- /dev/null
+++ b/test/core/json/corpus/e6c3dd630428fd54834172b8fd2735fed9416da4
@@ -0,0 +1 @@
+60
\ No newline at end of file
diff --git a/test/core/json/corpus/e71eb37fca2070521e1e07c503c2bcd6445b35ea b/test/core/json/corpus/e71eb37fca2070521e1e07c503c2bcd6445b35ea
new file mode 100644
index 0000000..67a6628
--- /dev/null
+++ b/test/core/json/corpus/e71eb37fca2070521e1e07c503c2bcd6445b35ea
Binary files differ
diff --git a/test/core/json/corpus/e760e6e22ae8cd1ea78fe28b5eb1f3d7b5fdc536 b/test/core/json/corpus/e760e6e22ae8cd1ea78fe28b5eb1f3d7b5fdc536
new file mode 100644
index 0000000..3e747cc
--- /dev/null
+++ b/test/core/json/corpus/e760e6e22ae8cd1ea78fe28b5eb1f3d7b5fdc536
@@ -0,0 +1 @@
+{:ˆ)!Ã"*¾?'ʳ³!!*!à):!*à:::\udbD8ˆ)Ã!:{!`!?`¾¾!?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/e95ff1142118a2ca5b84935612a8a64d55360e64 b/test/core/json/corpus/e95ff1142118a2ca5b84935612a8a64d55360e64
new file mode 100644
index 0000000..ca8bbcc
--- /dev/null
+++ b/test/core/json/corpus/e95ff1142118a2ca5b84935612a8a64d55360e64
@@ -0,0 +1 @@
+"ˆÃ{)!:*¾;?'ʳ³!!*!à):!*à:::\udb)8ˆÃ!‡:{!`!?`¾¾!?'!*m,');…'`
\ No newline at end of file
diff --git a/test/core/json/corpus/e9c5e2c67930513941753c2d54591c7098c82f6c b/test/core/json/corpus/e9c5e2c67930513941753c2d54591c7098c82f6c
new file mode 100644
index 0000000..f9991b4
--- /dev/null
+++ b/test/core/json/corpus/e9c5e2c67930513941753c2d54591c7098c82f6c
@@ -0,0 +1 @@
+[3]4*
\ No newline at end of file
diff --git a/test/core/json/corpus/eb26070d17ffa908204912e75cb4313835042038 b/test/core/json/corpus/eb26070d17ffa908204912e75cb4313835042038
new file mode 100644
index 0000000..8122937
--- /dev/null
+++ b/test/core/json/corpus/eb26070d17ffa908204912e75cb4313835042038
@@ -0,0 +1 @@
+["*]:Ã!{)¾?'ʳ³!!*!à):!*à:::\udbD8ˆ){Ã!:{!`!?`¾¾"(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/ebc6aee49e5ae57722df86e7fa33c420f045a449 b/test/core/json/corpus/ebc6aee49e5ae57722df86e7fa33c420f045a449
new file mode 100644
index 0000000..ee58b90
--- /dev/null
+++ b/test/core/json/corpus/ebc6aee49e5ae57722df86e7fa33c420f045a449
@@ -0,0 +1 @@
+03(
\ No newline at end of file
diff --git a/test/core/json/corpus/ed1dc11d713e7487de18ce8317b62916959206d0 b/test/core/json/corpus/ed1dc11d713e7487de18ce8317b62916959206d0
new file mode 100644
index 0000000..90e536e
--- /dev/null
+++ b/test/core/json/corpus/ed1dc11d713e7487de18ce8317b62916959206d0
@@ -0,0 +1 @@
+8324E6;)
\ No newline at end of file
diff --git a/test/core/json/corpus/ede3f66106acd7796da8b3942d029fe213058286 b/test/core/json/corpus/ede3f66106acd7796da8b3942d029fe213058286
new file mode 100644
index 0000000..69cea59
--- /dev/null
+++ b/test/core/json/corpus/ede3f66106acd7796da8b3942d029fe213058286
@@ -0,0 +1 @@
+5834E0y);)ˆ	)!Ã
\ No newline at end of file
diff --git a/test/core/json/corpus/eed7bd220cd511b6d42ce6553019266a22a3d56a b/test/core/json/corpus/eed7bd220cd511b6d42ce6553019266a22a3d56a
new file mode 100644
index 0000000..60f86bd
--- /dev/null
+++ b/test/core/json/corpus/eed7bd220cd511b6d42ce6553019266a22a3d56a
@@ -0,0 +1 @@
+0,0	
\ No newline at end of file
diff --git a/test/core/json/corpus/f090932162756b798b1a050b05e3d36a3437c4fc b/test/core/json/corpus/f090932162756b798b1a050b05e3d36a3437c4fc
new file mode 100644
index 0000000..24f98f2
--- /dev/null
+++ b/test/core/json/corpus/f090932162756b798b1a050b05e3d36a3437c4fc
@@ -0,0 +1 @@
+367
\ No newline at end of file
diff --git a/test/core/json/corpus/f1905eaa84ba6a3593ec6ac0486a5b42893c01f1 b/test/core/json/corpus/f1905eaa84ba6a3593ec6ac0486a5b42893c01f1
new file mode 100644
index 0000000..601a7b2
--- /dev/null
+++ b/test/core/json/corpus/f1905eaa84ba6a3593ec6ac0486a5b42893c01f1
@@ -0,0 +1 @@
+50{:ˆ)!Ã"*¾?'ʳ³!!*!à):!*à::8!9:\udbD8ˆ)Ã!:{!`
\ No newline at end of file
diff --git a/test/core/json/corpus/f4635fbbf765ead81a261ca152df02622e182d2c b/test/core/json/corpus/f4635fbbf765ead81a261ca152df02622e182d2c
new file mode 100644
index 0000000..30e0f2b
--- /dev/null
+++ b/test/core/json/corpus/f4635fbbf765ead81a261ca152df02622e182d2c
@@ -0,0 +1 @@
+"19
\ No newline at end of file
diff --git a/test/core/json/corpus/f46eeb1020c7c4153e742a50bc24c2c6939dab1e b/test/core/json/corpus/f46eeb1020c7c4153e742a50bc24c2c6939dab1e
new file mode 100644
index 0000000..8c0a186
--- /dev/null
+++ b/test/core/json/corpus/f46eeb1020c7c4153e742a50bc24c2c6939dab1e
@@ -0,0 +1 @@
+363
diff --git a/test/core/json/corpus/f473451610783521d51bc08cdd920ddd97f8a71f b/test/core/json/corpus/f473451610783521d51bc08cdd920ddd97f8a71f
new file mode 100644
index 0000000..b73c5ec
--- /dev/null
+++ b/test/core/json/corpus/f473451610783521d51bc08cdd920ddd97f8a71f
@@ -0,0 +1 @@
+{"*]:Ã!{)¾?'ʳ³ !*!à):!*à:::\udbD8\!)!{Ã:{!`!?`¾¾"(¡
\ No newline at end of file
diff --git a/test/core/json/corpus/f63aa599600f6e7d648c4287905e16e8e6e479fd b/test/core/json/corpus/f63aa599600f6e7d648c4287905e16e8e6e479fd
new file mode 100644
index 0000000..4b68125
--- /dev/null
+++ b/test/core/json/corpus/f63aa599600f6e7d648c4287905e16e8e6e479fd
@@ -0,0 +1 @@
+"ˆÃ{)!:"])Ã!:{"*¾?'ʳ³!!*!à):!*à:::\¾;?'ʳud
\ No newline at end of file
diff --git a/test/core/json/corpus/f667dcf1c06e87db2dc49d86ea1c285e796f8f8c b/test/core/json/corpus/f667dcf1c06e87db2dc49d86ea1c285e796f8f8c
new file mode 100644
index 0000000..b6dfbd5
--- /dev/null
+++ b/test/core/json/corpus/f667dcf1c06e87db2dc49d86ea1c285e796f8f8c
@@ -0,0 +1 @@
+813e124280
\ No newline at end of file
diff --git a/test/core/json/corpus/f8d0f85975e49b959799cc52847110cc940b9db1 b/test/core/json/corpus/f8d0f85975e49b959799cc52847110cc940b9db1
new file mode 100644
index 0000000..0c7f592
--- /dev/null
+++ b/test/core/json/corpus/f8d0f85975e49b959799cc52847110cc940b9db1
@@ -0,0 +1 @@
+604
\ No newline at end of file
diff --git a/test/core/json/corpus/f92c47e35da42d79a48beff54b93cd28f55f05fb b/test/core/json/corpus/f92c47e35da42d79a48beff54b93cd28f55f05fb
new file mode 100644
index 0000000..1444ba2
--- /dev/null
+++ b/test/core/json/corpus/f92c47e35da42d79a48beff54b93cd28f55f05fb
@@ -0,0 +1 @@
+1e9
\ No newline at end of file
diff --git a/test/core/json/corpus/f9a33bb8bd78d869fbafa402d9be58940ce2c318 b/test/core/json/corpus/f9a33bb8bd78d869fbafa402d9be58940ce2c318
new file mode 100644
index 0000000..fbcb9da
--- /dev/null
+++ b/test/core/json/corpus/f9a33bb8bd78d869fbafa402d9be58940ce2c318
@@ -0,0 +1 @@
+1E	"ˆÁ960
\ No newline at end of file
diff --git a/test/core/json/corpus/fbf6f3156c1bd4bb701839bc0e26533bdccd1c9a b/test/core/json/corpus/fbf6f3156c1bd4bb701839bc0e26533bdccd1c9a
new file mode 100644
index 0000000..d60f1d8
--- /dev/null
+++ b/test/core/json/corpus/fbf6f3156c1bd4bb701839bc0e26533bdccd1c9a
@@ -0,0 +1 @@
+0,fa%)
\ No newline at end of file
diff --git a/test/core/json/corpus/fe2ef495a1152561572949784c16bf23abb28057 b/test/core/json/corpus/fe2ef495a1152561572949784c16bf23abb28057
new file mode 100644
index 0000000..abc4eff
--- /dev/null
+++ b/test/core/json/corpus/fe2ef495a1152561572949784c16bf23abb28057
@@ -0,0 +1 @@
+46
\ No newline at end of file
diff --git a/test/core/json/corpus/fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f b/test/core/json/corpus/fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f
new file mode 100644
index 0000000..301160a
--- /dev/null
+++ b/test/core/json/corpus/fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f
@@ -0,0 +1 @@
+8
\ No newline at end of file
diff --git a/test/core/json/corpus/ff8fb34603c7f772768d61504954553e6bed173c b/test/core/json/corpus/ff8fb34603c7f772768d61504954553e6bed173c
new file mode 100644
index 0000000..9586ab9
--- /dev/null
+++ b/test/core/json/corpus/ff8fb34603c7f772768d61504954553e6bed173c
@@ -0,0 +1 @@
+n'
\ No newline at end of file
diff --git a/test/core/json/corpus/test1.json b/test/core/json/corpus/test1.json
new file mode 100644
index 0000000..2393cd0
--- /dev/null
+++ b/test/core/json/corpus/test1.json
@@ -0,0 +1 @@
+{"foo":"bar"}
diff --git a/test/core/json/corpus/test2.json b/test/core/json/corpus/test2.json
new file mode 100644
index 0000000..810c96e
--- /dev/null
+++ b/test/core/json/corpus/test2.json
@@ -0,0 +1 @@
+"foo"
diff --git a/test/core/json/corpus/test3.json b/test/core/json/corpus/test3.json
new file mode 100644
index 0000000..8adb9bb
--- /dev/null
+++ b/test/core/json/corpus/test3.json
@@ -0,0 +1 @@
+[1,2,3,4]
diff --git a/test/core/json/corpus/test4.json b/test/core/json/corpus/test4.json
new file mode 100644
index 0000000..4c3fcf9
--- /dev/null
+++ b/test/core/json/corpus/test4.json
@@ -0,0 +1 @@
+1e943923
diff --git a/test/core/json/corpus/test5.json b/test/core/json/corpus/test5.json
new file mode 100644
index 0000000..03f1d79
--- /dev/null
+++ b/test/core/json/corpus/test5.json
@@ -0,0 +1 @@
+100000000000000000000000000000000000000000000000000000000000001
diff --git a/test/core/json/corpus/test6.json b/test/core/json/corpus/test6.json
new file mode 100644
index 0000000..27ba77d
--- /dev/null
+++ b/test/core/json/corpus/test6.json
@@ -0,0 +1 @@
+true
diff --git a/test/core/json/corpus/test7.json b/test/core/json/corpus/test7.json
new file mode 100644
index 0000000..c508d53
--- /dev/null
+++ b/test/core/json/corpus/test7.json
@@ -0,0 +1 @@
+false
diff --git a/test/core/json/corpus/test8.json b/test/core/json/corpus/test8.json
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/test/core/json/corpus/test8.json
@@ -0,0 +1 @@
+null
diff --git a/test/core/json/corpus/test9.json b/test/core/json/corpus/test9.json
new file mode 100644
index 0000000..affaba3
--- /dev/null
+++ b/test/core/json/corpus/test9.json
@@ -0,0 +1 @@
+{"alpha":null,"beta":false,"gamma":2.3,"xyz":"abc","negative":-133}
diff --git a/test/core/json/fuzzer.c b/test/core/json/fuzzer.c
new file mode 100644
index 0000000..e94b41c
--- /dev/null
+++ b/test/core/json/fuzzer.c
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/json/json.h"
+#include "test/core/util/memory_counters.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  char *s;
+  struct grpc_memory_counters counters;
+  grpc_memory_counters_init();
+  s = gpr_malloc(size);
+  memcpy(s, data, size);
+  grpc_json *x;
+  if ((x = grpc_json_parse_string_with_len(s, size))) {
+    grpc_json_destroy(x);
+  }
+  gpr_free(s);
+  counters = grpc_memory_counters_snapshot();
+  grpc_memory_counters_destroy();
+  GPR_ASSERT(counters.total_size_relative == 0);
+  return 0;
+}
diff --git a/test/core/json/json_rewrite.c b/test/core/json/json_rewrite.c
index 0c615a9..c43c6e2 100644
--- a/test/core/json/json_rewrite.c
+++ b/test/core/json/json_rewrite.c
@@ -38,8 +38,8 @@
 #include <grpc/support/cmdline.h>
 #include <grpc/support/log.h>
 
-#include "src/core/json/json_reader.h"
-#include "src/core/json/json_writer.h"
+#include "src/core/lib/json/json_reader.h"
+#include "src/core/lib/json/json_writer.h"
 
 typedef struct json_writer_userdata { FILE *out; } json_writer_userdata;
 
diff --git a/test/core/json/json_rewrite_test.c b/test/core/json/json_rewrite_test.c
index d99cb0d..cf42670 100644
--- a/test/core/json/json_rewrite_test.c
+++ b/test/core/json/json_rewrite_test.c
@@ -35,12 +35,12 @@
 #include <stdlib.h>
 
 #include <grpc/support/alloc.h>
-#include <grpc/support/useful.h>
 #include <grpc/support/log.h>
+#include <grpc/support/useful.h>
 #include "test/core/util/test_config.h"
 
-#include "src/core/json/json_reader.h"
-#include "src/core/json/json_writer.h"
+#include "src/core/lib/json/json_reader.h"
+#include "src/core/lib/json/json_writer.h"
 
 typedef struct json_writer_userdata { FILE *cmp; } json_writer_userdata;
 
diff --git a/test/core/json/json_stream_error_test.c b/test/core/json/json_stream_error_test.c
index 4007767..82b9bd9 100644
--- a/test/core/json/json_stream_error_test.c
+++ b/test/core/json/json_stream_error_test.c
@@ -35,12 +35,12 @@
 #include <stdlib.h>
 
 #include <grpc/support/alloc.h>
-#include <grpc/support/useful.h>
 #include <grpc/support/log.h>
+#include <grpc/support/useful.h>
 #include "test/core/util/test_config.h"
 
-#include "src/core/json/json_reader.h"
-#include "src/core/json/json_writer.h"
+#include "src/core/lib/json/json_reader.h"
+#include "src/core/lib/json/json_writer.h"
 
 static int g_string_clear_once = 0;
 
diff --git a/test/core/json/json_test.c b/test/core/json/json_test.c
index 5add80d..ac1abbd 100644
--- a/test/core/json/json_test.c
+++ b/test/core/json/json_test.c
@@ -34,11 +34,11 @@
 #include <string.h>
 
 #include <grpc/support/alloc.h>
-#include <grpc/support/useful.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
-#include "src/core/json/json.h"
-#include "src/core/support/string.h"
+#include <grpc/support/useful.h>
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/support/string.h"
 
 #include "test/core/util/test_config.h"
 
@@ -64,9 +64,10 @@
     /* Testing UTF-8 character "𝄞", U+11D1E. */
     {"\"\xf0\x9d\x84\x9e\"", "\"\\ud834\\udd1e\""},
     {"\"\\ud834\\udd1e\"", "\"\\ud834\\udd1e\""},
+    {"{\"\\ud834\\udd1e\":0}", "{\"\\ud834\\udd1e\":0}"},
     /* Testing nested empty containers. */
     {
-     " [ [ ] , { } , [ ] ] ", "[[],{},[]]",
+        " [ [ ] , { } , [ ] ] ", "[[],{},[]]",
     },
     /* Testing escapes and control chars in key strings. */
     {" { \"\\u007f\x7f\\n\\r\\\"\\f\\b\\\\a , b\": 1, \"\": 0 } ",
@@ -85,20 +86,33 @@
     /* Testing plain invalid things, exercising the state machine. */
     {"\\", NULL},
     {"nu ll", NULL},
+    {"{\"foo\": bar}", NULL},
+    {"{\"foo\": bar\"x\"}", NULL},
     {"fals", NULL},
+    {"0,0 ", NULL},
+    {"\"foo\",[]", NULL},
     /* Testing unterminated string. */
     {"\"\\x", NULL},
     /* Testing invalid UTF-16 number. */
     {"\"\\u123x", NULL},
+    {"{\"\\u123x", NULL},
     /* Testing imbalanced surrogate pairs. */
     {"\"\\ud834f", NULL},
+    {"{\"\\ud834f\":0}", NULL},
     {"\"\\ud834\\n", NULL},
+    {"{\"\\ud834\\n\":0}", NULL},
     {"\"\\udd1ef", NULL},
+    {"{\"\\udd1ef\":0}", NULL},
     {"\"\\ud834\\ud834\"", NULL},
+    {"{\"\\ud834\\ud834\"\":0}", NULL},
     {"\"\\ud834\\u1234\"", NULL},
+    {"{\"\\ud834\\u1234\"\":0}", NULL},
     {"\"\\ud834]\"", NULL},
+    {"{\"\\ud834]\"\":0}", NULL},
     {"\"\\ud834 \"", NULL},
+    {"{\"\\ud834 \"\":0}", NULL},
     {"\"\\ud834\\\\\"", NULL},
+    {"{\"\\ud834\\\\\"\":0}", NULL},
     /* Testing embedded invalid whitechars. */
     {"\"\n\"", NULL},
     {"\"\t\"", NULL},
diff --git a/test/core/nanopb/corpus_response/0052f8fb6a7884ced8a6754aa13441be1f7dcd51 b/test/core/nanopb/corpus_response/0052f8fb6a7884ced8a6754aa13441be1f7dcd51
new file mode 100644
index 0000000..a88986e
--- /dev/null
+++ b/test/core/nanopb/corpus_response/0052f8fb6a7884ced8a6754aa13441be1f7dcd51
Binary files differ
diff --git a/test/core/nanopb/corpus_response/0c35544f40d428d103e9c5b969ad9cd16767b110 b/test/core/nanopb/corpus_response/0c35544f40d428d103e9c5b969ad9cd16767b110
new file mode 100644
index 0000000..2b5fc99
--- /dev/null
+++ b/test/core/nanopb/corpus_response/0c35544f40d428d103e9c5b969ad9cd16767b110
Binary files differ
diff --git a/test/core/nanopb/corpus_response/0c60ee9ed55c9af6190b132ef6636c1d2abe4540 b/test/core/nanopb/corpus_response/0c60ee9ed55c9af6190b132ef6636c1d2abe4540
new file mode 100644
index 0000000..85366be
--- /dev/null
+++ b/test/core/nanopb/corpus_response/0c60ee9ed55c9af6190b132ef6636c1d2abe4540
@@ -0,0 +1 @@
+½“½“2ƒ;΃;Î)±%Ì))±%Ì)::
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/0ecb3e69889c036a86d21eb942077dc9abd649be b/test/core/nanopb/corpus_response/0ecb3e69889c036a86d21eb942077dc9abd649be
new file mode 100644
index 0000000..74921b2
--- /dev/null
+++ b/test/core/nanopb/corpus_response/0ecb3e69889c036a86d21eb942077dc9abd649be
Binary files differ
diff --git a/test/core/nanopb/corpus_response/1324c95dafe597fe05f9babe92fe6fbf181c1897 b/test/core/nanopb/corpus_response/1324c95dafe597fe05f9babe92fe6fbf181c1897
new file mode 100644
index 0000000..4b7de2e
--- /dev/null
+++ b/test/core/nanopb/corpus_response/1324c95dafe597fe05f9babe92fe6fbf181c1897
@@ -0,0 +1 @@
+(z%;:8!(¼;ªo!>::†©;=È(	);;!ÞØ*:):B(r''' *þEàh;**!!Ý****
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/14eb42f7423081b455820daa2c02b358315dc0fa b/test/core/nanopb/corpus_response/14eb42f7423081b455820daa2c02b358315dc0fa
new file mode 100644
index 0000000..5a07792
--- /dev/null
+++ b/test/core/nanopb/corpus_response/14eb42f7423081b455820daa2c02b358315dc0fa
@@ -0,0 +1 @@
+(z%;:8!(¼;ª!>::†©;=È(	);;!ÞØ*:):B(r''' *þEàh;**!!Ý****
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/23121c5f633db5d7c1a9f2225240754246fee513 b/test/core/nanopb/corpus_response/23121c5f633db5d7c1a9f2225240754246fee513
new file mode 100644
index 0000000..e9db64b
--- /dev/null
+++ b/test/core/nanopb/corpus_response/23121c5f633db5d7c1a9f2225240754246fee513
Binary files differ
diff --git a/test/core/nanopb/corpus_response/235548307ee9f2b0855fded42a871990d9ade956 b/test/core/nanopb/corpus_response/235548307ee9f2b0855fded42a871990d9ade956
new file mode 100644
index 0000000..da1306d
--- /dev/null
+++ b/test/core/nanopb/corpus_response/235548307ee9f2b0855fded42a871990d9ade956
Binary files differ
diff --git a/test/core/nanopb/corpus_response/28ed3a797da3c48c309a4ef792147f3c56cfec40 b/test/core/nanopb/corpus_response/28ed3a797da3c48c309a4ef792147f3c56cfec40
new file mode 100644
index 0000000..f46d387
--- /dev/null
+++ b/test/core/nanopb/corpus_response/28ed3a797da3c48c309a4ef792147f3c56cfec40
@@ -0,0 +1 @@
+(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/2bf123dbfa1d37a04493b5662a4b3b9c147485fc b/test/core/nanopb/corpus_response/2bf123dbfa1d37a04493b5662a4b3b9c147485fc
new file mode 100644
index 0000000..7ea0b41
--- /dev/null
+++ b/test/core/nanopb/corpus_response/2bf123dbfa1d37a04493b5662a4b3b9c147485fc
Binary files differ
diff --git a/test/core/nanopb/corpus_response/2d4c0908ecc0310ea234d10b6bdb4f4ca3c41dd1 b/test/core/nanopb/corpus_response/2d4c0908ecc0310ea234d10b6bdb4f4ca3c41dd1
new file mode 100644
index 0000000..cd74051
--- /dev/null
+++ b/test/core/nanopb/corpus_response/2d4c0908ecc0310ea234d10b6bdb4f4ca3c41dd1
@@ -0,0 +1 @@
+):):\bJ'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/304e8cdc9122b709ec2c063a5c8c38489a788033 b/test/core/nanopb/corpus_response/304e8cdc9122b709ec2c063a5c8c38489a788033
new file mode 100644
index 0000000..a7571c0
--- /dev/null
+++ b/test/core/nanopb/corpus_response/304e8cdc9122b709ec2c063a5c8c38489a788033
Binary files differ
diff --git a/test/core/nanopb/corpus_response/324d4a2aed8bc1840fee212fd38dadec80a72ea2 b/test/core/nanopb/corpus_response/324d4a2aed8bc1840fee212fd38dadec80a72ea2
new file mode 100644
index 0000000..9ca38b3
--- /dev/null
+++ b/test/core/nanopb/corpus_response/324d4a2aed8bc1840fee212fd38dadec80a72ea2
Binary files differ
diff --git a/test/core/nanopb/corpus_response/33353a0b011901a13d010c6b165074ccdaa717ac b/test/core/nanopb/corpus_response/33353a0b011901a13d010c6b165074ccdaa717ac
new file mode 100644
index 0000000..9320a7a
--- /dev/null
+++ b/test/core/nanopb/corpus_response/33353a0b011901a13d010c6b165074ccdaa717ac
@@ -0,0 +1 @@
+ž½“ƒÎ)±Ì)::\!;):bJ):'\éb*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/37dfead09389fcd9b9d24ef817a0fed13d8ff2b0 b/test/core/nanopb/corpus_response/37dfead09389fcd9b9d24ef817a0fed13d8ff2b0
new file mode 100644
index 0000000..725e601
--- /dev/null
+++ b/test/core/nanopb/corpus_response/37dfead09389fcd9b9d24ef817a0fed13d8ff2b0
Binary files differ
diff --git a/test/core/nanopb/corpus_response/47879cc364be304754f6af15563ad6f9a538da41 b/test/core/nanopb/corpus_response/47879cc364be304754f6af15563ad6f9a538da41
new file mode 100644
index 0000000..b42661c
--- /dev/null
+++ b/test/core/nanopb/corpus_response/47879cc364be304754f6af15563ad6f9a538da41
Binary files differ
diff --git a/test/core/nanopb/corpus_response/49a5cef4c730ecab22712b156ddba5106f165afd b/test/core/nanopb/corpus_response/49a5cef4c730ecab22712b156ddba5106f165afd
new file mode 100644
index 0000000..4a551cf
--- /dev/null
+++ b/test/core/nanopb/corpus_response/49a5cef4c730ecab22712b156ddba5106f165afd
@@ -0,0 +1 @@
+(z!;:8!(¼;ªo!>::†©;=È(	);ö;!ÞØ*:):B(r''' *þEàh;**!!Ý****
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/4bbbbb794a098deeacff73b774c30f12c54ceacb b/test/core/nanopb/corpus_response/4bbbbb794a098deeacff73b774c30f12c54ceacb
new file mode 100644
index 0000000..d99c09f
--- /dev/null
+++ b/test/core/nanopb/corpus_response/4bbbbb794a098deeacff73b774c30f12c54ceacb
@@ -0,0 +1 @@
+(z%;28!(¼;ª!*>::†(z%;28!(¼;ª!>::†ùâåò©
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/4c498ce69c8476f745693deb23272930e05cad60 b/test/core/nanopb/corpus_response/4c498ce69c8476f745693deb23272930e05cad60
new file mode 100644
index 0000000..8618194
--- /dev/null
+++ b/test/core/nanopb/corpus_response/4c498ce69c8476f745693deb23272930e05cad60
Binary files differ
diff --git a/test/core/nanopb/corpus_response/4fb5e3085c32e9bccac9e18343cca07017d037de b/test/core/nanopb/corpus_response/4fb5e3085c32e9bccac9e18343cca07017d037de
new file mode 100644
index 0000000..59a8026
--- /dev/null
+++ b/test/core/nanopb/corpus_response/4fb5e3085c32e9bccac9e18343cca07017d037de
Binary files differ
diff --git a/test/core/nanopb/corpus_response/4fe5e46c1299e7f3e8a41dde3ae1bf1b60b4a43c b/test/core/nanopb/corpus_response/4fe5e46c1299e7f3e8a41dde3ae1bf1b60b4a43c
new file mode 100644
index 0000000..3d44fad
--- /dev/null
+++ b/test/core/nanopb/corpus_response/4fe5e46c1299e7f3e8a41dde3ae1bf1b60b4a43c
@@ -0,0 +1 @@
+a¶(6)!á•(	!!)b:'Ü:*¤();Ì0();)Ï(|)ÿ!V)'*¡!t<b߶…*!(b*()(:dVj)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/670cc6bae958cb4f15e7297fe63959ac5799aa42 b/test/core/nanopb/corpus_response/670cc6bae958cb4f15e7297fe63959ac5799aa42
new file mode 100644
index 0000000..2489cb7
--- /dev/null
+++ b/test/core/nanopb/corpus_response/670cc6bae958cb4f15e7297fe63959ac5799aa42
Binary files differ
diff --git a/test/core/nanopb/corpus_response/675f3263af7d1bbb084872f2b23f6d363227e85d b/test/core/nanopb/corpus_response/675f3263af7d1bbb084872f2b23f6d363227e85d
new file mode 100644
index 0000000..d2fb75c
--- /dev/null
+++ b/test/core/nanopb/corpus_response/675f3263af7d1bbb084872f2b23f6d363227e85d
Binary files differ
diff --git a/test/core/nanopb/corpus_response/67fe0d2acc727c8a39a707b92c6cebda9bd20986 b/test/core/nanopb/corpus_response/67fe0d2acc727c8a39a707b92c6cebda9bd20986
new file mode 100644
index 0000000..0ba194a
--- /dev/null
+++ b/test/core/nanopb/corpus_response/67fe0d2acc727c8a39a707b92c6cebda9bd20986
@@ -0,0 +1 @@
+½™'Ì)%±ƒ™Þ):
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/6995dd153f712ad257ab5a365e5a4b84dc676ed3 b/test/core/nanopb/corpus_response/6995dd153f712ad257ab5a365e5a4b84dc676ed3
new file mode 100644
index 0000000..a9ae5ff
--- /dev/null
+++ b/test/core/nanopb/corpus_response/6995dd153f712ad257ab5a365e5a4b84dc676ed3
Binary files differ
diff --git a/test/core/nanopb/corpus_response/6d15065785eb8f4b5f17357a520cb4815a2cb355 b/test/core/nanopb/corpus_response/6d15065785eb8f4b5f17357a520cb4815a2cb355
new file mode 100644
index 0000000..98da1dd
--- /dev/null
+++ b/test/core/nanopb/corpus_response/6d15065785eb8f4b5f17357a520cb4815a2cb355
@@ -0,0 +1 @@
+½™'ƒÎ)±%Ì):
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/73285d7a70d73b517648067520d921e4477dbbfa b/test/core/nanopb/corpus_response/73285d7a70d73b517648067520d921e4477dbbfa
new file mode 100644
index 0000000..193b899
--- /dev/null
+++ b/test/core/nanopb/corpus_response/73285d7a70d73b517648067520d921e4477dbbfa
Binary files differ
diff --git a/test/core/nanopb/corpus_response/747d1ed8bee4c6f0438beaf88ae76d8ef9f63da2 b/test/core/nanopb/corpus_response/747d1ed8bee4c6f0438beaf88ae76d8ef9f63da2
new file mode 100644
index 0000000..8387eab
--- /dev/null
+++ b/test/core/nanopb/corpus_response/747d1ed8bee4c6f0438beaf88ae76d8ef9f63da2
@@ -0,0 +1 @@
+½¤½“ž½“ƒÎ½ƒ);Î)±
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/763878a34b3adeb99a03b54d09768a4451617016 b/test/core/nanopb/corpus_response/763878a34b3adeb99a03b54d09768a4451617016
new file mode 100644
index 0000000..9c5c365
--- /dev/null
+++ b/test/core/nanopb/corpus_response/763878a34b3adeb99a03b54d09768a4451617016
@@ -0,0 +1 @@
+½“ž½“ƒÎ)ƒ;Î)±%Ì):
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/7b4b0c2555178333ba15203a930c88ef7e7500e7 b/test/core/nanopb/corpus_response/7b4b0c2555178333ba15203a930c88ef7e7500e7
new file mode 100644
index 0000000..b14d25a
--- /dev/null
+++ b/test/core/nanopb/corpus_response/7b4b0c2555178333ba15203a930c88ef7e7500e7
Binary files differ
diff --git a/test/core/nanopb/corpus_response/7b8a91aa46e370eb61307b4998889dc89775462f b/test/core/nanopb/corpus_response/7b8a91aa46e370eb61307b4998889dc89775462f
new file mode 100644
index 0000000..4061b65
--- /dev/null
+++ b/test/core/nanopb/corpus_response/7b8a91aa46e370eb61307b4998889dc89775462f
@@ -0,0 +1 @@
+	:)½:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/7cd11836c64f98742fa7beccec5c981ef4dd62ae b/test/core/nanopb/corpus_response/7cd11836c64f98742fa7beccec5c981ef4dd62ae
new file mode 100644
index 0000000..86fd08f
--- /dev/null
+++ b/test/core/nanopb/corpus_response/7cd11836c64f98742fa7beccec5c981ef4dd62ae
Binary files differ
diff --git a/test/core/nanopb/corpus_response/7d8f4f045e70e8a2cb45dc3c001504f5c2614b16 b/test/core/nanopb/corpus_response/7d8f4f045e70e8a2cb45dc3c001504f5c2614b16
new file mode 100644
index 0000000..dd8d136
--- /dev/null
+++ b/test/core/nanopb/corpus_response/7d8f4f045e70e8a2cb45dc3c001504f5c2614b16
Binary files differ
diff --git a/test/core/nanopb/corpus_response/7e9848558fb004e14795b3ebd3e1488dcde1db8c b/test/core/nanopb/corpus_response/7e9848558fb004e14795b3ebd3e1488dcde1db8c
new file mode 100644
index 0000000..be0dfca
--- /dev/null
+++ b/test/core/nanopb/corpus_response/7e9848558fb004e14795b3ebd3e1488dcde1db8c
@@ -0,0 +1 @@
+ùâåò!Ù.!Nñrª:U:(œ;!á)*(¾):!'i)b):þ°)'!P!:'á•***!)H:*)(àñÍ*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/89734c37ee267e69a6950c6d60ee541c1be5ccff b/test/core/nanopb/corpus_response/89734c37ee267e69a6950c6d60ee541c1be5ccff
new file mode 100644
index 0000000..023ef36
--- /dev/null
+++ b/test/core/nanopb/corpus_response/89734c37ee267e69a6950c6d60ee541c1be5ccff
Binary files differ
diff --git a/test/core/nanopb/corpus_response/9034aaf45143996a2b14465c352ab0c6fa26b221 b/test/core/nanopb/corpus_response/9034aaf45143996a2b14465c352ab0c6fa26b221
new file mode 100644
index 0000000..9c95a6b
--- /dev/null
+++ b/test/core/nanopb/corpus_response/9034aaf45143996a2b14465c352ab0c6fa26b221
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/91e3b6a3484ab4b95cdeecc5aefe1291824060e8 b/test/core/nanopb/corpus_response/91e3b6a3484ab4b95cdeecc5aefe1291824060e8
new file mode 100644
index 0000000..8d735ea
--- /dev/null
+++ b/test/core/nanopb/corpus_response/91e3b6a3484ab4b95cdeecc5aefe1291824060e8
@@ -0,0 +1 @@
+m!''÷:)ˆ');:Q(*á'!!m!Í()!;e''÷:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/95cd94c858e5e97f7df4a5eb7552e5e0d5ce1ec4 b/test/core/nanopb/corpus_response/95cd94c858e5e97f7df4a5eb7552e5e0d5ce1ec4
new file mode 100644
index 0000000..df2d819
--- /dev/null
+++ b/test/core/nanopb/corpus_response/95cd94c858e5e97f7df4a5eb7552e5e0d5ce1ec4
@@ -0,0 +1 @@
+	:)½:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/971f42d5a4d9816145ebc9dd28ba33ed3f5860b0 b/test/core/nanopb/corpus_response/971f42d5a4d9816145ebc9dd28ba33ed3f5860b0
new file mode 100644
index 0000000..edd078a
--- /dev/null
+++ b/test/core/nanopb/corpus_response/971f42d5a4d9816145ebc9dd28ba33ed3f5860b0
Binary files differ
diff --git a/test/core/nanopb/corpus_response/9db3a1854de87fd643b910aeab50553afc73e667 b/test/core/nanopb/corpus_response/9db3a1854de87fd643b910aeab50553afc73e667
new file mode 100644
index 0000000..7cbc8b7
--- /dev/null
+++ b/test/core/nanopb/corpus_response/9db3a1854de87fd643b910aeab50553afc73e667
Binary files differ
diff --git a/test/core/nanopb/corpus_response/a147873135c6c52d4da03c260a0165bc0ab1b979 b/test/core/nanopb/corpus_response/a147873135c6c52d4da03c260a0165bc0ab1b979
new file mode 100644
index 0000000..2f0a565
--- /dev/null
+++ b/test/core/nanopb/corpus_response/a147873135c6c52d4da03c260a0165bc0ab1b979
Binary files differ
diff --git a/test/core/nanopb/corpus_response/a710eead945dabbbffa213a980c75f9463a27398 b/test/core/nanopb/corpus_response/a710eead945dabbbffa213a980c75f9463a27398
new file mode 100644
index 0000000..3bc30a1
--- /dev/null
+++ b/test/core/nanopb/corpus_response/a710eead945dabbbffa213a980c75f9463a27398
@@ -0,0 +1 @@
+½“ƒ;Î)±%Ì):
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/a72406e3ca06d941fe8e168bbf67da88a81c947b b/test/core/nanopb/corpus_response/a72406e3ca06d941fe8e168bbf67da88a81c947b
new file mode 100644
index 0000000..811a33d
--- /dev/null
+++ b/test/core/nanopb/corpus_response/a72406e3ca06d941fe8e168bbf67da88a81c947b
@@ -0,0 +1 @@
+¼™'Ì)%±ƒ™Þ½)“½“2ƒ;΃;Î)±%Ì):)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/a8a62a7ebb7d68b211ae319e082575935c07d188 b/test/core/nanopb/corpus_response/a8a62a7ebb7d68b211ae319e082575935c07d188
new file mode 100644
index 0000000..7712307
--- /dev/null
+++ b/test/core/nanopb/corpus_response/a8a62a7ebb7d68b211ae319e082575935c07d188
Binary files differ
diff --git a/test/core/nanopb/corpus_response/a8abd012eb59b862bf9bc1ea443d2f35a1a2e222 b/test/core/nanopb/corpus_response/a8abd012eb59b862bf9bc1ea443d2f35a1a2e222
new file mode 100644
index 0000000..3f1695f
--- /dev/null
+++ b/test/core/nanopb/corpus_response/a8abd012eb59b862bf9bc1ea443d2f35a1a2e222
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/aab56035a3533b5d83a32a439f179eb678250113 b/test/core/nanopb/corpus_response/aab56035a3533b5d83a32a439f179eb678250113
new file mode 100644
index 0000000..c9f9b4d
--- /dev/null
+++ b/test/core/nanopb/corpus_response/aab56035a3533b5d83a32a439f179eb678250113
Binary files differ
diff --git a/test/core/nanopb/corpus_response/ac174acef2c5da26fadc7270bab9c8c4e938c463 b/test/core/nanopb/corpus_response/ac174acef2c5da26fadc7270bab9c8c4e938c463
new file mode 100644
index 0000000..a929daa
--- /dev/null
+++ b/test/core/nanopb/corpus_response/ac174acef2c5da26fadc7270bab9c8c4e938c463
@@ -0,0 +1 @@
+z(!;:8!(¼;ªo!>::†©;=È(	);ö;!ÞØ*:):B(r''' *Eàhþ;**!!Ý****
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/acbbd60eeb76e41ce254d0fef353b92abe69c831 b/test/core/nanopb/corpus_response/acbbd60eeb76e41ce254d0fef353b92abe69c831
new file mode 100644
index 0000000..da47491
--- /dev/null
+++ b/test/core/nanopb/corpus_response/acbbd60eeb76e41ce254d0fef353b92abe69c831
@@ -0,0 +1,2 @@
+½ƒ;Î)±}!;*;*°'';y©É:p	+'!(S‘ð?±(¬;I:;:*:w!)èŽwÄÂ)>Å?)N!õ;)—
+'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/c1eed32e1e353737987da851ad760312ea8e557c b/test/core/nanopb/corpus_response/c1eed32e1e353737987da851ad760312ea8e557c
new file mode 100644
index 0000000..8f8d149
--- /dev/null
+++ b/test/core/nanopb/corpus_response/c1eed32e1e353737987da851ad760312ea8e557c
@@ -0,0 +1 @@
+½)ƒ;Î)±}):):\!;):bJ):'\b*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/c4214ace2c4bab24bb356f71aedca08544baad70 b/test/core/nanopb/corpus_response/c4214ace2c4bab24bb356f71aedca08544baad70
new file mode 100644
index 0000000..ae25d72
--- /dev/null
+++ b/test/core/nanopb/corpus_response/c4214ace2c4bab24bb356f71aedca08544baad70
@@ -0,0 +1 @@
+):\bJ'!:׸¶…''*Ž;»*j:M[(…¤!yæ“:)T²P'^)(0©!e&–°ˆ(*W;Ânc''(!$)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/c4f87a6290aee1acfc1f26083974ce94621fca64 b/test/core/nanopb/corpus_response/c4f87a6290aee1acfc1f26083974ce94621fca64
new file mode 100644
index 0000000..a4ceb35
--- /dev/null
+++ b/test/core/nanopb/corpus_response/c4f87a6290aee1acfc1f26083974ce94621fca64
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/d285d78d3ba966b4b199453d38ead1aa36a7484f b/test/core/nanopb/corpus_response/d285d78d3ba966b4b199453d38ead1aa36a7484f
new file mode 100644
index 0000000..91b1d68
--- /dev/null
+++ b/test/core/nanopb/corpus_response/d285d78d3ba966b4b199453d38ead1aa36a7484f
Binary files differ
diff --git a/test/core/nanopb/corpus_response/df5200f371cff3cae0e1595cd86d641725f5d1ba b/test/core/nanopb/corpus_response/df5200f371cff3cae0e1595cd86d641725f5d1ba
new file mode 100644
index 0000000..bfd9f8b
--- /dev/null
+++ b/test/core/nanopb/corpus_response/df5200f371cff3cae0e1595cd86d641725f5d1ba
@@ -0,0 +1 @@
+((³34('‰Äúx¡'¦/8(ô](:'çxR$;§'*”!(Ú(!k:(³;;*(/'-½':*:mç4'å%·Â
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/dfc66cb172919102f3ba14f6816228aa46f78154 b/test/core/nanopb/corpus_response/dfc66cb172919102f3ba14f6816228aa46f78154
new file mode 100644
index 0000000..13f69eb
--- /dev/null
+++ b/test/core/nanopb/corpus_response/dfc66cb172919102f3ba14f6816228aa46f78154
@@ -0,0 +1 @@
+(z%;28!(¼;ª!>::†©;=(	;;)!ȏÞØm!''÷:)ˆ*:')
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/e53e789a4c175c6a2c468472f1047d0fe8db1177 b/test/core/nanopb/corpus_response/e53e789a4c175c6a2c468472f1047d0fe8db1177
new file mode 100644
index 0000000..a6991c8
--- /dev/null
+++ b/test/core/nanopb/corpus_response/e53e789a4c175c6a2c468472f1047d0fe8db1177
Binary files differ
diff --git a/test/core/nanopb/corpus_response/e67fe6794e755ea801272980f2c272edb027f6dc b/test/core/nanopb/corpus_response/e67fe6794e755ea801272980f2c272edb027f6dc
new file mode 100644
index 0000000..1b14867
--- /dev/null
+++ b/test/core/nanopb/corpus_response/e67fe6794e755ea801272980f2c272edb027f6dc
@@ -0,0 +1 @@
+½“ƒ;Î)±Ì):;:\!;):bJ):'\b*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/ead61e86fedf118df8e44ed70ce002be651cf291 b/test/core/nanopb/corpus_response/ead61e86fedf118df8e44ed70ce002be651cf291
new file mode 100644
index 0000000..a4c11a7
--- /dev/null
+++ b/test/core/nanopb/corpus_response/ead61e86fedf118df8e44ed70ce002be651cf291
Binary files differ
diff --git a/test/core/nanopb/corpus_response/eced8b29efbdc82eb8a1d0865c5f382f0ff78446 b/test/core/nanopb/corpus_response/eced8b29efbdc82eb8a1d0865c5f382f0ff78446
new file mode 100644
index 0000000..a0f0de0
--- /dev/null
+++ b/test/core/nanopb/corpus_response/eced8b29efbdc82eb8a1d0865c5f382f0ff78446
@@ -0,0 +1 @@
+(z%;28!(¼;ª!*>::†(z%;28!(¼;ª!>::†©©Ï
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/f107c60f00da44a2c412c5b89c733efe5f9be4aa b/test/core/nanopb/corpus_response/f107c60f00da44a2c412c5b89c733efe5f9be4aa
new file mode 100644
index 0000000..2bd503a
--- /dev/null
+++ b/test/core/nanopb/corpus_response/f107c60f00da44a2c412c5b89c733efe5f9be4aa
Binary files differ
diff --git a/test/core/nanopb/corpus_response/f58a9135d07ea9a5e3e710f6b3bf6d48d5942dfd b/test/core/nanopb/corpus_response/f58a9135d07ea9a5e3e710f6b3bf6d48d5942dfd
new file mode 100644
index 0000000..17dfae3
--- /dev/null
+++ b/test/core/nanopb/corpus_response/f58a9135d07ea9a5e3e710f6b3bf6d48d5942dfd
Binary files differ
diff --git a/test/core/nanopb/corpus_response/f8c2c4ddd2f474b4839f13a9be862c00ab0ece77 b/test/core/nanopb/corpus_response/f8c2c4ddd2f474b4839f13a9be862c00ab0ece77
new file mode 100644
index 0000000..a94e0c8
--- /dev/null
+++ b/test/core/nanopb/corpus_response/f8c2c4ddd2f474b4839f13a9be862c00ab0ece77
Binary files differ
diff --git a/test/core/nanopb/corpus_response/faa1781e1444bba5b8c677bc5e2a38d023a1ec65 b/test/core/nanopb/corpus_response/faa1781e1444bba5b8c677bc5e2a38d023a1ec65
new file mode 100644
index 0000000..013d565
--- /dev/null
+++ b/test/core/nanopb/corpus_response/faa1781e1444bba5b8c677bc5e2a38d023a1ec65
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/core/nanopb/corpus_response/fccda587af845f0685275960649d8f4a45272a95 b/test/core/nanopb/corpus_response/fccda587af845f0685275960649d8f4a45272a95
new file mode 100644
index 0000000..cfdf879
--- /dev/null
+++ b/test/core/nanopb/corpus_response/fccda587af845f0685275960649d8f4a45272a95
@@ -0,0 +1 @@
+½™'Ì)%±'ƒ™Þ½)ƒ;Î)±}9:):\!;):bJ)):'\:b*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/000def12957806bb0d40005cb651d35b4cde7b4e b/test/core/nanopb/corpus_serverlist/000def12957806bb0d40005cb651d35b4cde7b4e
new file mode 100644
index 0000000..3144257
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/000def12957806bb0d40005cb651d35b4cde7b4e
@@ -0,0 +1,3 @@
+	É=Éÿ
+'!
+É)='!'ïï'½=ï!)**Í
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0068af2acc3020f344ee84b2c8adfb90492354c3 b/test/core/nanopb/corpus_serverlist/0068af2acc3020f344ee84b2c8adfb90492354c3
new file mode 100644
index 0000000..d2ae365
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0068af2acc3020f344ee84b2c8adfb90492354c3
@@ -0,0 +1 @@
+Á²²Wo:'ì*'!@*(Á*!)(@)ÁP²²²²(!(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/009132022c3a1660b701728ac92e26baf82e8eac b/test/core/nanopb/corpus_serverlist/009132022c3a1660b701728ac92e26baf82e8eac
new file mode 100644
index 0000000..1b9e2f9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/009132022c3a1660b701728ac92e26baf82e8eac
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/00bf0233aa1155b34a3081e4a2b7a1c9cdf8ea1e b/test/core/nanopb/corpus_serverlist/00bf0233aa1155b34a3081e4a2b7a1c9cdf8ea1e
new file mode 100644
index 0000000..3fc89e8
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/00bf0233aa1155b34a3081e4a2b7a1c9cdf8ea1e
@@ -0,0 +1,2 @@
+Ų;Ų
+UõUú‰Ù(		Ų;²UUú‰*Ų;²UÅÙ(Ž²'Ö!…z%)#­€
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/013197cfb12b59755b807501c6d6615859f9cd3f b/test/core/nanopb/corpus_serverlist/013197cfb12b59755b807501c6d6615859f9cd3f
new file mode 100644
index 0000000..ae044dc
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/013197cfb12b59755b807501c6d6615859f9cd3f
@@ -0,0 +1 @@
+)Û)¦­'U!a	Øç•ÏøÉ=*×Éÿ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/018a4332eb19f2398162317cb6ad2e8cf700dfd6 b/test/core/nanopb/corpus_serverlist/018a4332eb19f2398162317cb6ad2e8cf700dfd6
new file mode 100644
index 0000000..2519ccb
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/018a4332eb19f2398162317cb6ad2e8cf700dfd6
@@ -0,0 +1 @@
+)B!B!à@)ò);'Ǔ¢ƒ§'à@*::sED'tÂ'–!();!)*!­)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0273d3496bf5f4594e59083ac319f8f863a15be0 b/test/core/nanopb/corpus_serverlist/0273d3496bf5f4594e59083ac319f8f863a15be0
new file mode 100644
index 0000000..609e652
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0273d3496bf5f4594e59083ac319f8f863a15be0
@@ -0,0 +1 @@
+Á²•Wo:'ì*#!@	:*)Á²²Wo:'Wo*'!@*()*()@)(!:)Áü²²²(!'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0355002521e74dcdb3a0c633338bd02ab1d85312 b/test/core/nanopb/corpus_serverlist/0355002521e74dcdb3a0c633338bd02ab1d85312
new file mode 100644
index 0000000..6e2df12
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0355002521e74dcdb3a0c633338bd02ab1d85312
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*')
+!((š;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©ä(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/053d8d6ceeba9453c97d0ee5374db863e6f77ad4 b/test/core/nanopb/corpus_serverlist/053d8d6ceeba9453c97d0ee5374db863e6f77ad4
new file mode 100644
index 0000000..268720a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/053d8d6ceeba9453c97d0ee5374db863e6f77ad4
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/0628c29e3ae264f8fa08652435bb3e61afe60883 b/test/core/nanopb/corpus_serverlist/0628c29e3ae264f8fa08652435bb3e61afe60883
new file mode 100644
index 0000000..235fa37
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0628c29e3ae264f8fa08652435bb3e61afe60883
@@ -0,0 +1 @@
+2;ò•:.<ý:*::ƒž*Š):’ªÜ:2;ò•:ô(ã**.<ý:*::ƒž*Š)!'dv!*!”¾(;'**:W
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/065e91578e5359b70a668164310af6f0dd40e922 b/test/core/nanopb/corpus_serverlist/065e91578e5359b70a668164310af6f0dd40e922
new file mode 100644
index 0000000..25d7947
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/065e91578e5359b70a668164310af6f0dd40e922
@@ -0,0 +1,2 @@
+
+Á²²ò
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/06b4b617d5937da8a7b58aed5341dc5ef6d1bcd7 b/test/core/nanopb/corpus_serverlist/06b4b617d5937da8a7b58aed5341dc5ef6d1bcd7
new file mode 100644
index 0000000..78bdaad
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/06b4b617d5937da8a7b58aed5341dc5ef6d1bcd7
@@ -0,0 +1 @@
+!¼;)@oCÙ
diff --git a/test/core/nanopb/corpus_serverlist/07216a4f5934890b89d845f6256546c2681350ce b/test/core/nanopb/corpus_serverlist/07216a4f5934890b89d845f6256546c2681350ce
new file mode 100644
index 0000000..e48a1b5
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/07216a4f5934890b89d845f6256546c2681350ce
@@ -0,0 +1,3 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×'	É=Éÿ
+!'!É
+)='!'ïïÉ=ÿ'):(:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/08584e8308b7f52f0fe380358800d7f585cba89c b/test/core/nanopb/corpus_serverlist/08584e8308b7f52f0fe380358800d7f585cba89c
new file mode 100644
index 0000000..20fafee
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/08584e8308b7f52f0fe380358800d7f585cba89c
@@ -0,0 +1 @@
+Øì÷(!½Æ)!5Sã::`…¶(p½!'e€*'U)))(:)婤;*:!p(È':Ö¶;óÑ))e);À'!;:µ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/085a37568e99ec5855bd96affd259921515479e8 b/test/core/nanopb/corpus_serverlist/085a37568e99ec5855bd96affd259921515479e8
new file mode 100644
index 0000000..b441046
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/085a37568e99ec5855bd96affd259921515479e8
@@ -0,0 +1,2 @@
+Á²•W!o:'ì*#!Á::()*@:)Á|²²²Á;9!'
+²Áƒ'’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0903d1e9297179c18de6a3707b16f27d0d54ed67 b/test/core/nanopb/corpus_serverlist/0903d1e9297179c18de6a3707b16f27d0d54ed67
new file mode 100644
index 0000000..ccb513d
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0903d1e9297179c18de6a3707b16f27d0d54ed67
@@ -0,0 +1 @@
+(Õ';¤**´'Xò;)()<!*Â9*!(t;*î{R'! *:Èz!µ\ù;(U^Ò)a8ä(:Î'Çuy';**
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0aa20a75bff4e8af10330c66d288e900146f1a39 b/test/core/nanopb/corpus_serverlist/0aa20a75bff4e8af10330c66d288e900146f1a39
new file mode 100644
index 0000000..8d2d5e9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0aa20a75bff4e8af10330c66d288e900146f1a39
@@ -0,0 +1 @@
+)*!B!Óà@'))ò);'Ǔ¹¢ƒ§U)àB!B
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0ae76e2b24ca999bd5e09e517aa4d88f5b5f58a4 b/test/core/nanopb/corpus_serverlist/0ae76e2b24ca999bd5e09e517aa4d88f5b5f58a4
new file mode 100644
index 0000000..dd58fda
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0ae76e2b24ca999bd5e09e517aa4d88f5b5f58a4
@@ -0,0 +1 @@
+Á²•Wì:o#'*!@Á²²Wo:'Wo:::*')
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0c3025fdfb008a6563ea2a2bb6cbc79b8ccbf8f3 b/test/core/nanopb/corpus_serverlist/0c3025fdfb008a6563ea2a2bb6cbc79b8ccbf8f3
new file mode 100644
index 0000000..6ec1b09
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0c3025fdfb008a6563ea2a2bb6cbc79b8ccbf8f3
@@ -0,0 +1,2 @@
+Ų;IJ
+UUú‰™(		!MÁ²²²Á²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0d219165cd317142afa36b8b5476cc022c95c4e6 b/test/core/nanopb/corpus_serverlist/0d219165cd317142afa36b8b5476cc022c95c4e6
new file mode 100644
index 0000000..6ac63d3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0d219165cd317142afa36b8b5476cc022c95c4e6
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/0e053123dd6256de5aff55b0731f913de250c18e b/test/core/nanopb/corpus_serverlist/0e053123dd6256de5aff55b0731f913de250c18e
new file mode 100644
index 0000000..b0f591e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0e053123dd6256de5aff55b0731f913de250c18e
@@ -0,0 +1,2 @@
+!'	§'*	É=Éÿ
+	'=ï!)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0e065f98325849ac05eed515865b33dba0264cd4 b/test/core/nanopb/corpus_serverlist/0e065f98325849ac05eed515865b33dba0264cd4
new file mode 100644
index 0000000..220e90b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0e065f98325849ac05eed515865b33dba0264cd4
@@ -0,0 +1 @@
+!'*.*:*’P§
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0e4ff715d491c9f0b471c400b71804739b6d400a b/test/core/nanopb/corpus_serverlist/0e4ff715d491c9f0b471c400b71804739b6d400a
new file mode 100644
index 0000000..c25468a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0e4ff715d491c9f0b471c400b71804739b6d400a
@@ -0,0 +1,2 @@
+!¼+@oCÙ'–((!*Ú*'‚'*')!!¼;@oCÙ'–((!*Ú*''*'	!
+’Œš;!x!(*(:)ÞN˚
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0ec94942046cd7e00bc058204c1d046075ca9531 b/test/core/nanopb/corpus_serverlist/0ec94942046cd7e00bc058204c1d046075ca9531
new file mode 100644
index 0000000..0184c3c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0ec94942046cd7e00bc058204c1d046075ca9531
@@ -0,0 +1 @@
+ȯõÜ!:)'*l:*\!D)…');ȯõÜ!WѯÈѯ2Ü:!:*ò)!D\õ*:l)…');W‘¯õÈѯÜ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0f0e8da530eb8c924cee6985d9c3dfd93274ef8c b/test/core/nanopb/corpus_serverlist/0f0e8da530eb8c924cee6985d9c3dfd93274ef8c
new file mode 100644
index 0000000..d49c2ca
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0f0e8da530eb8c924cee6985d9c3dfd93274ef8c
@@ -0,0 +1 @@
+'P:*!/!;'Ù*;kÜ*!'l;À‚°Q'(¼ã:)'*î#â;+Ç»(›²(«;w'!*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/0ff365225c981d74b89499d1e708684ed4d0b570 b/test/core/nanopb/corpus_serverlist/0ff365225c981d74b89499d1e708684ed4d0b570
new file mode 100644
index 0000000..101f136
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/0ff365225c981d74b89499d1e708684ed4d0b570
@@ -0,0 +1,2 @@
+!]!à
+!ØØìƽ÷ìƽ‰÷( )!!;n(!!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/113b1efff1677c1b9a24f89aec0c3ecc228ddf62 b/test/core/nanopb/corpus_serverlist/113b1efff1677c1b9a24f89aec0c3ecc228ddf62
new file mode 100644
index 0000000..2ed09e8
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/113b1efff1677c1b9a24f89aec0c3ecc228ddf62
@@ -0,0 +1,2 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×'	É=Éÿ
+'!pÉ)='!'ïïÉ=ÿ'):(:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/11697d621eab6743ba22715722d5b23830b79075 b/test/core/nanopb/corpus_serverlist/11697d621eab6743ba22715722d5b23830b79075
new file mode 100644
index 0000000..afbff83
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/11697d621eab6743ba22715722d5b23830b79075
@@ -0,0 +1 @@
+P:*:!/!;'Ù*;kÜ*!'l;À‚°Ê'¼Q:)'*;#+âîÇ»(›²(«;w'!*!J;Ó**)))r
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/12463318b795c756f389bc0fb1cca9645eafef28 b/test/core/nanopb/corpus_serverlist/12463318b795c756f389bc0fb1cca9645eafef28
new file mode 100644
index 0000000..1d5fe16
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/12463318b795c756f389bc0fb1cca9645eafef28
@@ -0,0 +1 @@
+!)fB!(j)ò	!)!Z!'!*M)!:“ ó'ØH(ã‰T('¯fBÒ!û)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/12784250cf16ec999529f601ae5c5798e853d34a b/test/core/nanopb/corpus_serverlist/12784250cf16ec999529f601ae5c5798e853d34a
new file mode 100644
index 0000000..f38c8f1
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/12784250cf16ec999529f601ae5c5798e853d34a
@@ -0,0 +1 @@
+2;ò•:.<ý:*::ƒž*Š):’ªÜ:ô(ã**!'dv!*!”¾(;'**W›!Øâ(!;;:/*f§¨Ça°î
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/13122d08c1cee0dae6434605917d4cc6d8ea8cc5 b/test/core/nanopb/corpus_serverlist/13122d08c1cee0dae6434605917d4cc6d8ea8cc5
new file mode 100644
index 0000000..110037c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/13122d08c1cee0dae6434605917d4cc6d8ea8cc5
@@ -0,0 +1 @@
+'=ï!)**Í(()#õhÕ|'µ)T;“Õq£!(Sª!*(*(4!;)*A!+*'§:*Ò;µk;'¢Ãp*!¿)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/148a1118649dd8aa9b4ed778efdf7c1611aa5d27 b/test/core/nanopb/corpus_serverlist/148a1118649dd8aa9b4ed778efdf7c1611aa5d27
new file mode 100644
index 0000000..f13399b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/148a1118649dd8aa9b4ed778efdf7c1611aa5d27
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/15dea2bb5fb36a3dd5172796da66a821a32918e7 b/test/core/nanopb/corpus_serverlist/15dea2bb5fb36a3dd5172796da66a821a32918e7
new file mode 100644
index 0000000..c88bba5
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/15dea2bb5fb36a3dd5172796da66a821a32918e7
@@ -0,0 +1,2 @@
+!
+(!Øìƽ‰÷(!)!°S::Ô`…¶(!q"!½!€e&@n;*'Un)))
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/16488fe15a7e33cb41f2b7c159c99154464b3fd3 b/test/core/nanopb/corpus_serverlist/16488fe15a7e33cb41f2b7c159c99154464b3fd3
new file mode 100644
index 0000000..ae939a0
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/16488fe15a7e33cb41f2b7c159c99154464b3fd3
@@ -0,0 +1 @@
+²U
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1870a48a3c9c1dd9027cbd85beb503b43cff6e89 b/test/core/nanopb/corpus_serverlist/1870a48a3c9c1dd9027cbd85beb503b43cff6e89
new file mode 100644
index 0000000..74a76f5
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1870a48a3c9c1dd9027cbd85beb503b43cff6e89
@@ -0,0 +1,2 @@
+!¼+@kCÙ'–((!*Ú*'‚'*')!)(;!x!(*:)ÞyËNœ“)
+:)I*ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1900b6a9123667a79020319aa7fd54d230bc7073 b/test/core/nanopb/corpus_serverlist/1900b6a9123667a79020319aa7fd54d230bc7073
new file mode 100644
index 0000000..3f1e26b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1900b6a9123667a79020319aa7fd54d230bc7073
@@ -0,0 +1,2 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×'	É=Éÿ
+'!I)='!'ïïÉ=ÿ'):(:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1a000f1cbccd2ab6f7e623e015ed2e84284c9dbf b/test/core/nanopb/corpus_serverlist/1a000f1cbccd2ab6f7e623e015ed2e84284c9dbf
new file mode 100644
index 0000000..1ae5730
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1a000f1cbccd2ab6f7e623e015ed2e84284c9dbf
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@
+Á²:*²ò):)Áü²²²Å;;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1c1d403f6175d52ac4430d1ef2401b549761707e b/test/core/nanopb/corpus_serverlist/1c1d403f6175d52ac4430d1ef2401b549761707e
new file mode 100644
index 0000000..9d25e35
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1c1d403f6175d52ac4430d1ef2401b549761707e
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/1c2ae0e1915e18dffc2215e9121f1afe0e4335c4 b/test/core/nanopb/corpus_serverlist/1c2ae0e1915e18dffc2215e9121f1afe0e4335c4
new file mode 100644
index 0000000..ead5846
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1c2ae0e1915e18dffc2215e9121f1afe0e4335c4
@@ -0,0 +1,3 @@
+!¼+@oCÙ'–((!*Ú*'‚'*')
+!!'@¼CoÙ;–((!*Ú*''*'	!
+’š;!x!(*(:)ÞN˚
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1c5d2eef52426db9d0842f3d57b27a219434c512 b/test/core/nanopb/corpus_serverlist/1c5d2eef52426db9d0842f3d57b27a219434c512
new file mode 100644
index 0000000..266ade1
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1c5d2eef52426db9d0842f3d57b27a219434c512
@@ -0,0 +1 @@
+P²²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1d0676867c1ebce84531035fa7eb86ed00762df5 b/test/core/nanopb/corpus_serverlist/1d0676867c1ebce84531035fa7eb86ed00762df5
new file mode 100644
index 0000000..d502f61
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1d0676867c1ebce84531035fa7eb86ed00762df5
@@ -0,0 +1 @@
+	!É=Éÿ'!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1d92b263fa70450b0d0aeb81bf5d2f69eefbbd99 b/test/core/nanopb/corpus_serverlist/1d92b263fa70450b0d0aeb81bf5d2f69eefbbd99
new file mode 100644
index 0000000..40ecfd3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1d92b263fa70450b0d0aeb81bf5d2f69eefbbd99
@@ -0,0 +1 @@
+!!Øìƽ÷(!)!5Sã::Ô`…¶8!q"€'!@ne½!;*'Un)))
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1e843ed4864d6a808b671dd6769ae191ac8a13ad b/test/core/nanopb/corpus_serverlist/1e843ed4864d6a808b671dd6769ae191ac8a13ad
new file mode 100644
index 0000000..4379eea
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1e843ed4864d6a808b671dd6769ae191ac8a13ad
@@ -0,0 +1 @@
+	É=Éÿ'!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/1eb06a34ee568d584c4b33472788889bc68af3f5 b/test/core/nanopb/corpus_serverlist/1eb06a34ee568d584c4b33472788889bc68af3f5
new file mode 100644
index 0000000..7bb8d45
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/1eb06a34ee568d584c4b33472788889bc68af3f5
@@ -0,0 +1,3 @@
+'	É=Éÿ
+	'=ï!)**Í(()#õhÕ|'µ)É=É'!
+É)ÿT=
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/2169c2b4d560d74a5487df68b56f3af1d648f544 b/test/core/nanopb/corpus_serverlist/2169c2b4d560d74a5487df68b56f3af1d648f544
new file mode 100644
index 0000000..055390e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/2169c2b4d560d74a5487df68b56f3af1d648f544
@@ -0,0 +1 @@
+ȯõÜ!:)'*l:*\!D)…');ȯõÜ!WѯõÈѯ1Ü:!:*ò)!D\õ*:l)…');WѯõÈѯ4Ü
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/21f8f7583e58c1c81a3ac8237b5fa58071edf8a4 b/test/core/nanopb/corpus_serverlist/21f8f7583e58c1c81a3ac8237b5fa58071edf8a4
new file mode 100644
index 0000000..0549191
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/21f8f7583e58c1c81a3ac8237b5fa58071edf8a4
@@ -0,0 +1 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×É=*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/231e348407fdcb14412c691b0b20982940160ccd b/test/core/nanopb/corpus_serverlist/231e348407fdcb14412c691b0b20982940160ccd
new file mode 100644
index 0000000..5ce84e4
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/231e348407fdcb14412c691b0b20982940160ccd
@@ -0,0 +1 @@
+'!=ï'o)**Í(()#õhÕ|(µ)T;“Õ²Wo:'*()@!½()(!('(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/27b8f060e3296eaef77dcdd4c2cd11d5650604ac b/test/core/nanopb/corpus_serverlist/27b8f060e3296eaef77dcdd4c2cd11d5650604ac
new file mode 100644
index 0000000..f82d1f9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/27b8f060e3296eaef77dcdd4c2cd11d5650604ac
@@ -0,0 +1,2 @@
+Ų;Ų
+UõUú‰Ù(		(Ų;²UUú‰*Ų;ÙU²Å(Ž²'Ö!…z%)#­€
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/28ed3a797da3c48c309a4ef792147f3c56cfec40 b/test/core/nanopb/corpus_serverlist/28ed3a797da3c48c309a4ef792147f3c56cfec40
new file mode 100644
index 0000000..f46d387
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/28ed3a797da3c48c309a4ef792147f3c56cfec40
@@ -0,0 +1 @@
+(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/291fcc6e043942638fa3c865c0a1be5e4dcc0e70 b/test/core/nanopb/corpus_serverlist/291fcc6e043942638fa3c865c0a1be5e4dcc0e70
new file mode 100644
index 0000000..58aebd9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/291fcc6e043942638fa3c865c0a1be5e4dcc0e70
@@ -0,0 +1,2 @@
+!
+!Øìƽ‰÷(!)!0S::Ô`…¶(!q"!½!€e&@n;*'Un)))
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/2a7f6c1f8fdc090b24ceb90ab4f3a7b331c06c86 b/test/core/nanopb/corpus_serverlist/2a7f6c1f8fdc090b24ceb90ab4f3a7b331c06c86
new file mode 100644
index 0000000..0fa7c0c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/2a7f6c1f8fdc090b24ceb90ab4f3a7b331c06c86
@@ -0,0 +1,2 @@
+!
+!Øìƽ÷(!)!5Sã::Ô`…¶(!q"€'!@ne½!;*'Un)))
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/2b85f180fe56f84925b274819ce10a8972a594e7 b/test/core/nanopb/corpus_serverlist/2b85f180fe56f84925b274819ce10a8972a594e7
new file mode 100644
index 0000000..f3078ce
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/2b85f180fe56f84925b274819ce10a8972a594e7
@@ -0,0 +1 @@
+Z!!Î!*M)!:“(ó'ØH(;ã‰T('¯Ò'û);<''šŸÐ*ÿÙÎ!Ë;;:t:t*(Œò8.€¨(;ñ!!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/2dea73d7d10ba0dcfd103f7542bdf7458e772b2b b/test/core/nanopb/corpus_serverlist/2dea73d7d10ba0dcfd103f7542bdf7458e772b2b
new file mode 100644
index 0000000..e7381b0
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/2dea73d7d10ba0dcfd103f7542bdf7458e772b2b
@@ -0,0 +1 @@
+Á²•Wo:'ì*#!@	å*)Á²²Wo:'Wo*'!@*()*()@)(!:)Áü²²²(!'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/2e9c19f98ef88b83ec2dea8b1b7f92b8337f757b b/test/core/nanopb/corpus_serverlist/2e9c19f98ef88b83ec2dea8b1b7f92b8337f757b
new file mode 100644
index 0000000..56a0cc3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/2e9c19f98ef88b83ec2dea8b1b7f92b8337f757b
@@ -0,0 +1 @@
+)::(:P:*/!;;'Ù*©;k:°
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/2fbd59ffb74aba392b86f4fe2ff8067b6d45cce8 b/test/core/nanopb/corpus_serverlist/2fbd59ffb74aba392b86f4fe2ff8067b6d45cce8
new file mode 100644
index 0000000..659d7e7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/2fbd59ffb74aba392b86f4fe2ff8067b6d45cce8
@@ -0,0 +1,3 @@
+!
+!(Øƽ÷(!)!:5ã:S!
+sèÔ`…!ØìƽÂ÷(!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/31059c32ea28d37b7442f51b20e966665662783c b/test/core/nanopb/corpus_serverlist/31059c32ea28d37b7442f51b20e966665662783c
new file mode 100644
index 0000000..9ce0e27
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/31059c32ea28d37b7442f51b20e966665662783c
@@ -0,0 +1 @@
+²²Wo:'Wo:'*()@!½(*()@)(!(!'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/31f78e35feb36037864df5f8f47136f8e6e4768a b/test/core/nanopb/corpus_serverlist/31f78e35feb36037864df5f8f47136f8e6e4768a
new file mode 100644
index 0000000..e19d8d2
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/31f78e35feb36037864df5f8f47136f8e6e4768a
@@ -0,0 +1,2 @@
+!à
+ ØØìƽ÷ìƽ‰÷ )!!;n(!!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/326d322d1aa31696a14518830e544770f12146ee b/test/core/nanopb/corpus_serverlist/326d322d1aa31696a14518830e544770f12146ee
new file mode 100644
index 0000000..da53230
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/326d322d1aa31696a14518830e544770f12146ee
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/337df26552e0884ff133cc1be8e72020be38f457 b/test/core/nanopb/corpus_serverlist/337df26552e0884ff133cc1be8e72020be38f457
new file mode 100644
index 0000000..d139d04
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/337df26552e0884ff133cc1be8e72020be38f457
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/33a2a0aa86956097e034b5ee16aeceacee7efc34 b/test/core/nanopb/corpus_serverlist/33a2a0aa86956097e034b5ee16aeceacee7efc34
new file mode 100644
index 0000000..897ad4b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/33a2a0aa86956097e034b5ee16aeceacee7efc34
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@:*):)Áü²²²Å;;!
+²Áƒ'’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/33d175d1ecb3a85be7dd93d24efc3ddda0a85ad6 b/test/core/nanopb/corpus_serverlist/33d175d1ecb3a85be7dd93d24efc3ddda0a85ad6
new file mode 100644
index 0000000..447cb5a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/33d175d1ecb3a85be7dd93d24efc3ddda0a85ad6
@@ -0,0 +1 @@
+Á²²²²Wo:'Wo:'*()@!½Wo:'(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/3718a1b790db16bcfc4ec30691fab24ea7bb0b74 b/test/core/nanopb/corpus_serverlist/3718a1b790db16bcfc4ec30691fab24ea7bb0b74
new file mode 100644
index 0000000..66abd73
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/3718a1b790db16bcfc4ec30691fab24ea7bb0b74
@@ -0,0 +1,3 @@
+!¼+@oCÙ'–((!*Ú*'‚'*')
+!!¼;@oCÙ'–((!*Ú*''*'	!
+’š;!x!(*(:)ÞN˚
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/37aa3946054035b712102a62b71c94747dfd1491 b/test/core/nanopb/corpus_serverlist/37aa3946054035b712102a62b71c94747dfd1491
new file mode 100644
index 0000000..a679fb2
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/37aa3946054035b712102a62b71c94747dfd1491
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*'((!	š
+;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/37b697adc0708ad12e4ed7355f3f8fdf1b7919ca b/test/core/nanopb/corpus_serverlist/37b697adc0708ad12e4ed7355f3f8fdf1b7919ca
new file mode 100644
index 0000000..0a6988c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/37b697adc0708ad12e4ed7355f3f8fdf1b7919ca
@@ -0,0 +1 @@
+2È;ò•:.<ý:*::ƒž*Š):’ªÜ:ô(ã**!'dv!*!”¾(;'**W›!Øâ(!;;:/*f§¨Ça°î
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/37bf4642c5e5a806e2042cdf5ead9bf3c97b9ac1 b/test/core/nanopb/corpus_serverlist/37bf4642c5e5a806e2042cdf5ead9bf3c97b9ac1
new file mode 100644
index 0000000..3069505
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/37bf4642c5e5a806e2042cdf5ead9bf3c97b9ac1
@@ -0,0 +1,2 @@
+Ų;Ų
+UõUú‰Ù(	Ų;²UUú‰*Ų;²UÅÙ(Ž(²'Ö!…z%)#­€
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/37d94ca6a20303389b35404f3dfd20aaa9ff0851 b/test/core/nanopb/corpus_serverlist/37d94ca6a20303389b35404f3dfd20aaa9ff0851
new file mode 100644
index 0000000..1955fc9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/37d94ca6a20303389b35404f3dfd20aaa9ff0851
@@ -0,0 +1 @@
+P:*!/!;'Ù*;kÜ*!'l;À‚°Q'ʼ:)'*î#â;+Ç»(›²(«;w'!*!J;Ó**ã)))r
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/39278604f6a1102366464bbe769ae846e542bc56 b/test/core/nanopb/corpus_serverlist/39278604f6a1102366464bbe769ae846e542bc56
new file mode 100644
index 0000000..e1e6558
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/39278604f6a1102366464bbe769ae846e542bc56
@@ -0,0 +1,2 @@
+!¼;@oCÙ'–(¾(!*Ú*''*'	!
+’ȯõÜ!:)'*l:*\!D)…');š;!x!(*:)ÞNȯË
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/396b57d9a11a1b135e36ad266e155cc0c3b77d21 b/test/core/nanopb/corpus_serverlist/396b57d9a11a1b135e36ad266e155cc0c3b77d21
new file mode 100644
index 0000000..b20c4d3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/396b57d9a11a1b135e36ad266e155cc0c3b77d21
@@ -0,0 +1,2 @@
+!)fBB!(@)ò	û!!'!*M)!:“(ó'1
+)fØH(ã‰T('¯Ò''û);<'BB!(@
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/39a49db120a807fe4e80c502254a5009625c7599 b/test/core/nanopb/corpus_serverlist/39a49db120a807fe4e80c502254a5009625c7599
new file mode 100644
index 0000000..ea06636
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/39a49db120a807fe4e80c502254a5009625c7599
@@ -0,0 +1 @@
+!)fBB!(@)ò	Z!!'!*M)!:“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/39f04d1c6d4beefa3e3d6eae3a5317d969787055 b/test/core/nanopb/corpus_serverlist/39f04d1c6d4beefa3e3d6eae3a5317d969787055
new file mode 100644
index 0000000..a0ea7a3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/39f04d1c6d4beefa3e3d6eae3a5317d969787055
@@ -0,0 +1,3 @@
+!!à
+!Ø
+Øìƽ÷ìƽ‰÷( )!!;n(!!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/3b199b80209fa0b8ffedba4381019f8729cc09d6 b/test/core/nanopb/corpus_serverlist/3b199b80209fa0b8ffedba4381019f8729cc09d6
new file mode 100644
index 0000000..382928e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/3b199b80209fa0b8ffedba4381019f8729cc09d6
@@ -0,0 +1 @@
+È2ò;•È;."ò:•
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/3ccf7ffb96c3e4789409db33cc12bfd8ddc24c1a b/test/core/nanopb/corpus_serverlist/3ccf7ffb96c3e4789409db33cc12bfd8ddc24c1a
new file mode 100644
index 0000000..e8d3a07
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/3ccf7ffb96c3e4789409db33cc12bfd8ddc24c1a
@@ -0,0 +1 @@
+?P:*!/!;'Š*'kܚ!'l;À‚°Q'ʼ:)'*î#â;+Ç»((²›«;w'!*!J;Ó**ã)))r
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/3d04382d1fe11ff3b717100aece7f9eff2d04b9b b/test/core/nanopb/corpus_serverlist/3d04382d1fe11ff3b717100aece7f9eff2d04b9b
new file mode 100644
index 0000000..fd14f42
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/3d04382d1fe11ff3b717100aece7f9eff2d04b9b
@@ -0,0 +1,4 @@
+!
+!(Øƽ÷(!)!:5ã:S!
+
+èÔ`…!ØìƽÂ÷(!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/3d4eb9f836bb40cf4c734073bcba8b73e4cc93ae b/test/core/nanopb/corpus_serverlist/3d4eb9f836bb40cf4c734073bcba8b73e4cc93ae
new file mode 100644
index 0000000..fdf49e4
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/3d4eb9f836bb40cf4c734073bcba8b73e4cc93ae
@@ -0,0 +1 @@
+'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/41dc8c55e41d32c30865f9761931ddd4c5b740f8 b/test/core/nanopb/corpus_serverlist/41dc8c55e41d32c30865f9761931ddd4c5b740f8
new file mode 100644
index 0000000..20387cc
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/41dc8c55e41d32c30865f9761931ddd4c5b740f8
@@ -0,0 +1 @@
+Á²²Wo:Wo:'*()@½(()@)(!(¡
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/41ef7b74d212f8f7f6681edcffd0db719030d31d b/test/core/nanopb/corpus_serverlist/41ef7b74d212f8f7f6681edcffd0db719030d31d
new file mode 100644
index 0000000..bea9067
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/41ef7b74d212f8f7f6681edcffd0db719030d31d
@@ -0,0 +1 @@
+Á²²Wo:'ì*'!@:(:Á*():)Á|	²²Á²²Wo:'ì*'!@*(Á*²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/431187b5926fa7d0823305a9f87635616ea3ef27 b/test/core/nanopb/corpus_serverlist/431187b5926fa7d0823305a9f87635616ea3ef27
new file mode 100644
index 0000000..c735a4b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/431187b5926fa7d0823305a9f87635616ea3ef27
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/44c6da04b8378986721f7225e70a1514695c176c b/test/core/nanopb/corpus_serverlist/44c6da04b8378986721f7225e70a1514695c176c
new file mode 100644
index 0000000..0b54830
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/44c6da04b8378986721f7225e70a1514695c176c
@@ -0,0 +1 @@
+)*!B!Óà@'))ò);'Ǔ¹¢ƒ§U)àB!U)B!B!à@)ò);'Çþ“¢ƒ§'à@*::sEBD
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/450161236e37a1dfc0da6398c4876df82ff640ac b/test/core/nanopb/corpus_serverlist/450161236e37a1dfc0da6398c4876df82ff640ac
new file mode 100644
index 0000000..5f8fe62
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/450161236e37a1dfc0da6398c4876df82ff640ac
@@ -0,0 +1 @@
+ȯõÜ!:)'*l:*\!D)…');WѯõÈѯ2Ü!:òõ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/45257a176ca6a05ec65a6df430bbb6b85d0a676f b/test/core/nanopb/corpus_serverlist/45257a176ca6a05ec65a6df430bbb6b85d0a676f
new file mode 100644
index 0000000..9e49f15
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/45257a176ca6a05ec65a6df430bbb6b85d0a676f
@@ -0,0 +1,2 @@
+²Wo:'*()@!½()(!('((Š—;ž'
+ý;œ¯C:'((½!D’'*c¸L™'!;±N!’K1!(:Íâ*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/46d1c2f2edcc9cdc0d1698fa0c8853cb19a6e7d9 b/test/core/nanopb/corpus_serverlist/46d1c2f2edcc9cdc0d1698fa0c8853cb19a6e7d9
new file mode 100644
index 0000000..61465c5
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/46d1c2f2edcc9cdc0d1698fa0c8853cb19a6e7d9
@@ -0,0 +1 @@
+'=ï!)**Í(()#õhÕ|'µ)T;“Õq£!(Sª=ï!)!***Í(()
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/4764bd4297bf0c405348d2bb87b8fbc02beadcb8 b/test/core/nanopb/corpus_serverlist/4764bd4297bf0c405348d2bb87b8fbc02beadcb8
new file mode 100644
index 0000000..6b6a461
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/4764bd4297bf0c405348d2bb87b8fbc02beadcb8
@@ -0,0 +1,2 @@
+É)='!'ïïÁ²•Wo:'ì*#!@
+*Á'½²:²ò!):)Á'ï!)**ü²²²(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/48199bfd0e2c160f56d03e881bb5dfe276eec462 b/test/core/nanopb/corpus_serverlist/48199bfd0e2c160f56d03e881bb5dfe276eec462
new file mode 100644
index 0000000..8156706
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/48199bfd0e2c160f56d03e881bb5dfe276eec462
@@ -0,0 +1,2 @@
+!
+!Øìƽ÷(!)!5Sã::Ô`…¶(!p"€'!@ne½!;*'Un))!)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/48e865c56e8db13640d6ecbfc0f2486eb77e07d1 b/test/core/nanopb/corpus_serverlist/48e865c56e8db13640d6ecbfc0f2486eb77e07d1
new file mode 100644
index 0000000..521f510
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/48e865c56e8db13640d6ecbfc0f2486eb77e07d1
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@
+*(Á²:²ò):)Áü²²²Å;;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/499b003b8b98edd9dbe2668c8c6af948769d7e87 b/test/core/nanopb/corpus_serverlist/499b003b8b98edd9dbe2668c8c6af948769d7e87
new file mode 100644
index 0000000..766b504
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/499b003b8b98edd9dbe2668c8c6af948769d7e87
@@ -0,0 +1 @@
+È;ò2È;ò•:.•
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/4a55591c4b390c5a36cecc6f1b6f5105300b546b b/test/core/nanopb/corpus_serverlist/4a55591c4b390c5a36cecc6f1b6f5105300b546b
new file mode 100644
index 0000000..14be25c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/4a55591c4b390c5a36cecc6f1b6f5105300b546b
@@ -0,0 +1 @@
+	'!†É=Éÿm'!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/4d33f97ec69c64e14dcf205be36a6319ddb8a20d b/test/core/nanopb/corpus_serverlist/4d33f97ec69c64e14dcf205be36a6319ddb8a20d
new file mode 100644
index 0000000..f06ce52
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/4d33f97ec69c64e14dcf205be36a6319ddb8a20d
@@ -0,0 +1 @@
+	Ų;²UU'ú‰(Ž'Ö	Ų;;²U!Uú‰Ù(Ž'Ö!…!…z%z%
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/4dbfb08904739928e19c2f459040b35ac410f699 b/test/core/nanopb/corpus_serverlist/4dbfb08904739928e19c2f459040b35ac410f699
new file mode 100644
index 0000000..c56ae64
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/4dbfb08904739928e19c2f459040b35ac410f699
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*')
+!((š;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/501bd6fe1de2719cf8d2c517a071e5d883fbe766 b/test/core/nanopb/corpus_serverlist/501bd6fe1de2719cf8d2c517a071e5d883fbe766
new file mode 100644
index 0000000..677eff2
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/501bd6fe1de2719cf8d2c517a071e5d883fbe766
@@ -0,0 +1 @@
+Á²•Wo:'ì*#!@	å*²)²ÁWo:'Wo*'!@*()*()Á@()):ü!²;²²(!'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5208871ea8948223b64b304336cea41ac3240244 b/test/core/nanopb/corpus_serverlist/5208871ea8948223b64b304336cea41ac3240244
new file mode 100644
index 0000000..695b701
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5208871ea8948223b64b304336cea41ac3240244
@@ -0,0 +1 @@
+Á²•Wo:'ì*#!@	'Á²²:*)Á²²Wo²:'W
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5348c71be34967458403bd4b58bb2a8a744d35ee b/test/core/nanopb/corpus_serverlist/5348c71be34967458403bd4b58bb2a8a744d35ee
new file mode 100644
index 0000000..0b0ec9c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5348c71be34967458403bd4b58bb2a8a744d35ee
@@ -0,0 +1 @@
+!)fBB!(@)ò	'Z!!Î!*M)!:“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/54362c2f6965268d0835a992c3ba656171b8f044 b/test/core/nanopb/corpus_serverlist/54362c2f6965268d0835a992c3ba656171b8f044
new file mode 100644
index 0000000..3f6909886
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/54362c2f6965268d0835a992c3ba656171b8f044
@@ -0,0 +1,4 @@
+!
+!(Øƽ÷(!)!:5ãS:
+
+!èÔ`…!ØìƽÂ÷(!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/54411aa13f6d9118028171935322bbbc74c15329 b/test/core/nanopb/corpus_serverlist/54411aa13f6d9118028171935322bbbc74c15329
new file mode 100644
index 0000000..488ceb9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/54411aa13f6d9118028171935322bbbc74c15329
@@ -0,0 +1,2 @@
+Ų;Ų
+UUú‰Ù(		ÅÁ²²²²²;²UW
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/54c50af22d147f192918499b4b3819eb389468a4 b/test/core/nanopb/corpus_serverlist/54c50af22d147f192918499b4b3819eb389468a4
new file mode 100644
index 0000000..ad654dd
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/54c50af22d147f192918499b4b3819eb389468a4
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/55441aac903d96b36bf8a11bc804234bcf0c04da b/test/core/nanopb/corpus_serverlist/55441aac903d96b36bf8a11bc804234bcf0c04da
new file mode 100644
index 0000000..13c4013
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/55441aac903d96b36bf8a11bc804234bcf0c04da
@@ -0,0 +1 @@
+É='!'ïï½
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/56e1a7c279482a57fcbca43468df96a791ee22b4 b/test/core/nanopb/corpus_serverlist/56e1a7c279482a57fcbca43468df96a791ee22b4
new file mode 100644
index 0000000..6612943
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/56e1a7c279482a57fcbca43468df96a791ee22b4
@@ -0,0 +1 @@
+!)fBB!(@)òÎ;!!Z'!*M)!:“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/57cbea7c563d5c4b6b290271b0009c3f348d92da b/test/core/nanopb/corpus_serverlist/57cbea7c563d5c4b6b290271b0009c3f348d92da
new file mode 100644
index 0000000..969aafa
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/57cbea7c563d5c4b6b290271b0009c3f348d92da
@@ -0,0 +1,2 @@
+!í!;:n!@"P^
+;;(!!ð!':;!+P:y5ua;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/57e11c7a62f0fc807d7b51bb1ef0f0e22f43795b b/test/core/nanopb/corpus_serverlist/57e11c7a62f0fc807d7b51bb1ef0f0e22f43795b
new file mode 100644
index 0000000..630d756
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/57e11c7a62f0fc807d7b51bb1ef0f0e22f43795b
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*''*'	!
+’š;!x!(*:)ÞNË):y
+œ“)I)?ô)):(”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/585183c1a240df6926689fe1bd8cb434664db4d8 b/test/core/nanopb/corpus_serverlist/585183c1a240df6926689fe1bd8cb434664db4d8
new file mode 100644
index 0000000..08579d1
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/585183c1a240df6926689fe1bd8cb434664db4d8
@@ -0,0 +1 @@
+!)fBB!(j)ò	!Z!'!*M)!:“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5b2ee8ca40508bf108a729dcb228191670ec34d6 b/test/core/nanopb/corpus_serverlist/5b2ee8ca40508bf108a729dcb228191670ec34d6
new file mode 100644
index 0000000..c46daca
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5b2ee8ca40508bf108a729dcb228191670ec34d6
@@ -0,0 +1 @@
+	Ų;²UUú‰Ù(Ž'Ö!…z%)#­€!*º*)Á²²W:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5b47eabaf74479348fd0318f174d649dbe96e7d2 b/test/core/nanopb/corpus_serverlist/5b47eabaf74479348fd0318f174d649dbe96e7d2
new file mode 100644
index 0000000..7a1285c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5b47eabaf74479348fd0318f174d649dbe96e7d2
@@ -0,0 +1,2 @@
+Ų;Ų
+UõUú‰Ù(	Ų;²UUú‰Ù(Ž
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5ba93c9db0cff93f52b521d7420e43f6eda2784f b/test/core/nanopb/corpus_serverlist/5ba93c9db0cff93f52b521d7420e43f6eda2784f
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5ba93c9db0cff93f52b521d7420e43f6eda2784f
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/5cc827e33932ccf8c72c6a839074e856d93463d8 b/test/core/nanopb/corpus_serverlist/5cc827e33932ccf8c72c6a839074e856d93463d8
new file mode 100644
index 0000000..9eb4935
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5cc827e33932ccf8c72c6a839074e856d93463d8
@@ -0,0 +1 @@
+²²'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5cc89bbf687f94ff87241a8f935905e1c441de33 b/test/core/nanopb/corpus_serverlist/5cc89bbf687f94ff87241a8f935905e1c441de33
new file mode 100644
index 0000000..f8de668
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5cc89bbf687f94ff87241a8f935905e1c441de33
@@ -0,0 +1,3 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×'	É=Éÿ
+'!
+É)='!'ïïÉ=ÿ'):(:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5ec6596f12462fe9f36924c262f97408b54bbba8 b/test/core/nanopb/corpus_serverlist/5ec6596f12462fe9f36924c262f97408b54bbba8
new file mode 100644
index 0000000..448ce08
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5ec6596f12462fe9f36924c262f97408b54bbba8
@@ -0,0 +1,3 @@
+!
+!;n!@"!;n!P^*;;(!!;ð!':;!+P:@"P^*;;(!!y0ua;)
+;ð!'::
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5f8f3af69295223fb04c37d28035bb75b4cbd705 b/test/core/nanopb/corpus_serverlist/5f8f3af69295223fb04c37d28035bb75b4cbd705
new file mode 100644
index 0000000..a47eac7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5f8f3af69295223fb04c37d28035bb75b4cbd705
@@ -0,0 +1,2 @@
+1
+*)fBB!(@)ò	'Z!!Î!*M)!:“(ó'ØHã(‰T('¯Ò'û);<'šŸÐ*“ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/5fd76d48b9fefecbdabd4511decc161b25db79dd b/test/core/nanopb/corpus_serverlist/5fd76d48b9fefecbdabd4511decc161b25db79dd
new file mode 100644
index 0000000..676bb61
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/5fd76d48b9fefecbdabd4511decc161b25db79dd
@@ -0,0 +1,2 @@
+!
+!Ø(ƽ÷(!)!5Sã::Ô`…¶(!p"€'!@ne½!;*'Un!)!)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/614cf839ccac2d896d61a0ba0ab1f42b2fabafea b/test/core/nanopb/corpus_serverlist/614cf839ccac2d896d61a0ba0ab1f42b2fabafea
new file mode 100644
index 0000000..b0173a3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/614cf839ccac2d896d61a0ba0ab1f42b2fabafea
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/618305cc2d3d3814d78b77ffbf421b769bd862cf b/test/core/nanopb/corpus_serverlist/618305cc2d3d3814d78b77ffbf421b769bd862cf
new file mode 100644
index 0000000..3f2ea6e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/618305cc2d3d3814d78b77ffbf421b769bd862cf
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@
+*Á²:²ò):)Áü²²²Å;;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/61dfcd913c4f0a8d005bd089c34e95d8dbbf1897 b/test/core/nanopb/corpus_serverlist/61dfcd913c4f0a8d005bd089c34e95d8dbbf1897
new file mode 100644
index 0000000..63ca029
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/61dfcd913c4f0a8d005bd089c34e95d8dbbf1897
@@ -0,0 +1 @@
+!;!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/65a89e10aab00039680e1f7d014737b634c74d8d b/test/core/nanopb/corpus_serverlist/65a89e10aab00039680e1f7d014737b634c74d8d
new file mode 100644
index 0000000..17f6f3e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/65a89e10aab00039680e1f7d014737b634c74d8d
@@ -0,0 +1 @@
+Èѯõ2Ü!:ò
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/66a273dbf5e37410efd45518a42b06a65cffe1f0 b/test/core/nanopb/corpus_serverlist/66a273dbf5e37410efd45518a42b06a65cffe1f0
new file mode 100644
index 0000000..92b830e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/66a273dbf5e37410efd45518a42b06a65cffe1f0
@@ -0,0 +1,3 @@
+'	É=Éÿ
+'!
+É)='!'ïï'½=ï!)**Í
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/673ff0de0702e8098892060a5365c175d8ef18fc b/test/core/nanopb/corpus_serverlist/673ff0de0702e8098892060a5365c175d8ef18fc
new file mode 100644
index 0000000..e26a533
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/673ff0de0702e8098892060a5365c175d8ef18fc
@@ -0,0 +1 @@
+	')­'Û)­'Û¦)U!a¦)U!a!†Éÿm'	Øç•ÏøÉ=*×Éÿ	Øç•!Ï
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/68465c782c37bfdd98ac493b0458444bb94336e5 b/test/core/nanopb/corpus_serverlist/68465c782c37bfdd98ac493b0458444bb94336e5
new file mode 100644
index 0000000..5b0075e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/68465c782c37bfdd98ac493b0458444bb94336e5
@@ -0,0 +1,2 @@
+Ų;Ų
+UõUú‰Ù(	ÅÕ²;²UŲ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/688451dee13d0be420598c6e205a3bc419173e18 b/test/core/nanopb/corpus_serverlist/688451dee13d0be420598c6e205a3bc419173e18
new file mode 100644
index 0000000..b5ea767
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/688451dee13d0be420598c6e205a3bc419173e18
@@ -0,0 +1 @@
+!)fBB!à@)ò	;'Ǔ¢ƒ§'à@*:s:ED'tÂ'–!();!)*!­)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/68a1d9150e1380c219e0a1deb3993f321e000ecd b/test/core/nanopb/corpus_serverlist/68a1d9150e1380c219e0a1deb3993f321e000ecd
new file mode 100644
index 0000000..b331f3c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/68a1d9150e1380c219e0a1deb3993f321e000ecd
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@:(:Á*):)Á|²²²Á;;!'
+²Áƒ'’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/69f49bf7ae8886f5b4c6296fdb1c570256919604 b/test/core/nanopb/corpus_serverlist/69f49bf7ae8886f5b4c6296fdb1c570256919604
new file mode 100644
index 0000000..8a35367
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/69f49bf7ae8886f5b4c6296fdb1c570256919604
@@ -0,0 +1,2 @@
+É)='!'ïïÁ•Wo:'ì*#!@
+*'Á²:½²ò!):)Á'ï!)**ü²²²(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/6a425f414cd69ffffdbaa34d03eb43841b432e11 b/test/core/nanopb/corpus_serverlist/6a425f414cd69ffffdbaa34d03eb43841b432e11
new file mode 100644
index 0000000..53f8bd4
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/6a425f414cd69ffffdbaa34d03eb43841b432e11
@@ -0,0 +1 @@
+:Á²²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/6ca9e6e85f9b007a0920b0112decbd1403d506da b/test/core/nanopb/corpus_serverlist/6ca9e6e85f9b007a0920b0112decbd1403d506da
new file mode 100644
index 0000000..155a67f
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/6ca9e6e85f9b007a0920b0112decbd1403d506da
@@ -0,0 +1 @@
+U)B!B!à@)ò);'Çþ“¢ƒ§'à@*::sED'tÂ'–!();!)'²;(N);)&ÑÅvŠÅ™:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/6cd62e3d67b4154639adbe753115bfdd770edddb b/test/core/nanopb/corpus_serverlist/6cd62e3d67b4154639adbe753115bfdd770edddb
new file mode 100644
index 0000000..9a30148
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/6cd62e3d67b4154639adbe753115bfdd770edddb
@@ -0,0 +1 @@
+	'=ï!)**Í(()#õhÕ|'µ)É=ÉÿT
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/6d4f2de4cc427417d6335ff5396ea2588509bb5b b/test/core/nanopb/corpus_serverlist/6d4f2de4cc427417d6335ff5396ea2588509bb5b
new file mode 100644
index 0000000..8e780ed
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/6d4f2de4cc427417d6335ff5396ea2588509bb5b
@@ -0,0 +1,2 @@
+Á²•W:'ì*#!@
+*:Á(²:²òD:)Áü²°²Å;;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/6ea84030dd0b5b03e4720c244ea8b4ec65e1f236 b/test/core/nanopb/corpus_serverlist/6ea84030dd0b5b03e4720c244ea8b4ec65e1f236
new file mode 100644
index 0000000..53cb812
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/6ea84030dd0b5b03e4720c244ea8b4ec65e1f236
@@ -0,0 +1 @@
+Ų;Ų‘UõUú‰Ù(Ų;²UUú‰*Ų;²HÅÙ(Ž(²'օ!z%)#­€
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/710c1fc8cf7dc1386312c34de5057933fcf868b3 b/test/core/nanopb/corpus_serverlist/710c1fc8cf7dc1386312c34de5057933fcf868b3
new file mode 100644
index 0000000..770e2ed
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/710c1fc8cf7dc1386312c34de5057933fcf868b3
@@ -0,0 +1,2 @@
+!
+Øìƽ÷(!)2;ò•:!.
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/720e81dcaf83f867288a90293c5de3b088d5c556 b/test/core/nanopb/corpus_serverlist/720e81dcaf83f867288a90293c5de3b088d5c556
new file mode 100644
index 0000000..623ad37
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/720e81dcaf83f867288a90293c5de3b088d5c556
@@ -0,0 +1 @@
+!)fBB!(@)ò	'Z!!Î!*M)!:“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/72cdc8f78ab5237f96ed354264c726ac79ec429c b/test/core/nanopb/corpus_serverlist/72cdc8f78ab5237f96ed354264c726ac79ec429c
new file mode 100644
index 0000000..a823783
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/72cdc8f78ab5237f96ed354264c726ac79ec429c
@@ -0,0 +1 @@
+):(:P:*!/!;·'Ù*©;k°
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/73535a4f7af7e4c6aa23556cacd63f6929ac33fe b/test/core/nanopb/corpus_serverlist/73535a4f7af7e4c6aa23556cacd63f6929ac33fe
new file mode 100644
index 0000000..ee7c14d
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/73535a4f7af7e4c6aa23556cacd63f6929ac33fe
@@ -0,0 +1 @@
+ȯõÜ!:)'*l:*\!D)…');ȯõÜ!WѯõÈѯ1Ü:!:*ò)!D\*:l)…');WѯõÈѯÔ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/73d7b933a5673a4d6f5905006ef6266dda1e4fba b/test/core/nanopb/corpus_serverlist/73d7b933a5673a4d6f5905006ef6266dda1e4fba
new file mode 100644
index 0000000..3887fa0
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/73d7b933a5673a4d6f5905006ef6266dda1e4fba
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/753aea13c82d1f8841c2bd4309b1b55d0ae2ba8d b/test/core/nanopb/corpus_serverlist/753aea13c82d1f8841c2bd4309b1b55d0ae2ba8d
new file mode 100644
index 0000000..05085ca
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/753aea13c82d1f8841c2bd4309b1b55d0ae2ba8d
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/754428e00e8a1d0471e00bd9e8f060ab88ab640e b/test/core/nanopb/corpus_serverlist/754428e00e8a1d0471e00bd9e8f060ab88ab640e
new file mode 100644
index 0000000..be9b4d5
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/754428e00e8a1d0471e00bd9e8f060ab88ab640e
@@ -0,0 +1 @@
+	Ų;²UUú‰Ù(Ž'Ö!…z%)#­€!*º*)Á²:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/761c29151b23b4d14ce6261626641df1182f7a96 b/test/core/nanopb/corpus_serverlist/761c29151b23b4d14ce6261626641df1182f7a96
new file mode 100644
index 0000000..6d91ac7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/761c29151b23b4d14ce6261626641df1182f7a96
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/7658451dd805f277a5b1c3d4065d752d2d8de5f4 b/test/core/nanopb/corpus_serverlist/7658451dd805f277a5b1c3d4065d752d2d8de5f4
new file mode 100644
index 0000000..f8a1e6f
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7658451dd805f277a5b1c3d4065d752d2d8de5f4
@@ -0,0 +1,2 @@
+¹!
+!ÆìÆØØ!ì½÷(!)!5Sã::Ô`…¶8!q½÷(!"€')2;ò•:!!.
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/767e91cedcd9bc1bdac882acc34a53cc23cf4d02 b/test/core/nanopb/corpus_serverlist/767e91cedcd9bc1bdac882acc34a53cc23cf4d02
new file mode 100644
index 0000000..1930875
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/767e91cedcd9bc1bdac882acc34a53cc23cf4d02
@@ -0,0 +1 @@
+¯õÜ!:)'*l:*\!D)…');W''í;:!Z2(x;*!:))FÓ':ã);)!!:"]W;;-)(!!!!;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/77d3754bdd4ea358369c936ed36b974b4181f6ab b/test/core/nanopb/corpus_serverlist/77d3754bdd4ea358369c936ed36b974b4181f6ab
new file mode 100644
index 0000000..8eb2c96
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/77d3754bdd4ea358369c936ed36b974b4181f6ab
@@ -0,0 +1 @@
+):(:P:*!/!;'Ù*©;k°
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/7a95295bebe6237f65deb15ffeccab22716d574d b/test/core/nanopb/corpus_serverlist/7a95295bebe6237f65deb15ffeccab22716d574d
new file mode 100644
index 0000000..a08ce91
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7a95295bebe6237f65deb15ffeccab22716d574d
@@ -0,0 +1,2 @@
+Ų;IJ
+UUú‰™(		!MÁ²²²²;²²UW
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/7ad88b82e87fbfb3d4bddaa2f6e201a151e3a007 b/test/core/nanopb/corpus_serverlist/7ad88b82e87fbfb3d4bddaa2f6e201a151e3a007
new file mode 100644
index 0000000..301079d
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7ad88b82e87fbfb3d4bddaa2f6e201a151e3a007
@@ -0,0 +1,3 @@
+¹!
+!¹!
+ØìÆ!ØìÆ!½÷
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/7b1010cc012e34af1d03e8845868ff0e1db3a601 b/test/core/nanopb/corpus_serverlist/7b1010cc012e34af1d03e8845868ff0e1db3a601
new file mode 100644
index 0000000..dd19e2e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7b1010cc012e34af1d03e8845868ff0e1db3a601
@@ -0,0 +1,3 @@
+!
+!(Øƽ÷(!)!³:0ã:!
+!(Øƽ÷(!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/7d3ddbd11e82807321c9a53835ea897cf43aa7f2 b/test/core/nanopb/corpus_serverlist/7d3ddbd11e82807321c9a53835ea897cf43aa7f2
new file mode 100644
index 0000000..99b53b2
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7d3ddbd11e82807321c9a53835ea897cf43aa7f2
@@ -0,0 +1 @@
+Á²²Wo:'Wo:'*()@!½(*()@)(!(!'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/7da9c5ab5f049da297b0f4c1322edd696202d02a b/test/core/nanopb/corpus_serverlist/7da9c5ab5f049da297b0f4c1322edd696202d02a
new file mode 100644
index 0000000..a9cba68
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7da9c5ab5f049da297b0f4c1322edd696202d02a
@@ -0,0 +1 @@
+	Ų;²UUú‰Ù(Ž'Ö!…z%)#­€!*º*)Á²²:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/7e265a019c02e5d089152849ac00bb005fa644f5 b/test/core/nanopb/corpus_serverlist/7e265a019c02e5d089152849ac00bb005fa644f5
new file mode 100644
index 0000000..b469075
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7e265a019c02e5d089152849ac00bb005fa644f5
@@ -0,0 +1,2 @@
+Á²²Wo:'ì*'!@:(Á*():)Á²²²(;('
+Á²²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/7f33bff4f740eb898b908374b0c1badd47566947 b/test/core/nanopb/corpus_serverlist/7f33bff4f740eb898b908374b0c1badd47566947
new file mode 100644
index 0000000..11b1d9b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/7f33bff4f740eb898b908374b0c1badd47566947
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@
+*Á²:²ò):)Áü²²²Å;;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/81f13b9b65891f2bfce77cb183a06045c461fee6 b/test/core/nanopb/corpus_serverlist/81f13b9b65891f2bfce77cb183a06045c461fee6
new file mode 100644
index 0000000..1ed1faf
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/81f13b9b65891f2bfce77cb183a06045c461fee6
@@ -0,0 +1 @@
+)­Û¦¬)U!açØ•ÏøÉÿ×É=*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/846a14a480ffa1ad0f6333f3ecf2be3057ce6aed b/test/core/nanopb/corpus_serverlist/846a14a480ffa1ad0f6333f3ecf2be3057ce6aed
new file mode 100644
index 0000000..b116189
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/846a14a480ffa1ad0f6333f3ecf2be3057ce6aed
@@ -0,0 +1,2 @@
+!
+!;Øì½÷(!)!5Sã::`…¶(!p½'e€n!@"!;*'Un))!)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/87373a7f89feba2d50591b433f69877044155af2 b/test/core/nanopb/corpus_serverlist/87373a7f89feba2d50591b433f69877044155af2
new file mode 100644
index 0000000..836f2de
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/87373a7f89feba2d50591b433f69877044155af2
@@ -0,0 +1,2 @@
+!;n!@"P^*;;(!!;ð!':;!+P:y0ua;)
+
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/8833ba4c780c94fc6c3c466f849c0387acefdb20 b/test/core/nanopb/corpus_serverlist/8833ba4c780c94fc6c3c466f849c0387acefdb20
new file mode 100644
index 0000000..1c3f541
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/8833ba4c780c94fc6c3c466f849c0387acefdb20
@@ -0,0 +1 @@
+	Ų;²UUú‰Ù(Ž'Ö!…z%)#­€!*º*)Á²²WÁ²²²²:Wo:'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/8c23a5ecd20db4da2c061f3463254e9de104c8b9 b/test/core/nanopb/corpus_serverlist/8c23a5ecd20db4da2c061f3463254e9de104c8b9
new file mode 100644
index 0000000..f7fa5a3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/8c23a5ecd20db4da2c061f3463254e9de104c8b9
@@ -0,0 +1 @@
+ÈѯõÈѯ2Ü!:òõ2Ü!:ò
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/8d883f1577ca8c334b7c6d75ccb71209d71ced13 b/test/core/nanopb/corpus_serverlist/8d883f1577ca8c334b7c6d75ccb71209d71ced13
new file mode 100644
index 0000000..5a77f05
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/8d883f1577ca8c334b7c6d75ccb71209d71ced13
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/8dc80bd5f5d1fea64412203e304432edcf5f52c4 b/test/core/nanopb/corpus_serverlist/8dc80bd5f5d1fea64412203e304432edcf5f52c4
new file mode 100644
index 0000000..c0942a6
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/8dc80bd5f5d1fea64412203e304432edcf5f52c4
@@ -0,0 +1,2 @@
+!
+!Øìƽ‰÷(!)!0S::Ô`…¶(!q"€&!@ne½!;*'Un)))
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/8fc9a9ea6ad7d6d51e770076eaddacad9f970c6f b/test/core/nanopb/corpus_serverlist/8fc9a9ea6ad7d6d51e770076eaddacad9f970c6f
new file mode 100644
index 0000000..1104074
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/8fc9a9ea6ad7d6d51e770076eaddacad9f970c6f
@@ -0,0 +1,2 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×'	É=Éÿ
+'!É)='!'ïïÉ=ÿ'):(:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/8fd167de17534776ef57aba2f27675789a11b8db b/test/core/nanopb/corpus_serverlist/8fd167de17534776ef57aba2f27675789a11b8db
new file mode 100644
index 0000000..34a190e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/8fd167de17534776ef57aba2f27675789a11b8db
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*'	!(
+(š;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/9117d3e51560813b3ce4615dced18fa0e4d0a25a b/test/core/nanopb/corpus_serverlist/9117d3e51560813b3ce4615dced18fa0e4d0a25a
new file mode 100644
index 0000000..620dc7e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/9117d3e51560813b3ce4615dced18fa0e4d0a25a
@@ -0,0 +1 @@
+2;ò•:.<ý:(*::ƒž*Š):’ªÜ(ô(ã*!*'dv!*!¾(;'**W›!Øâ(!;;:/*f§¨Ça°î
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/921c68eaa8776f7544e195ae52224355d08a2d4d b/test/core/nanopb/corpus_serverlist/921c68eaa8776f7544e195ae52224355d08a2d4d
new file mode 100644
index 0000000..3b35a59
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/921c68eaa8776f7544e195ae52224355d08a2d4d
@@ -0,0 +1 @@
+)ÿ!B!Óà@')ò);'Ǔ¹¢ƒ§U)àBuB
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/9293945411fca2dc81fc34b36b575a384e6d489e b/test/core/nanopb/corpus_serverlist/9293945411fca2dc81fc34b36b575a384e6d489e
new file mode 100644
index 0000000..4b3c2b4
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/9293945411fca2dc81fc34b36b575a384e6d489e
@@ -0,0 +1 @@
+)*!B!Óà@'))ò);'Ǔ¹¢ƒ§U)àB!B
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/933287d66c3ff3f0a21f2c583c763f2f65872ef8 b/test/core/nanopb/corpus_serverlist/933287d66c3ff3f0a21f2c583c763f2f65872ef8
new file mode 100644
index 0000000..7215240
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/933287d66c3ff3f0a21f2c583c763f2f65872ef8
@@ -0,0 +1 @@
+Á²²²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/933d1d91283403f0a56571f533f482e9744eb735 b/test/core/nanopb/corpus_serverlist/933d1d91283403f0a56571f533f482e9744eb735
new file mode 100644
index 0000000..3a9610d
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/933d1d91283403f0a56571f533f482e9744eb735
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/93855fc41b3e3004ca6ba85f34b985042d4c9869 b/test/core/nanopb/corpus_serverlist/93855fc41b3e3004ca6ba85f34b985042d4c9869
new file mode 100644
index 0000000..1afdd59
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/93855fc41b3e3004ca6ba85f34b985042d4c9869
@@ -0,0 +1,2 @@
+Ų;Ų
+UU¶‰Ù(	!ÅÁ²(²²²²;²UW
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/9544f445c39470f05785b52cfc31bb73bda22659 b/test/core/nanopb/corpus_serverlist/9544f445c39470f05785b52cfc31bb73bda22659
new file mode 100644
index 0000000..d0fc37b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/9544f445c39470f05785b52cfc31bb73bda22659
@@ -0,0 +1,2 @@
+É='!'ïï½'#Ų;Ų
+UÁ²•Wì:o#'*!@Á²²ÁÁ²²••®W:'ì*U¶
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/97757217fde05ff4fc15c864bf29e9f560fd1c62 b/test/core/nanopb/corpus_serverlist/97757217fde05ff4fc15c864bf29e9f560fd1c62
new file mode 100644
index 0000000..47e8811
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/97757217fde05ff4fc15c864bf29e9f560fd1c62
@@ -0,0 +1,2 @@
+!
+h!Øìƽ÷(!)!2Sã::Ô`…¶(!q"€'!@ne½!;*'Un)))
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/9877c0f2d40dd43878bb0209bbc4b5fa93bec55a b/test/core/nanopb/corpus_serverlist/9877c0f2d40dd43878bb0209bbc4b5fa93bec55a
new file mode 100644
index 0000000..daf888f
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/9877c0f2d40dd43878bb0209bbc4b5fa93bec55a
@@ -0,0 +1 @@
+!)fBB!(@)ò'Z!!Î!*M)!:“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/98bc5065f79dd9d20cdac14ba28f0cf39908cb5f b/test/core/nanopb/corpus_serverlist/98bc5065f79dd9d20cdac14ba28f0cf39908cb5f
new file mode 100644
index 0000000..09f3479
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/98bc5065f79dd9d20cdac14ba28f0cf39908cb5f
@@ -0,0 +1 @@
+‰É=ï!)**Í(()#õhÕ|T'µ)ÉT
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/992860817f7fb0e49423607355dab973aa7ab815 b/test/core/nanopb/corpus_serverlist/992860817f7fb0e49423607355dab973aa7ab815
new file mode 100644
index 0000000..aaaec94
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/992860817f7fb0e49423607355dab973aa7ab815
@@ -0,0 +1 @@
+Éÿ):(:=P:*!/!;·'Ù*©';k°
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/995ee3d74bc6042fd6a8908c9df5a4cb530378d8 b/test/core/nanopb/corpus_serverlist/995ee3d74bc6042fd6a8908c9df5a4cb530378d8
new file mode 100644
index 0000000..96e6a47
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/995ee3d74bc6042fd6a8908c9df5a4cb530378d8
@@ -0,0 +1,2 @@
+'#Ų;Ų
+UÁ²•Wì:o#'*!@Á²²ÁÁ²²••®W:'ì*U¶
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/9a38c24a6e87e99a72a3a4f007b117ec191a1705 b/test/core/nanopb/corpus_serverlist/9a38c24a6e87e99a72a3a4f007b117ec191a1705
new file mode 100644
index 0000000..6ab64b7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/9a38c24a6e87e99a72a3a4f007b117ec191a1705
@@ -0,0 +1 @@
+ȯõÜ!:)'*l:*\!D)…');ȯõÜ!WѯõÈѯ1Ü!:ò:)'*l:*\!õD)…');WѯõÈѯ2Ü
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/9aa97a0ffcdc37a8ef487355fb7271eb6891deaa b/test/core/nanopb/corpus_serverlist/9aa97a0ffcdc37a8ef487355fb7271eb6891deaa
new file mode 100644
index 0000000..ab22206
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/9aa97a0ffcdc37a8ef487355fb7271eb6891deaa
@@ -0,0 +1,2 @@
+!
+!;n!@"P^*;;(!!;ð!':;!+P:y0ua;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/9b9fddc17ed7bc05a81c18f01e800a4e9efd0c8d b/test/core/nanopb/corpus_serverlist/9b9fddc17ed7bc05a81c18f01e800a4e9efd0c8d
new file mode 100644
index 0000000..5d7be44
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/9b9fddc17ed7bc05a81c18f01e800a4e9efd0c8d
@@ -0,0 +1 @@
+!)gB!(j)ò	!)!Z!'!!)*M)“ ó'ØH(ã‰T('fBÒ!û)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a0d4cb9a5a30bb01e8e4f68d636fb173632ed29d b/test/core/nanopb/corpus_serverlist/a0d4cb9a5a30bb01e8e4f68d636fb173632ed29d
new file mode 100644
index 0000000..4e38d90
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a0d4cb9a5a30bb01e8e4f68d636fb173632ed29d
@@ -0,0 +1 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×É=ÿ):(:=
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a1e070288ec564d10a8c59779aa07fa771fa1d4f b/test/core/nanopb/corpus_serverlist/a1e070288ec564d10a8c59779aa07fa771fa1d4f
new file mode 100644
index 0000000..29b2797
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a1e070288ec564d10a8c59779aa07fa771fa1d4f
@@ -0,0 +1 @@
+Á²²Wo'ì*'!@:(:Á*r):)Á|	²²Á²²Wo:'ì*'!@*(Á*²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a23d10723415d20f4ef1ed9b14d9dc24494856a0 b/test/core/nanopb/corpus_serverlist/a23d10723415d20f4ef1ed9b14d9dc24494856a0
new file mode 100644
index 0000000..e34e7f3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a23d10723415d20f4ef1ed9b14d9dc24494856a0
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/a245750cfe4212dca7bfde918de85f64eb053232 b/test/core/nanopb/corpus_serverlist/a245750cfe4212dca7bfde918de85f64eb053232
new file mode 100644
index 0000000..e33de0f
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a245750cfe4212dca7bfde918de85f64eb053232
@@ -0,0 +1 @@
+)­'Û¦)U!a:Øç•Ïø×*;'e«:c6U’êNŠ'ò:;Æ)ÚrþP:*!!G*:'³*:Ï)­ZÑSÒ!!]
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a24bbe3600f4dfd61bb8415c6a291e0521e4f267 b/test/core/nanopb/corpus_serverlist/a24bbe3600f4dfd61bb8415c6a291e0521e4f267
new file mode 100644
index 0000000..a387266
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a24bbe3600f4dfd61bb8415c6a291e0521e4f267
@@ -0,0 +1 @@
+V!;n)@"P^*;;(!*!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a25104d039a549c8d457ecea3b55369ed312f086 b/test/core/nanopb/corpus_serverlist/a25104d039a549c8d457ecea3b55369ed312f086
new file mode 100644
index 0000000..a048566
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a25104d039a549c8d457ecea3b55369ed312f086
@@ -0,0 +1,3 @@
+!¼+@oCÙ'–((!*Ú*'‚'*')
+!(š(;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a33c4fcabe6aebe012cd01c8cb851a9ab0a12098 b/test/core/nanopb/corpus_serverlist/a33c4fcabe6aebe012cd01c8cb851a9ab0a12098
new file mode 100644
index 0000000..4dbb720
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a33c4fcabe6aebe012cd01c8cb851a9ab0a12098
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*')
+!*š;!x!(*:)ÞNË):y
+œ“)I;ô9;()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a393e1727b0decca9f193179765c3a83d7096437 b/test/core/nanopb/corpus_serverlist/a393e1727b0decca9f193179765c3a83d7096437
new file mode 100644
index 0000000..3cb479c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a393e1727b0decca9f193179765c3a83d7096437
@@ -0,0 +1 @@
+)*!B!Óà@'))ò);'Ǔ¢ƒ§à':E:@sD'tÂ'–!();!­	'³(N);)&
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a5507f06be4735a3a9e416ea986d52c1a6a20909 b/test/core/nanopb/corpus_serverlist/a5507f06be4735a3a9e416ea986d52c1a6a20909
new file mode 100644
index 0000000..e341f43
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a5507f06be4735a3a9e416ea986d52c1a6a20909
@@ -0,0 +1 @@
+ȯõÜ!:)'*l:*\!D)…');ȯõÜ!WÑHÈѯ2Ü:!:*ò)!D\õ*:l)…');_‘õÈ'ѯÜ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a5adf028c902d17dd6a7ddeadabbed2b36420313 b/test/core/nanopb/corpus_serverlist/a5adf028c902d17dd6a7ddeadabbed2b36420313
new file mode 100644
index 0000000..a4e17bc
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a5adf028c902d17dd6a7ddeadabbed2b36420313
@@ -0,0 +1 @@
+ȯõÜ!:)'*l:*\!D)…');ȯõÜ!WѯõÈѯ1Ü:!:*ò)!D\õ*:l)…');WѯõÈѯÔ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a6aa1237a282ee3a93f2544bb6bb7704e565209e b/test/core/nanopb/corpus_serverlist/a6aa1237a282ee3a93f2544bb6bb7704e565209e
new file mode 100644
index 0000000..ea6e832
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a6aa1237a282ee3a93f2544bb6bb7704e565209e
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/a871185cabce7b96c9e2f6ffb40d9901c774b335 b/test/core/nanopb/corpus_serverlist/a871185cabce7b96c9e2f6ffb40d9901c774b335
new file mode 100644
index 0000000..dab50d7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a871185cabce7b96c9e2f6ffb40d9901c774b335
@@ -0,0 +1,2 @@
+Á²²Wo:'ì*'!@:(:Á*):)Á|²²²Á(;('
+²Á'’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a89d0e67bf53e22533a635f103d1fd400969ad56 b/test/core/nanopb/corpus_serverlist/a89d0e67bf53e22533a635f103d1fd400969ad56
new file mode 100644
index 0000000..fe06987
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a89d0e67bf53e22533a635f103d1fd400969ad56
@@ -0,0 +1 @@
+Á²²Wo:'Wo*'!@*()*()@)(!(!'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/a8d1b4e5672a501d7a6cd14b2929297f3a82e035 b/test/core/nanopb/corpus_serverlist/a8d1b4e5672a501d7a6cd14b2929297f3a82e035
new file mode 100644
index 0000000..dfbbf33
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/a8d1b4e5672a501d7a6cd14b2929297f3a82e035
@@ -0,0 +1 @@
+'P:*!/!;'Ù*;k):(:P:*!/!Ü*;!'l;À‚°Q'(¼ã:'Ù*)'*î©;k#
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/aa614cc8d05a3a58c30a890c10b9a0c1d609b228 b/test/core/nanopb/corpus_serverlist/aa614cc8d05a3a58c30a890c10b9a0c1d609b228
new file mode 100644
index 0000000..60e69d9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/aa614cc8d05a3a58c30a890c10b9a0c1d609b228
@@ -0,0 +1 @@
+	!†É=Éÿ'!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/aa65320376f63805cc82b247612b2e05b87bdbee b/test/core/nanopb/corpus_serverlist/aa65320376f63805cc82b247612b2e05b87bdbee
new file mode 100644
index 0000000..9100de9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/aa65320376f63805cc82b247612b2e05b87bdbee
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/abd3f6e2cc8887942de20e1c257427b825aed0ad b/test/core/nanopb/corpus_serverlist/abd3f6e2cc8887942de20e1c257427b825aed0ad
new file mode 100644
index 0000000..5cd8f75
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/abd3f6e2cc8887942de20e1c257427b825aed0ad
@@ -0,0 +1,2 @@
+!
+è!Øìƽ÷(!)!5Sã::Ô`…¶(!q"€'!@ne½!;*'Un)))
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ad0653a3a63675a7ce797e69b4673866b88ace33 b/test/core/nanopb/corpus_serverlist/ad0653a3a63675a7ce797e69b4673866b88ace33
new file mode 100644
index 0000000..03c166f
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ad0653a3a63675a7ce797e69b4673866b88ace33
@@ -0,0 +1,2 @@
+Ų;Ų
+UõUú‰Ù(		Ų;²UŲ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ae2ce27806f67312e0d0e29a492db9ab9cb9bf4e b/test/core/nanopb/corpus_serverlist/ae2ce27806f67312e0d0e29a492db9ab9cb9bf4e
new file mode 100644
index 0000000..4cfc263
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ae2ce27806f67312e0d0e29a492db9ab9cb9bf4e
@@ -0,0 +1 @@
+	'!I†Éÿm'!	
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ae4c0e671bd004165a1e7877d9c67249a165d2df b/test/core/nanopb/corpus_serverlist/ae4c0e671bd004165a1e7877d9c67249a165d2df
new file mode 100644
index 0000000..ddc8006
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ae4c0e671bd004165a1e7877d9c67249a165d2df
@@ -0,0 +1 @@
+)­'Û¦)U!aØç•ÏøÉÿ×É=*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/af75c24dff7e22948ed141c763a1309e6f540bcc b/test/core/nanopb/corpus_serverlist/af75c24dff7e22948ed141c763a1309e6f540bcc
new file mode 100644
index 0000000..cdbbf29
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/af75c24dff7e22948ed141c763a1309e6f540bcc
@@ -0,0 +1 @@
+`:`xŒV)ýÚ*)!Óx*'**‹;'(±DßP§Ü/!¯†nÃ!$—:a(j)*ƒ!'/**(ñå;îÄVÐ'*)*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b0f228c6d0cbbc9f10117f344d5aae6f001d00fa b/test/core/nanopb/corpus_serverlist/b0f228c6d0cbbc9f10117f344d5aae6f001d00fa
new file mode 100644
index 0000000..5c7579e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b0f228c6d0cbbc9f10117f344d5aae6f001d00fa
@@ -0,0 +1,3 @@
+!
+!(Øƽ÷(!)!:5ã:S!
+èÔ`…!ØìƽÂ÷(!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b2c6eab05580b85cda591093d3f05c44bf453fce b/test/core/nanopb/corpus_serverlist/b2c6eab05580b85cda591093d3f05c44bf453fce
new file mode 100644
index 0000000..3d66477
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b2c6eab05580b85cda591093d3f05c44bf453fce
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/b35281c0aae174d1ddc8999d97b9713f8004f285 b/test/core/nanopb/corpus_serverlist/b35281c0aae174d1ddc8999d97b9713f8004f285
new file mode 100644
index 0000000..d6a4f2a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b35281c0aae174d1ddc8999d97b9713f8004f285
@@ -0,0 +1 @@
+!!;n!@"P^*;;(!!;ð!':;!+P:y0ua;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b484ae40795cf9730ba94d5a4ca40aa47b88eacb b/test/core/nanopb/corpus_serverlist/b484ae40795cf9730ba94d5a4ca40aa47b88eacb
new file mode 100644
index 0000000..0b64857
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b484ae40795cf9730ba94d5a4ca40aa47b88eacb
@@ -0,0 +1,2 @@
+Ų;Ų
+UU¶‰Ù(		!ÅÁ²(²²²²;²UW
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b49c2fed1417a981ba29b32be73ee1700bea7ec9 b/test/core/nanopb/corpus_serverlist/b49c2fed1417a981ba29b32be73ee1700bea7ec9
new file mode 100644
index 0000000..aa3bcd1
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b49c2fed1417a981ba29b32be73ee1700bea7ec9
@@ -0,0 +1 @@
+(‹
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b68542373c05c0ed25231d09955b2c699d37c45b b/test/core/nanopb/corpus_serverlist/b68542373c05c0ed25231d09955b2c699d37c45b
new file mode 100644
index 0000000..050ac90
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b68542373c05c0ed25231d09955b2c699d37c45b
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b6d42cbe913f7275b574a71f0768781bdb6f45b7 b/test/core/nanopb/corpus_serverlist/b6d42cbe913f7275b574a71f0768781bdb6f45b7
new file mode 100644
index 0000000..08dd3a3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b6d42cbe913f7275b574a71f0768781bdb6f45b7
@@ -0,0 +1 @@
+)B!B!à@)ò);'Çþ“¢ƒ§'à@*::sED'tÂ'–!();!)'²;(N);)&ÑÅvŠÅ™:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b80b6c2cae83c2097c7e4c1fb181d47cb8fd0519 b/test/core/nanopb/corpus_serverlist/b80b6c2cae83c2097c7e4c1fb181d47cb8fd0519
new file mode 100644
index 0000000..c94bcd7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b80b6c2cae83c2097c7e4c1fb181d47cb8fd0519
@@ -0,0 +1,2 @@
+1
+)fBB!(@)ò	'Z!!Î!*M)!:“(ó'ØHã(‰T('¯Ò'û);<'šŸÐ*“ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/b90ab62d8591182fd90cd21cdb893178d97f7e0e b/test/core/nanopb/corpus_serverlist/b90ab62d8591182fd90cd21cdb893178d97f7e0e
new file mode 100644
index 0000000..c4462f3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/b90ab62d8591182fd90cd21cdb893178d97f7e0e
@@ -0,0 +1 @@
+Øìƽ÷!;2(!);
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ba45c93ee6b8b286798d8791ec049207c448f7cd b/test/core/nanopb/corpus_serverlist/ba45c93ee6b8b286798d8791ec049207c448f7cd
new file mode 100644
index 0000000..e9f2235
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ba45c93ee6b8b286798d8791ec049207c448f7cd
@@ -0,0 +1 @@
+*Ã
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ba67e81ef0f9a14bf5a1ca228bff87c681e83a44 b/test/core/nanopb/corpus_serverlist/ba67e81ef0f9a14bf5a1ca228bff87c681e83a44
new file mode 100644
index 0000000..eeff9f4
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ba67e81ef0f9a14bf5a1ca228bff87c681e83a44
@@ -0,0 +1 @@
+	Ų;²UUú‰Ù(Ž'Ö!…z%)­€!*:')Á²²W:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/bbd1f06ddee4fbbd0e5c9c915889862e5df34f9c b/test/core/nanopb/corpus_serverlist/bbd1f06ddee4fbbd0e5c9c915889862e5df34f9c
new file mode 100644
index 0000000..cb45343
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/bbd1f06ddee4fbbd0e5c9c915889862e5df34f9c
@@ -0,0 +1 @@
+Á²•Wo:'ì*#!@*P; õú‰(Á²:²Ù
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/bd982feb5dd4362e6bd9746ed216c25ce2749df4 b/test/core/nanopb/corpus_serverlist/bd982feb5dd4362e6bd9746ed216c25ce2749df4
new file mode 100644
index 0000000..fe76f88
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/bd982feb5dd4362e6bd9746ed216c25ce2749df4
@@ -0,0 +1 @@
+È.¯
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/be77053335e6496288fcf8b6c4d0b4abf86493ff b/test/core/nanopb/corpus_serverlist/be77053335e6496288fcf8b6c4d0b4abf86493ff
new file mode 100644
index 0000000..eaa7408
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/be77053335e6496288fcf8b6c4d0b4abf86493ff
@@ -0,0 +1 @@
+!!;n!@"P^*;;(!!;ð!':;!+P:y0ua;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/bfb53203499969fac4f4be48e1bcd9235c2fa101 b/test/core/nanopb/corpus_serverlist/bfb53203499969fac4f4be48e1bcd9235c2fa101
new file mode 100644
index 0000000..b28e40e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/bfb53203499969fac4f4be48e1bcd9235c2fa101
@@ -0,0 +1,2 @@
+Ų;Ų
+UU¶‰Ù(		!ÅÁ²²²²²;²UW
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c143576bdb5b34ad89fa3319507ae382a721f587 b/test/core/nanopb/corpus_serverlist/c143576bdb5b34ad89fa3319507ae382a721f587
new file mode 100644
index 0000000..6c15b37
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c143576bdb5b34ad89fa3319507ae382a721f587
@@ -0,0 +1 @@
+!)fBB!(@)òZ!!'!*M)!::“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c1ac502a15c53a90a1934f4a31d30f93db36dc8a b/test/core/nanopb/corpus_serverlist/c1ac502a15c53a90a1934f4a31d30f93db36dc8a
new file mode 100644
index 0000000..d2e8bdb
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c1ac502a15c53a90a1934f4a31d30f93db36dc8a
@@ -0,0 +1 @@
+	É=Éÿ'!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c1b29883768551fa5aadc38ba6eaad8007b9b85b b/test/core/nanopb/corpus_serverlist/c1b29883768551fa5aadc38ba6eaad8007b9b85b
new file mode 100644
index 0000000..29c3b9f
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c1b29883768551fa5aadc38ba6eaad8007b9b85b
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*'	
+!((š;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c2331fe0660ab5e411f6d38968c706aed390d8f6 b/test/core/nanopb/corpus_serverlist/c2331fe0660ab5e411f6d38968c706aed390d8f6
new file mode 100644
index 0000000..cd6e0b2
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c2331fe0660ab5e411f6d38968c706aed390d8f6
@@ -0,0 +1 @@
+É)='!'ïï'½=ï!)**Í(()#õhÕ|'µ)T;“Õq£!(Sª=ï!)!***Í
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c32647119c244cc018bb1863853d5c7bd37090df b/test/core/nanopb/corpus_serverlist/c32647119c244cc018bb1863853d5c7bd37090df
new file mode 100644
index 0000000..07d457a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c32647119c244cc018bb1863853d5c7bd37090df
@@ -0,0 +1 @@
+	É=Éÿ'!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c4098733900c27861bbf74a71afcbbd93d62f8ee b/test/core/nanopb/corpus_serverlist/c4098733900c27861bbf74a71afcbbd93d62f8ee
new file mode 100644
index 0000000..3e69c25
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c4098733900c27861bbf74a71afcbbd93d62f8ee
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*')
+!(([;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c4f5769bf3b4f2a55c006b4cf5a3bba44b347241 b/test/core/nanopb/corpus_serverlist/c4f5769bf3b4f2a55c006b4cf5a3bba44b347241
new file mode 100644
index 0000000..c42581a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c4f5769bf3b4f2a55c006b4cf5a3bba44b347241
@@ -0,0 +1,2 @@
+Ų;IJ
+UUú‰™(		MÁ²²²Á²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c6ea7b2d47402a458d5d03235bb042b61e05b2e8 b/test/core/nanopb/corpus_serverlist/c6ea7b2d47402a458d5d03235bb042b61e05b2e8
new file mode 100644
index 0000000..d5ca5ed
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c6ea7b2d47402a458d5d03235bb042b61e05b2e8
@@ -0,0 +1 @@
+	!!;n!@"P^*;;(!!;ð!':;!+P:y1ua;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c7255dc48b42d44f6c0676d6009051b7e1aa885b b/test/core/nanopb/corpus_serverlist/c7255dc48b42d44f6c0676d6009051b7e1aa885b
new file mode 100644
index 0000000..c30d058
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c7255dc48b42d44f6c0676d6009051b7e1aa885b
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c7d77af55176ae0ae5e59f46e48e1e6ea108d799 b/test/core/nanopb/corpus_serverlist/c7d77af55176ae0ae5e59f46e48e1e6ea108d799
new file mode 100644
index 0000000..dd7d5d1
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c7d77af55176ae0ae5e59f46e48e1e6ea108d799
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/c80827341dcdf1c21b303b82ec7e6df7eaf63f3d b/test/core/nanopb/corpus_serverlist/c80827341dcdf1c21b303b82ec7e6df7eaf63f3d
new file mode 100644
index 0000000..dc88210
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c80827341dcdf1c21b303b82ec7e6df7eaf63f3d
@@ -0,0 +1 @@
+)B!B!à@)ò);'Ǔ¢ƒ§'à@::sED'tÂ'–!();!­	'³(N);)&ÑÅvŠÅ™:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c9501031a75c067b6602e2831f03421b87be4496 b/test/core/nanopb/corpus_serverlist/c9501031a75c067b6602e2831f03421b87be4496
new file mode 100644
index 0000000..4c223e9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c9501031a75c067b6602e2831f03421b87be4496
@@ -0,0 +1 @@
+'ÐB!à@)ò);'Ǔ¢ƒ''*::sED'';B!à@)ò)t;'Ç“
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/c98f88d962dfbc2a83e08bfbd8a87b0cc5a8b330 b/test/core/nanopb/corpus_serverlist/c98f88d962dfbc2a83e08bfbd8a87b0cc5a8b330
new file mode 100644
index 0000000..c1cf859
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/c98f88d962dfbc2a83e08bfbd8a87b0cc5a8b330
@@ -0,0 +1 @@
+!)fBB!à@)ò	';'Ǔ¢ƒ§'à@*:s:ED'tÂ'–!();!)*!­O)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ccd33fa22b2983978f9617b3cde76ea05b683c2c b/test/core/nanopb/corpus_serverlist/ccd33fa22b2983978f9617b3cde76ea05b683c2c
new file mode 100644
index 0000000..47c119b
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ccd33fa22b2983978f9617b3cde76ea05b683c2c
@@ -0,0 +1,3 @@
+!¼+@oCÙ'–((!*Ú*'‚'*'
+!!'@¼CoÙ;–((!*Ú*''*'	!
+’š;!x!(*(:)ÞN˚
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/cd0e7701fd79879c56f680817a0d2705751b1f44 b/test/core/nanopb/corpus_serverlist/cd0e7701fd79879c56f680817a0d2705751b1f44
new file mode 100644
index 0000000..c42b736
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/cd0e7701fd79879c56f680817a0d2705751b1f44
@@ -0,0 +1,2 @@
+Á²²Wo:'ì*'!@:(:Á*():)Á|²²²Á(;('
+²Á²’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/cd1c2b5c2684d831aab5265e9cd6f1ee045dab9b b/test/core/nanopb/corpus_serverlist/cd1c2b5c2684d831aab5265e9cd6f1ee045dab9b
new file mode 100644
index 0000000..42148d8
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/cd1c2b5c2684d831aab5265e9cd6f1ee045dab9b
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/cf98e8b01e7a759f28a9c5f59c896317d74ac47c b/test/core/nanopb/corpus_serverlist/cf98e8b01e7a759f28a9c5f59c896317d74ac47c
new file mode 100644
index 0000000..5682057
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/cf98e8b01e7a759f28a9c5f59c896317d74ac47c
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*')
+!((š;!x!(*:)ÞNË):y
+œ“)I;ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d1d171589e035be85dc347278f0735151a342d68 b/test/core/nanopb/corpus_serverlist/d1d171589e035be85dc347278f0735151a342d68
new file mode 100644
index 0000000..0542aae
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d1d171589e035be85dc347278f0735151a342d68
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/d243143bf9b8adf6be92a157428ec6cbfd785423 b/test/core/nanopb/corpus_serverlist/d243143bf9b8adf6be92a157428ec6cbfd785423
new file mode 100644
index 0000000..693233c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d243143bf9b8adf6be92a157428ec6cbfd785423
@@ -0,0 +1 @@
+Á²•Wì:o#'*!@Á²²ÁÁ²²••®W:'ì*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d2cd278979f2842ebd890f1d84712750273ad0fc b/test/core/nanopb/corpus_serverlist/d2cd278979f2842ebd890f1d84712750273ad0fc
new file mode 100644
index 0000000..b12dc95
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d2cd278979f2842ebd890f1d84712750273ad0fc
@@ -0,0 +1,2 @@
+!¼+@oCÙ'–((!*Ú*'‚'*')!(š(;!x!(*:)ÞNË):y
+œ“)I*ô):()”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d2e96eb2699c7dd4a183f13d3a063a1aa9c192fd b/test/core/nanopb/corpus_serverlist/d2e96eb2699c7dd4a183f13d3a063a1aa9c192fd
new file mode 100644
index 0000000..59e8225
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d2e96eb2699c7dd4a183f13d3a063a1aa9c192fd
@@ -0,0 +1 @@
+!!;n!@"P^*;;(!!;ð!':;!+P:y1ua;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d3178f8b0d26275667c27bb8533a61643213e4d8 b/test/core/nanopb/corpus_serverlist/d3178f8b0d26275667c27bb8533a61643213e4d8
new file mode 100644
index 0000000..b3d0493
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d3178f8b0d26275667c27bb8533a61643213e4d8
@@ -0,0 +1,2 @@
+!¼+@oCÙ'–((!*Ú*'‚'*')!(š(;!x!(*:)ÞNË):y
+œ“)I*ô:')”o:;©£(ª(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d46f536ea4b601c0ff313a5eb5b47e2b55aa9eb0 b/test/core/nanopb/corpus_serverlist/d46f536ea4b601c0ff313a5eb5b47e2b55aa9eb0
new file mode 100644
index 0000000..59ecd84
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d46f536ea4b601c0ff313a5eb5b47e2b55aa9eb0
@@ -0,0 +1 @@
+É=ï!)**Í(()#õhÕ|T'µ)T;“Õq£!(SÀª=ï!)!***Í(()
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d4be3038631eac422022ee23f43b47905a15b2b5 b/test/core/nanopb/corpus_serverlist/d4be3038631eac422022ee23f43b47905a15b2b5
new file mode 100644
index 0000000..14ab54c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d4be3038631eac422022ee23f43b47905a15b2b5
@@ -0,0 +1 @@
+'!=ï'o)**Í(()#hÕ|(µ)T;“Õ²Wo:'*()@!½()(!('(
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d56b30a2d1b5a2a13ae00392bcb4ca72085310d9 b/test/core/nanopb/corpus_serverlist/d56b30a2d1b5a2a13ae00392bcb4ca72085310d9
new file mode 100644
index 0000000..8c74e89
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d56b30a2d1b5a2a13ae00392bcb4ca72085310d9
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@
+*P; õú‰(Á²:²Ù
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d67f85948143218d11e2fb7936a119741036045d b/test/core/nanopb/corpus_serverlist/d67f85948143218d11e2fb7936a119741036045d
new file mode 100644
index 0000000..09d7d97
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d67f85948143218d11e2fb7936a119741036045d
@@ -0,0 +1 @@
+)B!B!à@)ò);'Ǔ¢ƒ§'à@*::sED'tÂ'–!();!­)'²(N);)&ÑÅvŠÅ™:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d6930ea81dfd91856a06a0c16483e47616642b4b b/test/core/nanopb/corpus_serverlist/d6930ea81dfd91856a06a0c16483e47616642b4b
new file mode 100644
index 0000000..9f8cd38
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d6930ea81dfd91856a06a0c16483e47616642b4b
@@ -0,0 +1 @@
+U)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d737c10038a92add90e2ebea5c174ed249de8018 b/test/core/nanopb/corpus_serverlist/d737c10038a92add90e2ebea5c174ed249de8018
new file mode 100644
index 0000000..41c37cb
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d737c10038a92add90e2ebea5c174ed249de8018
@@ -0,0 +1 @@
+)­'Û¦)U!a	Øç•ÏøÉ=*×Éÿ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/d758a67f018b176dfc7d29630cf8cb587f5b2a6b b/test/core/nanopb/corpus_serverlist/d758a67f018b176dfc7d29630cf8cb587f5b2a6b
new file mode 100644
index 0000000..df361cb
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/d758a67f018b176dfc7d29630cf8cb587f5b2a6b
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@::*):)Áü²²²Á;;!'
+²Áƒ'’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/dc7139105787f3ba67d7971d80796e9cf5786a91 b/test/core/nanopb/corpus_serverlist/dc7139105787f3ba67d7971d80796e9cf5786a91
new file mode 100644
index 0000000..6f0d40a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/dc7139105787f3ba67d7971d80796e9cf5786a91
@@ -0,0 +1 @@
+Øìƽ÷(!)!5Sã::`…¶(!p½'e€*'U)))(:)婤;*:!p(È':Ö¶;óÑ))e¿);À';:µ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/dc8ec35f43e994b9c4ac61275d6b934990d42181 b/test/core/nanopb/corpus_serverlist/dc8ec35f43e994b9c4ac61275d6b934990d42181
new file mode 100644
index 0000000..e8bf4a9
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/dc8ec35f43e994b9c4ac61275d6b934990d42181
@@ -0,0 +1,2 @@
+Á²•Wo:'ì*#!@:*):)Áü²²²Å;;!
+²Áƒ'’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/dd2694fe12a018bc6af6f288b5c22a030eec8049 b/test/core/nanopb/corpus_serverlist/dd2694fe12a018bc6af6f288b5c22a030eec8049
new file mode 100644
index 0000000..7646d3e
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/dd2694fe12a018bc6af6f288b5c22a030eec8049
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/de7424f44508582a953f137195533b7a0191eda7 b/test/core/nanopb/corpus_serverlist/de7424f44508582a953f137195533b7a0191eda7
new file mode 100644
index 0000000..988584a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/de7424f44508582a953f137195533b7a0191eda7
@@ -0,0 +1 @@
+)­'Û¦)U!a	Øç•ÏøÉÿ×=É*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/de91a02040d792dfcb71a4cb5aa4c1c006201273 b/test/core/nanopb/corpus_serverlist/de91a02040d792dfcb71a4cb5aa4c1c006201273
new file mode 100644
index 0000000..6119c72
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/de91a02040d792dfcb71a4cb5aa4c1c006201273
@@ -0,0 +1 @@
+''=ï!)**Í(()#õhÕ|'µ)T;“Õq£!(Sª=ï!)!***Í(()
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/deb576067b11f6e2a3a39b0f2ef38ddae5c67b18 b/test/core/nanopb/corpus_serverlist/deb576067b11f6e2a3a39b0f2ef38ddae5c67b18
new file mode 100644
index 0000000..6a960cd
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/deb576067b11f6e2a3a39b0f2ef38ddae5c67b18
@@ -0,0 +1 @@
+È2ò;•È;.ò:•
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/df58248c414f342c81e056b40bee12d17a08bf61 b/test/core/nanopb/corpus_serverlist/df58248c414f342c81e056b40bee12d17a08bf61
new file mode 100644
index 0000000..f59ec20
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/df58248c414f342c81e056b40bee12d17a08bf61
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e076020b2826abd3a4b960fb33a35fd7d0606dd8 b/test/core/nanopb/corpus_serverlist/e076020b2826abd3a4b960fb33a35fd7d0606dd8
new file mode 100644
index 0000000..2cf8f97
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e076020b2826abd3a4b960fb33a35fd7d0606dd8
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/e0bcf682342967c002621acd2563a2157826d156 b/test/core/nanopb/corpus_serverlist/e0bcf682342967c002621acd2563a2157826d156
new file mode 100644
index 0000000..d9c8b2d
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e0bcf682342967c002621acd2563a2157826d156
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/e1edca08a7654b42a64647abb0e773eddddb580b b/test/core/nanopb/corpus_serverlist/e1edca08a7654b42a64647abb0e773eddddb580b
new file mode 100644
index 0000000..cb23b40
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e1edca08a7654b42a64647abb0e773eddddb580b
@@ -0,0 +1,2 @@
+!
+!;Øì½÷(!)!5Sã::`…¶(!p½'e€n!@"!;*'Un))!)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e2fa528289b5971f5b40b3687a2a6f0d17348de6 b/test/core/nanopb/corpus_serverlist/e2fa528289b5971f5b40b3687a2a6f0d17348de6
new file mode 100644
index 0000000..d4224c7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e2fa528289b5971f5b40b3687a2a6f0d17348de6
@@ -0,0 +1,2 @@
+!
+!;Øìƽ÷(!)!5Sã::`…¶(!p½'e€n!@"!;*'Un))!)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e52af0ba8750572b98f3a8968de77811ddff0893 b/test/core/nanopb/corpus_serverlist/e52af0ba8750572b98f3a8968de77811ddff0893
new file mode 100644
index 0000000..661acf3
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e52af0ba8750572b98f3a8968de77811ddff0893
@@ -0,0 +1 @@
+Á²•W'oÁ²:'²WÁ²²Wo'ì*'!@:(:Á*r):)Á|²²Á²²W
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e5a0f40647f805b5001645ce2d94505e72fa64f3 b/test/core/nanopb/corpus_serverlist/e5a0f40647f805b5001645ce2d94505e72fa64f3
new file mode 100644
index 0000000..4da511f
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e5a0f40647f805b5001645ce2d94505e72fa64f3
@@ -0,0 +1,2 @@
+!à
+!Øìƽ‰÷( )!!;n!@"P^*;;(!!;ð!':;!+!P:y0ua;5S::Ô`
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e69762f0c6a2750c0b03503a6aec90ffc94bcb72 b/test/core/nanopb/corpus_serverlist/e69762f0c6a2750c0b03503a6aec90ffc94bcb72
new file mode 100644
index 0000000..3334433
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e69762f0c6a2750c0b03503a6aec90ffc94bcb72
@@ -0,0 +1 @@
+ZB!
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e7064f0b80f61dbc65915311032d27baa569ae2a b/test/core/nanopb/corpus_serverlist/e7064f0b80f61dbc65915311032d27baa569ae2a
new file mode 100644
index 0000000..e8a0f87
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e7064f0b80f61dbc65915311032d27baa569ae2a
@@ -0,0 +1 @@
+)
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e863a4420854c36168d2b8dd39ce474ebe11cd26 b/test/core/nanopb/corpus_serverlist/e863a4420854c36168d2b8dd39ce474ebe11cd26
new file mode 100644
index 0000000..9170f6c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e863a4420854c36168d2b8dd39ce474ebe11cd26
@@ -0,0 +1 @@
+ÁÁ²²²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e8993f97bb9c83f87c64cfc429095eeaccf32953 b/test/core/nanopb/corpus_serverlist/e8993f97bb9c83f87c64cfc429095eeaccf32953
new file mode 100644
index 0000000..4a284b5
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e8993f97bb9c83f87c64cfc429095eeaccf32953
@@ -0,0 +1 @@
+	Ų;ŲU!Uú‰Ù(Ž'Ö!…z%)­V!*:')Á²²W:
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e9875d9a54b3ebc57df4da886cd30a39252ac666 b/test/core/nanopb/corpus_serverlist/e9875d9a54b3ebc57df4da886cd30a39252ac666
new file mode 100644
index 0000000..5fb45a7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e9875d9a54b3ebc57df4da886cd30a39252ac666
@@ -0,0 +1,3 @@
+!;n!@"P^*;;(!!;ð!':;!+P:y0ua;)
+:';ü':
+;}!—£)®*)ô'Ŗ”':(!):!Fý
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/e98a9d92bbbac9b1e64c0641e967adebd681b2aa b/test/core/nanopb/corpus_serverlist/e98a9d92bbbac9b1e64c0641e967adebd681b2aa
new file mode 100644
index 0000000..3555391
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/e98a9d92bbbac9b1e64c0641e967adebd681b2aa
@@ -0,0 +1 @@
+ѯõ2ÜÈ!:ò
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/eb7c31f48c77b742fa29126ac78a2c06c41208e8 b/test/core/nanopb/corpus_serverlist/eb7c31f48c77b742fa29126ac78a2c06c41208e8
new file mode 100644
index 0000000..db926fd
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/eb7c31f48c77b742fa29126ac78a2c06c41208e8
@@ -0,0 +1 @@
+²U—
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ec174492517f988010ed3ddbd003cb388f477bb6 b/test/core/nanopb/corpus_serverlist/ec174492517f988010ed3ddbd003cb388f477bb6
new file mode 100644
index 0000000..23b7293
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ec174492517f988010ed3ddbd003cb388f477bb6
@@ -0,0 +1 @@
+U)B!à@
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ec4d6a393be7ec80ccb8c531337a7fc3ef140e66 b/test/core/nanopb/corpus_serverlist/ec4d6a393be7ec80ccb8c531337a7fc3ef140e66
new file mode 100644
index 0000000..6402f35
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ec4d6a393be7ec80ccb8c531337a7fc3ef140e66
@@ -0,0 +1 @@
+)­'Û¦)U!a	!:Øç•ÏøÉ=×Éÿ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ecd40909ab5e2c61841d9fb95b8aacc87651100c b/test/core/nanopb/corpus_serverlist/ecd40909ab5e2c61841d9fb95b8aacc87651100c
new file mode 100644
index 0000000..f74e810
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ecd40909ab5e2c61841d9fb95b8aacc87651100c
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/ed17c8ddb6cc8a0b653dc87aca999d31e80c781a b/test/core/nanopb/corpus_serverlist/ed17c8ddb6cc8a0b653dc87aca999d31e80c781a
new file mode 100644
index 0000000..359a205
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ed17c8ddb6cc8a0b653dc87aca999d31e80c781a
@@ -0,0 +1 @@
+Ų;Ų‘UõUú‰Ù(	Ų;²UUú‰*Ų;²UÅÙ(Ž(²'Ö!…z%)#­€
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ee0b476126bb1c2249b299323718ecef1250645e b/test/core/nanopb/corpus_serverlist/ee0b476126bb1c2249b299323718ecef1250645e
new file mode 100644
index 0000000..954e32c
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ee0b476126bb1c2249b299323718ecef1250645e
@@ -0,0 +1,2 @@
+¹!
+!ØìÆ!Øìƽ÷(!)!5Sã::Ô`…¶8!q½÷(!"€')2;ò•:!!.
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ee1fb6a0b4139c07f1cf6bce850eaac9a2db29ba b/test/core/nanopb/corpus_serverlist/ee1fb6a0b4139c07f1cf6bce850eaac9a2db29ba
new file mode 100644
index 0000000..5611bc5
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ee1fb6a0b4139c07f1cf6bce850eaac9a2db29ba
@@ -0,0 +1 @@
+!)fBB!(@)ò	'ÇZ!!Î!*M)!:“(ó'ØH(;ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/eeac145c017ed35305f0ae69f820fc41e26e7997 b/test/core/nanopb/corpus_serverlist/eeac145c017ed35305f0ae69f820fc41e26e7997
new file mode 100644
index 0000000..e20a603
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/eeac145c017ed35305f0ae69f820fc41e26e7997
@@ -0,0 +1 @@
+'#9k;*;7»*)õ!!$*!H?*'›¼ßE ‹Í(±;o'*!:Ã:Ȏ*­;:ï%!)†!;*!tcÈ®:ˆ
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/efac7390c6e3a653d3ce93c3d6902f2f1c281ce0 b/test/core/nanopb/corpus_serverlist/efac7390c6e3a653d3ce93c3d6902f2f1c281ce0
new file mode 100644
index 0000000..921afe4
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/efac7390c6e3a653d3ce93c3d6902f2f1c281ce0
@@ -0,0 +1 @@
+Á²•Wo:'ì*#!@	':*)Á²²Wo:'Wo*'!@*()*()@)(!:)Áü²²²(!'
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/f0f0dace93d51cd8e045aeacca89424fc836eebc b/test/core/nanopb/corpus_serverlist/f0f0dace93d51cd8e045aeacca89424fc836eebc
new file mode 100644
index 0000000..74f82e6
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f0f0dace93d51cd8e045aeacca89424fc836eebc
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/f3341b8cc55c0bb6e2d0a1f7f06d68e4f04057f5 b/test/core/nanopb/corpus_serverlist/f3341b8cc55c0bb6e2d0a1f7f06d68e4f04057f5
new file mode 100644
index 0000000..aa1c2e7
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f3341b8cc55c0bb6e2d0a1f7f06d68e4f04057f5
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/f59ff56e341b94f2bddfd718b48ae9ab1692d720 b/test/core/nanopb/corpus_serverlist/f59ff56e341b94f2bddfd718b48ae9ab1692d720
new file mode 100644
index 0000000..8bc99b6
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f59ff56e341b94f2bddfd718b48ae9ab1692d720
@@ -0,0 +1,2 @@
+Á²²Wo:'ì*'!@*(Á*()@)Á²²²(!(!'
+Á²²ò
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/f5a1824b9fd9f124df8097017607bcfa00eccfce b/test/core/nanopb/corpus_serverlist/f5a1824b9fd9f124df8097017607bcfa00eccfce
new file mode 100644
index 0000000..a4cbfd6
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f5a1824b9fd9f124df8097017607bcfa00eccfce
@@ -0,0 +1,2 @@
+Á²²Wo:'ì*'!@:(:Á*():)Á|²²Á(;('
+²Á²’²
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/f5b92b69853a5d123bffdc6b0ab093f767ec30ad b/test/core/nanopb/corpus_serverlist/f5b92b69853a5d123bffdc6b0ab093f767ec30ad
new file mode 100644
index 0000000..10b6509
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f5b92b69853a5d123bffdc6b0ab093f767ec30ad
Binary files differ
diff --git a/test/core/nanopb/corpus_serverlist/f6aea4c380e41ddef2489ee581ab35e17fa3e8dd b/test/core/nanopb/corpus_serverlist/f6aea4c380e41ddef2489ee581ab35e17fa3e8dd
new file mode 100644
index 0000000..9f4d935
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f6aea4c380e41ddef2489ee581ab35e17fa3e8dd
@@ -0,0 +1,2 @@
+Ų;IJ
+UUú‰™(		MÁ²²²²;²²UW
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/f7b7254a3af7c41cb86e4b23bb93c5a6d55e2583 b/test/core/nanopb/corpus_serverlist/f7b7254a3af7c41cb86e4b23bb93c5a6d55e2583
new file mode 100644
index 0000000..3085daf
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f7b7254a3af7c41cb86e4b23bb93c5a6d55e2583
@@ -0,0 +1 @@
+)*!B!Óà@'))ò);'Ǔ¢ƒ§à:E:@sD'tÂ'–!();!­	''³(N);)&
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/f7bdc1b174f53a49c6ef8f8cdb9b8e74e0a5d4ab b/test/core/nanopb/corpus_serverlist/f7bdc1b174f53a49c6ef8f8cdb9b8e74e0a5d4ab
new file mode 100644
index 0000000..1f4ca95
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f7bdc1b174f53a49c6ef8f8cdb9b8e74e0a5d4ab
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*'‚'*')
+!*š;!x!(*:)ÞNË):y
+œ“)I;ô9;()”o:;¨'¨*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/f98c78c028baf22f39c77faf6e70edb86ac1d927 b/test/core/nanopb/corpus_serverlist/f98c78c028baf22f39c77faf6e70edb86ac1d927
new file mode 100644
index 0000000..a8a1af8
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/f98c78c028baf22f39c77faf6e70edb86ac1d927
@@ -0,0 +1 @@
+ŲU
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/fb440171bca6ff922727e9ff2a4ac40d8d7905ff b/test/core/nanopb/corpus_serverlist/fb440171bca6ff922727e9ff2a4ac40d8d7905ff
new file mode 100644
index 0000000..681ba0a
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/fb440171bca6ff922727e9ff2a4ac40d8d7905ff
@@ -0,0 +1 @@
+	
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/fc76cc4030b422e4cb5c145c3e8ed122e242acf0 b/test/core/nanopb/corpus_serverlist/fc76cc4030b422e4cb5c145c3e8ed122e242acf0
new file mode 100644
index 0000000..fde5853
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/fc76cc4030b422e4cb5c145c3e8ed122e242acf0
@@ -0,0 +1 @@
+!)fBB!(@)ò	Z!!'!*M)!:“(ó'ØH(ã‰T('¯Ò'û);<''šŸÐ*“¢ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/fcab3b80624b431e464dc12d3b6da1cf538bd15e b/test/core/nanopb/corpus_serverlist/fcab3b80624b431e464dc12d3b6da1cf538bd15e
new file mode 100644
index 0000000..690c0a1
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/fcab3b80624b431e464dc12d3b6da1cf538bd15e
@@ -0,0 +1,2 @@
+!
+)fBB!(@)ò	'Z!!Î!*M)!:“(ó'ØHã(‰T('¯Ò'û);<'šŸÐ*“<ƒÿ§'à
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/fdb3a9b59798d7e851d9074db69422b1d2df38dd b/test/core/nanopb/corpus_serverlist/fdb3a9b59798d7e851d9074db69422b1d2df38dd
new file mode 100644
index 0000000..adbe858
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/fdb3a9b59798d7e851d9074db69422b1d2df38dd
@@ -0,0 +1 @@
+È;2È;ò•òÈ;ò2
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/fe5de5f387e31b029d589d9b1777fd0d6b3e47b3 b/test/core/nanopb/corpus_serverlist/fe5de5f387e31b029d589d9b1777fd0d6b3e47b3
new file mode 100644
index 0000000..83c20ee
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/fe5de5f387e31b029d589d9b1777fd0d6b3e47b3
@@ -0,0 +1,3 @@
+!¼;@oCÙ'–((!*Ú*''*'	!
+(š;!x!(*:)ÞNË):y
+œ“)I?ô)):(”o:;©'(*(;
\ No newline at end of file
diff --git a/test/core/nanopb/corpus_serverlist/ff52d938aaa10c08b2eb0830fc0066c3b57e040f b/test/core/nanopb/corpus_serverlist/ff52d938aaa10c08b2eb0830fc0066c3b57e040f
new file mode 100644
index 0000000..4975d72
--- /dev/null
+++ b/test/core/nanopb/corpus_serverlist/ff52d938aaa10c08b2eb0830fc0066c3b57e040f
Binary files differ
diff --git a/test/core/nanopb/fuzzer_response.c b/test/core/nanopb/fuzzer_response.c
new file mode 100644
index 0000000..b4e3860
--- /dev/null
+++ b/test/core/nanopb/fuzzer_response.c
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
+  grpc_grpclb_response *response;
+  if ((response = grpc_grpclb_response_parse(slice))) {
+    grpc_grpclb_response_destroy(response);
+  }
+  gpr_slice_unref(slice);
+  return 0;
+}
diff --git a/test/core/nanopb/fuzzer_serverlist.c b/test/core/nanopb/fuzzer_serverlist.c
new file mode 100644
index 0000000..d4ec74f
--- /dev/null
+++ b/test/core/nanopb/fuzzer_serverlist.c
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
+  grpc_grpclb_serverlist *serverlist;
+  if ((serverlist = grpc_grpclb_response_parse_serverlist(slice))) {
+    grpc_grpclb_destroy_serverlist(serverlist);
+  }
+  gpr_slice_unref(slice);
+  return 0;
+}
diff --git a/test/core/network_benchmarks/low_level_ping_pong.c b/test/core/network_benchmarks/low_level_ping_pong.c
index dd1544c..1b40895 100644
--- a/test/core/network_benchmarks/low_level_ping_pong.c
+++ b/test/core/network_benchmarks/low_level_ping_pong.c
@@ -49,13 +49,14 @@
 #endif
 #include <sys/socket.h>
 
-#include "src/core/iomgr/socket_utils_posix.h"
+#include <grpc/support/alloc.h>
 #include <grpc/support/cmdline.h>
 #include <grpc/support/histogram.h>
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/iomgr/socket_utils_posix.h"
 
 typedef struct fd_pair {
   int read_fd;
@@ -265,19 +266,19 @@
 #endif
 
 static void server_thread(thread_args *args) {
-  char *buf = malloc(args->msg_size);
+  char *buf = gpr_malloc(args->msg_size);
   if (args->setup(args) < 0) {
     gpr_log(GPR_ERROR, "Setup failed");
   }
   for (;;) {
     if (args->read_bytes(args, buf) < 0) {
       gpr_log(GPR_ERROR, "Server read failed");
-      free(buf);
+      gpr_free(buf);
       return;
     }
     if (args->write_bytes(args, buf) < 0) {
       gpr_log(GPR_ERROR, "Server write failed");
-      free(buf);
+      gpr_free(buf);
       return;
     }
   }
@@ -304,7 +305,8 @@
 }
 
 static void client_thread(thread_args *args) {
-  char *buf = calloc(args->msg_size, sizeof(char));
+  char *buf = gpr_malloc(args->msg_size * sizeof(char));
+  memset(buf, 0, args->msg_size * sizeof(char));
   gpr_histogram *histogram = gpr_histogram_create(0.01, 60e9);
   double start_time;
   double end_time;
@@ -333,7 +335,7 @@
   }
   print_histogram(histogram);
 error:
-  free(buf);
+  gpr_free(buf);
   gpr_histogram_destroy(histogram);
 }
 
@@ -596,8 +598,8 @@
     test_strategy *strategy = &test_strategies[i];
     size_t j;
     for (j = 0; j < GPR_ARRAY_SIZE(socket_types); ++j) {
-      thread_args *client_args = malloc(sizeof(thread_args));
-      thread_args *server_args = malloc(sizeof(thread_args));
+      thread_args *client_args = gpr_malloc(sizeof(thread_args));
+      thread_args *server_args = gpr_malloc(sizeof(thread_args));
       char *socket_type = socket_types[j];
 
       client_args->read_bytes = strategy->read_strategy;
@@ -620,8 +622,8 @@
 }
 
 int main(int argc, char **argv) {
-  thread_args *client_args = malloc(sizeof(thread_args));
-  thread_args *server_args = malloc(sizeof(thread_args));
+  thread_args *client_args = gpr_malloc(sizeof(thread_args));
+  thread_args *server_args = gpr_malloc(sizeof(thread_args));
   int msg_size = -1;
   char *read_strategy = NULL;
   char *socket_type = NULL;
diff --git a/test/core/profiling/timers_test.c b/test/core/profiling/timers_test.c
index 7070fe4..284589a 100644
--- a/test/core/profiling/timers_test.c
+++ b/test/core/profiling/timers_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/profiling/timers.h"
+#include "src/core/lib/profiling/timers.h"
 #include <stdlib.h>
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/security/auth_context_test.c b/test/core/security/auth_context_test.c
index d091c7e..d1ead16 100644
--- a/test/core/security/auth_context_test.c
+++ b/test/core/security/auth_context_test.c
@@ -33,8 +33,8 @@
 
 #include <string.h>
 
-#include "src/core/security/security_context.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/util/test_config.h"
 
 #include <grpc/support/log.h>
diff --git a/test/core/security/b64_test.c b/test/core/security/b64_test.c
index 772514e..cea8703 100644
--- a/test/core/security/b64_test.c
+++ b/test/core/security/b64_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/security/b64.h"
+#include "src/core/lib/security/b64.h"
 
 #include <string.h>
 
diff --git a/test/core/security/create_jwt.c b/test/core/security/create_jwt.c
index 4c0cf43..6d4707f 100644
--- a/test/core/security/create_jwt.c
+++ b/test/core/security/create_jwt.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,9 +34,9 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/security/credentials.h"
-#include "src/core/security/json_token.h"
-#include "src/core/support/load_file.h"
+#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/json_token.h"
+#include "src/core/lib/support/load_file.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/cmdline.h>
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 98133ef..7867293 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,7 @@
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/security/credentials.h"
+#include "src/core/lib/security/credentials.h"
 
 #include <openssl/rsa.h>
 #include <stdlib.h>
@@ -44,11 +44,11 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 
-#include "src/core/httpcli/httpcli.h"
-#include "src/core/security/json_token.h"
-#include "src/core/support/env.h"
-#include "src/core/support/tmpfile.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/security/json_token.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/tmpfile.h"
 #include "test/core/util/test_config.h"
 
 /* -- Mock channel credentials. -- */
@@ -536,12 +536,12 @@
   GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "metadata") == 0);
   GPR_ASSERT(
-      strcmp(request->path,
+      strcmp(request->http.path,
              "/computeMetadata/v1/instance/service-accounts/default/token") ==
       0);
-  GPR_ASSERT(request->hdr_count == 1);
-  GPR_ASSERT(strcmp(request->hdrs[0].key, "Metadata-Flavor") == 0);
-  GPR_ASSERT(strcmp(request->hdrs[0].value, "Google") == 0);
+  GPR_ASSERT(request->http.hdr_count == 1);
+  GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Metadata-Flavor") == 0);
+  GPR_ASSERT(strcmp(request->http.hdrs[0].value, "Google") == 0);
 }
 
 static int compute_engine_httpcli_get_success_override(
@@ -639,11 +639,12 @@
   gpr_free(expected_body);
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0);
-  GPR_ASSERT(strcmp(request->path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0);
-  GPR_ASSERT(request->hdr_count == 1);
-  GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
   GPR_ASSERT(
-      strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0);
+      strcmp(request->http.path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0);
+  GPR_ASSERT(request->http.hdr_count == 1);
+  GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0);
+  GPR_ASSERT(strcmp(request->http.hdrs[0].value,
+                    "application/x-www-form-urlencoded") == 0);
 }
 
 static int refresh_token_httpcli_post_success(
@@ -898,12 +899,12 @@
     gpr_timespec deadline, grpc_httpcli_response_cb on_response,
     void *user_data) {
   grpc_httpcli_response response = http_response(200, "");
-  grpc_httpcli_header header;
+  grpc_http_header header;
   header.key = "Metadata-Flavor";
   header.value = "Google";
   response.hdr_count = 1;
   response.hdrs = &header;
-  GPR_ASSERT(strcmp(request->path, "/") == 0);
+  GPR_ASSERT(strcmp(request->http.path, "/") == 0);
   GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0);
   on_response(exec_ctx, user_data, &response);
   return 1;
@@ -961,7 +962,7 @@
     void *user_data) {
   /* No magic header. */
   grpc_httpcli_response response = http_response(200, "");
-  GPR_ASSERT(strcmp(request->path, "/") == 0);
+  GPR_ASSERT(strcmp(request->http.path, "/") == 0);
   GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0);
   on_response(exec_ctx, user_data, &response);
   return 1;
diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c
index 87b54f1..bd314e9 100644
--- a/test/core/security/fetch_oauth2.c
+++ b/test/core/security/fetch_oauth2.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,8 +42,8 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/security/credentials.h"
-#include "src/core/support/load_file.h"
+#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/support/load_file.h"
 #include "test/core/security/oauth2_utils.h"
 
 static grpc_call_credentials *create_refresh_token_creds(
diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c
index 4d80c16..3aee52e 100644
--- a/test/core/security/json_token_test.c
+++ b/test/core/security/json_token_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/security/json_token.h"
+#include "src/core/lib/security/json_token.h"
 
 #include <openssl/evp.h>
 #include <string.h>
@@ -41,8 +41,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
 
-#include "src/core/json/json.h"
-#include "src/core/security/b64.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/security/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 f6ec9e1..077f44d 100644
--- a/test/core/security/jwt_verifier_test.c
+++ b/test/core/security/jwt_verifier_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,20 +31,22 @@
  *
  */
 
-#include "src/core/security/jwt_verifier.h"
+#include "src/core/lib/security/jwt_verifier.h"
 
 #include <string.h>
 
-#include "src/core/httpcli/httpcli.h"
-#include "src/core/security/b64.h"
-#include "src/core/security/json_token.h"
-#include "test/core/util/test_config.h"
+#include <grpc/grpc.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
 #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 "test/core/util/test_config.h"
+
 /* This JSON key was generated with the GCE console and revoked immediately.
    The identifiers have been changed as well.
    Maximum size for a string literal is 509 chars in C89, yay!  */
@@ -288,7 +290,7 @@
   grpc_httpcli_response response = http_response(200, good_google_email_keys());
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
-  GPR_ASSERT(strcmp(request->path,
+  GPR_ASSERT(strcmp(request->http.path,
                     "/robot/v1/metadata/x509/"
                     "777-abaslkan11hlb6nmim3bpspl31ud@developer."
                     "gserviceaccount.com") == 0);
@@ -336,7 +338,7 @@
   grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0);
-  GPR_ASSERT(strcmp(request->path, "/jwk/foo@bar.com") == 0);
+  GPR_ASSERT(strcmp(request->http.path, "/jwk/foo@bar.com") == 0);
   on_response(exec_ctx, user_data, &response);
   gpr_free(response.body);
   return 1;
@@ -372,7 +374,7 @@
   grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
-  GPR_ASSERT(strcmp(request->path, "/oauth2/v3/certs") == 0);
+  GPR_ASSERT(strcmp(request->http.path, "/oauth2/v3/certs") == 0);
   on_response(exec_ctx, user_data, &response);
   gpr_free(response.body);
   return 1;
@@ -387,7 +389,7 @@
       http_response(200, gpr_strdup(good_openid_config));
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "accounts.google.com") == 0);
-  GPR_ASSERT(strcmp(request->path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0);
+  GPR_ASSERT(strcmp(request->http.path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0);
   grpc_httpcli_set_override(httpcli_get_jwk_set,
                             httpcli_post_should_not_be_called);
   on_response(exec_ctx, user_data, &response);
@@ -568,6 +570,7 @@
 
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
+  grpc_init();
   test_claims_success();
   test_expired_claims_failure();
   test_invalid_claims_failure();
@@ -579,5 +582,6 @@
   test_jwt_verifier_bad_json_key();
   test_jwt_verifier_bad_signature();
   test_jwt_verifier_bad_format();
+  grpc_shutdown();
   return 0;
 }
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index 9b70aff..20815d1 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,7 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/security/credentials.h"
+#include "src/core/lib/security/credentials.h"
 
 typedef struct {
   gpr_mu *mu;
diff --git a/test/core/security/oauth2_utils.h b/test/core/security/oauth2_utils.h
index b35fe79..eff9827 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/security/credentials.h"
+#include "src/core/lib/security/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 09673f3..99bce4f 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,8 +42,8 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/security/credentials.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/support/string.h"
 
 typedef struct {
   gpr_mu *mu;
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index 0e8c38a..aeaf382 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,10 +39,10 @@
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/security/secure_endpoint.h"
-#include "src/core/tsi/fake_transport_security.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/tsi/fake_transport_security.h"
 #include "test/core/util/test_config.h"
 
 static gpr_mu *g_mu;
diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c
index 609d874..1a4e64b 100644
--- a/test/core/security/security_connector_test.c
+++ b/test/core/security/security_connector_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,13 +40,13 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/security/security_connector.h"
-#include "src/core/security/security_context.h"
-#include "src/core/support/env.h"
-#include "src/core/support/tmpfile.h"
-#include "src/core/support/string.h"
-#include "src/core/tsi/ssl_transport_security.h"
-#include "src/core/tsi/transport_security.h"
+#include "src/core/lib/security/security_connector.h"
+#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/tmpfile.h"
+#include "src/core/lib/tsi/ssl_transport_security.h"
+#include "src/core/lib/tsi/transport_security.h"
 #include "test/core/util/test_config.h"
 
 static int check_transport_security_type(const grpc_auth_context *ctx) {
diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c
index eb86589..2274fe1 100644
--- a/test/core/security/verify_jwt.c
+++ b/test/core/security/verify_jwt.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,7 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/security/jwt_verifier.h"
+#include "src/core/lib/security/jwt_verifier.h"
 
 typedef struct {
   grpc_pollset *pollset;
diff --git a/test/core/statistics/census_log_tests.c b/test/core/statistics/census_log_tests.c
index 77cc57d..8646a2f 100644
--- a/test/core/statistics/census_log_tests.c
+++ b/test/core/statistics/census_log_tests.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,10 +31,7 @@
  *
  */
 
-#include "src/core/statistics/census_log.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include "src/core/ext/census/census_log.h"
 #include <grpc/support/cpu.h>
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
@@ -42,6 +39,9 @@
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include "test/core/util/test_config.h"
 
 /* Fills in 'record' of size 'size'. Each byte in record is filled in with the
diff --git a/test/core/statistics/census_stub_test.c b/test/core/statistics/census_stub_test.c
index 8e409a3..f9dddb6 100644
--- a/test/core/statistics/census_stub_test.c
+++ b/test/core/statistics/census_stub_test.c
@@ -34,10 +34,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "src/core/statistics/census_interface.h"
-#include "src/core/statistics/census_rpc_stats.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include "src/core/ext/census/census_interface.h"
+#include "src/core/ext/census/census_rpc_stats.h"
 #include "test/core/util/test_config.h"
 
 /* Tests census noop stubs in a simulated rpc flow */
diff --git a/test/core/statistics/hash_table_test.c b/test/core/statistics/hash_table_test.c
index 3b119db..f63c1a3 100644
--- a/test/core/statistics/hash_table_test.c
+++ b/test/core/statistics/hash_table_test.c
@@ -35,13 +35,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "src/core/statistics/hash_table.h"
+#include "src/core/ext/census/hash_table.h"
 
-#include "src/core/support/murmur_hash.h"
-#include "src/core/support/string.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
+#include "src/core/lib/support/murmur_hash.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/util/test_config.h"
 
 static uint64_t hash64(const void *k) {
@@ -65,8 +65,8 @@
 static void test_create_table(void) {
   /* Create table with uint64 key type */
   census_ht *ht = NULL;
-  census_ht_option ht_options = {CENSUS_HT_UINT64, 1999, NULL, NULL, NULL,
-                                 NULL};
+  census_ht_option ht_options = {
+      CENSUS_HT_UINT64, 1999, NULL, NULL, NULL, NULL};
   ht = census_ht_create(&ht_options);
   GPR_ASSERT(ht != NULL);
   GPR_ASSERT(census_ht_get_size(ht) == 0);
@@ -120,8 +120,8 @@
 
 /* Test that there is no memory leak when keys and values are owned by table. */
 static void test_value_and_key_deleter(void) {
-  census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, &cmp_str_keys,
-                          &free_data, &free_data};
+  census_ht_option opt = {CENSUS_HT_POINTER, 7,          &hash64,
+                          &cmp_str_keys,     &free_data, &free_data};
   census_ht *ht = census_ht_create(&opt);
   census_ht_key key;
   char *val = NULL;
@@ -185,8 +185,8 @@
 }
 
 static void test_insertion_and_deletion_with_high_collision_rate(void) {
-  census_ht_option opt = {CENSUS_HT_POINTER, 13, &force_collision,
-                          &cmp_str_keys, NULL, NULL};
+  census_ht_option opt = {CENSUS_HT_POINTER, 13,   &force_collision,
+                          &cmp_str_keys,     NULL, NULL};
   census_ht *ht = census_ht_create(&opt);
   char key_str[1000][GPR_LTOA_MIN_BUFSIZE];
   uint64_t val = 0;
@@ -209,12 +209,12 @@
 }
 
 static void test_table_with_string_key(void) {
-  census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, &cmp_str_keys, NULL,
-                          NULL};
+  census_ht_option opt = {CENSUS_HT_POINTER, 7,    &hash64,
+                          &cmp_str_keys,     NULL, NULL};
   census_ht *ht = census_ht_create(&opt);
-  const char *keys[] = {"k1", "a", "000", "apple",
-                        "banana_a_long_long_long_banana", "%$", "111", "foo",
-                        "b"};
+  const char *keys[] = {
+      "k1", "a",   "000", "apple", "banana_a_long_long_long_banana",
+      "%$", "111", "foo", "b"};
   const int vals[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
   int i = 0;
   GPR_ASSERT(ht != NULL);
diff --git a/test/core/statistics/rpc_stats_test.c b/test/core/statistics/rpc_stats_test.c
index b1d8814..14def4b 100644
--- a/test/core/statistics/rpc_stats_test.c
+++ b/test/core/statistics/rpc_stats_test.c
@@ -33,15 +33,15 @@
 
 #include <string.h>
 
-#include "src/core/statistics/census_interface.h"
-#include "src/core/statistics/census_rpc_stats.h"
-#include "src/core/statistics/census_tracing.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
 #include <grpc/support/string.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
+#include "src/core/ext/census/census_interface.h"
+#include "src/core/ext/census/census_rpc_stats.h"
+#include "src/core/ext/census/census_tracing.h"
 #include "test/core/util/test_config.h"
 
 /* Ensure all possible state transitions are called without causing problem */
diff --git a/test/core/statistics/trace_test.c b/test/core/statistics/trace_test.c
index 7590404..790507f 100644
--- a/test/core/statistics/trace_test.c
+++ b/test/core/statistics/trace_test.c
@@ -31,12 +31,9 @@
  *
  */
 
-#include <string.h>
 #include <stdio.h>
+#include <string.h>
 
-#include "src/core/statistics/census_interface.h"
-#include "src/core/statistics/census_tracing.h"
-#include "src/core/statistics/census_tracing.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
@@ -44,6 +41,9 @@
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/ext/census/census_interface.h"
+#include "src/core/ext/census/census_tracing.h"
+#include "src/core/ext/census/census_tracing.h"
 #include "test/core/util/test_config.h"
 
 /* Ensure all possible state transitions are called without causing problem */
diff --git a/test/core/statistics/window_stats_test.c b/test/core/statistics/window_stats_test.c
index 578138f..5d71ba6 100644
--- a/test/core/statistics/window_stats_test.c
+++ b/test/core/statistics/window_stats_test.c
@@ -31,10 +31,10 @@
  *
  */
 
-#include "src/core/statistics/window_stats.h"
-#include <stdlib.h>
+#include "src/core/ext/census/window_stats.h"
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
+#include <stdlib.h>
 #include "test/core/util/test_config.h"
 
 typedef struct test_stat {
diff --git a/test/core/support/alloc_test.c b/test/core/support/alloc_test.c
index 6bdba8c..451c580 100644
--- a/test/core/support/alloc_test.c
+++ b/test/core/support/alloc_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,8 @@
  *
  */
 
-#include <grpc/support/log.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
 #include "test/core/util/test_config.h"
 
 static void *fake_malloc(size_t size) { return (void *)size; }
@@ -46,7 +46,7 @@
 static void test_custom_allocs() {
   const gpr_allocation_functions default_fns = gpr_get_allocation_functions();
   intptr_t addr_to_free = 0;
-  int *i;
+  char *i;
   gpr_allocation_functions fns = {fake_malloc, fake_realloc, fake_free};
 
   gpr_set_allocation_functions(fns);
@@ -58,7 +58,7 @@
 
   /* Restore and check we don't get funky values and that we don't leak */
   gpr_set_allocation_functions(default_fns);
-  GPR_ASSERT((void *)1 != (i = gpr_malloc(sizeof(*i))));
+  GPR_ASSERT((void *)sizeof(*i) != (i = gpr_malloc(sizeof(*i))));
   GPR_ASSERT((void *)2 != (i = gpr_realloc(i, 2)));
   gpr_free(i);
 }
diff --git a/test/core/support/avl_test.c b/test/core/support/avl_test.c
index d8d8b36..83cc263 100644
--- a/test/core/support/avl_test.c
+++ b/test/core/support/avl_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/support/backoff_test.c b/test/core/support/backoff_test.c
index 870b60b..13cba7d 100644
--- a/test/core/support/backoff_test.c
+++ b/test/core/support/backoff_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/support/backoff.h"
+#include "src/core/lib/support/backoff.h"
 
 #include <grpc/support/log.h>
 
diff --git a/test/core/support/cpu_test.c b/test/core/support/cpu_test.c
index da16f13..a5c5244 100644
--- a/test/core/support/cpu_test.c
+++ b/test/core/support/cpu_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/support/env_test.c b/test/core/support/env_test.c
index 69aebcc..bd6a8bd 100644
--- a/test/core/support/env_test.c
+++ b/test/core/support/env_test.c
@@ -37,8 +37,8 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/support/env.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x)
diff --git a/test/core/support/load_file_test.c b/test/core/support/load_file_test.c
index 70189b7..0125fd9 100644
--- a/test/core/support/load_file_test.c
+++ b/test/core/support/load_file_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,9 +38,9 @@
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
 
-#include "src/core/support/load_file.h"
-#include "src/core/support/tmpfile.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/support/tmpfile.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x)
diff --git a/test/core/support/log_test.c b/test/core/support/log_test.c
index b39b069..0ae298a 100644
--- a/test/core/support/log_test.c
+++ b/test/core/support/log_test.c
@@ -33,16 +33,40 @@
 
 #include <grpc/support/log.h>
 
+#include <stdbool.h>
 #include <string.h>
 
+#include "src/core/lib/support/env.h"
 #include "test/core/util/test_config.h"
 
+static bool log_func_reached = false;
+
 static void test_callback(gpr_log_func_args *args) {
   GPR_ASSERT(0 == strcmp(__FILE__, args->file));
   GPR_ASSERT(args->severity == GPR_LOG_SEVERITY_INFO);
   GPR_ASSERT(0 == strcmp(args->message, "hello 1 2 3"));
 }
 
+static void test_should_log(gpr_log_func_args *args) {
+  log_func_reached = true;
+}
+
+static void test_should_not_log(gpr_log_func_args *args) { GPR_ASSERT(false); }
+
+#define test_log_function_reached(SEVERITY)     \
+  gpr_set_log_function(test_should_log);        \
+  log_func_reached = false;                     \
+  gpr_log_message(SEVERITY, "hello 1 2 3");     \
+  GPR_ASSERT(log_func_reached);                 \
+  log_func_reached = false;                     \
+  gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3); \
+  GPR_ASSERT(log_func_reached);
+
+#define test_log_function_unreached(SEVERITY) \
+  gpr_set_log_function(test_should_not_log);  \
+  gpr_log_message(SEVERITY, "hello 1 2 3");   \
+  gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3);
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   /* test logging at various verbosity levels */
@@ -54,6 +78,44 @@
   gpr_set_log_function(test_callback);
   gpr_log_message(GPR_INFO, "hello 1 2 3");
   gpr_log(GPR_INFO, "hello %d %d %d", 1, 2, 3);
+
+  /* gpr_log_verbosity_init() will be effective only once, and only before
+   * gpr_set_log_verbosity() is called */
+  gpr_setenv("GRPC_VERBOSITY", "ERROR");
+  gpr_log_verbosity_init();
+  test_log_function_reached(GPR_ERROR);
+  test_log_function_unreached(GPR_INFO);
+  test_log_function_unreached(GPR_DEBUG);
+
+  /* gpr_log_verbosity_init() should not be effective */
+  gpr_setenv("GRPC_VERBOSITY", "DEBUG");
+  gpr_log_verbosity_init();
+  test_log_function_reached(GPR_ERROR);
+  test_log_function_unreached(GPR_INFO);
+  test_log_function_unreached(GPR_DEBUG);
+
+  gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG);
+  test_log_function_reached(GPR_ERROR);
+  test_log_function_reached(GPR_INFO);
+  test_log_function_reached(GPR_DEBUG);
+
+  gpr_set_log_verbosity(GPR_LOG_SEVERITY_INFO);
+  test_log_function_reached(GPR_ERROR);
+  test_log_function_reached(GPR_INFO);
+  test_log_function_unreached(GPR_DEBUG);
+
+  gpr_set_log_verbosity(GPR_LOG_SEVERITY_ERROR);
+  test_log_function_reached(GPR_ERROR);
+  test_log_function_unreached(GPR_INFO);
+  test_log_function_unreached(GPR_DEBUG);
+
+  /* gpr_log_verbosity_init() should not be effective */
+  gpr_setenv("GRPC_VERBOSITY", "DEBUG");
+  gpr_log_verbosity_init();
+  test_log_function_reached(GPR_ERROR);
+  test_log_function_unreached(GPR_INFO);
+  test_log_function_unreached(GPR_DEBUG);
+
   /* TODO(ctiller): should we add a GPR_ASSERT failure test here */
   return 0;
 }
diff --git a/test/core/support/murmur_hash_test.c b/test/core/support/murmur_hash_test.c
index 562b956..ef32719 100644
--- a/test/core/support/murmur_hash_test.c
+++ b/test/core/support/murmur_hash_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/support/murmur_hash.h"
+#include "src/core/lib/support/murmur_hash.h"
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include "test/core/util/test_config.h"
diff --git a/test/core/support/stack_lockfree_test.c b/test/core/support/stack_lockfree_test.c
index 0f49e6f..745157f 100644
--- a/test/core/support/stack_lockfree_test.c
+++ b/test/core/support/stack_lockfree_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/support/stack_lockfree.h"
+#include "src/core/lib/support/stack_lockfree.h"
 
 #include <stdlib.h>
 
diff --git a/test/core/support/string_test.c b/test/core/support/string_test.c
index c1d0f12..d5f8107 100644
--- a/test/core/support/string_test.c
+++ b/test/core/support/string_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/support/string.h"
+#include "src/core/lib/support/string.h"
 
 #include <limits.h>
 #include <stddef.h>
diff --git a/test/core/support/sync_test.c b/test/core/support/sync_test.c
index d311eb1..0fcf08b 100644
--- a/test/core/support/sync_test.c
+++ b/test/core/support/sync_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,13 +33,13 @@
 
 /* Test of gpr synchronization support. */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include "test/core/util/test_config.h"
 
 /* ==================Example use of interface===================
diff --git a/test/core/support/thd_test.c b/test/core/support/thd_test.c
index 0c176da..c00fd5a 100644
--- a/test/core/support/thd_test.c
+++ b/test/core/support/thd_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,12 +33,12 @@
 
 /* Test of gpr thread support. */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include "test/core/util/test_config.h"
 
 #define NUM_THREADS 300
diff --git a/test/core/support/time_test.c b/test/core/support/time_test.c
index 6cc3786..e9ca08d 100644
--- a/test/core/support/time_test.c
+++ b/test/core/support/time_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,14 +33,14 @@
 
 /* Test of gpr time support. */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include "test/core/util/test_config.h"
 
 static void to_fp(void *arg, const char *buf, size_t len) {
diff --git a/test/core/support/tls_test.c b/test/core/support/tls_test.c
index c6fb1a4..7b732ee 100644
--- a/test/core/support/tls_test.c
+++ b/test/core/support/tls_test.c
@@ -33,12 +33,12 @@
 
 /* Test of gpr thread local storage support. */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/tls.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include "test/core/util/test_config.h"
 
 #define NUM_THREADS 100
diff --git a/test/core/support/useful_test.c b/test/core/support/useful_test.c
index 3665bbf..7d19022 100644
--- a/test/core/support/useful_test.c
+++ b/test/core/support/useful_test.c
@@ -31,9 +31,9 @@
  *
  */
 
-#include <grpc/support/useful.h>
-#include <grpc/support/port_platform.h>
 #include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
 #include "test/core/util/test_config.h"
 
 int main(int argc, char **argv) {
diff --git a/test/core/surface/byte_buffer_reader_test.c b/test/core/surface/byte_buffer_reader_test.c
index c87fbdc..9c6734e 100644
--- a/test/core/surface/byte_buffer_reader_test.c
+++ b/test/core/surface/byte_buffer_reader_test.c
@@ -31,10 +31,10 @@
  *
  */
 
-#include <grpc/byte_buffer_reader.h>
 #include <grpc/byte_buffer.h>
-#include <grpc/support/slice.h>
+#include <grpc/byte_buffer_reader.h>
 #include <grpc/grpc.h>
+#include <grpc/support/slice.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -42,7 +42,7 @@
 #include <grpc/support/time.h>
 #include "test/core/util/test_config.h"
 
-#include "src/core/compression/message_compress.h"
+#include "src/core/lib/compression/message_compress.h"
 
 #include <string.h>
 
diff --git a/test/core/surface/channel_create_test.c b/test/core/surface/channel_create_test.c
index 044e766..450cc37 100644
--- a/test/core/surface/channel_create_test.c
+++ b/test/core/surface/channel_create_test.c
@@ -33,7 +33,7 @@
 
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
-#include "src/core/client_config/resolver_registry.h"
+#include "src/core/ext/client_config/resolver_registry.h"
 #include "test/core/util/test_config.h"
 
 void test_unknown_scheme_target(void) {
@@ -43,7 +43,8 @@
   grpc_resolver_registry_init("");
 
   chan = grpc_insecure_channel_create("blah://blah", NULL, NULL);
-  GPR_ASSERT(chan == NULL);
+  GPR_ASSERT(chan != NULL);
+  grpc_channel_destroy(chan);
 }
 
 int main(int argc, char **argv) {
diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c
index ec49840..d62d5a9 100644
--- a/test/core/surface/completion_queue_test.c
+++ b/test/core/surface/completion_queue_test.c
@@ -31,14 +31,14 @@
  *
  */
 
-#include "src/core/surface/completion_queue.h"
+#include "src/core/lib/surface/completion_queue.h"
 
-#include "src/core/iomgr/iomgr.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/iomgr/iomgr.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index 96761b0..28ddf58 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -31,12 +31,21 @@
 *
 */
 
+#include <memory.h>
 #include <stdio.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/thd.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/tcp_server.h"
+
+#include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
 #define NUM_THREADS 100
@@ -45,10 +54,13 @@
 #define DELAY_MILLIS 10
 #define POLL_MILLIS 3000
 
-void create_loop_destroy(void* unused) {
+static void *tag(int n) { return (void *)(uintptr_t)n; }
+static int detag(void *p) { return (int)(uintptr_t)p; }
+
+void create_loop_destroy(void *addr) {
   for (int i = 0; i < NUM_OUTER_LOOPS; ++i) {
-    grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
-    grpc_channel* chan = grpc_insecure_channel_create("localhost", NULL, NULL);
+    grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+    grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL);
 
     for (int j = 0; j < NUM_INNER_LOOPS; ++j) {
       gpr_timespec later_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(DELAY_MILLIS);
@@ -64,18 +76,149 @@
   }
 }
 
-int main(int argc, char** argv) {
+struct server_thread_args {
+  char *addr;
+  grpc_server *server;
+  grpc_completion_queue *cq;
+  grpc_pollset *pollset;
+  gpr_mu *mu;
+  gpr_event ready;
+  gpr_atm stop;
+};
+
+void server_thread(void *vargs) {
+  struct server_thread_args *args = (struct server_thread_args *)vargs;
+  grpc_event ev;
+  gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  ev = grpc_completion_queue_next(args->cq, deadline, NULL);
+  GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(detag(ev.tag) == 0xd1e);
+}
+
+static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp,
+                       grpc_tcp_server_acceptor *acceptor) {
+  struct server_thread_args *args = (struct server_thread_args *)vargs;
+  (void)acceptor;
+  grpc_endpoint_shutdown(exec_ctx, tcp);
+  grpc_endpoint_destroy(exec_ctx, tcp);
+  grpc_pollset_kick(args->pollset, NULL);
+}
+
+void bad_server_thread(void *vargs) {
+  struct server_thread_args *args = (struct server_thread_args *)vargs;
+
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  struct sockaddr_storage addr;
+  socklen_t addr_len = sizeof(addr);
+  int port;
+  grpc_tcp_server *s = grpc_tcp_server_create(NULL);
+  memset(&addr, 0, sizeof(addr));
+  addr.ss_family = AF_INET;
+  port = grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len);
+  GPR_ASSERT(port > 0);
+  gpr_asprintf(&args->addr, "localhost:%d", port);
+
+  grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args);
+  gpr_event_set(&args->ready, (void *)1);
+
+  gpr_mu_lock(args->mu);
+  while (gpr_atm_acq_load(&args->stop) == 0) {
+    gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+    gpr_timespec deadline =
+        gpr_time_add(now, gpr_time_from_millis(100, GPR_TIMESPAN));
+
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, args->pollset, &worker, now, deadline);
+    gpr_mu_unlock(args->mu);
+    grpc_exec_ctx_finish(&exec_ctx);
+    gpr_mu_lock(args->mu);
+  }
+  gpr_mu_unlock(args->mu);
+
+  grpc_tcp_server_unref(&exec_ctx, s);
+
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  gpr_free(args->addr);
+}
+
+static void done_pollset_shutdown(grpc_exec_ctx *exec_ctx, void *pollset,
+                                  bool success) {
+  grpc_pollset_destroy(pollset);
+  gpr_free(pollset);
+}
+
+int main(int argc, char **argv) {
+  struct server_thread_args args;
+  memset(&args, 0, sizeof(args));
+
   grpc_test_init(argc, argv);
   grpc_init();
+
   gpr_thd_id threads[NUM_THREADS];
+  gpr_thd_id server;
+
+  char *localhost = gpr_strdup("localhost:54321");
+  gpr_thd_options options = gpr_thd_options_default();
+  gpr_thd_options_set_joinable(&options);
+
+  /* First round, no server */
+  gpr_log(GPR_DEBUG, "Wave 1");
   for (size_t i = 0; i < NUM_THREADS; ++i) {
-    gpr_thd_options options = gpr_thd_options_default();
-    gpr_thd_options_set_joinable(&options);
-    gpr_thd_new(&threads[i], create_loop_destroy, NULL, &options);
+    gpr_thd_new(&threads[i], create_loop_destroy, localhost, &options);
   }
   for (size_t i = 0; i < NUM_THREADS; ++i) {
     gpr_thd_join(threads[i]);
   }
+  gpr_free(localhost);
+
+  /* Second round, actual grpc server */
+  gpr_log(GPR_DEBUG, "Wave 2");
+  int port = grpc_pick_unused_port_or_die();
+  gpr_asprintf(&args.addr, "localhost:%d", port);
+  args.server = grpc_server_create(NULL, NULL);
+  grpc_server_add_insecure_http2_port(args.server, args.addr);
+  args.cq = grpc_completion_queue_create(NULL);
+  grpc_server_register_completion_queue(args.server, args.cq, NULL);
+  grpc_server_start(args.server);
+  gpr_thd_new(&server, server_thread, &args, &options);
+
+  for (size_t i = 0; i < NUM_THREADS; ++i) {
+    gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options);
+  }
+  for (size_t i = 0; i < NUM_THREADS; ++i) {
+    gpr_thd_join(threads[i]);
+  }
+  grpc_server_shutdown_and_notify(args.server, args.cq, tag(0xd1e));
+
+  gpr_thd_join(server);
+  grpc_server_destroy(args.server);
+  grpc_completion_queue_destroy(args.cq);
+  gpr_free(args.addr);
+
+  /* Third round, bogus tcp server */
+  gpr_log(GPR_DEBUG, "Wave 3");
+  args.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(args.pollset, &args.mu);
+  gpr_event_init(&args.ready);
+  gpr_thd_new(&server, bad_server_thread, &args, &options);
+  gpr_event_wait(&args.ready, gpr_inf_future(GPR_CLOCK_MONOTONIC));
+
+  for (size_t i = 0; i < NUM_THREADS; ++i) {
+    gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options);
+  }
+  for (size_t i = 0; i < NUM_THREADS; ++i) {
+    gpr_thd_join(threads[i]);
+  }
+
+  gpr_atm_rel_store(&args.stop, 1);
+  gpr_thd_join(server);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_pollset_shutdown(
+      &exec_ctx, args.pollset,
+      grpc_closure_create(done_pollset_shutdown, args.pollset));
+  grpc_exec_ctx_finish(&exec_ctx);
+
   grpc_shutdown();
   return 0;
 }
diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c
index 79e53cb..12fa9de 100644
--- a/test/core/surface/lame_client_test.c
+++ b/test/core/surface/lame_client_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,10 +36,10 @@
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
-#include "src/core/channel/channel_stack.h"
-#include "src/core/iomgr/closure.h"
-#include "src/core/surface/channel.h"
-#include "src/core/transport/transport.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/transport/transport.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 579faa4..0eede6c 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -37,6 +37,7 @@
 #include <grpc/compression.h>
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
+#include <grpc/grpc_security_constants.h>
 #include <grpc/impl/codegen/alloc.h>
 #include <grpc/impl/codegen/atm.h>
 #include <grpc/impl/codegen/byte_buffer.h>
diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c
index f3e5fef..80419ef 100644
--- a/test/core/surface/secure_channel_create_test.c
+++ b/test/core/surface/secure_channel_create_test.c
@@ -36,10 +36,10 @@
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
 #include <grpc/support/log.h>
-#include "src/core/client_config/resolver_registry.h"
-#include "src/core/security/credentials.h"
-#include "src/core/security/security_connector.h"
-#include "src/core/surface/channel.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/surface/channel.h"
 #include "test/core/util/test_config.h"
 
 void test_unknown_scheme_target(void) {
diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c
index 84b345b..d22c164 100644
--- a/test/core/surface/server_chttp2_test.c
+++ b/test/core/surface/server_chttp2_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,8 +37,8 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
-#include "src/core/security/credentials.h"
-#include "src/core/tsi/fake_transport_security.h"
+#include "src/core/lib/security/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 1d5211d..3d2e253 100644
--- a/test/core/surface/server_test.c
+++ b/test/core/surface/server_test.c
@@ -42,11 +42,25 @@
   grpc_server *server = grpc_server_create(NULL, NULL);
   void *method;
   void *method_old;
-  method = grpc_server_register_method(server, NULL, NULL);
+  method =
+      grpc_server_register_method(server, NULL, NULL, GRPC_SRM_PAYLOAD_NONE, 0);
   GPR_ASSERT(method == NULL);
-  method_old = grpc_server_register_method(server, "m", "h");
+  method_old =
+      grpc_server_register_method(server, "m", "h", GRPC_SRM_PAYLOAD_NONE, 0);
   GPR_ASSERT(method_old != NULL);
-  method = grpc_server_register_method(server, "m", "h");
+  method = grpc_server_register_method(
+      server, "m", "h", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0);
+  GPR_ASSERT(method == NULL);
+  method_old =
+      grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE,
+                                  GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
+  GPR_ASSERT(method_old != NULL);
+  method =
+      grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE, 0);
+  GPR_ASSERT(method == NULL);
+  method = grpc_server_register_method(
+      server, "m2", "h2", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER,
+      GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
   GPR_ASSERT(method == NULL);
   grpc_server_destroy(server);
 }
diff --git a/test/core/transport/chttp2/alpn_test.c b/test/core/transport/chttp2/alpn_test.c
index 9a7d5ef..48064ec 100644
--- a/test/core/transport/chttp2/alpn_test.c
+++ b/test/core/transport/chttp2/alpn_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/transport/chttp2/alpn.h"
+#include "src/core/ext/transport/chttp2/alpn/alpn.h"
 
 #include <grpc/support/log.h>
 #include "test/core/util/test_config.h"
diff --git a/test/core/transport/chttp2/bin_encoder_test.c b/test/core/transport/chttp2/bin_encoder_test.c
index d183807..095861e 100644
--- a/test/core/transport/chttp2/bin_encoder_test.c
+++ b/test/core/transport/chttp2/bin_encoder_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/transport/chttp2/bin_encoder.h"
+#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
 
 #include <string.h>
 
@@ -39,9 +39,9 @@
  * TODO(murgatroid99): Remove this
  */
 #include <grpc/grpc.h>
-#include "src/core/support/string.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include "src/core/lib/support/string.h"
 
 static int all_ok = 1;
 
@@ -83,7 +83,7 @@
   gpr_slice input = gpr_slice_from_copied_buffer(s, len);
   gpr_slice base64 = grpc_chttp2_base64_encode(input);
   gpr_slice expect = grpc_chttp2_huffman_compress(base64);
-  gpr_slice got = grpc_chttp2_base64_encode_and_huffman_compress(input);
+  gpr_slice got = grpc_chttp2_base64_encode_and_huffman_compress_impl(input);
   if (0 != gpr_slice_cmp(expect, got)) {
     char *t = gpr_dump_slice(input, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *e = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
diff --git a/test/core/transport/chttp2/hpack_encoder_test.c b/test/core/transport/chttp2/hpack_encoder_test.c
index 4a9d143..186bb64 100644
--- a/test/core/transport/chttp2/hpack_encoder_test.c
+++ b/test/core/transport/chttp2/hpack_encoder_test.c
@@ -31,16 +31,18 @@
  *
  */
 
-#include "src/core/transport/chttp2/hpack_encoder.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
 
 #include <stdio.h>
+#include <string.h>
 
-#include "src/core/support/string.h"
-#include "src/core/transport/chttp2/hpack_parser.h"
-#include "src/core/transport/metadata.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
+
+#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/metadata.h"
 #include "test/core/util/parse_hexstring.h"
 #include "test/core/util/slice_splitter.h"
 #include "test/core/util/test_config.h"
@@ -93,7 +95,10 @@
 
   gpr_slice_buffer_init(&output);
 
-  grpc_chttp2_encode_header(&g_compressor, 0xdeadbeef, &b, eof, &output);
+  grpc_transport_one_way_stats stats;
+  memset(&stats, 0, sizeof(stats));
+  grpc_chttp2_encode_header(&g_compressor, 0xdeadbeef, &b, eof, &stats,
+                            &output);
   merged = grpc_slice_merge(output.slices, output.count);
   gpr_slice_buffer_destroy(&output);
   grpc_metadata_batch_destroy(&b);
@@ -179,6 +184,37 @@
   verify(0, 0, 0, "000007 0104 deadbeef 40 026161 026261", 1, "aa", "ba");
 }
 
+static void verify_table_size_change_match_elem_size(const char *key,
+                                                     const char *value) {
+  gpr_slice_buffer output;
+  grpc_mdelem *elem = grpc_mdelem_from_strings(key, value);
+  size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
+  size_t initial_table_size = g_compressor.table_size;
+  grpc_linked_mdelem *e = gpr_malloc(sizeof(*e));
+  grpc_metadata_batch b;
+  grpc_metadata_batch_init(&b);
+  e[0].md = elem;
+  e[0].prev = NULL;
+  e[0].next = NULL;
+  b.list.head = &e[0];
+  b.list.tail = &e[0];
+  gpr_slice_buffer_init(&output);
+
+  grpc_transport_one_way_stats stats;
+  memset(&stats, 0, sizeof(stats));
+  grpc_chttp2_encode_header(&g_compressor, 0xdeadbeef, &b, 0, &stats, &output);
+  gpr_slice_buffer_destroy(&output);
+  grpc_metadata_batch_destroy(&b);
+
+  GPR_ASSERT(g_compressor.table_size == elem_size + initial_table_size);
+  gpr_free(e);
+}
+
+static void test_encode_header_size(void) {
+  verify_table_size_change_match_elem_size("hello", "world");
+  verify_table_size_change_match_elem_size("hello-bin", "world");
+}
+
 static void run_test(void (*test)(), const char *name) {
   gpr_log(GPR_INFO, "RUN TEST: %s", name);
   grpc_chttp2_hpack_compressor_init(&g_compressor);
@@ -193,6 +229,7 @@
   grpc_init();
   TEST(test_basic_headers);
   TEST(test_decode_table_overflow);
+  TEST(test_encode_header_size);
   grpc_shutdown();
   for (i = 0; i < num_to_delete; i++) {
     gpr_free(to_delete[i]);
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda b/test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda
new file mode 100644
index 0000000..76b1250
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda
@@ -0,0 +1 @@
+(?¤¤¤Û¤Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599 b/test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599
new file mode 100644
index 0000000..e28a586
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6 b/test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6
new file mode 100644
index 0000000..0ea34c4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6
@@ -0,0 +1 @@
+¤!ƒÛð¤!ƒ¶Ûð*c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76 b/test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76
new file mode 100644
index 0000000..ce65ec6
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76
@@ -0,0 +1 @@
+¤¤ð¤-bin;?0c!(ðK	ð[N!‹c[:¤ð¤-\!õG!):[(!!¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2 b/test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2
new file mode 100644
index 0000000..a7936f2
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2
@@ -0,0 +1 @@
+ð[(-bin!	ð(!\	?* ¤®@:ð[
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e b/test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e
new file mode 100644
index 0000000..be20eb5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2 b/test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2
new file mode 100644
index 0000000..0edc9f9
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2
@@ -0,0 +1 @@
+®€¤ˆ(cc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4 b/test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4
new file mode 100644
index 0000000..ebb1e88
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4
@@ -0,0 +1 @@
+¤!ƒÛðð¤!ƒÛððc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129 b/test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129
new file mode 100644
index 0000000..e880d55
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	!åGý!*(!	!åGýA)(!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610 b/test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610
new file mode 100644
index 0000000..af778fb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610
@@ -0,0 +1 @@
+¤¤Ûð!ð	cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7 b/test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7
new file mode 100644
index 0000000..e0c8806
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707 b/test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707
new file mode 100644
index 0000000..93f599d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	!!?¤Ûð!ð{(-binð	!\	!åé;?Gí[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148 b/test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148
new file mode 100644
index 0000000..1e92896
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148
@@ -0,0 +1 @@
+¤¤ð¤-bin‹äc[ò)('-bi.	*)!?¤Ûâ!ð{(-bi\n!	!	ðåé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a b/test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a
new file mode 100644
index 0000000..94a6997
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464 b/test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464
new file mode 100644
index 0000000..389f58b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe b/test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe
new file mode 100644
index 0000000..e4ec780
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f b/test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f
new file mode 100644
index 0000000..229a890
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361 b/test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361
new file mode 100644
index 0000000..001fd0b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361
@@ -0,0 +1 @@
+f!(!!	i[Ñ!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8 b/test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8
new file mode 100644
index 0000000..398077e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8
@@ -0,0 +1 @@
+¤Ê!ð	c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2 b/test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2
new file mode 100644
index 0000000..6019162
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e b/test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e
new file mode 100644
index 0000000..ca7cbd0
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)('-bh	*!!?¤Ûâ!ð{(-bi\n!	!	ðåé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378 b/test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378
new file mode 100644
index 0000000..203837b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2 b/test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2
new file mode 100644
index 0000000..8a3ef9e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc b/test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc
new file mode 100644
index 0000000..fdeb10a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444 b/test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444
new file mode 100644
index 0000000..480a056
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444
@@ -0,0 +1 @@
+¤¤ð¤-bin‹)['(-cbin	!!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e b/test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e
new file mode 100644
index 0000000..f706bd9
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e
@@ -0,0 +1 @@
+;?0c!(ðK	ð[N!\!õG![(!!	!åGýA)(!)í!*åG€¾ýA))Ù+©Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8 b/test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8
new file mode 100644
index 0000000..e4c217c
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd b/test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd
new file mode 100644
index 0000000..64fdd96
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd
@@ -0,0 +1 @@
+¤¤ð¤-bin‹í¤-[c'!)¤bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e b/test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e
new file mode 100644
index 0000000..b576e9f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a b/test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a
new file mode 100644
index 0000000..4830972
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c b/test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c
new file mode 100644
index 0000000..75aa45a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c
@@ -0,0 +1 @@
+;?0cð[(!	ð[N!\	!åGý![(!!	!åGýA)(!)í!¼*)åGýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd b/test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd
new file mode 100644
index 0000000..914e443
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[')(-'bin	!!?¤Ûð!ð{(-banð	!\	!(åé–;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a b/test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a
new file mode 100644
index 0000000..fc2f5a5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723 b/test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723
new file mode 100644
index 0000000..6ae0cd1
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc b/test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc
new file mode 100644
index 0000000..970a912
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719 b/test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719
new file mode 100644
index 0000000..ae0ab51
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719
@@ -0,0 +1 @@
+?*®@:[ðøc	(!!\þ;ð!~	ÛåG¤¤Ûðý!Ðam¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291 b/test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291
new file mode 100644
index 0000000..68b2d0e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b b/test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b
new file mode 100644
index 0000000..64ab9ba
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b
@@ -0,0 +1 @@
+¤¤ð¤-bin‹™[)('-bin	!!?¤Ûð!ð{(-bi\n!	!	ðåé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f b/test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f
new file mode 100644
index 0000000..2715d4e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f
@@ -0,0 +1 @@
+ð[(-bin!	ð(!\	!åGý:[(!'ð[(!!	ð[(*!	!å!ýGåGýA)([(	!!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14 b/test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14
new file mode 100644
index 0000000..ccb7d82
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14
@@ -0,0 +1 @@
+*¤ð¤-bén'ƒ'c)[ði(bn-!?¤Ûð!	ð(!\c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65 b/test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65
new file mode 100644
index 0000000..2b22f5c
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65
@@ -0,0 +1 @@
+¤¤ð¤-bin‹-[c'()bin	!!?¤Ûð!;ð{(-binð	!\	!˜é;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858 b/test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858
new file mode 100644
index 0000000..7112c43
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210 b/test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210
new file mode 100644
index 0000000..f58d558
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	1!?¤Ûð!;*ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112 b/test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112
new file mode 100644
index 0000000..bbd1dae
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112
@@ -0,0 +1 @@
+?* ¤®@:ð[øc	(;þ!!\ð	!~	ÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658 b/test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658
new file mode 100644
index 0000000..6b6a742
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf b/test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf
new file mode 100644
index 0000000..c0cee4f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf
@@ -0,0 +1 @@
+¤!ƒÛðФ!ƒ:[oððc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05 b/test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05
new file mode 100644
index 0000000..cf1dac3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	!!?¤Ûð!ð{(-binð	!\	!å7é;?Gí([(!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b b/test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b
new file mode 100644
index 0000000..c5d69b5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49 b/test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49
new file mode 100644
index 0000000..598576b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49
@@ -0,0 +1 @@
+¤pƒÛðð¤!ƒÛ')ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c b/test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c
new file mode 100644
index 0000000..689d7f2
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c
@@ -0,0 +1 @@
+¤!ƒðñ¤!ƒÛð±ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f b/test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f
new file mode 100644
index 0000000..57727ac
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941 b/test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941
new file mode 100644
index 0000000..6c900ea
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941
@@ -0,0 +1 @@
+ð[(!	ð[(!\	!åGý:[(!![(	!åGýA)(!)í!¸*!!	)
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620 b/test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620
new file mode 100644
index 0000000..b706187
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620
@@ -0,0 +1 @@
+* ¤®@ð[:øc	8;'þ!!\ð	!~	ÛDGý!ðkm'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1 b/test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1
new file mode 100644
index 0000000..b1c0905
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	!åEý!*(!!	!åGýA)(!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d b/test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d
new file mode 100644
index 0000000..21f59d4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb b/test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb
new file mode 100644
index 0000000..d692193
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb
@@ -0,0 +1 @@
+):;!œÊ'ÒØ)*;}v)7IÏ!¤);–-M*±äâ!'d*Cu«‘X$0):ó*;:äÝ;;();:]ïæ@
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7 b/test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7
new file mode 100644
index 0000000..982af7b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7
@@ -0,0 +1 @@
+;¤¤ð¤-bin‹c*[)¤¤¤(ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436 b/test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436
new file mode 100644
index 0000000..cd20401
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436
@@ -0,0 +1 @@
+?¤Óð!Üð	c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01 b/test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01
new file mode 100644
index 0000000..99507d2
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c)(-'bin	!!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff b/test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff
new file mode 100644
index 0000000..6fdb662
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff
@@ -0,0 +1 @@
+* ¤®@:ð[(øc	(;þ!!\	!cåGý:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2 b/test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2
new file mode 100644
index 0000000..164b22a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2
@@ -0,0 +1 @@
+;?.ð[(-bin!	ð(!¤\	!åGý:[(!'ð[(!'cð!	ðc[
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881 b/test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881
new file mode 100644
index 0000000..54400a3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881
@@ -0,0 +1 @@
+¤ð[('!	ð(!\	!åGý:(!'ð[(!!	¤[ð!ð	cð[(!!	!åGý!åGý'A)([(	'!!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70 b/test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70
new file mode 100644
index 0000000..b243e62
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	A!!?¤Ûð!b{ði-(nð	!\	!åé;?Gí!!:[((\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f b/test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f
new file mode 100644
index 0000000..345b8b2
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f
@@ -0,0 +1 @@
+¤¤Ûð¤ƒ
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d b/test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d
new file mode 100644
index 0000000..dceaf04
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d
@@ -0,0 +1 @@
+f*!(!!	i[Ñ!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601 b/test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601
new file mode 100644
index 0000000..1e49a89
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601
@@ -0,0 +1 @@
+¤¤ð¤-bin‹¤Ê!ð	c)[''(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e b/test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e
new file mode 100644
index 0000000..f1e7a8e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e
@@ -0,0 +1 @@
+¤¤ð¤-bin?ð‹c[)(-'bin	!!?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95 b/test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95
new file mode 100644
index 0000000..6d2446a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95
@@ -0,0 +1 @@
+¤c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b b/test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b
new file mode 100644
index 0000000..98ff11f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)¤(*¤;[('¤ð!(-	bni'!!/¤	Ûð!(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b b/test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b
new file mode 100644
index 0000000..7d875fe
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	!!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9 b/test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9
new file mode 100644
index 0000000..ddf6c7c
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b b/test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b
new file mode 100644
index 0000000..0350f5a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b
@@ -0,0 +1 @@
+.:¤c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd b/test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd
new file mode 100644
index 0000000..c72af1a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd
@@ -0,0 +1 @@
+¤¤ð¤-bin‹¤Ûð!c[)('-bl	*!!?¤Ûâ!ðð{(-bin\	c!'	!	ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88 b/test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88
new file mode 100644
index 0000000..2bfbdf5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	#!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd b/test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd
new file mode 100644
index 0000000..24f6a24
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849 b/test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849
new file mode 100644
index 0000000..6eebe10
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4 b/test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4
new file mode 100644
index 0000000..4616caf
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d b/test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d
new file mode 100644
index 0000000..f9c4871
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd b/test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd
new file mode 100644
index 0000000..c000da7
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd
@@ -0,0 +1 @@
+ð[(-bin!	ð(!	!åGý:[(!'ð[(¤!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e b/test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e
new file mode 100644
index 0000000..9fd52af
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e
@@ -0,0 +1 @@
+¤!ƒÛ*¤ð¤-bin¤¤ððÛðcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea b/test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea
new file mode 100644
index 0000000..3894ad5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea
@@ -0,0 +1 @@
+;?0c!(ðK	ð[N!\!åG![(!!	!åGýA)(!)í!*åG€¾ýA)(Ù;Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096 b/test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096
new file mode 100644
index 0000000..acb7629
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836 b/test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836
new file mode 100644
index 0000000..da07fc4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836
@@ -0,0 +1 @@
+¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d b/test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d
new file mode 100644
index 0000000..5d9d035
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8 b/test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8
new file mode 100644
index 0000000..49a5a11
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8
@@ -0,0 +1 @@
+¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273 b/test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273
new file mode 100644
index 0000000..5b390fd
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8 b/test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8
new file mode 100644
index 0000000..22cebb5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8 b/test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8
new file mode 100644
index 0000000..6b93c82
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8 b/test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8
new file mode 100644
index 0000000..3bf6b6e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777 b/test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777
new file mode 100644
index 0000000..fc8bdd1
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777
@@ -0,0 +1 @@
+(B¤:?ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e b/test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e
new file mode 100644
index 0000000..778ecf7
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d b/test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d
new file mode 100644
index 0000000..3a3c61a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c)(-'*in	!!?¤Ûð!!ð{(-binð	!\H!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf b/test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf
new file mode 100644
index 0000000..e5a06a1
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f b/test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f
new file mode 100644
index 0000000..e2e8f9b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f
@@ -0,0 +1 @@
+;;?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538 b/test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538
new file mode 100644
index 0000000..1b08af8
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538
@@ -0,0 +1 @@
+*¤ð¤-bin¤¤Û'(?¤ð;[('¤ð!	(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b b/test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b
new file mode 100644
index 0000000..ebcc009
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b
@@ -0,0 +1 @@
+* ¤®@:ð[(øc	(;þ!!\'!cåGý:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d b/test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d
new file mode 100644
index 0000000..b26118f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d
@@ -0,0 +1 @@
+¤¤Ûððƒcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210 b/test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210
new file mode 100644
index 0000000..103692a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075 b/test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075
new file mode 100644
index 0000000..06858ed
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8 b/test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8
new file mode 100644
index 0000000..fcec5d6
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	bå3Gý!*(!!	BåGýA)(!)í!d*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe b/test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe
new file mode 100644
index 0000000..aaada4f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe
@@ -0,0 +1 @@
+?* ¤®@ð:[øc	(;þ!!\ð	!~	ÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7 b/test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7
new file mode 100644
index 0000000..ac9c813
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4 b/test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4
new file mode 100644
index 0000000..c947224
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[(*)? ¤®@:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3 b/test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3
new file mode 100644
index 0000000..463f1a4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3
@@ -0,0 +1 @@
+¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2 b/test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2
new file mode 100644
index 0000000..1bfc596
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083 b/test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083
new file mode 100644
index 0000000..48c1dfe
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083
@@ -0,0 +1 @@
+¤¤ð¤-bin‹!c[)(-'bin	!!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a b/test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a
new file mode 100644
index 0000000..e7e115f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(;-''bin	!!?¤Ûð!ð{(-binð	!\	!åé;:?íå[((!;!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7 b/test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7
new file mode 100644
index 0000000..c1c4166
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)-'bin	1!?¤Ûð!;'*ð{(-binð	!\	!åé;?Gí:[((!!Lð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad b/test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad
new file mode 100644
index 0000000..198c062
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad
@@ -0,0 +1 @@
+¤[ð!ð	c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513 b/test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513
new file mode 100644
index 0000000..144e68b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513
@@ -0,0 +1 @@
+¤pƒÛðð¤!ƒÛð)ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282 b/test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282
new file mode 100644
index 0000000..eb49d1d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	!åGý!*(!	!ÔåGýA)(!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a b/test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a
new file mode 100644
index 0000000..4f5a887
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a
@@ -0,0 +1 @@
+¤¤ð¤-bin‹¤ð[c'!)¤bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d b/test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d
new file mode 100644
index 0000000..0d758c9
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d
@@ -0,0 +1 @@
+?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56 b/test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56
new file mode 100644
index 0000000..d8e3155
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56
@@ -0,0 +1 @@
+;?0c!(ðK	ð[N!\!åG![(!!	!åGýA)(!)í!*åG€¾A)(Ù;Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85 b/test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85
new file mode 100644
index 0000000..d38481c
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d b/test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d
new file mode 100644
index 0000000..f0ce5a2
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d
@@ -0,0 +1 @@
+?* ¤®@:ð[(øc	(;þ!!\ð	!c	åÛGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c b/test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c
new file mode 100644
index 0000000..1ae539b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54 b/test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54
new file mode 100644
index 0000000..0759d5b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	;!!?¤Ûð!ð{(-binð	!\	!åé;?Gí[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9 b/test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9
new file mode 100644
index 0000000..06af54d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	bå3Gý!*(!!	BåGýA)(!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a b/test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a
new file mode 100644
index 0000000..3357333
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96 b/test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96
new file mode 100644
index 0000000..9aa7b9d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)¤(-	bni'!!/¤Ûð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992 b/test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992
new file mode 100644
index 0000000..1203eb1
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992
@@ -0,0 +1 @@
+¤!ƒÛððcc'_
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c b/test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c
new file mode 100644
index 0000000..a273e99
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c
@@ -0,0 +1 @@
+'ð[(!!	ð[(!!	!åGý!åGýA)(!)í!¼)Ù:;‡Š*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35 b/test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35
new file mode 100644
index 0000000..8ac4292
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35
@@ -0,0 +1 @@
+[ð!ð	'(![(!!	!åGý!åGýA)(!)í!¼)Ù:;‡Š*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a b/test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a
new file mode 100644
index 0000000..07cf3ef
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin)#!?¤Ûð!ð{(-binð	!\!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87 b/test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87
new file mode 100644
index 0000000..c5a8cc6
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87
@@ -0,0 +1 @@
+?* ¤®P®€¤ˆ:ð[øc	8;þ!!\ð	!~(	ÛDGý!ðmc:c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828 b/test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828
new file mode 100644
index 0000000..3ad7a92
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b b/test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b
new file mode 100644
index 0000000..cfe8f60
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b
@@ -0,0 +1 @@
+¤¤ð¤-b!n‹¤-[c'!)¤bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c b/test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c
new file mode 100644
index 0000000..2fb6e28
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9 b/test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9
new file mode 100644
index 0000000..bb540ad
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb b/test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb
new file mode 100644
index 0000000..56c98a4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)¨-.'bi*	!!(?¤Û!ð!:ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74 b/test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74
new file mode 100644
index 0000000..9f2955b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94 b/test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94
new file mode 100644
index 0000000..cc3c4dd
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94
@@ -0,0 +1 @@
+¤!ƒÛ*¤ð¤-bin¤¦ððÛðcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004 b/test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004
new file mode 100644
index 0000000..b57b2aa
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	!åGý!*(!	!åGýA)(!!í!¼(*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c b/test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c
new file mode 100644
index 0000000..3a78289
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43 b/test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43
new file mode 100644
index 0000000..e87f23e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[i¤(-'bin	!!?¤Ûð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f b/test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f
new file mode 100644
index 0000000..d0a7c64
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)('-bin	!!?¤Ûð!ð{(-bi\n!	!	ðåé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a b/test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a
new file mode 100644
index 0000000..5b7c52d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a
@@ -0,0 +1 @@
+?* ¤®P®€¤ˆ:ð[øc	8;þ!!\ð	!~(	ÛDGý!ðcmc:c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7 b/test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7
new file mode 100644
index 0000000..e9dc85e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7
@@ -0,0 +1 @@
+(?¤›ð!	c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c b/test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c
new file mode 100644
index 0000000..c901c4c
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-.'bin	!!?¤Ûð!:ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd b/test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd
new file mode 100644
index 0000000..74d4392
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1 b/test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1
new file mode 100644
index 0000000..ad5695b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1
@@ -0,0 +1 @@
+¤¤Ûððƒ€cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f b/test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f
new file mode 100644
index 0000000..53ba7aa
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	«!?¤Ûð!;*ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481 b/test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481
new file mode 100644
index 0000000..5529b96
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d b/test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d
new file mode 100644
index 0000000..bf413be
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905 b/test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905
new file mode 100644
index 0000000..8985a07
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905
@@ -0,0 +1 @@
+¤!ƒÛððcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213 b/test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213
new file mode 100644
index 0000000..291a16d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)¨-'bin	'!!?¤Ûð!ð{;?0c!(-b(inð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815 b/test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815
new file mode 100644
index 0000000..2b2b727
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f b/test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f
new file mode 100644
index 0000000..bf77deb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf b/test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf
new file mode 100644
index 0000000..cda608f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf
@@ -0,0 +1 @@
+¤¤ð¤-bin‹¤-[c'!)¦bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87 b/test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87
new file mode 100644
index 0000000..003033b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)¤'(­¤Ûð'ð(ƒcin	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc b/test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc
new file mode 100644
index 0000000..a384358
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc
@@ -0,0 +1 @@
+f!(!!c'	i[Ñ!ð[(!!	ð[(!!	!åHý![(!!	!åGýåA)(!)í!¼*)åGýA)(Ù!)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a b/test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a
new file mode 100644
index 0000000..2760e03
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[):¤(-¤Ûð'ðbƒcin	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c b/test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c
new file mode 100644
index 0000000..a9663a0
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c
@@ -0,0 +1 @@
+Õðcª	Ûð'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8 b/test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8
new file mode 100644
index 0000000..6a23452
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb b/test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb
new file mode 100644
index 0000000..d5a3aee
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec b/test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec
new file mode 100644
index 0000000..0f7035b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec
@@ -0,0 +1 @@
+*@®¤ :ð[(øc	(;þ!!\	!cå¤Gý:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9 b/test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9
new file mode 100644
index 0000000..42b9598
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	!!?¤!ðÛð{(öbénð	!	\!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8 b/test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8
new file mode 100644
index 0000000..8fe5277
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8
@@ -0,0 +1 @@
+(?*¤!ð¤hemeƒ¤'('¤ð!c	
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4 b/test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4
new file mode 100644
index 0000000..20ab849
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad b/test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad
new file mode 100644
index 0000000..65f4c69
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad
@@ -0,0 +1 @@
+;?0c!(ðK	ð[N!\!õG![(!!	!åGýA)(!)í!*åG€¾ýA)(Ù+)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1 b/test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1
new file mode 100644
index 0000000..4ede523
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97 b/test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97
new file mode 100644
index 0000000..8f5c7a8
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f b/test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f
new file mode 100644
index 0000000..bae722a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bin	!!?OÛð!ð{(-b	\ni!ð	!åé;?Gí[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe b/test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe
new file mode 100644
index 0000000..fc8f2ae
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe
@@ -0,0 +1 @@
+¤ÿ
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6 b/test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6
new file mode 100644
index 0000000..7d35cc8
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6
@@ -0,0 +1 @@
+?*®@:[ðøc	(!!\þ;ð!~	ÛåGý!Ðam:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51 b/test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51
new file mode 100644
index 0000000..e92f115
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51
@@ -0,0 +1 @@
+¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c b/test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c
new file mode 100644
index 0000000..ded03ee
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206 b/test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206
new file mode 100644
index 0000000..218bfa3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206
@@ -0,0 +1 @@
+?*®@:[ðøc	(!!\þ;ð!~	ÛåGý!Ðam'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693 b/test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693
new file mode 100644
index 0000000..4cb5926
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)( ?¤-'bin	!!?¤:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637 b/test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637
new file mode 100644
index 0000000..573daa7
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637
@@ -0,0 +1 @@
+¤¤ð¤-bin‹()[c-'bin	!!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((#!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04 b/test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04
new file mode 100644
index 0000000..11e43ba
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c*[)¤(-¤Ûð'ðbƒcin	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644 b/test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644
new file mode 100644
index 0000000..a4a1f3c
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1 b/test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1
new file mode 100644
index 0000000..3a98220
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa b/test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa
new file mode 100644
index 0000000..c7552c3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426 b/test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426
new file mode 100644
index 0000000..5c87575
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0 b/test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0
new file mode 100644
index 0000000..828e12f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0
@@ -0,0 +1 @@
+¤¤ð¤-binc[)(-'bin	!!?¤Ûð!ð{(-binð	!\	!åŸé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076 b/test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076
new file mode 100644
index 0000000..24e9fc4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33 b/test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33
new file mode 100644
index 0000000..3378b55
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199 b/test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199
new file mode 100644
index 0000000..532ee69
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199
@@ -0,0 +1 @@
+¤c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055 b/test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055
new file mode 100644
index 0000000..4bff0ff
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055
@@ -0,0 +1 @@
+®ð[(€¤-bdin!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193 b/test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193
new file mode 100644
index 0000000..fcaef32
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453 b/test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453
new file mode 100644
index 0000000..34951fe
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453
@@ -0,0 +1 @@
+?* ¤®@:ð[øc	(!!\þ;ð	!~	ÛåGý!Ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435 b/test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435
new file mode 100644
index 0000000..0e176e3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435
@@ -0,0 +1 @@
+?* ¤®@:ð[(nc	(;þ!;\ð	!c	ÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323 b/test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323
new file mode 100644
index 0000000..cbf58cf
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323
@@ -0,0 +1 @@
+¤¤Ûð¤1ƒ
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60 b/test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60
new file mode 100644
index 0000000..0efdf47
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60
@@ -0,0 +1 @@
+¤¤ð¤-bin‹)['(=cbin	a!?¤Ûð!ð{(-bin¤ð¤Û
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597 b/test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597
new file mode 100644
index 0000000..78e29a4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51 b/test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51
new file mode 100644
index 0000000..449c0da
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51
@@ -0,0 +1 @@
+(?8¤¤¤Û!×Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f b/test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f
new file mode 100644
index 0000000..38402df
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df b/test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df
new file mode 100644
index 0000000..9265e2f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc b/test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc
new file mode 100644
index 0000000..b8c71bd
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc
@@ -0,0 +1 @@
+cð[(!	ð[(!\	!åGý![(!!	!åGýA)(!)í!¸*)åGýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446 b/test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446
new file mode 100644
index 0000000..2ac2d76
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854 b/test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854
new file mode 100644
index 0000000..941f553
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854
@@ -0,0 +1 @@
+¤(* ¤®@:ð[(?¤;:('¤ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247 b/test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247
new file mode 100644
index 0000000..252816d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978 b/test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978
new file mode 100644
index 0000000..d1028f3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978
@@ -0,0 +1 @@
+¤¤¤ð-bin‹c[)Î@®?*¤ :
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040 b/test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040
new file mode 100644
index 0000000..eafc765
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040
@@ -0,0 +1 @@
+[(!!	![ð!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f b/test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f
new file mode 100644
index 0000000..168a215
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f b/test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f
new file mode 100644
index 0000000..5173bb4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e b/test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e
new file mode 100644
index 0000000..838d0d2
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a b/test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a
new file mode 100644
index 0000000..b7855d7
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a
@@ -0,0 +1 @@
+¤pƒÛðð¤!ƒ[ðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d b/test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d
new file mode 100644
index 0000000..f10b76b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d
@@ -0,0 +1 @@
+¤¤ð¤-bin‹¤-[c'!)¤bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c b/test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c
new file mode 100644
index 0000000..e1d551a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2 b/test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2
new file mode 100644
index 0000000..dec67b6
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'b)n	#!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5 b/test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5
new file mode 100644
index 0000000..0855a4d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c*[)¤[((¤-Ûð'ðb!ƒcin	!!	!![ð!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b b/test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b
new file mode 100644
index 0000000..4781557
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b
@@ -0,0 +1 @@
+?¤Ûð!𤤐ð	c'¤-bin‹¤ò[c'!)¤bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c b/test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c
new file mode 100644
index 0000000..c60f729
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c
@@ -0,0 +1 @@
+(* ¤®@:ð[(?¤;[('¤ð!	(øc	(;þ!!\	!cråGý:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462 b/test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462
new file mode 100644
index 0000000..ac44166
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462
@@ -0,0 +1 @@
+c'ð[(!!	ð[(!!	!åGý![(!!	!åGýA)(!)í!¼*)åGýA)(Ù!)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6 b/test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6
new file mode 100644
index 0000000..40a6ab5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6
@@ -0,0 +1 @@
+?* ¤®@:ð[øc	(!!\þ;ð!~	ÛåGý!Ðim:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587 b/test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587
new file mode 100644
index 0000000..6c655aa
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3 b/test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3
new file mode 100644
index 0000000..7fff586
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3
@@ -0,0 +1 @@
+;?0c!(òK	ð[NÔ\	!åG![(!!	!åGýA)(!)í!*å¼G€ýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf b/test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf
new file mode 100644
index 0000000..d6a316b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf
@@ -0,0 +1 @@
+*¤ð¤-bin¤¤Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2 b/test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2
new file mode 100644
index 0000000..45cce54
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2
@@ -0,0 +1 @@
+¤!ƒßðð¤!ƒÛ¤ä
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f b/test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f
new file mode 100644
index 0000000..6a28aa1
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f
@@ -0,0 +1 @@
+;?0c!(ðK	ð[NÔ\	!åG![(!!	!åGýA)(!)í!*å¼G€ýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3 b/test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3
new file mode 100644
index 0000000..cba4e44
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3
@@ -0,0 +1 @@
+¤¤ð¤-bin‹¤-[c'ù)¤bi
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f b/test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f
new file mode 100644
index 0000000..ba1a5db
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561 b/test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561
new file mode 100644
index 0000000..59295ac
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3 b/test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3
new file mode 100644
index 0000000..039af40
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)¤(-'bin	!!?¤Ûð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a b/test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a
new file mode 100644
index 0000000..a61dd28
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a
@@ -0,0 +1 @@
+?* ¤®@:ð[(øc	(;þ!!\ð	!c	ÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf b/test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf
new file mode 100644
index 0000000..e359cb7
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400 b/test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400
new file mode 100644
index 0000000..39985fb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400
@@ -0,0 +1 @@
+?* ¦®@:ð[øc	(!!\þ;ð!~	Gý!Ðim:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76 b/test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76
new file mode 100644
index 0000000..71cc57a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76
@@ -0,0 +1 @@
+¤?
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9 b/test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9
new file mode 100644
index 0000000..7691001
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9
@@ -0,0 +1 @@
+¤pƒÛðð¤!ƒÛððc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d b/test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d
new file mode 100644
index 0000000..3217162
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d
@@ -0,0 +1 @@
+(?¤¤¤ÛÛð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d b/test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d
new file mode 100644
index 0000000..4ea1b6b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d
@@ -0,0 +1 @@
+¤¤ð¤£bin‹äc[ò)'-bi.	*)!?¤Ûâð{(-bi\n!	!	ðåé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c b/test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c
new file mode 100644
index 0000000..3261071
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c
@@ -0,0 +1 @@
+¤):;!œÊ'ÒØ)*;}v)7IÏ!¤);–-M*±äâ!'d*Cu«‘X$0):ó*;:äÝ;;();:]ïæ@
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f b/test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f
new file mode 100644
index 0000000..691e650
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f
@@ -0,0 +1 @@
+¤pƒÛð¤!ƒÛðc
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9 b/test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9
new file mode 100644
index 0000000..cc073f4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)('-bi.	*!!?¤Ûâ!ð{(-bi\n!	!	ðåé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e b/test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e
new file mode 100644
index 0000000..e93670e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e
@@ -0,0 +1 @@
+¤¤Ûðð	cc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780 b/test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780
new file mode 100644
index 0000000..6d66d37
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780
@@ -0,0 +1 @@
+?* ¤®@ð:[øc	(;þ!!\ð	#~	Ûårý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d b/test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d
new file mode 100644
index 0000000..d2cbccc
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	#åGý!*(!!	!åGýA)(!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e b/test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e
new file mode 100644
index 0000000..2a4856a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e
@@ -0,0 +1 @@
+;?0c!(ðK	ð[N!\;åG![(!!	!åGýA)(!)í!*åG€¾A)(Ù;Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7 b/test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7
new file mode 100644
index 0000000..81d87fa
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7
@@ -0,0 +1 @@
+¤¤ð¤-bin‹‰c[)¤(-'bin	!!?¤Ûð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3 b/test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3
new file mode 100644
index 0000000..3c7fb6e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075 b/test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075
new file mode 100644
index 0000000..de4be31
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	!åGý!*(!!	!åGýA)(!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c b/test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c
new file mode 100644
index 0000000..704e797
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c
@@ -0,0 +1 @@
+?* ¤®@:ð[øc	8;þ!!\ð	!~	ÛDGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc b/test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc
new file mode 100644
index 0000000..4f0cbfb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122 b/test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122
new file mode 100644
index 0000000..fb6b7bd
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c*[)¤(¤-Ûð'ðbƒcin	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375 b/test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375
new file mode 100644
index 0000000..cb679b9
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375
@@ -0,0 +1 @@
+ð[(-bin¤¤ð¤-bin‹c[)(-'bin	!!?¤Ûð!ð{(-binð!	ð(	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f b/test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f
new file mode 100644
index 0000000..482d7db
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f
@@ -0,0 +1 @@
+;?0c!(ðK	ð[N!\	!åG![(!!	!åGýA)(!)í!*å¼G€ýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf b/test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf
new file mode 100644
index 0000000..6553242
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf
@@ -0,0 +1 @@
+(?*¤ð¤-binƒ¤;[('¤ð!c	
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1 b/test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1
new file mode 100644
index 0000000..52f518b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-b¤¤ð¤-bin‹c[)('-bi.	*!!?¤Ûâ
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696 b/test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696
new file mode 100644
index 0000000..7c9ca45
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(-'bni	!%?¤Ûð!ð{(-binð	!\!åé;?G[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1 b/test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1
new file mode 100644
index 0000000..120b74b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1
@@ -0,0 +1 @@
+;?0c!'ðK	ð[N!\!åG![(!!	!åGýA)(!)í!*åG€¾A)(Ù;Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c b/test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c
new file mode 100644
index 0000000..ced68eb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7 b/test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7
new file mode 100644
index 0000000..2d3d63a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2 b/test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2
new file mode 100644
index 0000000..2c7912f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659 b/test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659
new file mode 100644
index 0000000..5b704f8
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659
@@ -0,0 +1 @@
+¤¤ð¤-bin)c[)-'bin	1¤¤!?¤Ûð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe b/test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe
new file mode 100644
index 0000000..3e28333
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe
@@ -0,0 +1 @@
+?* ¤®@:ð_øc	(!!\þ;ð!~	!ÛåGý!Ð;m:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3 b/test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3
new file mode 100644
index 0000000..7e26216
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3
@@ -0,0 +1 @@
+¤¤ð¤-binƒc)-bi	(n'!!?¤Û!ðð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7 b/test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7
new file mode 100644
index 0000000..efcad33
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7
@@ -0,0 +1 @@
+?* ¬®@ð:[øc	(;þ!\!ð	!~	Û-binåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec b/test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec
new file mode 100644
index 0000000..104ab47
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb b/test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb
new file mode 100644
index 0000000..d43c094
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb
@@ -0,0 +1 @@
+?* ¤®@:ð[øc	(!!\þ;ð!~	ÛåGý!Ðam:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076 b/test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076
new file mode 100644
index 0000000..0a104c7
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076
@@ -0,0 +1 @@
+ð[(-bin!	ð(!\	!åGý¤!:[(!'ð[(!!	ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da b/test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da
new file mode 100644
index 0000000..4d95be6
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da
@@ -0,0 +1 @@
+?!cð	ß}'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd b/test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd
new file mode 100644
index 0000000..1cbb336
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)¤(-¤Ûð'ðbƒcin	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35 b/test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35
new file mode 100644
index 0000000..b2d3847
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35
@@ -0,0 +1 @@
+?* ¤®@:ð[øã	4;þ!!\ð	!~	ÛDGýðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745 b/test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745
new file mode 100644
index 0000000..fa972a4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564 b/test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564
new file mode 100644
index 0000000..718a9e5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564
@@ -0,0 +1 @@
++¤¤ð¤-bin9c[)(-b¤¤ð¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3 b/test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3
new file mode 100644
index 0000000..4d63ccb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3
@@ -0,0 +1 @@
+¤¤ð¤-bin‹#Z)¤(-¤b¤	ð¤-bin?ð‹c[)(-ni''bin!!	!/¤!?'ð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456 b/test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456
new file mode 100644
index 0000000..6caf38a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456
@@ -0,0 +1 @@
+;?0c!(ðK	ð[N!\!åG![(!!	!åGýA)(!)í!*åG€¾ýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285 b/test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285
new file mode 100644
index 0000000..a311265
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b b/test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b
new file mode 100644
index 0000000..350c941
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b
@@ -0,0 +1 @@
+;?'cð[)!	ð[N!Ü	bå4Gý!*(!!	BåGýA)!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6 b/test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6
new file mode 100644
index 0000000..4d7ff3e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6
@@ -0,0 +1 @@
+'?0c!(ðK	ð[N!\!åG![(!!	!åG)Aý(!)å!*åG€A¾)(Ù;;Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d b/test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d
new file mode 100644
index 0000000..a422dc4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9 b/test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9
new file mode 100644
index 0000000..c0404ba
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9
@@ -0,0 +1 @@
+¤¤ð¤-bin‹) ¤['(=cbin	a!?äÛð!ð{(-bin¤ð¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f b/test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f
new file mode 100644
index 0000000..4547f5a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7 b/test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7
new file mode 100644
index 0000000..272be74
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07 b/test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07
new file mode 100644
index 0000000..e9cb788
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07
@@ -0,0 +1 @@
+?* ¤®@:ð[(øc	(3þ!!\ð	!c	(ÛåGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0 b/test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0
new file mode 100644
index 0000000..be8b804
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336 b/test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336
new file mode 100644
index 0000000..8c906c5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336
@@ -0,0 +1 @@
+*¤ð¤-bin¤¤¤¸ð¤-Û'(?¤ð;[(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f b/test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f
new file mode 100644
index 0000000..ed929eb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f
@@ -0,0 +1 @@
+*¤ð¤-binƒ(€'[ði(bn-!? 
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2 b/test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2
new file mode 100644
index 0000000..81cc0fc
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2
@@ -0,0 +1 @@
+¤ä—
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24 b/test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24
new file mode 100644
index 0000000..9ed0c80
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24
@@ -0,0 +1 @@
+?* ¤®@:ð[øc	(!!\þ;ð!~	ÛåGý!Ðim:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f b/test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f
new file mode 100644
index 0000000..e55083f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc b/test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc
new file mode 100644
index 0000000..e752baf
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc
@@ -0,0 +1 @@
+¤¤ð¤rbin‹c[)(-'bin	!!?¤Ûð!ð{(-binð	!\	!åé;?G[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66 b/test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66
new file mode 100644
index 0000000..cb9bf61
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66
@@ -0,0 +1 @@
+¤¤Û)€ððŽcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205 b/test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205
new file mode 100644
index 0000000..bad7f60
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205
@@ -0,0 +1 @@
+¤pƒÛðð¤!ƒËTð*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25 b/test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25
new file mode 100644
index 0000000..5a2a027
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25
@@ -0,0 +1 @@
+¤¤ð¤-bin‹#Z)¤(-¤¤	bð¤-bin?ð‹c[)(-ni''bin!;	!/¤!?'ð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2 b/test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2
new file mode 100644
index 0000000..1ceb559
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2
@@ -0,0 +1 @@
+¤¤ð¤-bin‹)['(;-cbin	!!?¤Ûð!ð{(-binð	!\	!åé;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18 b/test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18
new file mode 100644
index 0000000..713d178
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef b/test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef
new file mode 100644
index 0000000..a4520fb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033 b/test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033
new file mode 100644
index 0000000..10b7a9f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977 b/test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977
new file mode 100644
index 0000000..6e31189
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977
@@ -0,0 +1 @@
+ð[(-`in¤¤ð¤-Þin‹c[)(:'bin	!!)?¤Ûð!ð{(:-binð!	ð(	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8 b/test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8
new file mode 100644
index 0000000..df57477
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8
@@ -0,0 +1 @@
+¤!ƒßð¤!ƒÛ¤ð¤¤-binƒc[-'bä:nð	!?¤Ûð!(!\ð	c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936 b/test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936
new file mode 100644
index 0000000..eb157d3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93 b/test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93
new file mode 100644
index 0000000..bc92a9f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93
@@ -0,0 +1 @@
+?¤Ûð!ð	c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847 b/test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847
new file mode 100644
index 0000000..d00c6b4
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847
@@ -0,0 +1 @@
+¤¤Ûððƒcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209 b/test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209
new file mode 100644
index 0000000..c989830
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209
@@ -0,0 +1 @@
+¤¤ð¤-bin‹-[c*()bin	!!?¤Ûð!;ð{(-binð	!\	!*é;?Gí:[((!!\ð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909 b/test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909
new file mode 100644
index 0000000..9296f0e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c b/test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c
new file mode 100644
index 0000000..34de7ad
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c
@@ -0,0 +1 @@
+):;!œÊ'ÒØ)*;}v-7IÏ!¤)–-M*±äâ!'d*Cu«X$0):ó*;:äÝ;;();:]ïæ@
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3 b/test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3
new file mode 100644
index 0000000..84f4753
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3
@@ -0,0 +1 @@
+¤¤ð¤-binc([)¤(¤-Û
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2 b/test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2
new file mode 100644
index 0000000..274e09d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2
@@ -0,0 +1 @@
+;'cð[(!	ð[N!\‡!åGý!*(!	!åGýA)(!)í!¼*)åGýI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021 b/test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021
new file mode 100644
index 0000000..720a576
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689 b/test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689
new file mode 100644
index 0000000..b818778
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4 b/test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4
new file mode 100644
index 0000000..fce39c6
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259 b/test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259
new file mode 100644
index 0000000..b87a36f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c*[)¤(* ¤®@:ð[(?¤;[('¤ð(-¤Û!	ð'ðb
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb b/test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb
new file mode 100644
index 0000000..0a16a74
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb
@@ -0,0 +1 @@
+ð[(-bin¤¤ð¤-bin‹c[)(-'bin	!!?¤Ûð!ð{(-binð!	ð(	!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b b/test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b
new file mode 100644
index 0000000..ffa9431
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b
@@ -0,0 +1 @@
+¤¤ð¤-bin‹#Z)¤(-¤	b¤ð¤-bin?ð‹c[)(-ni''bin!!	!/¤!?Ûð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78 b/test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78
new file mode 100644
index 0000000..b92817b
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78
@@ -0,0 +1 @@
+¤¤ÛððÜcc'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7 b/test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7
new file mode 100644
index 0000000..cb68dfd
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f b/test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f
new file mode 100644
index 0000000..9b15875
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5 b/test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5
new file mode 100644
index 0000000..5ef662d
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1 b/test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1
new file mode 100644
index 0000000..cd45daf
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904 b/test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904
new file mode 100644
index 0000000..9c27b38
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904
@@ -0,0 +1 @@
+?ð	Û!ðcm'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b b/test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b
new file mode 100644
index 0000000..4535127
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b
@@ -0,0 +1 @@
+0c'ð[(!	ð[(!\	!åGý![(!!	!åGýA)(!)í!¼*)åGýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41 b/test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41
new file mode 100644
index 0000000..c3c6d73
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb b/test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb
new file mode 100644
index 0000000..be01d46
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)²(-'bin¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e b/test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e
new file mode 100644
index 0000000..58cc22f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e
@@ -0,0 +1 @@
+;?0c!(ðK	ðNÔ\	!åG![(!!	!åGýA)(:)í!*å¼G€ýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41 b/test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41
new file mode 100644
index 0000000..0926c63
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41
@@ -0,0 +1 @@
+0cð[(!	ð[(!\	!åGý![(!!	!åGýA)(!)í!¼*)åGýA)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8 b/test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8
new file mode 100644
index 0000000..9e21c0e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8
@@ -0,0 +1 @@
+(?¤:›ð!	c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43 b/test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43
new file mode 100644
index 0000000..a217e4f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423 b/test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423
new file mode 100644
index 0000000..ee6ac4e
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9 b/test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9
new file mode 100644
index 0000000..9b0d16f
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[)(?* ¤®@:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e b/test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e
new file mode 100644
index 0000000..8926de3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e
@@ -0,0 +1 @@
+(?¤;[('¤ð!	(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6 b/test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6
new file mode 100644
index 0000000..0c8d290
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6
@@ -0,0 +1 @@
+?* ¤®@Znð:(c	(;þ!(c!	;\	ÛäGý!ðcm:'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e b/test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e
new file mode 100644
index 0000000..a7c841c
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e
@@ -0,0 +1 @@
+¤¤ð¤-b)n‹c[)(:* ¤®@1:
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67 b/test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67
new file mode 100644
index 0000000..1ab7be3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67
@@ -0,0 +1 @@
+¤pƒÛðð¤!ƒÛðTð*
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8 b/test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8
new file mode 100644
index 0000000..669e4a8
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8
@@ -0,0 +1 @@
+¤c
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb b/test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb
new file mode 100644
index 0000000..0fee687
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb
@@ -0,0 +1 @@
+¤Ûð!ð	c'
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800 b/test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800
new file mode 100644
index 0000000..667c246
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c[''(-'bin	!!?¤¤cÛð!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74 b/test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74
new file mode 100644
index 0000000..67f84c5
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74
@@ -0,0 +1 @@
+ð[(!	ð(!\	!åGý:[(!'ð[(!!	ð[(!!	!åGý!åGýA)([(	!!å
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb b/test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb
new file mode 100644
index 0000000..99d90a0
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8 b/test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8
new file mode 100644
index 0000000..c5005c7
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836 b/test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836
new file mode 100644
index 0000000..fcae5ce
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836
@@ -0,0 +1 @@
+¤¤ð¤-bin‹Ê!ð	c(?¤)['›ð!	c'(
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a b/test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a
new file mode 100644
index 0000000..4ed844a
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a
@@ -0,0 +1 @@
+(??;[(¤('?¤
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170 b/test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170
new file mode 100644
index 0000000..e8e30c8
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c b/test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c
new file mode 100644
index 0000000..b9b44ea
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de b/test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de
new file mode 100644
index 0000000..58337fb
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de
@@ -0,0 +1 @@
+¤¤ð¤-bin‹c—*[)¤(-¤Ûð'ð!bƒcin	;!!
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
new file mode 100644
index 0000000..e41eda8
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
+
+static void onhdr(void *ud, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
+static void dont_log(gpr_log_func_args *args) {}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  grpc_test_only_set_metadata_hash_seed(0);
+  gpr_set_log_function(dont_log);
+  grpc_init();
+  grpc_chttp2_hpack_parser parser;
+  grpc_chttp2_hpack_parser_init(&parser);
+  parser.on_header = onhdr;
+  grpc_chttp2_hpack_parser_parse(&parser, data, data + size);
+  grpc_chttp2_hpack_parser_destroy(&parser);
+  grpc_shutdown();
+  return 0;
+}
diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c
index 4456e19..51bf48d 100644
--- a/test/core/transport/chttp2/hpack_parser_test.c
+++ b/test/core/transport/chttp2/hpack_parser_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/transport/chttp2/hpack_parser.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
 
 #include <stdarg.h>
 
diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c
index 3c5f2e4..73e59f1 100644
--- a/test/core/transport/chttp2/hpack_table_test.c
+++ b/test/core/transport/chttp2/hpack_table_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,17 +31,17 @@
  *
  */
 
-#include "src/core/transport/chttp2/hpack_table.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_table.h"
 
-#include <string.h>
 #include <stdio.h>
+#include <string.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/support/string.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
diff --git a/test/core/transport/chttp2/status_conversion_test.c b/test/core/transport/chttp2/status_conversion_test.c
index e2729a0..e6fc785 100644
--- a/test/core/transport/chttp2/status_conversion_test.c
+++ b/test/core/transport/chttp2/status_conversion_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/transport/chttp2/status_conversion.h"
+#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
 #include <grpc/support/log.h>
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/transport/chttp2/stream_map_test.c b/test/core/transport/chttp2/stream_map_test.c
index 527d2fe..83d740a 100644
--- a/test/core/transport/chttp2/stream_map_test.c
+++ b/test/core/transport/chttp2/stream_map_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/transport/chttp2/stream_map.h"
+#include "src/core/ext/transport/chttp2/transport/stream_map.h"
 #include <grpc/support/log.h>
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/transport/chttp2/timeout_encoding_test.c b/test/core/transport/chttp2/timeout_encoding_test.c
index 483e79f..6763993 100644
--- a/test/core/transport/chttp2/timeout_encoding_test.c
+++ b/test/core/transport/chttp2/timeout_encoding_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,16 +31,16 @@
  *
  */
 
-#include "src/core/transport/chttp2/timeout_encoding.h"
+#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
 
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/support/string.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
@@ -128,11 +128,10 @@
   decode_suite('H', gpr_time_from_hours);
   assert_decodes_as("1000000000S",
                     gpr_time_from_seconds(1000 * 1000 * 1000, GPR_TIMESPAN));
-  assert_decodes_as("1000000000000000000000u",
-                    gpr_inf_future(GPR_CLOCK_REALTIME));
-  assert_decodes_as("1000000001S", gpr_inf_future(GPR_CLOCK_REALTIME));
-  assert_decodes_as("2000000001S", gpr_inf_future(GPR_CLOCK_REALTIME));
-  assert_decodes_as("9999999999S", gpr_inf_future(GPR_CLOCK_REALTIME));
+  assert_decodes_as("1000000000000000000000u", gpr_inf_future(GPR_TIMESPAN));
+  assert_decodes_as("1000000001S", gpr_inf_future(GPR_TIMESPAN));
+  assert_decodes_as("2000000001S", gpr_inf_future(GPR_TIMESPAN));
+  assert_decodes_as("9999999999S", gpr_inf_future(GPR_TIMESPAN));
 }
 
 void test_decoding_fails(void) {
diff --git a/test/core/transport/chttp2/varint_test.c b/test/core/transport/chttp2/varint_test.c
index f06116a..3552bf0 100644
--- a/test/core/transport/chttp2/varint_test.c
+++ b/test/core/transport/chttp2/varint_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/transport/chttp2/varint.h"
+#include "src/core/ext/transport/chttp2/transport/varint.h"
 
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
diff --git a/test/core/transport/connectivity_state_test.c b/test/core/transport/connectivity_state_test.c
index 4b2d0aa..6bb7c3b 100644
--- a/test/core/transport/connectivity_state_test.c
+++ b/test/core/transport/connectivity_state_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/transport/connectivity_state.h"
+#include "src/core/lib/transport/connectivity_state.h"
 
 #include <string.h>
 
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index 928fba7..a4e9694 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -31,17 +31,19 @@
  *
  */
 
-#include "src/core/transport/metadata.h"
+#include "src/core/lib/transport/metadata.h"
 
 #include <stdio.h>
+#include <string.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/support/string.h"
-#include "src/core/transport/chttp2/bin_encoder.h"
+#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
@@ -260,6 +262,54 @@
   grpc_shutdown();
 }
 
+static void verify_ascii_header_size(const char *key, const char *value) {
+  grpc_mdelem *elem = grpc_mdelem_from_strings(key, value);
+  size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
+  size_t expected_size = 32 + strlen(key) + strlen(value);
+  GPR_ASSERT(expected_size == elem_size);
+  GRPC_MDELEM_UNREF(elem);
+}
+
+static void verify_binary_header_size(const char *key, const uint8_t *value,
+                                      size_t value_len) {
+  grpc_mdelem *elem = grpc_mdelem_from_string_and_buffer(key, value, value_len);
+  GPR_ASSERT(grpc_is_binary_header(key, strlen(key)));
+  size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
+  gpr_slice value_slice =
+      gpr_slice_from_copied_buffer((const char *)value, value_len);
+  gpr_slice base64_encoded = grpc_chttp2_base64_encode(value_slice);
+  size_t expected_size = 32 + strlen(key) + GPR_SLICE_LENGTH(base64_encoded);
+  GPR_ASSERT(expected_size == elem_size);
+  gpr_slice_unref(value_slice);
+  gpr_slice_unref(base64_encoded);
+  GRPC_MDELEM_UNREF(elem);
+}
+
+#define BUFFER_SIZE 64
+static void test_mdelem_sizes_in_hpack(void) {
+  LOG_TEST("test_mdelem_size");
+  grpc_init();
+
+  uint8_t binary_value[BUFFER_SIZE] = {0};
+  for (uint8_t i = 0; i < BUFFER_SIZE; i++) {
+    binary_value[i] = i;
+  }
+
+  verify_ascii_header_size("hello", "world");
+  verify_ascii_header_size("hello", "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+  verify_ascii_header_size(":scheme", "http");
+
+  for (uint8_t i = 0; i < BUFFER_SIZE; i++) {
+    verify_binary_header_size("hello-bin", binary_value, i);
+  }
+
+  const char *static_metadata = grpc_static_metadata_strings[0];
+  memcpy(binary_value, static_metadata, strlen(static_metadata));
+  verify_binary_header_size("hello-bin", binary_value, strlen(static_metadata));
+
+  grpc_shutdown();
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_no_op();
@@ -272,5 +322,6 @@
   test_slices_work();
   test_base64_and_huffman_works();
   test_user_data_works();
+  test_mdelem_sizes_in_hpack();
   return 0;
 }
diff --git a/test/core/tsi/transport_security_test.c b/test/core/tsi/transport_security_test.c
index 667d3f0..01e8770 100644
--- a/test/core/tsi/transport_security_test.c
+++ b/test/core/tsi/transport_security_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/tsi/transport_security.h"
+#include "src/core/lib/tsi/transport_security.h"
 
 #include <string.h>
 
@@ -42,9 +42,9 @@
 
 #include <openssl/crypto.h>
 
-#include "src/core/support/string.h"
-#include "src/core/tsi/fake_transport_security.h"
-#include "src/core/tsi/ssl_transport_security.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"
 #include "test/core/util/test_config.h"
 
 typedef struct {
diff --git a/test/core/util/memory_counters.c b/test/core/util/memory_counters.c
new file mode 100644
index 0000000..bebe94e
--- /dev/null
+++ b/test/core/util/memory_counters.c
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/sync.h>
+
+#include "test/core/util/memory_counters.h"
+
+static gpr_mu g_memory_mutex;
+static struct grpc_memory_counters g_memory_counters;
+static gpr_allocation_functions g_old_allocs;
+
+static void *guard_malloc(size_t size);
+static void *guard_realloc(void *vptr, size_t size);
+static void guard_free(void *vptr);
+
+static void *guard_malloc(size_t size) {
+  size_t *ptr;
+  if (!size) return NULL;
+  gpr_mu_lock(&g_memory_mutex);
+  g_memory_counters.total_size_absolute += size;
+  g_memory_counters.total_size_relative += size;
+  g_memory_counters.total_allocs_absolute++;
+  g_memory_counters.total_allocs_relative++;
+  gpr_mu_unlock(&g_memory_mutex);
+  ptr = g_old_allocs.malloc_fn(size + sizeof(size));
+  *ptr++ = size;
+  return ptr;
+}
+
+static void *guard_realloc(void *vptr, size_t size) {
+  size_t *ptr = vptr;
+  if (vptr == NULL) {
+    return guard_malloc(size);
+  }
+  if (size == 0) {
+    guard_free(vptr);
+    return NULL;
+  }
+  --ptr;
+  gpr_mu_lock(&g_memory_mutex);
+  g_memory_counters.total_size_absolute += size;
+  g_memory_counters.total_size_relative -= *ptr;
+  g_memory_counters.total_size_relative += size;
+  g_memory_counters.total_allocs_absolute++;
+  gpr_mu_unlock(&g_memory_mutex);
+  ptr = g_old_allocs.realloc_fn(ptr, size + sizeof(size));
+  *ptr++ = size;
+  return ptr;
+}
+
+static void guard_free(void *vptr) {
+  size_t *ptr = vptr;
+  if (!vptr) return;
+  --ptr;
+  gpr_mu_lock(&g_memory_mutex);
+  g_memory_counters.total_size_relative -= *ptr;
+  g_memory_counters.total_allocs_relative--;
+  gpr_mu_unlock(&g_memory_mutex);
+  g_old_allocs.free_fn(ptr);
+}
+
+struct gpr_allocation_functions g_guard_allocs = {guard_malloc, guard_realloc,
+                                                  guard_free};
+
+void grpc_memory_counters_init() {
+  memset(&g_memory_counters, 0, sizeof(g_memory_counters));
+  gpr_mu_init(&g_memory_mutex);
+  g_old_allocs = gpr_get_allocation_functions();
+  gpr_set_allocation_functions(g_guard_allocs);
+}
+
+void grpc_memory_counters_destroy() {
+  gpr_set_allocation_functions(g_old_allocs);
+  gpr_mu_destroy(&g_memory_mutex);
+}
+
+struct grpc_memory_counters grpc_memory_counters_snapshot() {
+  struct grpc_memory_counters counters;
+  gpr_mu_lock(&g_memory_mutex);
+  counters = g_memory_counters;
+  gpr_mu_unlock(&g_memory_mutex);
+  return counters;
+}
diff --git a/test/core/util/memory_counters.h b/test/core/util/memory_counters.h
new file mode 100644
index 0000000..f332816
--- /dev/null
+++ b/test/core/util/memory_counters.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_TEST_CORE_UTIL_MEMORY_COUNTERS_H
+#define GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H
+
+struct grpc_memory_counters {
+  size_t total_size_relative;
+  size_t total_size_absolute;
+  size_t total_allocs_relative;
+  size_t total_allocs_absolute;
+};
+
+void grpc_memory_counters_init();
+void grpc_memory_counters_destroy();
+struct grpc_memory_counters grpc_memory_counters_snapshot();
+
+#endif
diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c
new file mode 100644
index 0000000..7768413
--- /dev/null
+++ b/test/core/util/mock_endpoint.c
@@ -0,0 +1,124 @@
+/*
+ *
+ * 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 "test/core/util/mock_endpoint.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+typedef struct grpc_mock_endpoint {
+  grpc_endpoint base;
+  gpr_mu mu;
+  void (*on_write)(gpr_slice slice);
+  gpr_slice_buffer read_buffer;
+  gpr_slice_buffer *on_read_out;
+  grpc_closure *on_read;
+} grpc_mock_endpoint;
+
+static void me_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                    gpr_slice_buffer *slices, grpc_closure *cb) {
+  grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
+  gpr_mu_lock(&m->mu);
+  if (m->read_buffer.count > 0) {
+    gpr_slice_buffer_swap(&m->read_buffer, slices);
+    grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+  } else {
+    m->on_read = cb;
+    m->on_read_out = slices;
+  }
+  gpr_mu_unlock(&m->mu);
+}
+
+static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                     gpr_slice_buffer *slices, grpc_closure *cb) {
+  grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
+  for (size_t i = 0; i < slices->count; i++) {
+    m->on_write(slices->slices[i]);
+  }
+  grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+}
+
+static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                              grpc_pollset *pollset) {}
+
+static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                  grpc_pollset_set *pollset) {}
+
+static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
+  gpr_mu_lock(&m->mu);
+  if (m->on_read) {
+    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, false, NULL);
+    m->on_read = NULL;
+  }
+  gpr_mu_unlock(&m->mu);
+}
+
+static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
+  gpr_slice_buffer_destroy(&m->read_buffer);
+  gpr_free(m);
+}
+
+static char *me_get_peer(grpc_endpoint *ep) {
+  return gpr_strdup("fake:mock_endpoint");
+}
+
+static const grpc_endpoint_vtable vtable = {
+    me_read,     me_write,   me_add_to_pollset, me_add_to_pollset_set,
+    me_shutdown, me_destroy, me_get_peer,
+};
+
+grpc_endpoint *grpc_mock_endpoint_create(void (*on_write)(gpr_slice slice)) {
+  grpc_mock_endpoint *m = gpr_malloc(sizeof(*m));
+  m->base.vtable = &vtable;
+  gpr_slice_buffer_init(&m->read_buffer);
+  gpr_mu_init(&m->mu);
+  m->on_write = on_write;
+  m->on_read = NULL;
+  return &m->base;
+}
+
+void grpc_mock_endpoint_put_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                 gpr_slice slice) {
+  grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
+  gpr_mu_lock(&m->mu);
+  if (m->on_read != NULL) {
+    gpr_slice_buffer_add(m->on_read_out, slice);
+    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, true, NULL);
+    m->on_read = NULL;
+  } else {
+    gpr_slice_buffer_add(&m->read_buffer, slice);
+  }
+  gpr_mu_unlock(&m->mu);
+}
diff --git a/test/core/util/mock_endpoint.h b/test/core/util/mock_endpoint.h
new file mode 100644
index 0000000..051af98
--- /dev/null
+++ b/test/core/util/mock_endpoint.h
@@ -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.
+ *
+ */
+
+#ifndef MOCK_ENDPOINT_H
+#define MOCK_ENDPOINT_H
+
+#include "src/core/lib/iomgr/endpoint.h"
+
+grpc_endpoint *grpc_mock_endpoint_create(void (*on_write)(gpr_slice slice));
+void grpc_mock_endpoint_put_read(grpc_exec_ctx *exec_ctx,
+                                 grpc_endpoint *mock_endpoint, gpr_slice slice);
+
+#endif
diff --git a/test/core/util/one_corpus_entry_fuzzer.c b/test/core/util/one_corpus_entry_fuzzer.c
new file mode 100644
index 0000000..41f9558
--- /dev/null
+++ b/test/core/util/one_corpus_entry_fuzzer.c
@@ -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.
+ *
+ */
+
+#include <grpc/support/log.h>
+#include "src/core/lib/support/load_file.h"
+
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+int main(int argc, char **argv) {
+  int ok = 0;
+  gpr_slice buffer = gpr_load_file(argv[1], 0, &ok);
+  GPR_ASSERT(ok);
+  LLVMFuzzerTestOneInput(GPR_SLICE_START_PTR(buffer), GPR_SLICE_LENGTH(buffer));
+  gpr_slice_unref(buffer);
+  return 0;
+}
diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c
new file mode 100644
index 0000000..168ae59
--- /dev/null
+++ b/test/core/util/passthru_endpoint.c
@@ -0,0 +1,158 @@
+/*
+ *
+ * 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 "test/core/util/passthru_endpoint.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+typedef struct passthru_endpoint passthru_endpoint;
+
+typedef struct {
+  grpc_endpoint base;
+  passthru_endpoint *parent;
+  gpr_slice_buffer read_buffer;
+  gpr_slice_buffer *on_read_out;
+  grpc_closure *on_read;
+} half;
+
+struct passthru_endpoint {
+  gpr_mu mu;
+  int halves;
+  bool shutdown;
+  half client;
+  half server;
+};
+
+static void me_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                    gpr_slice_buffer *slices, grpc_closure *cb) {
+  half *m = (half *)ep;
+  gpr_mu_lock(&m->parent->mu);
+  if (m->parent->shutdown) {
+    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+  } else if (m->read_buffer.count > 0) {
+    gpr_slice_buffer_swap(&m->read_buffer, slices);
+    grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+  } else {
+    m->on_read = cb;
+    m->on_read_out = slices;
+  }
+  gpr_mu_unlock(&m->parent->mu);
+}
+
+static half *other_half(half *h) {
+  if (h == &h->parent->client) return &h->parent->server;
+  return &h->parent->client;
+}
+
+static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                     gpr_slice_buffer *slices, grpc_closure *cb) {
+  half *m = other_half((half *)ep);
+  gpr_mu_lock(&m->parent->mu);
+  bool ok = true;
+  if (m->parent->shutdown) {
+    ok = false;
+  } else if (m->on_read != NULL) {
+    gpr_slice_buffer_addn(m->on_read_out, slices->slices, slices->count);
+    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, true, NULL);
+    m->on_read = NULL;
+  } else {
+    gpr_slice_buffer_addn(&m->read_buffer, slices->slices, slices->count);
+  }
+  gpr_mu_unlock(&m->parent->mu);
+  grpc_exec_ctx_enqueue(exec_ctx, cb, ok, NULL);
+}
+
+static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                              grpc_pollset *pollset) {}
+
+static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                  grpc_pollset_set *pollset) {}
+
+static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  half *m = (half *)ep;
+  gpr_mu_lock(&m->parent->mu);
+  m->parent->shutdown = true;
+  if (m->on_read) {
+    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, false, NULL);
+    m->on_read = NULL;
+  }
+  m = other_half(m);
+  if (m->on_read) {
+    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, false, NULL);
+    m->on_read = NULL;
+  }
+  gpr_mu_unlock(&m->parent->mu);
+}
+
+static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  passthru_endpoint *p = ((half *)ep)->parent;
+  gpr_mu_lock(&p->mu);
+  if (0 == --p->halves) {
+    gpr_mu_unlock(&p->mu);
+    gpr_mu_destroy(&p->mu);
+    gpr_slice_buffer_destroy(&p->client.read_buffer);
+    gpr_slice_buffer_destroy(&p->server.read_buffer);
+    gpr_free(p);
+  } else {
+    gpr_mu_unlock(&p->mu);
+  }
+}
+
+static char *me_get_peer(grpc_endpoint *ep) {
+  return gpr_strdup("fake:mock_endpoint");
+}
+
+static const grpc_endpoint_vtable vtable = {
+    me_read,     me_write,   me_add_to_pollset, me_add_to_pollset_set,
+    me_shutdown, me_destroy, me_get_peer,
+};
+
+static void half_init(half *m, passthru_endpoint *parent) {
+  m->base.vtable = &vtable;
+  m->parent = parent;
+  gpr_slice_buffer_init(&m->read_buffer);
+  m->on_read = NULL;
+}
+
+void grpc_passthru_endpoint_create(grpc_endpoint **client,
+                                   grpc_endpoint **server) {
+  passthru_endpoint *m = gpr_malloc(sizeof(*m));
+  m->halves = 2;
+  m->shutdown = 0;
+  half_init(&m->client, m);
+  half_init(&m->server, m);
+  gpr_mu_init(&m->mu);
+  *client = &m->client.base;
+  *server = &m->server.base;
+}
diff --git a/test/core/util/passthru_endpoint.h b/test/core/util/passthru_endpoint.h
new file mode 100644
index 0000000..aa1d3a1
--- /dev/null
+++ b/test/core/util/passthru_endpoint.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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 MOCK_ENDPOINT_H
+#define MOCK_ENDPOINT_H
+
+#include "src/core/lib/iomgr/endpoint.h"
+
+void grpc_passthru_endpoint_create(grpc_endpoint **client,
+                                   grpc_endpoint **server);
+
+#endif
diff --git a/test/core/util/port_posix.c b/test/core/util/port_posix.c
index 5c0b271..eabd62f 100644
--- a/test/core/util/port_posix.c
+++ b/test/core/util/port_posix.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/support/env.h"
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/support/env.h"
 #include "test/core/util/port_server_client.h"
 
 #define NUM_RANDOM_PORTS_TO_PICK 100
diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c
index 653ecb2..84e9054 100644
--- a/test/core/util/port_server_client.c
+++ b/test/core/util/port_server_client.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
-#include "src/core/httpcli/httpcli.h"
+#include "src/core/lib/http/httpcli.h"
 
 typedef struct freereq {
   gpr_mu *mu;
@@ -91,7 +91,7 @@
 
   req.host = server;
   gpr_asprintf(&path, "/drop/%d", port);
-  req.path = path;
+  req.http.path = path;
 
   grpc_httpcli_context_init(&context);
   grpc_httpcli_get(&exec_ctx, &context, pr.pollset, &req,
@@ -150,7 +150,7 @@
             GPR_TIMESPAN)));
     pr->retries++;
     req.host = pr->server;
-    req.path = "/get";
+    req.http.path = "/get";
     grpc_httpcli_get(exec_ctx, pr->ctx, pr->pollset, &req,
                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                      pr);
@@ -189,7 +189,7 @@
   pr.ctx = &context;
 
   req.host = server;
-  req.path = "/get";
+  req.http.path = "/get";
 
   grpc_httpcli_context_init(&context);
   grpc_httpcli_get(&exec_ctx, &context, pr.pollset, &req,
diff --git a/test/core/util/port_server_client.h b/test/core/util/port_server_client.h
index fc209cd..4370064 100644
--- a/test/core/util/port_server_client.h
+++ b/test/core/util/port_server_client.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/util/port_windows.c b/test/core/util/port_windows.c
index a810683..2b6d3dd 100644
--- a/test/core/util/port_windows.c
+++ b/test/core/util/port_windows.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,17 +37,18 @@
 
 #include "test/core/util/port.h"
 
+#include <errno.h>
 #include <process.h>
 #include <stdio.h>
-#include <errno.h>
 #include <string.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-#include "src/core/support/env.h"
-#include "src/core/iomgr/sockaddr_utils.h"
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/support/env.h"
 #include "test/core/util/port_server_client.h"
 
 #define NUM_RANDOM_PORTS_TO_PICK 100
diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c
index 57225aa..d408374 100644
--- a/test/core/util/reconnect_server.c
+++ b/test/core/util/reconnect_server.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,9 +40,9 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <string.h>
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/sockaddr.h"
-#include "src/core/iomgr/tcp_server.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/tcp_server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_tcp_server.h"
 
@@ -60,8 +60,12 @@
             i, backoff / 1000.0, expected_backoff / 1000.0,
             (backoff - expected_backoff) * 100.0 / expected_backoff);
     expected_backoff *= 1.6;
-    if (expected_backoff > 120 * 1000) {
-      expected_backoff = 120 * 1000;
+    int max_reconnect_backoff_ms = 120 * 1000;
+    if (server->max_reconnect_backoff_ms > 0) {
+      max_reconnect_backoff_ms = server->max_reconnect_backoff_ms;
+    }
+    if (expected_backoff > max_reconnect_backoff_ms) {
+      expected_backoff = max_reconnect_backoff_ms;
     }
   }
 }
@@ -108,6 +112,7 @@
   server->head = NULL;
   server->tail = NULL;
   server->peer = NULL;
+  server->max_reconnect_backoff_ms = 0;
 }
 
 void reconnect_server_start(reconnect_server *server, int port) {
diff --git a/test/core/util/reconnect_server.h b/test/core/util/reconnect_server.h
index e2e6a02..ed02d49 100644
--- a/test/core/util/reconnect_server.h
+++ b/test/core/util/reconnect_server.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
@@ -52,6 +52,7 @@
   timestamp_list *head;
   timestamp_list *tail;
   char *peer;
+  int max_reconnect_backoff_ms;
 } reconnect_server;
 
 void reconnect_server_init(reconnect_server *server);
diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c
index f408048..3155a4e 100644
--- a/test/core/util/test_config.c
+++ b/test/core/util/test_config.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include "src/core/support/string.h"
+#include "src/core/lib/support/string.h"
 
 double g_fixture_slowdown_factor = 1.0;
 
diff --git a/test/core/util/test_config.h b/test/core/util/test_config.h
index f6bb2e1..76686f1 100644
--- a/test/core/util/test_config.h
+++ b/test/core/util/test_config.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c
index ab37944..e39a957 100644
--- a/test/core/util/test_tcp_server.c
+++ b/test/core/util/test_tcp_server.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,9 +40,9 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <string.h>
-#include "src/core/iomgr/endpoint.h"
-#include "src/core/iomgr/sockaddr.h"
-#include "src/core/iomgr/tcp_server.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/tcp_server.h"
 #include "test/core/util/port.h"
 
 static void on_server_destroyed(grpc_exec_ctx *exec_ctx, void *data,
diff --git a/test/core/util/test_tcp_server.h b/test/core/util/test_tcp_server.h
index 15fcb4f..d10b166 100644
--- a/test/core/util/test_tcp_server.h
+++ b/test/core/util/test_tcp_server.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,7 @@
 #define GRPC_TEST_CORE_UTIL_TEST_TCP_SERVER_H
 
 #include <grpc/support/sync.h>
-#include "src/core/iomgr/tcp_server.h"
+#include "src/core/lib/iomgr/tcp_server.h"
 
 typedef struct test_tcp_server {
   grpc_tcp_server *tcp_server;
diff --git a/test/cpp/codegen/codegen_test.cc b/test/cpp/codegen/codegen_test.cc
deleted file mode 100644
index 735755a..0000000
--- a/test/cpp/codegen/codegen_test.cc
+++ /dev/null
@@ -1,49 +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 <gtest/gtest.h>
-
-namespace grpc {
-namespace {
-
-class CodegenTest : public ::testing::Test {};
-
-TEST_F(CodegenTest, Build) {}
-
-}  // namespace
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
diff --git a/test/cpp/codegen/codegen_test_full.cc b/test/cpp/codegen/codegen_test_full.cc
new file mode 100644
index 0000000..4500540
--- /dev/null
+++ b/test/cpp/codegen/codegen_test_full.cc
@@ -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.
+ *
+ */
+
+#include <grpc++/completion_queue.h>
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace {
+
+class CodegenTestFull : public ::testing::Test {};
+
+TEST_F(CodegenTestFull, Init) {
+  grpc::CompletionQueue cq;
+  void* tag;
+  bool ok;
+  cq.AsyncNext(&tag, &ok, gpr_time_0(GPR_CLOCK_REALTIME));
+  ASSERT_FALSE(ok);
+}
+
+}  // namespace
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/codegen/codegen_test_minimal.cc b/test/cpp/codegen/codegen_test_minimal.cc
new file mode 100644
index 0000000..d660a6c
--- /dev/null
+++ b/test/cpp/codegen/codegen_test_minimal.cc
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 <gtest/gtest.h>
+
+namespace grpc {
+namespace {
+
+class CodegenTestMinimal : public ::testing::Test {};
+
+TEST_F(CodegenTestMinimal, Build) {}
+
+}  // namespace
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/common/alarm_cpp_test.cc b/test/cpp/common/alarm_cpp_test.cc
index d4381c0..a05ac30 100644
--- a/test/cpp/common/alarm_cpp_test.cc
+++ b/test/cpp/common/alarm_cpp_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc
index a629ff5..0e43d4e 100644
--- a/test/cpp/common/auth_property_iterator_test.cc
+++ b/test/cpp/common/auth_property_iterator_test.cc
@@ -31,14 +31,14 @@
  *
  */
 
-#include <grpc/grpc_security.h>
 #include <grpc++/security/auth_context.h>
+#include <grpc/grpc_security.h>
 #include <gtest/gtest.h>
 #include "src/cpp/common/secure_auth_context.h"
 #include "test/cpp/util/string_ref_helper.h"
 
 extern "C" {
-#include "src/core/security/security_context.h"
+#include "src/core/lib/security/security_context.h"
 }
 
 using ::grpc::testing::ToString;
diff --git a/test/cpp/common/channel_arguments_test.cc b/test/cpp/common/channel_arguments_test.cc
index a4821b4..1443eb2 100644
--- a/test/cpp/common/channel_arguments_test.cc
+++ b/test/cpp/common/channel_arguments_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
index 11de646..0673613 100644
--- a/test/cpp/common/secure_auth_context_test.cc
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -31,14 +31,14 @@
  *
  */
 
-#include <grpc/grpc_security.h>
-#include <grpc++/security/auth_context.h>
-#include <gtest/gtest.h>
 #include "src/cpp/common/secure_auth_context.h"
+#include <grpc++/security/auth_context.h>
+#include <grpc/grpc_security.h>
+#include <gtest/gtest.h>
 #include "test/cpp/util/string_ref_helper.h"
 
 extern "C" {
-#include "src/core/security/security_context.h"
+#include "src/core/lib/security/security_context.h"
 }
 
 using grpc::testing::ToString;
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index dc8c2bb..7e4d604 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -53,7 +53,7 @@
 #include "test/cpp/util/string_ref_helper.h"
 
 #ifdef GPR_POSIX_SOCKET
-#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/lib/iomgr/ev_posix.h"
 #endif
 
 using grpc::testing::EchoRequest;
diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc
index 5ca5cd7..30b04fb 100644
--- a/test/cpp/end2end/client_crash_test.cc
+++ b/test/cpp/end2end/client_crash_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -88,6 +88,7 @@
   EchoRequest request;
   EchoResponse response;
   ClientContext context;
+  context.set_fail_fast(false);
 
   auto stream = stub->BidiStream(&context);
 
@@ -113,6 +114,7 @@
   EchoRequest request;
   EchoResponse response;
   ClientContext context;
+  context.set_fail_fast(false);
 
   auto stream = stub->BidiStream(&context);
 
diff --git a/test/cpp/end2end/client_crash_test_server.cc b/test/cpp/end2end/client_crash_test_server.cc
index 1ec641c..9568ca2 100644
--- a/test/cpp/end2end/client_crash_test_server.cc
+++ b/test/cpp/end2end/client_crash_test_server.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 4759818..0c9313f 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,7 @@
 #include <grpc/support/time.h>
 #include <gtest/gtest.h>
 
-#include "src/core/security/credentials.h"
+#include "src/core/lib/security/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/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index 4e6d50e..d0cf6ae 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -135,6 +135,8 @@
       std::unique_ptr<ByteBuffer> send_buffer =
           SerializeToByteBuffer(&send_request);
       call->Write(*send_buffer, tag(2));
+      // Send ByteBuffer can be destroyed after calling Write.
+      send_buffer.reset();
       client_ok(2);
       call->WritesDone(tag(3));
       client_ok(3);
@@ -154,6 +156,7 @@
       send_response.set_message(recv_request.message());
       send_buffer = SerializeToByteBuffer(&send_response);
       stream.Write(*send_buffer, tag(6));
+      send_buffer.reset();
       server_ok(6);
 
       stream.Finish(Status::OK, tag(7));
@@ -223,6 +226,7 @@
   std::unique_ptr<ByteBuffer> send_buffer =
       SerializeToByteBuffer(&send_request);
   cli_stream->Write(*send_buffer, tag(3));
+  send_buffer.reset();
   client_ok(3);
 
   ByteBuffer recv_buffer;
@@ -234,6 +238,7 @@
   send_response.set_message(recv_request.message());
   send_buffer = SerializeToByteBuffer(&send_response);
   srv_stream.Write(*send_buffer, tag(5));
+  send_buffer.reset();
   server_ok(5);
 
   cli_stream->Read(&recv_buffer, tag(6));
diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc
index c72e206..02043a8 100644
--- a/test/cpp/end2end/hybrid_end2end_test.cc
+++ b/test/cpp/end2end/hybrid_end2end_test.cc
@@ -356,7 +356,8 @@
 
 TEST_F(HybridEnd2endTest, AsyncEchoRequestStream) {
   EchoTestService::WithAsyncMethod_RequestStream<
-      EchoTestService::WithAsyncMethod_Echo<TestServiceImpl> > service;
+      EchoTestService::WithAsyncMethod_Echo<TestServiceImpl> >
+      service;
   SetUpServer(&service, nullptr, nullptr);
   ResetStub();
   std::thread echo_handler_thread(
@@ -436,7 +437,8 @@
 
 TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream) {
   EchoTestService::WithAsyncMethod_RequestStream<
-      EchoTestService::WithGenericMethod_Echo<TestServiceImpl> > service;
+      EchoTestService::WithGenericMethod_Echo<TestServiceImpl> >
+      service;
   AsyncGenericService generic_service;
   SetUpServer(&service, nullptr, &generic_service);
   ResetStub();
@@ -453,7 +455,8 @@
 // Add a second service with one sync method.
 TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_SyncDupService) {
   EchoTestService::WithAsyncMethod_RequestStream<
-      EchoTestService::WithGenericMethod_Echo<TestServiceImpl> > service;
+      EchoTestService::WithGenericMethod_Echo<TestServiceImpl> >
+      service;
   AsyncGenericService generic_service;
   TestServiceImplDupPkg dup_service;
   SetUpServer(&service, &dup_service, &generic_service);
@@ -472,7 +475,8 @@
 // Add a second service with one async method.
 TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_AsyncDupService) {
   EchoTestService::WithAsyncMethod_RequestStream<
-      EchoTestService::WithGenericMethod_Echo<TestServiceImpl> > service;
+      EchoTestService::WithGenericMethod_Echo<TestServiceImpl> >
+      service;
   AsyncGenericService generic_service;
   duplicate::EchoTestService::AsyncService dup_service;
   SetUpServer(&service, &dup_service, &generic_service);
diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc
index 1d29096..0ace5d9 100644
--- a/test/cpp/end2end/mock_test.cc
+++ b/test/cpp/end2end/mock_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc
index 9bf9423..e447360 100644
--- a/test/cpp/end2end/server_crash_test.cc
+++ b/test/cpp/end2end/server_crash_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc
index b0e6ac6..ece948d 100644
--- a/test/cpp/end2end/server_crash_test_client.cc
+++ b/test/cpp/end2end/server_crash_test_client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@
   EchoRequest request;
   EchoResponse response;
   grpc::ClientContext context;
+  context.set_fail_fast(false);
 
   if (FLAGS_mode == "bidi") {
     auto stream = stub->BidiStream(&context);
diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc
index dbbda3a..aa8d421 100644
--- a/test/cpp/end2end/shutdown_test.cc
+++ b/test/cpp/end2end/shutdown_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,7 @@
 #include <grpc/support/sync.h>
 #include <gtest/gtest.h>
 
-#include "src/core/support/env.h"
+#include "src/core/lib/support/env.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
diff --git a/test/cpp/end2end/streaming_throughput_test.cc b/test/cpp/end2end/streaming_throughput_test.cc
index 4777b88..9e82c30 100644
--- a/test/cpp/end2end/streaming_throughput_test.cc
+++ b/test/cpp/end2end/streaming_throughput_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc
index fe29c4a..2f5dd6d 100644
--- a/test/cpp/end2end/test_service_impl.cc
+++ b/test/cpp/end2end/test_service_impl.cc
@@ -129,10 +129,9 @@
   if (request->has_param() && request->param().echo_metadata()) {
     const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata =
         context->client_metadata();
-    for (
-        std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator iter =
-            client_metadata.begin();
-        iter != client_metadata.end(); ++iter) {
+    for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
+             iter = client_metadata.begin();
+         iter != client_metadata.end(); ++iter) {
       context->AddTrailingMetadata(ToString(iter->first),
                                    ToString(iter->second));
     }
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index e246c0b..94541f9 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,7 @@
 #include <grpc/support/time.h>
 #include <gtest/gtest.h>
 
-#include "src/core/surface/api_trace.h"
+#include "src/core/lib/surface/api_trace.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"
@@ -58,6 +58,7 @@
 const int kNumThreads = 100;  // Number of threads
 const int kNumAsyncSendThreads = 2;
 const int kNumAsyncReceiveThreads = 50;
+const int kNumAsyncServerThreads = 50;
 const int kNumRpcs = 1000;  // Number of RPCs per thread
 
 namespace grpc {
@@ -174,23 +175,13 @@
   }
 };
 
+template <class Service>
 class CommonStressTest {
  public:
   CommonStressTest() : kMaxMessageSize_(8192) {}
-  void SetUp() {
-    int port = grpc_pick_unused_port_or_die();
-    server_address_ << "localhost:" << port;
-    // Setup server
-    ServerBuilder builder;
-    builder.AddListeningPort(server_address_.str(),
-                             InsecureServerCredentials());
-    builder.RegisterService(&service_);
-    builder.SetMaxMessageSize(
-        kMaxMessageSize_);  // For testing max message size.
-    builder.RegisterService(&dup_pkg_service_);
-    server_ = builder.BuildAndStart();
-  }
-  void TearDown() { server_->Shutdown(); }
+  virtual ~CommonStressTest() {}
+  virtual void SetUp() = 0;
+  virtual void TearDown() = 0;
   void ResetStub() {
     std::shared_ptr<Channel> channel =
         CreateChannel(server_address_.str(), InsecureChannelCredentials());
@@ -198,15 +189,137 @@
   }
   grpc::testing::EchoTestService::Stub* GetStub() { return stub_.get(); }
 
+ protected:
+  void SetUpStart(ServerBuilder* builder, Service* service) {
+    int port = grpc_pick_unused_port_or_die();
+    server_address_ << "localhost:" << port;
+    // Setup server
+    builder->AddListeningPort(server_address_.str(),
+                              InsecureServerCredentials());
+    builder->RegisterService(service);
+    builder->SetMaxMessageSize(
+        kMaxMessageSize_);  // For testing max message size.
+    builder->RegisterService(&dup_pkg_service_);
+  }
+  void SetUpEnd(ServerBuilder* builder) { server_ = builder->BuildAndStart(); }
+  void TearDownStart() { server_->Shutdown(); }
+  void TearDownEnd() {}
+
  private:
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
   std::unique_ptr<Server> server_;
   std::ostringstream server_address_;
   const int kMaxMessageSize_;
-  TestServiceImpl service_;
   TestServiceImplDupPkg dup_pkg_service_;
 };
 
+class CommonStressTestSyncServer : public CommonStressTest<TestServiceImpl> {
+ public:
+  void SetUp() GRPC_OVERRIDE {
+    ServerBuilder builder;
+    SetUpStart(&builder, &service_);
+    SetUpEnd(&builder);
+  }
+  void TearDown() GRPC_OVERRIDE {
+    TearDownStart();
+    TearDownEnd();
+  }
+
+ private:
+  TestServiceImpl service_;
+};
+
+class CommonStressTestAsyncServer
+    : public CommonStressTest<::grpc::testing::EchoTestService::AsyncService> {
+ public:
+  void SetUp() GRPC_OVERRIDE {
+    shutting_down_ = false;
+    ServerBuilder builder;
+    SetUpStart(&builder, &service_);
+    cq_ = builder.AddCompletionQueue();
+    SetUpEnd(&builder);
+    contexts_ = new Context[kNumAsyncServerThreads * 100];
+    for (int i = 0; i < kNumAsyncServerThreads * 100; i++) {
+      RefreshContext(i);
+    }
+    for (int i = 0; i < kNumAsyncServerThreads; i++) {
+      server_threads_.push_back(
+          new std::thread(&CommonStressTestAsyncServer::ProcessRpcs, this));
+    }
+  }
+  void TearDown() GRPC_OVERRIDE {
+    {
+      unique_lock<mutex> l(mu_);
+      TearDownStart();
+      shutting_down_ = true;
+      cq_->Shutdown();
+    }
+
+    for (int i = 0; i < kNumAsyncServerThreads; i++) {
+      server_threads_[i]->join();
+      delete server_threads_[i];
+    }
+
+    void* ignored_tag;
+    bool ignored_ok;
+    while (cq_->Next(&ignored_tag, &ignored_ok))
+      ;
+    TearDownEnd();
+    delete[] contexts_;
+  }
+
+ private:
+  void ProcessRpcs() {
+    void* tag;
+    bool ok;
+    while (cq_->Next(&tag, &ok)) {
+      if (ok) {
+        int i = static_cast<int>(reinterpret_cast<intptr_t>(tag));
+        switch (contexts_[i].state) {
+          case Context::READY: {
+            contexts_[i].state = Context::DONE;
+            EchoResponse send_response;
+            send_response.set_message(contexts_[i].recv_request.message());
+            contexts_[i].response_writer->Finish(send_response, Status::OK,
+                                                 tag);
+            break;
+          }
+          case Context::DONE:
+            RefreshContext(i);
+            break;
+        }
+      }
+    }
+  }
+  void RefreshContext(int i) {
+    unique_lock<mutex> l(mu_);
+    if (!shutting_down_) {
+      contexts_[i].state = Context::READY;
+      contexts_[i].srv_ctx.reset(new ServerContext);
+      contexts_[i].response_writer.reset(
+          new grpc::ServerAsyncResponseWriter<EchoResponse>(
+              contexts_[i].srv_ctx.get()));
+      service_.RequestEcho(contexts_[i].srv_ctx.get(),
+                           &contexts_[i].recv_request,
+                           contexts_[i].response_writer.get(), cq_.get(),
+                           cq_.get(), (void*)(intptr_t)i);
+    }
+  }
+  struct Context {
+    std::unique_ptr<ServerContext> srv_ctx;
+    std::unique_ptr<grpc::ServerAsyncResponseWriter<EchoResponse>>
+        response_writer;
+    EchoRequest recv_request;
+    enum { READY, DONE } state;
+  } * contexts_;
+  ::grpc::testing::EchoTestService::AsyncService service_;
+  std::unique_ptr<ServerCompletionQueue> cq_;
+  bool shutting_down_;
+  mutex mu_;
+  std::vector<std::thread*> server_threads_;
+};
+
+template <class Common>
 class End2endTest : public ::testing::Test {
  protected:
   End2endTest() {}
@@ -214,7 +327,7 @@
   void TearDown() GRPC_OVERRIDE { common_.TearDown(); }
   void ResetStub() { common_.ResetStub(); }
 
-  CommonStressTest common_;
+  Common common_;
 };
 
 static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs) {
@@ -230,11 +343,16 @@
   }
 }
 
-TEST_F(End2endTest, ThreadStress) {
-  common_.ResetStub();
+typedef ::testing::Types<CommonStressTestSyncServer,
+                         CommonStressTestAsyncServer>
+    CommonTypes;
+TYPED_TEST_CASE(End2endTest, CommonTypes);
+TYPED_TEST(End2endTest, ThreadStress) {
+  this->common_.ResetStub();
   std::vector<std::thread*> threads;
   for (int i = 0; i < kNumThreads; ++i) {
-    threads.push_back(new std::thread(SendRpc, common_.GetStub(), kNumRpcs));
+    threads.push_back(
+        new std::thread(SendRpc, this->common_.GetStub(), kNumRpcs));
   }
   for (int i = 0; i < kNumThreads; ++i) {
     threads[i]->join();
@@ -242,6 +360,7 @@
   }
 }
 
+template <class Common>
 class AsyncClientEnd2endTest : public ::testing::Test {
  protected:
   AsyncClientEnd2endTest() : rpcs_outstanding_(0) {}
@@ -309,31 +428,33 @@
     }
   }
 
-  CommonStressTest common_;
+  Common common_;
   CompletionQueue cq_;
   mutex mu_;
   condition_variable cv_;
   int rpcs_outstanding_;
 };
 
-TEST_F(AsyncClientEnd2endTest, ThreadStress) {
-  common_.ResetStub();
-  std::vector<std::thread*> send_threads, completion_threads;
+TYPED_TEST_CASE(AsyncClientEnd2endTest, CommonTypes);
+TYPED_TEST(AsyncClientEnd2endTest, ThreadStress) {
+  this->common_.ResetStub();
+  std::vector<std::thread *> send_threads, completion_threads;
   for (int i = 0; i < kNumAsyncReceiveThreads; ++i) {
     completion_threads.push_back(new std::thread(
-        &AsyncClientEnd2endTest_ThreadStress_Test::AsyncCompleteRpc, this));
+        &AsyncClientEnd2endTest_ThreadStress_Test<TypeParam>::AsyncCompleteRpc,
+        this));
   }
   for (int i = 0; i < kNumAsyncSendThreads; ++i) {
-    send_threads.push_back(
-        new std::thread(&AsyncClientEnd2endTest_ThreadStress_Test::AsyncSendRpc,
-                        this, kNumRpcs));
+    send_threads.push_back(new std::thread(
+        &AsyncClientEnd2endTest_ThreadStress_Test<TypeParam>::AsyncSendRpc,
+        this, kNumRpcs));
   }
   for (int i = 0; i < kNumAsyncSendThreads; ++i) {
     send_threads[i]->join();
     delete send_threads[i];
   }
 
-  Wait();
+  this->Wait();
   for (int i = 0; i < kNumAsyncReceiveThreads; ++i) {
     completion_threads[i]->join();
     delete completion_threads[i];
diff --git a/test/cpp/end2end/zookeeper_test.cc b/test/cpp/end2end/zookeeper_test.cc
index bbf1b0e..12853a1 100644
--- a/test/cpp/end2end/zookeeper_test.cc
+++ b/test/cpp/end2end/zookeeper_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,7 @@
 #include <gtest/gtest.h>
 #include <zookeeper/zookeeper.h>
 
-#include "src/core/support/env.h"
+#include "src/core/lib/support/env.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc
index bd4885f..92f93c8 100644
--- a/test/cpp/grpclb/grpclb_api_test.cc
+++ b/test/cpp/grpclb/grpclb_api_test.cc
@@ -34,7 +34,7 @@
 #include <gtest/gtest.h>
 #include <string>
 
-#include "src/core/client_config/lb_policies/load_balancer_api.h"
+#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
 #include "src/proto/grpc/lb/v0/load_balancer.pb.h"  // C++ version
 
 namespace grpc {
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 788adef..9af6a88 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,11 +35,11 @@
 
 #include <unistd.h>
 
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
 #include <gflags/gflags.h>
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
 
 #include "test/cpp/interop/client_helper.h"
 #include "test/cpp/interop/interop_client.h"
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 5caf0f2..c8b1e50 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -39,13 +39,13 @@
 #include <memory>
 #include <sstream>
 
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
 #include <gflags/gflags.h>
 #include <grpc++/channel.h>
 #include <grpc++/create_channel.h>
 #include <grpc++/security/credentials.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
 
 #include "src/cpp/client/secure_credentials.h"
 #include "test/core/security/oauth2_utils.h"
diff --git a/test/cpp/interop/client_helper.h b/test/cpp/interop/client_helper.h
index 0f77474..622b96e 100644
--- a/test/cpp/interop/client_helper.h
+++ b/test/cpp/interop/client_helper.h
@@ -38,7 +38,7 @@
 
 #include <grpc++/channel.h>
 
-#include "src/core/surface/call_test_only.h"
+#include "src/core/lib/surface/call_test_only.h"
 
 namespace grpc {
 namespace testing {
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index 46f6fda..22293d2 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,10 +46,10 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/transport/byte_stream.h"
+#include "src/core/lib/transport/byte_stream.h"
 #include "src/proto/grpc/testing/empty.grpc.pb.h"
-#include "src/proto/grpc/testing/test.grpc.pb.h"
 #include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/test.grpc.pb.h"
 #include "test/cpp/interop/client_helper.h"
 
 namespace grpc {
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index 3f57f3c..a3794fd 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,8 +36,8 @@
 
 #include <memory>
 
-#include <grpc/grpc.h>
 #include <grpc++/channel.h>
+#include <grpc/grpc.h>
 #include "src/proto/grpc/testing/messages.grpc.pb.h"
 #include "src/proto/grpc/testing/test.grpc.pb.h"
 
diff --git a/test/cpp/interop/interop_test.cc b/test/cpp/interop/interop_test.cc
index faf6698..8e71a2b 100644
--- a/test/cpp/interop/interop_test.cc
+++ b/test/cpp/interop/interop_test.cc
@@ -35,14 +35,14 @@
 #define _POSIX_SOURCE
 #endif
 
-#include <unistd.h>
 #include <assert.h>
-#include <stdio.h>
-#include <string.h>
 #include <signal.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
@@ -51,8 +51,8 @@
 #include "test/core/util/port.h"
 
 extern "C" {
-#include "src/core/iomgr/socket_utils_posix.h"
-#include "src/core/support/string.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/support/string.h"
 }
 
 int test_client(const char* root, const char* host, int port) {
diff --git a/test/cpp/interop/metrics_client.cc b/test/cpp/interop/metrics_client.cc
index bd48c7d..cc304f2 100644
--- a/test/cpp/interop/metrics_client.cc
+++ b/test/cpp/interop/metrics_client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/interop/reconnect_interop_client.cc b/test/cpp/interop/reconnect_interop_client.cc
index 79a60cc..797e52c 100644
--- a/test/cpp/interop/reconnect_interop_client.cc
+++ b/test/cpp/interop/reconnect_interop_client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,27 +34,33 @@
 #include <memory>
 #include <sstream>
 
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
 #include <gflags/gflags.h>
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
-#include "test/cpp/util/create_test_channel.h"
-#include "test/cpp/util/test_config.h"
-#include "src/proto/grpc/testing/test.grpc.pb.h"
+#include <grpc++/support/channel_arguments.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
 #include "src/proto/grpc/testing/empty.grpc.pb.h"
 #include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/test.grpc.pb.h"
+#include "test/cpp/util/create_test_channel.h"
+#include "test/cpp/util/test_config.h"
 
 DEFINE_int32(server_control_port, 0, "Server port for control rpcs.");
 DEFINE_int32(server_retry_port, 0, "Server port for testing reconnection.");
 DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
+DEFINE_int32(max_reconnect_backoff_ms, 0,
+             "Maximum backoff time, or 0 for default.");
 
+using grpc::CallCredentials;
 using grpc::Channel;
+using grpc::ChannelArguments;
 using grpc::ClientContext;
 using grpc::CreateTestChannel;
 using grpc::Status;
 using grpc::testing::Empty;
 using grpc::testing::ReconnectInfo;
+using grpc::testing::ReconnectParams;
 using grpc::testing::ReconnectService;
 
 int main(int argc, char** argv) {
@@ -68,17 +74,25 @@
       ReconnectService::NewStub(
           CreateTestChannel(server_address.str(), false)));
   ClientContext start_context;
-  Empty empty_request;
+  ReconnectParams reconnect_params;
+  reconnect_params.set_max_reconnect_backoff_ms(FLAGS_max_reconnect_backoff_ms);
   Empty empty_response;
   Status start_status =
-      control_stub->Start(&start_context, empty_request, &empty_response);
+      control_stub->Start(&start_context, reconnect_params, &empty_response);
   GPR_ASSERT(start_status.ok());
 
   gpr_log(GPR_INFO, "Starting connections with retries.");
   server_address.str("");
   server_address << FLAGS_server_host << ':' << FLAGS_server_retry_port;
+  ChannelArguments channel_args;
+  if (FLAGS_max_reconnect_backoff_ms > 0) {
+    channel_args.SetInt(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS,
+                        FLAGS_max_reconnect_backoff_ms);
+  }
   std::shared_ptr<Channel> retry_channel =
-      CreateTestChannel(server_address.str(), true);
+      CreateTestChannel(server_address.str(), "foo.test.google.fr", true, false,
+                        std::shared_ptr<CallCredentials>(), channel_args);
+
   // About 13 retries.
   const int kDeadlineSeconds = 540;
   // Use any rpc to test retry.
@@ -88,15 +102,15 @@
   retry_context.set_deadline(std::chrono::system_clock::now() +
                              std::chrono::seconds(kDeadlineSeconds));
   Status retry_status =
-      retry_stub->Start(&retry_context, empty_request, &empty_response);
+      retry_stub->Start(&retry_context, reconnect_params, &empty_response);
   GPR_ASSERT(retry_status.error_code() == grpc::StatusCode::DEADLINE_EXCEEDED);
   gpr_log(GPR_INFO, "Done retrying, getting final data from server");
 
   ClientContext stop_context;
   ReconnectInfo response;
-  Status stop_status =
-      control_stub->Stop(&stop_context, empty_request, &response);
+  Status stop_status = control_stub->Stop(&stop_context, Empty(), &response);
   GPR_ASSERT(stop_status.ok());
   GPR_ASSERT(response.passed() == true);
+  gpr_log(GPR_INFO, "Passed");
   return 0;
 }
diff --git a/test/cpp/interop/reconnect_interop_server.cc b/test/cpp/interop/reconnect_interop_server.cc
index 1f9147d..53d51e8 100644
--- a/test/cpp/interop/reconnect_interop_server.cc
+++ b/test/cpp/interop/reconnect_interop_server.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -71,6 +71,7 @@
 using grpc::testing::Empty;
 using grpc::testing::ReconnectService;
 using grpc::testing::ReconnectInfo;
+using grpc::testing::ReconnectParams;
 
 static bool got_sigint = false;
 
@@ -92,7 +93,8 @@
 
   void Poll(int seconds) { reconnect_server_poll(&tcp_server_, seconds); }
 
-  Status Start(ServerContext* context, const Empty* request, Empty* response) {
+  Status Start(ServerContext* context, const ReconnectParams* request,
+               Empty* response) {
     bool start_server = true;
     std::unique_lock<std::mutex> lock(mu_);
     while (serving_ && !shutdown_) {
@@ -105,6 +107,8 @@
     if (server_started_) {
       start_server = false;
     } else {
+      tcp_server_.max_reconnect_backoff_ms =
+          request->max_reconnect_backoff_ms();
       server_started_ = true;
     }
     lock.unlock();
@@ -133,7 +137,9 @@
     const double kTransmissionDelay = 100.0;
     const double kBackoffMultiplier = 1.6;
     const double kJitterFactor = 0.2;
-    const int kMaxBackoffMs = 120 * 1000;
+    const int kMaxBackoffMs = tcp_server_.max_reconnect_backoff_ms
+                                  ? tcp_server_.max_reconnect_backoff_ms
+                                  : 120 * 1000;
     bool passed = true;
     for (timestamp_list* cur = tcp_server_.head; cur && cur->next;
          cur = cur->next) {
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index 9a28409..c6d891a 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -38,7 +38,7 @@
 #include <gflags/gflags.h>
 #include <grpc++/security/server_credentials.h>
 
-#include "src/core/surface/call_test_only.h"
+#include "src/core/lib/surface/call_test_only.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 
 DECLARE_bool(use_tls);
diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h
index 57337e5..12865e4 100644
--- a/test/cpp/interop/server_helper.h
+++ b/test/cpp/interop/server_helper.h
@@ -36,9 +36,9 @@
 
 #include <memory>
 
-#include <grpc/compression.h>
-#include <grpc++/server_context.h>
 #include <grpc++/security/server_credentials.h>
+#include <grpc++/server_context.h>
+#include <grpc/compression.h>
 
 namespace grpc {
 namespace testing {
diff --git a/test/cpp/interop/server_main.cc b/test/cpp/interop/server_main.cc
index 18ac35d..889874f 100644
--- a/test/cpp/interop/server_main.cc
+++ b/test/cpp/interop/server_main.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,19 +40,19 @@
 #include <thread>
 
 #include <gflags/gflags.h>
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
+#include <grpc++/security/server_credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/security/server_credentials.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
 
-#include "test/cpp/interop/server_helper.h"
-#include "test/cpp/util/test_config.h"
-#include "src/proto/grpc/testing/test.grpc.pb.h"
 #include "src/proto/grpc/testing/empty.grpc.pb.h"
 #include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/test.grpc.pb.h"
+#include "test/cpp/interop/server_helper.h"
+#include "test/cpp/util/test_config.h"
 
 DEFINE_bool(use_tls, false, "Whether to use tls.");
 DEFINE_int32(port, 0, "Server port.");
diff --git a/test/cpp/interop/stress_interop_client.cc b/test/cpp/interop/stress_interop_client.cc
index b581e9b..04671fb 100644
--- a/test/cpp/interop/stress_interop_client.cc
+++ b/test/cpp/interop/stress_interop_client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc
index 702354d..38caf31 100644
--- a/test/cpp/interop/stress_test.cc
+++ b/test/cpp/interop/stress_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,12 +43,12 @@
 #include <grpc++/impl/thd.h>
 #include <grpc/support/time.h>
 
+#include "src/proto/grpc/testing/metrics.grpc.pb.h"
+#include "src/proto/grpc/testing/metrics.pb.h"
 #include "test/cpp/interop/interop_client.h"
 #include "test/cpp/interop/stress_interop_client.h"
 #include "test/cpp/util/metrics_server.h"
 #include "test/cpp/util/test_config.h"
-#include "src/proto/grpc/testing/metrics.grpc.pb.h"
-#include "src/proto/grpc/testing/metrics.pb.h"
 
 extern "C" {
 extern void gpr_default_log(gpr_log_func_args* args);
@@ -98,11 +98,11 @@
               " 'large_unary', 10% of the time and 'empty_stream' the remaining"
               " 70% of the time");
 
-DEFINE_int32(log_level, GPR_LOG_SEVERITY_DEBUG,
+DEFINE_int32(log_level, GPR_LOG_SEVERITY_INFO,
              "Severity level of messages that should be logged. Any messages "
              "greater than or equal to the level set here will be logged. "
              "The choices are: 0 (GPR_LOG_SEVERITY_DEBUG), 1 "
-             "(GPR_LOG_SEVERITY_INFO) and 2 (GPR_LOG_SEVERITY_ERROR.");
+             "(GPR_LOG_SEVERITY_INFO) and 2 (GPR_LOG_SEVERITY_ERROR)");
 
 using grpc::testing::kTestCaseList;
 using grpc::testing::MetricsService;
diff --git a/test/cpp/qps/async_streaming_ping_pong_test.cc b/test/cpp/qps/async_streaming_ping_pong_test.cc
index d9fbb39..4b6bae0 100644
--- a/test/cpp/qps/async_streaming_ping_pong_test.cc
+++ b/test/cpp/qps/async_streaming_ping_pong_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/async_unary_ping_pong_test.cc b/test/cpp/qps/async_unary_ping_pong_test.cc
index 5ab8619..571a8b7 100644
--- a/test/cpp/qps/async_unary_ping_pong_test.cc
+++ b/test/cpp/qps/async_unary_ping_pong_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index 92e77ee..5a9027a 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -173,20 +173,6 @@
         random_dist.reset(
             new ExpDist(load.poisson().offered_load() / num_threads));
         break;
-      case LoadParams::kUniform:
-        random_dist.reset(
-            new UniformDist(load.uniform().interarrival_lo() * num_threads,
-                            load.uniform().interarrival_hi() * num_threads));
-        break;
-      case LoadParams::kDeterm:
-        random_dist.reset(
-            new DetDist(num_threads / load.determ().offered_load()));
-        break;
-      case LoadParams::kPareto:
-        random_dist.reset(
-            new ParetoDist(load.pareto().interarrival_base() * num_threads,
-                           load.pareto().alpha()));
-        break;
       default:
         GPR_ASSERT(false);
     }
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index 9e9da99..e72cef2 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -141,7 +141,8 @@
   std::function<gpr_timespec()> next_issue_;
   std::function<std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>(
       BenchmarkService::Stub*, grpc::ClientContext*, const RequestType&,
-      CompletionQueue*)> start_req_;
+      CompletionQueue*)>
+      start_req_;
   grpc::Status status_;
   double start_;
   std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>
@@ -359,10 +360,10 @@
   State next_state_;
   std::function<void(grpc::Status, ResponseType*)> callback_;
   std::function<gpr_timespec()> next_issue_;
-  std::function<
-      std::unique_ptr<grpc::ClientAsyncReaderWriter<RequestType, ResponseType>>(
-          BenchmarkService::Stub*, grpc::ClientContext*, CompletionQueue*,
-          void*)> start_req_;
+  std::function<std::unique_ptr<
+      grpc::ClientAsyncReaderWriter<RequestType, ResponseType>>(
+      BenchmarkService::Stub*, grpc::ClientContext*, CompletionQueue*, void*)>
+      start_req_;
   grpc::Status status_;
   double start_;
   std::unique_ptr<grpc::ClientAsyncReaderWriter<RequestType, ResponseType>>
@@ -491,7 +492,8 @@
   std::function<gpr_timespec()> next_issue_;
   std::function<std::unique_ptr<grpc::GenericClientAsyncReaderWriter>(
       grpc::GenericStub*, grpc::ClientContext*, const grpc::string&,
-      CompletionQueue*, void*)> start_req_;
+      CompletionQueue*, void*)>
+      start_req_;
   grpc::Status status_;
   double start_;
   std::unique_ptr<grpc::GenericClientAsyncReaderWriter> stream_;
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index 4284e07..fb161f7 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -53,7 +53,7 @@
 #include <grpc/support/time.h>
 #include <gtest/gtest.h>
 
-#include "src/core/profiling/timers.h"
+#include "src/core/lib/profiling/timers.h"
 #include "src/proto/grpc/testing/services.grpc.pb.h"
 #include "test/cpp/qps/client.h"
 #include "test/cpp/qps/histogram.h"
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index 6c05799..2583ceb 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,13 +45,14 @@
 #include <grpc/support/log.h>
 #include <gtest/gtest.h>
 
-#include "src/core/support/env.h"
+#include "src/core/lib/support/env.h"
 #include "src/proto/grpc/testing/services.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/histogram.h"
 #include "test/cpp/qps/qps_worker.h"
+#include "test/cpp/qps/stats.h"
 
 using std::list;
 using std::thread;
@@ -115,6 +116,47 @@
   }
 }
 
+// helpers for postprocess_scenario_result
+static double WallTime(ClientStats s) { return s.time_elapsed(); }
+static double SystemTime(ClientStats s) { return s.time_system(); }
+static double UserTime(ClientStats s) { return s.time_user(); }
+static double ServerWallTime(ServerStats s) { return s.time_elapsed(); }
+static double ServerSystemTime(ServerStats s) { return s.time_system(); }
+static double ServerUserTime(ServerStats s) { return s.time_user(); }
+static int Cores(int n) { return n; }
+
+// Postprocess ScenarioResult and populate result summary.
+static void postprocess_scenario_result(ScenarioResult* result) {
+  Histogram histogram;
+  histogram.MergeProto(result->latencies());
+
+  auto qps = histogram.Count() / average(result->client_stats(), WallTime);
+  auto qps_per_server_core = qps / sum(result->server_cores(), Cores);
+
+  result->mutable_summary()->set_qps(qps);
+  result->mutable_summary()->set_qps_per_server_core(qps_per_server_core);
+  result->mutable_summary()->set_latency_50(histogram.Percentile(50));
+  result->mutable_summary()->set_latency_90(histogram.Percentile(90));
+  result->mutable_summary()->set_latency_95(histogram.Percentile(95));
+  result->mutable_summary()->set_latency_99(histogram.Percentile(99));
+  result->mutable_summary()->set_latency_999(histogram.Percentile(99.9));
+
+  auto server_system_time = 100.0 *
+                            sum(result->server_stats(), ServerSystemTime) /
+                            sum(result->server_stats(), ServerWallTime);
+  auto server_user_time = 100.0 * sum(result->server_stats(), ServerUserTime) /
+                          sum(result->server_stats(), ServerWallTime);
+  auto client_system_time = 100.0 * sum(result->client_stats(), SystemTime) /
+                            sum(result->client_stats(), WallTime);
+  auto client_user_time = 100.0 * sum(result->client_stats(), UserTime) /
+                          sum(result->client_stats(), WallTime);
+
+  result->mutable_summary()->set_server_system_time(server_system_time);
+  result->mutable_summary()->set_server_user_time(server_user_time);
+  result->mutable_summary()->set_client_system_time(client_system_time);
+  result->mutable_summary()->set_client_user_time(client_user_time);
+}
+
 // Namespace for classes and functions used only in RunScenario
 // Using this rather than local definitions to workaround gcc-4.4 limitations
 // regarding using templates without linkage
@@ -343,8 +385,8 @@
 
   // Finish a run
   std::unique_ptr<ScenarioResult> result(new ScenarioResult);
-  result->client_config = result_client_config;
-  result->server_config = result_server_config;
+  Histogram merged_latencies;
+
   gpr_log(GPR_INFO, "Finishing clients");
   for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
     GPR_ASSERT(client->stream->Write(client_mark));
@@ -353,9 +395,8 @@
   for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
     GPR_ASSERT(client->stream->Read(&client_status));
     const auto& stats = client_status.stats();
-    result->latencies.MergeProto(stats.latencies());
-    result->client_resources.emplace_back(
-        stats.time_elapsed(), stats.time_user(), stats.time_system(), -1);
+    merged_latencies.MergeProto(stats.latencies());
+    result->add_client_stats()->CopyFrom(stats);
     GPR_ASSERT(!client->stream->Read(&client_status));
   }
   for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
@@ -363,6 +404,8 @@
   }
   delete[] clients;
 
+  merged_latencies.FillProto(result->mutable_latencies());
+
   gpr_log(GPR_INFO, "Finishing servers");
   for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
     GPR_ASSERT(server->stream->Write(server_mark));
@@ -370,10 +413,8 @@
   }
   for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
     GPR_ASSERT(server->stream->Read(&server_status));
-    const auto& stats = server_status.stats();
-    result->server_resources.emplace_back(
-        stats.time_elapsed(), stats.time_user(), stats.time_system(),
-        server_status.cores());
+    result->add_server_stats()->CopyFrom(server_status.stats());
+    result->add_server_cores(server_status.cores());
     GPR_ASSERT(!server->stream->Read(&server_status));
   }
   for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
@@ -381,6 +422,8 @@
   }
 
   delete[] servers;
+
+  postprocess_scenario_result(result.get());
   return result;
 }
 
diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h
index 3af61f7..3a5cf13 100644
--- a/test/cpp/qps/driver.h
+++ b/test/cpp/qps/driver.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,34 +36,11 @@
 
 #include <memory>
 
-#include "test/cpp/qps/histogram.h"
 #include "src/proto/grpc/testing/control.grpc.pb.h"
+#include "test/cpp/qps/histogram.h"
 
 namespace grpc {
 namespace testing {
-class ResourceUsage {
- public:
-  ResourceUsage(double w, double u, double s, int c)
-      : wall_time_(w), user_time_(u), system_time_(s), cores_(c) {}
-  double wall_time() const { return wall_time_; }
-  double user_time() const { return user_time_; }
-  double system_time() const { return system_time_; }
-  int cores() const { return cores_; }
-
- private:
-  double wall_time_;
-  double user_time_;
-  double system_time_;
-  int cores_;
-};
-
-struct ScenarioResult {
-  Histogram latencies;
-  std::vector<ResourceUsage> client_resources;
-  std::vector<ResourceUsage> server_resources;
-  ClientConfig client_config;
-  ServerConfig server_config;
-};
 
 std::unique_ptr<ScenarioResult> RunScenario(
     const grpc::testing::ClientConfig& client_config, size_t num_clients,
diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py
new file mode 100755
index 0000000..9d6bf2a
--- /dev/null
+++ b/test/cpp/qps/gen_build_yaml.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python2.7
+
+# 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.
+
+import json
+import pipes
+import shutil
+import sys
+import os
+import yaml
+
+run_tests_root = os.path.abspath(os.path.join(
+    os.path.dirname(sys.argv[0]),
+    '../../../tools/run_tests'))
+sys.path.append(run_tests_root)
+
+import performance.scenario_config as scenario_config
+
+print yaml.dump({
+  'tests': [
+    {
+      'name': 'json_run_localhost',
+      'shortname': 'json_run_localhost:%s' % js['name'],
+      'args': ['--scenario_json', pipes.quote(json.dumps(js))],
+      'ci_platforms': ['linux', 'mac', 'posix', 'windows'],
+      'platforms': ['linux', 'mac', 'posix', 'windows'],
+      'flaky': False,
+      'language': 'c++',
+      'boringssl': True,
+      'defaults': 'boringssl',
+      'cpu_cost': 1000.0,
+      'exclude_configs': []
+    }
+    for js 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
index 77ed11f..ea373ec 100644
--- a/test/cpp/qps/generic_async_streaming_ping_pong_test.cc
+++ b/test/cpp/qps/generic_async_streaming_ping_pong_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,7 @@
   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);
diff --git a/test/cpp/qps/interarrival.h b/test/cpp/qps/interarrival.h
index b6fd67b..0980d5e 100644
--- a/test/cpp/qps/interarrival.h
+++ b/test/cpp/qps/interarrival.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -82,62 +82,6 @@
   double lambda_recip_;
 };
 
-// UniformDist implements a random distribution that has
-// interarrival time uniformly spread between [lo,hi). The
-// mean interarrival time is (lo+hi)/2. For more information,
-// see http://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29
-
-class UniformDist GRPC_FINAL : public RandomDistInterface {
- public:
-  UniformDist(double lo, double hi) : lo_(lo), range_(hi - lo) {}
-  ~UniformDist() GRPC_OVERRIDE {}
-  double transform(double uni) const GRPC_OVERRIDE {
-    return uni * range_ + lo_;
-  }
-
- private:
-  double lo_;
-  double range_;
-};
-
-// DetDist provides a random distribution with interarrival time
-// of val. Note that this is not additive, so using this on multiple
-// flows of control (threads within the same client or separate
-// clients) will not preserve any deterministic interarrival gap across
-// requests.
-
-class DetDist GRPC_FINAL : public RandomDistInterface {
- public:
-  explicit DetDist(double val) : val_(val) {}
-  ~DetDist() GRPC_OVERRIDE {}
-  double transform(double uni) const GRPC_OVERRIDE { return val_; }
-
- private:
-  double val_;
-};
-
-// ParetoDist provides a random distribution with interarrival time
-// spread according to a Pareto (heavy-tailed) distribution. In this
-// model, many interarrival times are close to the base, but a sufficient
-// number will be high (up to infinity) as to disturb the mean. It is a
-// good representation of the response times of data center jobs. See
-// http://en.wikipedia.org/wiki/Pareto_distribution
-
-class ParetoDist GRPC_FINAL : public RandomDistInterface {
- public:
-  ParetoDist(double base, double alpha)
-      : base_(base), alpha_recip_(1.0 / alpha) {}
-  ~ParetoDist() GRPC_OVERRIDE {}
-  double transform(double uni) const GRPC_OVERRIDE {
-    // Note: Use 1.0-uni above to avoid div by zero if uni is 0
-    return base_ / pow(1.0 - uni, alpha_recip_);
-  }
-
- private:
-  double base_;
-  double alpha_recip_;
-};
-
 // A class library for generating pseudo-random interarrival times
 // in an efficient re-entrant way. The random table is built at construction
 // time, and each call must include the thread id of the invoker
diff --git a/test/cpp/qps/json_run_localhost.cc b/test/cpp/qps/json_run_localhost.cc
new file mode 100644
index 0000000..6545dc2
--- /dev/null
+++ b/test/cpp/qps/json_run_localhost.cc
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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 <memory>
+#include <sstream>
+#include <string>
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/support/env.h"
+#include "test/core/util/port.h"
+#include "test/cpp/util/subprocess.h"
+
+using grpc::SubProcess;
+
+template <class T>
+std::string as_string(const T& val) {
+  std::ostringstream out;
+  out << val;
+  return out.str();
+}
+
+int main(int argc, char** argv) {
+  typedef std::unique_ptr<SubProcess> SubProcessPtr;
+  std::vector<SubProcessPtr> jobs;
+
+  std::string my_bin = argv[0];
+  std::string bin_dir = my_bin.substr(0, my_bin.rfind('/'));
+
+  std::ostringstream env;
+  bool first = true;
+
+  for (int i = 0; i < 2; i++) {
+    auto port = grpc_pick_unused_port_or_die();
+    std::vector<std::string> args = {bin_dir + "/qps_worker", "-driver_port",
+                                     as_string(port)};
+    jobs.emplace_back(new SubProcess(args));
+    if (!first) env << ",";
+    env << "localhost:" << port;
+    first = false;
+  }
+
+  gpr_setenv("QPS_WORKERS", env.str().c_str());
+  std::vector<std::string> args = {bin_dir + "/qps_json_driver"};
+  for (int i = 1; i < argc; i++) {
+    args.push_back(argv[i]);
+  }
+  SubProcess(args).Join();
+
+  for (auto it = jobs.begin(); it != jobs.end(); ++it) {
+    (*it)->Interrupt();
+  }
+  for (auto it = jobs.begin(); it != jobs.end(); ++it) {
+    (*it)->Join();
+  }
+}
diff --git a/test/cpp/qps/parse_json.cc b/test/cpp/qps/parse_json.cc
new file mode 100644
index 0000000..df7a62f
--- /dev/null
+++ b/test/cpp/qps/parse_json.cc
@@ -0,0 +1,67 @@
+/*
+ *
+ * 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 <grpc++/support/config_protobuf.h>
+
+#include "test/cpp/qps/parse_json.h"
+
+#include <string>
+
+#include <google/protobuf/util/json_util.h>
+#include <google/protobuf/util/type_resolver_util.h>
+#include <grpc/support/log.h>
+
+namespace grpc {
+namespace testing {
+
+void ParseJson(const grpc::string& json, const grpc::string& type,
+               GRPC_CUSTOM_MESSAGE* msg) {
+  std::unique_ptr<google::protobuf::util::TypeResolver> type_resolver(
+      google::protobuf::util::NewTypeResolverForDescriptorPool(
+          "type.googleapis.com",
+          google::protobuf::DescriptorPool::generated_pool()));
+  grpc::string binary;
+  auto status = JsonToBinaryString(
+      type_resolver.get(), "type.googleapis.com/" + type, json, &binary);
+  if (!status.ok()) {
+    grpc::string errmsg(status.error_message());
+    gpr_log(GPR_ERROR, "Failed to convert json to binary: errcode=%d msg=%s",
+            status.error_code(), errmsg.c_str());
+    gpr_log(GPR_ERROR, "JSON: ", json.c_str());
+    abort();
+  }
+  GPR_ASSERT(msg->ParseFromString(binary));
+}
+
+}  // testing
+}  // grpc
diff --git a/test/cpp/qps/parse_json.h b/test/cpp/qps/parse_json.h
new file mode 100644
index 0000000..4b8ca79
--- /dev/null
+++ b/test/cpp/qps/parse_json.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 TEST_QPS_PARSE_JSON_H
+#define TEST_QPS_PARSE_JSON_H
+
+#include <grpc++/support/config.h>
+#include <grpc++/support/config_protobuf.h>
+
+namespace grpc {
+namespace testing {
+
+void ParseJson(const grpc::string& json, const grpc::string& type,
+               GRPC_CUSTOM_MESSAGE* msg);
+
+}  // testing
+}  // grpc
+
+#endif  // TEST_QPS_PARSE_JSON_H
diff --git a/test/cpp/qps/perf_db_client.h b/test/cpp/qps/perf_db_client.h
index ece020a..b74c70d 100644
--- a/test/cpp/qps/perf_db_client.h
+++ b/test/cpp/qps/perf_db_client.h
@@ -31,17 +31,17 @@
  *
  */
 
+#include <cfloat>
 #include <iostream>
 #include <memory>
 #include <string>
-#include <cfloat>
 
-#include <grpc/grpc.h>
-#include <grpc++/support/channel_arguments.h>
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
 #include <grpc++/security/credentials.h>
+#include <grpc++/support/channel_arguments.h>
+#include <grpc/grpc.h>
 #include "src/proto/grpc/testing/perf_db.grpc.pb.h"
 
 namespace grpc {
diff --git a/test/cpp/qps/qps-sweep.sh b/test/cpp/qps/qps-sweep.sh
deleted file mode 100755
index 9d3f053..0000000
--- a/test/cpp/qps/qps-sweep.sh
+++ /dev/null
@@ -1,170 +0,0 @@
-#!/bin/sh
-
-# 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.
-
-if [ x"$QPS_WORKERS" == x ]; then
-  echo Error: Must set QPS_WORKERS variable in form \
-    "host:port,host:port,..." 1>&2
-  exit 1
-fi
-
-bins=`find . .. ../.. ../../.. -name bins | head -1`
-
-# Print out each command that gets executed
-set -x
-
-#
-# Specify parameters used in some of the tests
-#
-
-# big is the size in bytes of large messages (0 is the size otherwise)
-big=65536
-
-# wide is the number of client channels in multi-channel tests (1 otherwise)
-wide=64
-
-# deep is the number of RPCs outstanding on a channel in non-ping-pong tests
-# (the value used is 1 otherwise)
-deep=100
-
-# half is half the count of worker processes, used in the crossbar scenario
-# that uses equal clients and servers. The other scenarios use only 1 server
-# and either 1 client or N-1 clients as appropriate
-half=`echo $QPS_WORKERS | awk -F, '{print int(NF/2)}'`
-
-for secure in true false; do
-  # Scenario 1: generic async streaming ping-pong (contentionless latency)
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=1 --bbuf_req_size=0 --bbuf_resp_size=0 \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-
-  # Scenario 2: generic async streaming "unconstrained" (QPS)
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=0 2>&1 | tee /tmp/qps-test.$$
-
-  # Scenario 2b: QPS with a single server core
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=0 --server_core_limit=1
-
-  # Scenario 2c: protobuf-based QPS
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=$wide --simple_req_size=0 --simple_resp_size=0 \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=0
-
-  # Scenario 3: Latency at sub-peak load (all clients equally loaded)
-  for loadfactor in 0.2 0.5 0.7; do
-    "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-      --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-      --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
-      --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-      --num_servers=1 --num_clients=0 --poisson_load=`awk -v lf=$loadfactor \
-      '$5 == "QPS:" {print int(lf * $6); exit}' /tmp/qps-test.$$`
-  done
-
-  rm /tmp/qps-test.$$
-
-  # Scenario 4: Single-channel bidirectional throughput test (like TCP_STREAM).
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=1 --bbuf_req_size=$big --bbuf_resp_size=$big \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-
-  # Scenario 5: Sync unary ping-pong with protobufs
-  "$bins"/opt/qps_driver --rpc_type=UNARY --client_type=SYNC_CLIENT \
-    --server_type=SYNC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \
-    --secure_test=$secure --num_servers=1 --num_clients=1
-
-  # Scenario 6: Sync streaming ping-pong with protobufs
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=SYNC_CLIENT \
-    --server_type=SYNC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \
-    --secure_test=$secure --num_servers=1 --num_clients=1
-
-  # Scenario 7: Async unary ping-pong with protobufs
-  "$bins"/opt/qps_driver --rpc_type=UNARY --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-
-  # Scenario 8: Async streaming ping-pong with protobufs
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-
-  # Scenario 9: Crossbar QPS test
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=$half --num_clients=0
-
-  # Scenario 10: Multi-channel bidir throughput test
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=$wide --bbuf_req_size=$big --bbuf_resp_size=$big \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-
-  # Scenario 11: Single-channel request throughput test
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=1 --bbuf_req_size=$big --bbuf_resp_size=0 \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-
-  # Scenario 12: Single-channel response throughput test
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=1 --bbuf_req_size=0 --bbuf_resp_size=$big \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-
-  # Scenario 13: Single-channel bidirectional protobuf throughput test
-  "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=1 --simple_req_size=$big --simple_resp_size=$big \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1
-done
diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc
deleted file mode 100644
index 69fb4d7..0000000
--- a/test/cpp/qps/qps_driver.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- *
- * 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 <memory>
-#include <set>
-
-#include <gflags/gflags.h>
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-#include "test/cpp/util/benchmark_config.h"
-
-DEFINE_int32(num_clients, 1, "Number of client binaries");
-DEFINE_int32(num_servers, 1, "Number of server binaries");
-
-DEFINE_int32(warmup_seconds, 5, "Warmup time (in seconds)");
-DEFINE_int32(benchmark_seconds, 30, "Benchmark time (in seconds)");
-DEFINE_int32(local_workers, 0, "Number of local workers to start");
-
-// Server config
-DEFINE_int32(async_server_threads, 1, "Number of threads for async servers");
-DEFINE_string(server_type, "SYNC_SERVER", "Server type");
-DEFINE_int32(server_core_limit, -1, "Limit on server cores to use");
-
-// Client config
-DEFINE_string(rpc_type, "UNARY", "Type of RPC: UNARY or STREAMING");
-DEFINE_int32(outstanding_rpcs_per_channel, 1,
-             "Number of outstanding rpcs per channel");
-DEFINE_int32(client_channels, 1, "Number of client channels");
-
-DEFINE_int32(simple_req_size, -1, "Simple proto request payload size");
-DEFINE_int32(simple_resp_size, -1, "Simple proto response payload size");
-DEFINE_int32(bbuf_req_size, -1, "Byte-buffer request payload size");
-DEFINE_int32(bbuf_resp_size, -1, "Byte-buffer response payload size");
-
-DEFINE_string(client_type, "SYNC_CLIENT", "Client type");
-DEFINE_int32(async_client_threads, 1, "Async client threads");
-
-DEFINE_double(poisson_load, -1.0, "Poisson offered load (qps)");
-DEFINE_double(uniform_lo, -1.0, "Uniform low interarrival time (us)");
-DEFINE_double(uniform_hi, -1.0, "Uniform high interarrival time (us)");
-DEFINE_double(determ_load, -1.0, "Deterministic offered load (qps)");
-DEFINE_double(pareto_base, -1.0, "Pareto base interarrival time (us)");
-DEFINE_double(pareto_alpha, -1.0, "Pareto alpha value");
-
-DEFINE_int32(client_core_limit, -1, "Limit on client cores to use");
-
-DEFINE_bool(secure_test, false, "Run a secure test");
-
-DEFINE_bool(quit, false, "Quit the workers");
-
-using grpc::testing::ClientConfig;
-using grpc::testing::ServerConfig;
-using grpc::testing::ClientType;
-using grpc::testing::ServerType;
-using grpc::testing::RpcType;
-using grpc::testing::ResourceUsage;
-using grpc::testing::SecurityParams;
-
-namespace grpc {
-namespace testing {
-
-static void QpsDriver() {
-  if (FLAGS_quit) {
-    RunQuit();
-    return;
-  }
-
-  RpcType rpc_type;
-  GPR_ASSERT(RpcType_Parse(FLAGS_rpc_type, &rpc_type));
-
-  ClientType client_type;
-  ServerType server_type;
-  GPR_ASSERT(ClientType_Parse(FLAGS_client_type, &client_type));
-  GPR_ASSERT(ServerType_Parse(FLAGS_server_type, &server_type));
-
-  ClientConfig client_config;
-  client_config.set_client_type(client_type);
-  client_config.set_outstanding_rpcs_per_channel(
-      FLAGS_outstanding_rpcs_per_channel);
-  client_config.set_client_channels(FLAGS_client_channels);
-
-  // Decide which type to use based on the response type
-  if (FLAGS_simple_resp_size >= 0) {
-    auto params =
-        client_config.mutable_payload_config()->mutable_simple_params();
-    params->set_resp_size(FLAGS_simple_resp_size);
-    if (FLAGS_simple_req_size >= 0) {
-      params->set_req_size(FLAGS_simple_req_size);
-    }
-  } else if (FLAGS_bbuf_resp_size >= 0) {
-    auto params =
-        client_config.mutable_payload_config()->mutable_bytebuf_params();
-    params->set_resp_size(FLAGS_bbuf_resp_size);
-    if (FLAGS_bbuf_req_size >= 0) {
-      params->set_req_size(FLAGS_bbuf_req_size);
-    }
-  } else {
-    // set a reasonable default: proto but no payload
-    client_config.mutable_payload_config()->mutable_simple_params();
-  }
-
-  client_config.set_async_client_threads(FLAGS_async_client_threads);
-  client_config.set_rpc_type(rpc_type);
-
-  // set up the load parameters
-  if (FLAGS_poisson_load > 0.0) {
-    auto poisson = client_config.mutable_load_params()->mutable_poisson();
-    poisson->set_offered_load(FLAGS_poisson_load);
-  } else if (FLAGS_uniform_lo > 0.0) {
-    auto uniform = client_config.mutable_load_params()->mutable_uniform();
-    uniform->set_interarrival_lo(FLAGS_uniform_lo / 1e6);
-    uniform->set_interarrival_hi(FLAGS_uniform_hi / 1e6);
-  } else if (FLAGS_determ_load > 0.0) {
-    auto determ = client_config.mutable_load_params()->mutable_determ();
-    determ->set_offered_load(FLAGS_determ_load);
-  } else if (FLAGS_pareto_base > 0.0) {
-    auto pareto = client_config.mutable_load_params()->mutable_pareto();
-    pareto->set_interarrival_base(FLAGS_pareto_base / 1e6);
-    pareto->set_alpha(FLAGS_pareto_alpha);
-  } else {
-    client_config.mutable_load_params()->mutable_closed_loop();
-    // No further load parameters to set up for closed loop
-  }
-
-  client_config.mutable_histogram_params()->set_resolution(
-      Histogram::default_resolution());
-  client_config.mutable_histogram_params()->set_max_possible(
-      Histogram::default_max_possible());
-
-  if (FLAGS_client_core_limit > 0) {
-    client_config.set_core_limit(FLAGS_client_core_limit);
-  }
-
-  ServerConfig server_config;
-  server_config.set_server_type(server_type);
-  server_config.set_async_server_threads(FLAGS_async_server_threads);
-
-  if (FLAGS_server_core_limit > 0) {
-    server_config.set_core_limit(FLAGS_server_core_limit);
-  }
-
-  if (FLAGS_secure_test) {
-    // Set up security params
-    SecurityParams security;
-    security.set_use_test_ca(true);
-    security.set_server_host_override("foo.test.google.fr");
-    client_config.mutable_security_params()->CopyFrom(security);
-    server_config.mutable_security_params()->CopyFrom(security);
-  }
-
-  // Make sure that if we are performing a generic (bytebuf) test
-  // that we are also using async streaming
-  GPR_ASSERT(!client_config.payload_config().has_bytebuf_params() ||
-             (client_config.client_type() == ASYNC_CLIENT &&
-              client_config.rpc_type() == STREAMING &&
-              server_config.server_type() == ASYNC_GENERIC_SERVER));
-
-  const auto result = RunScenario(
-      client_config, FLAGS_num_clients, server_config, FLAGS_num_servers,
-      FLAGS_warmup_seconds, FLAGS_benchmark_seconds, FLAGS_local_workers);
-
-  GetReporter()->ReportQPS(*result);
-  GetReporter()->ReportQPSPerCore(*result);
-  GetReporter()->ReportLatency(*result);
-  GetReporter()->ReportTimes(*result);
-}
-
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc::testing::QpsDriver();
-
-  return 0;
-}
diff --git a/test/cpp/qps/qps_interarrival_test.cc b/test/cpp/qps/qps_interarrival_test.cc
index 77e81fb..4055c8a 100644
--- a/test/cpp/qps/qps_interarrival_test.cc
+++ b/test/cpp/qps/qps_interarrival_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,14 +63,8 @@
 }
 
 using grpc::testing::ExpDist;
-using grpc::testing::DetDist;
-using grpc::testing::UniformDist;
-using grpc::testing::ParetoDist;
 
 int main(int argc, char **argv) {
   RunTest(ExpDist(10.0), 5, std::string("Exponential(10)"));
-  RunTest(DetDist(5.0), 5, std::string("Det(5)"));
-  RunTest(UniformDist(0.0, 10.0), 5, std::string("Uniform(0,10)"));
-  RunTest(ParetoDist(1.0, 1.0), 5, std::string("Pareto(1,1)"));
   return 0;
 }
diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc
new file mode 100644
index 0000000..d7642f0
--- /dev/null
+++ b/test/cpp/qps/qps_json_driver.cc
@@ -0,0 +1,124 @@
+/*
+ *
+ * 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 <memory>
+#include <set>
+
+#include <grpc++/support/config_protobuf.h>
+
+#include <gflags/gflags.h>
+#include <grpc/support/log.h>
+
+#include "test/cpp/qps/driver.h"
+#include "test/cpp/qps/parse_json.h"
+#include "test/cpp/qps/report.h"
+#include "test/cpp/util/benchmark_config.h"
+
+DEFINE_string(scenarios_file, "",
+              "JSON file containing an array of Scenario objects");
+DEFINE_string(scenarios_json, "",
+              "JSON string containing an array of Scenario objects");
+DEFINE_bool(quit, false, "Quit the workers");
+
+namespace grpc {
+namespace testing {
+
+static void QpsDriver() {
+  grpc::string json;
+
+  bool scfile = (FLAGS_scenarios_file != "");
+  bool scjson = (FLAGS_scenarios_json != "");
+  if ((!scfile && !scjson && !FLAGS_quit) ||
+      (scfile && (scjson || FLAGS_quit)) || (scjson && FLAGS_quit)) {
+    gpr_log(GPR_ERROR,
+            "Exactly one of --scenarios_file, --scenarios_json, "
+            "or --quit must be set");
+    abort();
+  }
+
+  if (scfile) {
+    // Read the json data from disk
+    FILE *json_file = fopen(FLAGS_scenarios_file.c_str(), "r");
+    GPR_ASSERT(json_file != NULL);
+    fseek(json_file, 0, SEEK_END);
+    long len = ftell(json_file);
+    char *data = new char[len];
+    fseek(json_file, 0, SEEK_SET);
+    GPR_ASSERT(len == (long)fread(data, 1, len, json_file));
+    fclose(json_file);
+    json = grpc::string(data, data + len);
+    delete[] data;
+  } else if (scjson) {
+    json = FLAGS_scenarios_json.c_str();
+  } else if (FLAGS_quit) {
+    RunQuit();
+    return;
+  }
+
+  // Parse into an array of scenarios
+  Scenarios scenarios;
+  ParseJson(json.c_str(), "grpc.testing.Scenarios", &scenarios);
+
+  // Make sure that there is at least some valid scenario here
+  GPR_ASSERT(scenarios.scenarios_size() > 0);
+
+  for (int i = 0; i < scenarios.scenarios_size(); i++) {
+    const Scenario &scenario = scenarios.scenarios(i);
+    std::cerr << "RUNNING SCENARIO: " << scenario.name() << "\n";
+    auto result =
+        RunScenario(scenario.client_config(), scenario.num_clients(),
+                    scenario.server_config(), scenario.num_servers(),
+                    scenario.warmup_seconds(), scenario.benchmark_seconds(),
+                    scenario.spawn_local_worker_count());
+
+    // Amend the result with scenario config. Eventually we should adjust
+    // RunScenario contract so we don't need to touch the result here.
+    result->mutable_scenario()->CopyFrom(scenario);
+
+    GetReporter()->ReportQPS(*result);
+    GetReporter()->ReportQPSPerCore(*result);
+    GetReporter()->ReportLatency(*result);
+    GetReporter()->ReportTimes(*result);
+  }
+}
+
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char **argv) {
+  grpc::testing::InitBenchmark(&argc, &argv, true);
+
+  grpc::testing::QpsDriver();
+
+  return 0;
+}
diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc
index 2ae0afb..8dc50ac 100644
--- a/test/cpp/qps/qps_openloop_test.cc
+++ b/test/cpp/qps/qps_openloop_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/qps_test.cc b/test/cpp/qps/qps_test.cc
index b6a2e1e..c3e72d9 100644
--- a/test/cpp/qps/qps_test.cc
+++ b/test/cpp/qps/qps_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/qps_test_with_poll.cc b/test/cpp/qps/qps_test_with_poll.cc
index 8340a63..c64e6c9 100644
--- a/test/cpp/qps/qps_test_with_poll.cc
+++ b/test/cpp/qps/qps_test_with_poll.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@
 #include "test/cpp/util/benchmark_config.h"
 
 extern "C" {
-#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/lib/iomgr/pollset_posix.h"
 }
 
 namespace grpc {
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index b83e9d1..f514e23 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/qps_worker.h b/test/cpp/qps/qps_worker.h
index 624c182..7f04c92 100644
--- a/test/cpp/qps/qps_worker.h
+++ b/test/cpp/qps/qps_worker.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index b230eb4..3ae4139 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -33,6 +33,11 @@
 
 #include "test/cpp/qps/report.h"
 
+#include <fstream>
+
+#include <google/protobuf/util/json_util.h>
+#include <google/protobuf/util/type_resolver_util.h>
+
 #include <grpc/support/log.h>
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/stats.h"
@@ -40,11 +45,6 @@
 namespace grpc {
 namespace testing {
 
-static double WallTime(ResourceUsage u) { return u.wall_time(); }
-static double UserTime(ResourceUsage u) { return u.user_time(); }
-static double SystemTime(ResourceUsage u) { return u.system_time(); }
-static int Cores(ResourceUsage u) { return u.cores(); }
-
 void CompositeReporter::add(std::unique_ptr<Reporter> reporter) {
   reporters_.emplace_back(std::move(reporter));
 }
@@ -74,102 +74,63 @@
 }
 
 void GprLogReporter::ReportQPS(const ScenarioResult& result) {
-  gpr_log(
-      GPR_INFO, "QPS: %.1f",
-      result.latencies.Count() / average(result.client_resources, WallTime));
+  gpr_log(GPR_INFO, "QPS: %.1f", result.summary().qps());
 }
 
 void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result) {
-  auto qps =
-      result.latencies.Count() / average(result.client_resources, WallTime);
-
-  gpr_log(GPR_INFO, "QPS: %.1f (%.1f/server core)", qps,
-          qps / sum(result.server_resources, Cores));
+  gpr_log(GPR_INFO, "QPS: %.1f (%.1f/server core)", result.summary().qps(),
+          result.summary().qps_per_server_core());
 }
 
 void GprLogReporter::ReportLatency(const ScenarioResult& result) {
   gpr_log(GPR_INFO,
           "Latencies (50/90/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f/%.1f us",
-          result.latencies.Percentile(50) / 1000,
-          result.latencies.Percentile(90) / 1000,
-          result.latencies.Percentile(95) / 1000,
-          result.latencies.Percentile(99) / 1000,
-          result.latencies.Percentile(99.9) / 1000);
+          result.summary().latency_50() / 1000,
+          result.summary().latency_90() / 1000,
+          result.summary().latency_95() / 1000,
+          result.summary().latency_99() / 1000,
+          result.summary().latency_999() / 1000);
 }
 
 void GprLogReporter::ReportTimes(const ScenarioResult& result) {
   gpr_log(GPR_INFO, "Server system time: %.2f%%",
-          100.0 * sum(result.server_resources, SystemTime) /
-              sum(result.server_resources, WallTime));
+          result.summary().server_system_time());
   gpr_log(GPR_INFO, "Server user time:   %.2f%%",
-          100.0 * sum(result.server_resources, UserTime) /
-              sum(result.server_resources, WallTime));
+          result.summary().server_user_time());
   gpr_log(GPR_INFO, "Client system time: %.2f%%",
-          100.0 * sum(result.client_resources, SystemTime) /
-              sum(result.client_resources, WallTime));
+          result.summary().client_system_time());
   gpr_log(GPR_INFO, "Client user time:   %.2f%%",
-          100.0 * sum(result.client_resources, UserTime) /
-              sum(result.client_resources, WallTime));
+          result.summary().client_user_time());
 }
 
-void PerfDbReporter::ReportQPS(const ScenarioResult& result) {
-  auto qps =
-      result.latencies.Count() / average(result.client_resources, WallTime);
+void JsonReporter::ReportQPS(const ScenarioResult& result) {
+  std::unique_ptr<google::protobuf::util::TypeResolver> type_resolver(
+      google::protobuf::util::NewTypeResolverForDescriptorPool(
+          "type.googleapis.com",
+          google::protobuf::DescriptorPool::generated_pool()));
+  grpc::string binary;
+  grpc::string json_string;
+  result.SerializeToString(&binary);
+  auto status = BinaryToJsonString(
+      type_resolver.get(), "type.googleapis.com/grpc.testing.ScenarioResult",
+      binary, &json_string);
+  GPR_ASSERT(status.ok());
 
-  perf_db_client_.setQps(qps);
-  perf_db_client_.setConfigs(result.client_config, result.server_config);
+  std::ofstream output_file(report_file_);
+  output_file << json_string;
+  output_file.close();
 }
 
-void PerfDbReporter::ReportQPSPerCore(const ScenarioResult& result) {
-  auto qps =
-      result.latencies.Count() / average(result.client_resources, WallTime);
-
-  auto qps_per_core = qps / sum(result.server_resources, Cores);
-
-  perf_db_client_.setQps(qps);
-  perf_db_client_.setQpsPerCore(qps_per_core);
-  perf_db_client_.setConfigs(result.client_config, result.server_config);
+void JsonReporter::ReportQPSPerCore(const ScenarioResult& result) {
+  // NOP - all reporting is handled by ReportQPS.
 }
 
-void PerfDbReporter::ReportLatency(const ScenarioResult& result) {
-  perf_db_client_.setLatencies(result.latencies.Percentile(50) / 1000,
-                               result.latencies.Percentile(90) / 1000,
-                               result.latencies.Percentile(95) / 1000,
-                               result.latencies.Percentile(99) / 1000,
-                               result.latencies.Percentile(99.9) / 1000);
-  perf_db_client_.setConfigs(result.client_config, result.server_config);
+void JsonReporter::ReportLatency(const ScenarioResult& result) {
+  // NOP - all reporting is handled by ReportQPS.
 }
 
-void PerfDbReporter::ReportTimes(const ScenarioResult& result) {
-  const double server_system_time = 100.0 *
-                                    sum(result.server_resources, SystemTime) /
-                                    sum(result.server_resources, WallTime);
-  const double server_user_time = 100.0 *
-                                  sum(result.server_resources, UserTime) /
-                                  sum(result.server_resources, WallTime);
-  const double client_system_time = 100.0 *
-                                    sum(result.client_resources, SystemTime) /
-                                    sum(result.client_resources, WallTime);
-  const double client_user_time = 100.0 *
-                                  sum(result.client_resources, UserTime) /
-                                  sum(result.client_resources, WallTime);
-
-  perf_db_client_.setTimes(server_system_time, server_user_time,
-                           client_system_time, client_user_time);
-  perf_db_client_.setConfigs(result.client_config, result.server_config);
-}
-
-void PerfDbReporter::SendData() {
-  // send data to performance database
-  bool data_state =
-      perf_db_client_.sendData(hashed_id_, test_name_, sys_info_, tag_);
-
-  // check state of data sending
-  if (data_state) {
-    gpr_log(GPR_INFO, "Data sent to performance database successfully");
-  } else {
-    gpr_log(GPR_INFO, "Data could not be sent to performance database");
-  }
+void JsonReporter::ReportTimes(const ScenarioResult& result) {
+  // NOP - all reporting is handled by ReportQPS.
 }
 
 }  // namespace testing
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index 5caf3fe..8f04d84 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -104,33 +104,19 @@
   void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
 };
 
-/** Reporter for performance database tool */
-class PerfDbReporter : public Reporter {
+/** Dumps the report to a JSON file. */
+class JsonReporter : public Reporter {
  public:
-  PerfDbReporter(const string& name, const string& hashed_id,
-                 const string& test_name, const string& sys_info,
-                 const string& server_address, const string& tag)
-      : Reporter(name),
-        hashed_id_(hashed_id),
-        test_name_(test_name),
-        sys_info_(sys_info),
-        tag_(tag) {
-    perf_db_client_.init(grpc::CreateChannel(
-        server_address, grpc::InsecureChannelCredentials()));
-  }
-  ~PerfDbReporter() GRPC_OVERRIDE { SendData(); };
+  JsonReporter(const string& name, const string& report_file)
+      : Reporter(name), report_file_(report_file) {}
 
  private:
-  PerfDbClient perf_db_client_;
-  std::string hashed_id_;
-  std::string test_name_;
-  std::string sys_info_;
-  std::string tag_;
   void ReportQPS(const ScenarioResult& result) GRPC_OVERRIDE;
   void ReportQPSPerCore(const ScenarioResult& result) GRPC_OVERRIDE;
   void ReportLatency(const ScenarioResult& result) GRPC_OVERRIDE;
   void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
-  void SendData();
+
+  const string report_file_;
 };
 
 }  // namespace testing
diff --git a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
index 946c76f..d0c47d1 100644
--- a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
+++ b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h
index de46452..e8bc396 100644
--- a/test/cpp/qps/server.h
+++ b/test/cpp/qps/server.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index d7b3f76..a68f1ae 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -387,12 +387,14 @@
 }
 
 std::unique_ptr<Server> CreateAsyncServer(const ServerConfig &config) {
-  return std::unique_ptr<Server>(new AsyncQpsServerTest<
-      SimpleRequest, SimpleResponse, BenchmarkService::AsyncService,
-      grpc::ServerContext>(
-      config, RegisterBenchmarkService,
-      &BenchmarkService::AsyncService::RequestUnaryCall,
-      &BenchmarkService::AsyncService::RequestStreamingCall, ProcessSimpleRPC));
+  return std::unique_ptr<Server>(
+      new AsyncQpsServerTest<SimpleRequest, SimpleResponse,
+                             BenchmarkService::AsyncService,
+                             grpc::ServerContext>(
+          config, RegisterBenchmarkService,
+          &BenchmarkService::AsyncService::RequestUnaryCall,
+          &BenchmarkService::AsyncService::RequestStreamingCall,
+          ProcessSimpleRPC));
 }
 std::unique_ptr<Server> CreateAsyncGenericServer(const ServerConfig &config) {
   return std::unique_ptr<Server>(
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index b7682f5..9e64f47 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh
deleted file mode 100755
index f5356f1..0000000
--- a/test/cpp/qps/single_run_localhost.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/sh
-# 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.
-
-# performs a single qps run with one client and one server
-
-set -ex
-
-cd $(dirname $0)/../../..
-
-killall qps_worker || true
-
-config=opt
-
-NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'`
-
-make CONFIG=$config qps_worker qps_driver -j$NUMCPUS
-
-bins/$config/qps_worker -driver_port 10000 &
-PID1=$!
-bins/$config/qps_worker -driver_port 10010 &
-PID2=$!
-
-export QPS_WORKERS="localhost:10000,localhost:10010"
-
-bins/$config/qps_driver $*
-
-kill -2 $PID1 $PID2
-wait
-
diff --git a/test/cpp/qps/sync_streaming_ping_pong_test.cc b/test/cpp/qps/sync_streaming_ping_pong_test.cc
index ee1bbc7..67c62f4 100644
--- a/test/cpp/qps/sync_streaming_ping_pong_test.cc
+++ b/test/cpp/qps/sync_streaming_ping_pong_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/sync_unary_ping_pong_test.cc b/test/cpp/qps/sync_unary_ping_pong_test.cc
index 4dccfee..aa0c0c3 100644
--- a/test/cpp/qps/sync_unary_ping_pong_test.cc
+++ b/test/cpp/qps/sync_unary_ping_pong_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/usage_timer.cc b/test/cpp/qps/usage_timer.cc
index 6663a9a..ff595b2 100644
--- a/test/cpp/qps/usage_timer.cc
+++ b/test/cpp/qps/usage_timer.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/usage_timer.h b/test/cpp/qps/usage_timer.h
index d19f820..8343cd6 100644
--- a/test/cpp/qps/usage_timer.h
+++ b/test/cpp/qps/usage_timer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc
index f42cfe3..2068b7c 100644
--- a/test/cpp/qps/worker.cc
+++ b/test/cpp/qps/worker.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/util/benchmark_config.cc b/test/cpp/util/benchmark_config.cc
index 3c38221..6fc8640 100644
--- a/test/cpp/util/benchmark_config.cc
+++ b/test/cpp/util/benchmark_config.cc
@@ -31,14 +31,14 @@
  *
  */
 
-#include <gflags/gflags.h>
 #include "test/cpp/util/benchmark_config.h"
+#include <gflags/gflags.h>
 
 DEFINE_bool(enable_log_reporter, true,
             "Enable reporting of benchmark results through GprLog");
 
-DEFINE_bool(report_metrics_db, false,
-            "True if metrics to be reported to performance database");
+DEFINE_string(scenario_result_file, "",
+              "Write JSON benchmark report to the file specified.");
 
 DEFINE_string(hashed_id, "", "Hash of the user id");
 
@@ -71,10 +71,9 @@
     composite_reporter->add(
         std::unique_ptr<Reporter>(new GprLogReporter("LogReporter")));
   }
-  if (FLAGS_report_metrics_db) {
+  if (FLAGS_scenario_result_file != "") {
     composite_reporter->add(std::unique_ptr<Reporter>(
-        new PerfDbReporter("PerfDbReporter", FLAGS_hashed_id, FLAGS_test_name,
-                           FLAGS_sys_info, FLAGS_server_address, FLAGS_tag)));
+        new JsonReporter("JsonReporter", FLAGS_scenario_result_file)));
   }
 
   return std::shared_ptr<Reporter>(composite_reporter);
diff --git a/test/cpp/util/byte_buffer_test.cc b/test/cpp/util/byte_buffer_test.cc
index f36c32c..1167c79 100644
--- a/test/cpp/util/byte_buffer_test.cc
+++ b/test/cpp/util/byte_buffer_test.cc
@@ -36,8 +36,8 @@
 #include <cstring>
 #include <vector>
 
-#include <grpc/support/slice.h>
 #include <grpc++/support/slice.h>
+#include <grpc/support/slice.h>
 #include <gtest/gtest.h>
 
 namespace grpc {
@@ -105,6 +105,24 @@
   EXPECT_TRUE(SliceEqual(slices[1], world));
 }
 
+TEST_F(ByteBufferTest, SerializationMakesCopy) {
+  gpr_slice hello = gpr_slice_from_copied_string(kContent1);
+  gpr_slice world = gpr_slice_from_copied_string(kContent2);
+  std::vector<Slice> slices;
+  slices.push_back(Slice(hello, Slice::STEAL_REF));
+  slices.push_back(Slice(world, Slice::STEAL_REF));
+  grpc_byte_buffer* send_buffer = nullptr;
+  bool owned = false;
+  ByteBuffer buffer(&slices[0], 2);
+  slices.clear();
+  auto status = SerializationTraits<ByteBuffer, void>::Serialize(
+      buffer, &send_buffer, &owned);
+  EXPECT_TRUE(status.ok());
+  EXPECT_TRUE(owned);
+  EXPECT_TRUE(send_buffer != nullptr);
+  grpc_byte_buffer_destroy(send_buffer);
+}
+
 }  // namespace
 }  // namespace grpc
 
diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc
index d452be3..99fad7f 100644
--- a/test/cpp/util/cli_call.cc
+++ b/test/cpp/util/cli_call.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 5fdf519..75e90f8 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,18 +33,18 @@
 
 #include "test/cpp/util/cli_call.h"
 
-#include <grpc/grpc.h>
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
+#include <grpc/grpc.h>
 #include <gtest/gtest.h>
 
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
-#include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/cpp/util/string_ref_helper.h"
 
 using grpc::testing::EchoRequest;
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index 0cd9f9e..fe8b5d5 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.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
@@ -58,8 +58,9 @@
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
     bool enable_ssl, bool use_prod_roots,
-    const std::shared_ptr<CallCredentials>& creds) {
-  ChannelArguments channel_args;
+    const std::shared_ptr<CallCredentials>& creds,
+    const ChannelArguments& args) {
+  ChannelArguments channel_args(args);
   if (enable_ssl) {
     const char* roots_certs = use_prod_roots ? "" : test_root_cert;
     SslCredentialsOptions ssl_opts = {roots_certs, "", ""};
@@ -83,6 +84,14 @@
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
+    bool enable_ssl, bool use_prod_roots,
+    const std::shared_ptr<CallCredentials>& creds) {
+  return CreateTestChannel(server, override_hostname, enable_ssl,
+                           use_prod_roots, creds, ChannelArguments());
+}
+
+std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, const grpc::string& override_hostname,
     bool enable_ssl, bool use_prod_roots) {
   return CreateTestChannel(server, override_hostname, enable_ssl,
                            use_prod_roots, std::shared_ptr<CallCredentials>());
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index b50d653..4ff666d 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.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
@@ -53,6 +53,12 @@
     bool enable_ssl, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds);
 
+std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, const grpc::string& override_hostname,
+    bool enable_ssl, bool use_prod_roots,
+    const std::shared_ptr<CallCredentials>& creds,
+    const ChannelArguments& args);
+
 }  // namespace grpc
 
 #endif  // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index f9b9f0c..68cf411 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -65,11 +65,11 @@
 #include <sstream>
 
 #include <gflags/gflags.h>
-#include <grpc/grpc.h>
 #include <grpc++/channel.h>
 #include <grpc++/create_channel.h>
 #include <grpc++/security/credentials.h>
 #include <grpc++/support/string_ref.h>
+#include <grpc/grpc.h>
 
 #include "test/cpp/util/cli_call.h"
 #include "test/cpp/util/string_ref_helper.h"
diff --git a/test/cpp/util/metrics_server.cc b/test/cpp/util/metrics_server.cc
index 34d51eb..d9b44a6 100644
--- a/test/cpp/util/metrics_server.cc
+++ b/test/cpp/util/metrics_server.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/util/subprocess.cc b/test/cpp/util/subprocess.cc
index 33f3820..00c6244 100644
--- a/test/cpp/util/subprocess.cc
+++ b/test/cpp/util/subprocess.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,15 +39,15 @@
 
 namespace grpc {
 
-static gpr_subprocess *MakeProcess(std::initializer_list<std::string> args) {
-  std::vector<const char *> vargs;
+static gpr_subprocess* MakeProcess(const std::vector<std::string>& args) {
+  std::vector<const char*> vargs;
   for (auto it = args.begin(); it != args.end(); ++it) {
     vargs.push_back(it->c_str());
   }
   return gpr_subprocess_create(vargs.size(), &vargs[0]);
 }
 
-SubProcess::SubProcess(std::initializer_list<std::string> args)
+SubProcess::SubProcess(const std::vector<std::string>& args)
     : subprocess_(MakeProcess(args)) {}
 
 SubProcess::~SubProcess() { gpr_subprocess_destroy(subprocess_); }
diff --git a/test/cpp/util/subprocess.h b/test/cpp/util/subprocess.h
index 8fafe3d..f7b553a 100644
--- a/test/cpp/util/subprocess.h
+++ b/test/cpp/util/subprocess.h
@@ -36,6 +36,7 @@
 
 #include <initializer_list>
 #include <string>
+#include <vector>
 
 struct gpr_subprocess;
 
@@ -43,7 +44,7 @@
 
 class SubProcess {
  public:
-  SubProcess(std::initializer_list<std::string> args);
+  SubProcess(const std::vector<std::string>& args);
   ~SubProcess();
 
   int Join();
diff --git a/test/cpp/util/test_config.cc b/test/cpp/util/test_config.cc
index e74f8fb..8711746 100644
--- a/test/cpp/util/test_config.cc
+++ b/test/cpp/util/test_config.cc
@@ -31,8 +31,8 @@
  *
  */
 
-#include <gflags/gflags.h>
 #include "test/cpp/util/test_config.h"
+#include <gflags/gflags.h>
 
 // In some distros, gflags is in the namespace google, and in some others,
 // in gflags. This hack is enabling us to find both.
diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc
index e314fd6..9c09a73 100644
--- a/test/cpp/util/test_credentials_provider.cc
+++ b/test/cpp/util/test_credentials_provider.cc
@@ -36,8 +36,8 @@
 
 #include <unordered_map>
 
-#include <grpc/support/sync.h>
 #include <grpc++/impl/sync.h>
+#include <grpc/support/sync.h>
 
 #include "test/core/end2end/data/ssl_test_data.h"
 
diff --git a/test/cpp/util/time_test.cc b/test/cpp/util/time_test.cc
index 48c6ce7..a292c21 100644
--- a/test/cpp/util/time_test.cc
+++ b/test/cpp/util/time_test.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,8 @@
  *
  */
 
-#include <grpc/support/time.h>
 #include <grpc++/support/time.h>
+#include <grpc/support/time.h>
 #include <gtest/gtest.h>
 
 using std::chrono::duration_cast;
diff --git a/test/distrib/csharp/DistribTest/Program.cs b/test/distrib/csharp/DistribTest/Program.cs
index e944648..c68b380 100644
--- a/test/distrib/csharp/DistribTest/Program.cs
+++ b/test/distrib/csharp/DistribTest/Program.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015-2016, Google Inc.
+// Copyright 2015, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
diff --git a/test/distrib/csharp/run_distrib_test.sh b/test/distrib/csharp/run_distrib_test.sh
index 934174a..64e98d8 100755
--- a/test/distrib/csharp/run_distrib_test.sh
+++ b/test/distrib/csharp/run_distrib_test.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/test/distrib/csharp/update_version.sh b/test/distrib/csharp/update_version.sh
index b0d0772..189d0ad 100755
--- a/test/distrib/csharp/update_version.sh
+++ b/test/distrib/csharp/update_version.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/test/distrib/node/distrib_test.js b/test/distrib/node/distrib_test.js
index cdd8eba..8efd33a 100755
--- a/test/distrib/node/distrib_test.js
+++ b/test/distrib/node/distrib_test.js
@@ -1,7 +1,7 @@
 #!/usr/bin/env node
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/distrib/node/run_distrib_test.sh b/test/distrib/node/run_distrib_test.sh
index 9b8f157..d429eb2 100755
--- a/test/distrib/node/run_distrib_test.sh
+++ b/test/distrib/node/run_distrib_test.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -28,23 +28,31 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+function finish() {
+  rv=$?
+  kill $STATIC_PID || true
+  curl "localhost:32767/drop/$STATIC_PORT" || true
+  exit $rv
+}
+
+trap finish EXIT
+
 NODE_VERSION=$1
 source ~/.nvm/nvm.sh
-set -ex
 
 cd $(dirname $0)
 
 nvm install $NODE_VERSION
+set -ex
 
 npm install -g node-static
 
-# Kill off existing static servers
-kill -9 $(ps aux | grep '[n]ode .*static' | awk '{print $2}') || true
-
 STATIC_SERVER=127.0.0.1
-STATIC_PORT=8080
+# If port_server is running, get port from that. Otherwise, assume we're in
+# docker and use 8080
+STATIC_PORT=$(curl 'localhost:32767/get' || echo '8080')
 
-# Serves the input_artifacts directory statically at localhost:8080
+# Serves the input_artifacts directory statically at localhost:
 static "$EXTERNAL_GIT_ROOT/input_artifacts" -a $STATIC_SERVER -p $STATIC_PORT &
 STATIC_PID=$!
 
@@ -52,6 +60,4 @@
 
 npm install --unsafe-perm $STATIC_URL/grpc.tgz --grpc_node_binary_host_mirror=$STATIC_URL
 
-kill -9 $STATIC_PID
-
 ./distrib_test.js
diff --git a/test/distrib/php/run_distrib_test.sh b/test/distrib/php/run_distrib_test.sh
index 43b28d8..5c86283 100755
--- a/test/distrib/php/run_distrib_test.sh
+++ b/test/distrib/php/run_distrib_test.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/test/distrib/python/run_distrib_test.sh b/test/distrib/python/run_distrib_test.sh
index 8fd7ffb..79893af 100755
--- a/test/distrib/python/run_distrib_test.sh
+++ b/test/distrib/python/run_distrib_test.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/test/distrib/ruby/run_distrib_test.sh b/test/distrib/ruby/run_distrib_test.sh
index be60e44..b0954b0 100755
--- a/test/distrib/ruby/run_distrib_test.sh
+++ b/test/distrib/ruby/run_distrib_test.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/third_party/boringssl b/third_party/boringssl
index 907ae62..c880e42 160000
--- a/third_party/boringssl
+++ b/third_party/boringssl
@@ -1 +1 @@
-Subproject commit 907ae62b9d81121cb86b604f83e6b811a43f7a87
+Subproject commit c880e42ba1c8032d4cdde2aba0541d8a9d9fa2e9
diff --git a/tools/buildgen/build-cleaner.py b/tools/buildgen/build-cleaner.py
index 12054da..f09a01f 100755
--- a/tools/buildgen/build-cleaner.py
+++ b/tools/buildgen/build-cleaner.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/buildgen/bunch.py b/tools/buildgen/bunch.py
index 3f5af53..9d9dafa 100755
--- a/tools/buildgen/bunch.py
+++ b/tools/buildgen/bunch.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/buildgen/generate_build_additions.sh b/tools/buildgen/generate_build_additions.sh
index 4e7ba9e..9a1a7a7 100644
--- a/tools/buildgen/generate_build_additions.sh
+++ b/tools/buildgen/generate_build_additions.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,8 @@
   src/zlib             \
   test/core/bad_client \
   test/core/bad_ssl    \
-  test/core/end2end"
+  test/core/end2end    \
+  test/cpp/qps"
 gen_build_files=""
 for gen_build_yaml in $gen_build_yaml_dirs
 do
@@ -42,4 +43,3 @@
   $gen_build_yaml/gen_build_yaml.py > $output_file
   gen_build_files="$gen_build_files $output_file"
 done
-
diff --git a/tools/buildgen/generate_projects.py b/tools/buildgen/generate_projects.py
index 0602d93..5e78ad5 100755
--- a/tools/buildgen/generate_projects.py
+++ b/tools/buildgen/generate_projects.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2.7
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
 argp = argparse.ArgumentParser()
 argp.add_argument('build_files', nargs='+', default=[])
 argp.add_argument('--templates', nargs='+', default=[])
+argp.add_argument('--output_merged', default=None, type=str)
 argp.add_argument('--jobs', '-j', default=multiprocessing.cpu_count(), type=int)
 args = argp.parse_args()
 
@@ -74,6 +75,9 @@
 cmd.append('-w')
 preprocessed_build = '.preprocessed_build'
 cmd.append(preprocessed_build)
+if args.output_merged is not None:
+  cmd.append('-M')
+  cmd.append(args.output_merged)
 pre_jobs.append(jobset.JobSpec(cmd, shortname='preprocess', timeout_seconds=None))
 
 jobs = []
diff --git a/tools/buildgen/mako_renderer.py b/tools/buildgen/mako_renderer.py
index 5f23f12..866e6fd 100755
--- a/tools/buildgen/mako_renderer.py
+++ b/tools/buildgen/mako_renderer.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -81,9 +81,10 @@
   plugins = []
   output_name = None
   got_preprocessed_input = False
+  output_merged = None
 
   try:
-    opts, args = getopt.getopt(argv, 'hm:d:o:p:t:P:w:')
+    opts, args = getopt.getopt(argv, 'hM:m:d:o:p:t:P:w:')
   except getopt.GetoptError:
     out('Unknown option')
     showhelp()
@@ -107,6 +108,12 @@
         showhelp()
         sys.exit(4)
       module_directory = arg
+    elif opt == '-M':
+      if output_merged is not None:
+        out('Got more than one output merged path')
+        showhelp()
+        sys.exit(5)
+      output_merged = arg
     elif opt == '-P':
       assert not got_preprocessed_input
       assert json_dict == {}
@@ -126,6 +133,9 @@
   if not got_preprocessed_input:
     for plugin in plugins:
       plugin.mako_plugin(json_dict)
+    if output_merged:
+      with open(output_merged, 'w') as yaml_file:
+        yaml_file.write(yaml.dump(json_dict))
     for k, v in json_dict.items():
       dictionary[k] = bunch.to_bunch(v)
 
diff --git a/tools/buildgen/plugins/expand_bin_attrs.py b/tools/buildgen/plugins/expand_bin_attrs.py
index c30df2a..dc72bf3 100755
--- a/tools/buildgen/plugins/expand_bin_attrs.py
+++ b/tools/buildgen/plugins/expand_bin_attrs.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/buildgen/plugins/expand_filegroups.py b/tools/buildgen/plugins/expand_filegroups.py
index 156bdc4..477e69c 100755
--- a/tools/buildgen/plugins/expand_filegroups.py
+++ b/tools/buildgen/plugins/expand_filegroups.py
@@ -42,6 +42,24 @@
   return False
 
 
+def uniquify(lst):
+  out = []
+  for el in lst:
+    if el not in out:
+      out.append(el)
+  return out
+
+
+FILEGROUP_LISTS = ['src', 'headers', 'public_headers', 'deps']
+
+
+FILEGROUP_DEFAULTS = {
+  'language': 'c',
+  'boringssl': False,
+  'zlib': False,
+}
+
+
 def mako_plugin(dictionary):
   """The exported plugin code for expand_filegroups.
 
@@ -51,24 +69,98 @@
 
   """
   libs = dictionary.get('libs')
+  targets = dictionary.get('targets')
   filegroups_list = dictionary.get('filegroups')
   filegroups = {}
 
   for fg in filegroups_list:
-    filegroups[fg['name']] = fg
+    for lst in FILEGROUP_LISTS:
+      fg[lst] = fg.get(lst, [])
+      fg['own_%s' % lst] = list(fg[lst])
+    for attr, val in FILEGROUP_DEFAULTS.iteritems():
+      if attr not in fg:
+        fg[attr] = val
 
-  for lib in libs:
+  todo = list(filegroups_list)
+  skips = 0
+
+  while todo:
+    assert skips != len(todo), "infinite loop in filegroup uses clauses"
+    # take the first element of the todo list
+    cur = todo[0]
+    todo = todo[1:]
+    # check all uses filegroups are present (if no, skip and come back later)
+    skip = False
+    for uses in cur.get('uses', []):
+      if uses not in filegroups:
+        skip = True
+    if skip:
+      skips += 1
+      todo.append(cur)
+    else:
+      skips = 0
+      assert 'plugins' not in cur
+      plugins = []
+      for uses in cur.get('uses', []):
+        for plugin in filegroups[uses]['plugins']:
+          if plugin not in plugins:
+            plugins.append(plugin)
+        for lst in FILEGROUP_LISTS:
+          vals = cur.get(lst, [])
+          vals.extend(filegroups[uses].get(lst, []))
+          cur[lst] = vals
+      cur_plugin_name = cur.get('plugin')
+      if cur_plugin_name:
+        plugins.append(cur_plugin_name)
+      cur['plugins'] = plugins
+      filegroups[cur['name']] = cur
+
+  # build reverse dependency map
+  things = {}
+  for thing in dictionary['libs'] + dictionary['targets'] + dictionary['filegroups']:
+    things[thing['name']] = thing
+    thing['used_by'] = []
+  thing_deps = lambda t: t.get('uses', []) + t.get('filegroups', []) + t.get('deps', [])
+  for thing in things.itervalues():
+    done = set()
+    todo = thing_deps(thing)
+    while todo:
+      cur = todo[0]
+      todo = todo[1:]
+      if cur in done: continue
+      things[cur]['used_by'].append(thing['name'])
+      todo.extend(thing_deps(things[cur]))
+      done.add(cur)
+
+  # the above expansion can introduce duplicate filenames: contract them here
+  for fg in filegroups.itervalues():
+    for lst in FILEGROUP_LISTS:
+      fg[lst] = uniquify(fg.get(lst, []))
+
+  for tgt in dictionary['targets']:
+    for lst in FILEGROUP_LISTS:
+      tgt[lst] = tgt.get(lst, [])
+      tgt['own_%s' % lst] = list(tgt[lst])
+
+  for lib in libs + targets:
+    assert 'plugins' not in lib
+    plugins = []
+    for lst in FILEGROUP_LISTS:
+      vals = lib.get(lst, [])
+      lib[lst] = list(vals)
+      lib['own_%s' % lst] = list(vals)
     for fg_name in lib.get('filegroups', []):
       fg = filegroups[fg_name]
-
-      src = lib.get('src', [])
-      src.extend(fg.get('src', []))
-      lib['src'] = src
-
-      headers = lib.get('headers', [])
-      headers.extend(fg.get('headers', []))
-      lib['headers'] = headers
-
-      public_headers = lib.get('public_headers', [])
-      public_headers.extend(fg.get('public_headers', []))
-      lib['public_headers'] = public_headers
+      for plugin in fg['plugins']:
+        if plugin not in plugins:
+          plugins.append(plugin)
+      for lst in FILEGROUP_LISTS:
+        vals = lib.get(lst, [])
+        vals.extend(fg.get(lst, []))
+        lib[lst] = vals
+      lib['plugins'] = plugins
+    if lib.get('generate_plugin_registry', False):
+      lib['src'].append('src/core/plugin_registry/%s_plugin_registry.c' %
+                        lib['name'])
+    for lst in FILEGROUP_LISTS:
+      lib[lst] = uniquify(lib.get(lst, []))
diff --git a/tools/buildgen/plugins/expand_version.py b/tools/buildgen/plugins/expand_version.py
index b55e1b1..dd77f7a 100755
--- a/tools/buildgen/plugins/expand_version.py
+++ b/tools/buildgen/plugins/expand_version.py
@@ -84,6 +84,11 @@
     else:
       return '%d.%d.%d' % (self.major, self.minor, self.patch)
 
+  def php(self):
+    """Version string in PHP style"""
+    """PECL does not allow tag in version string"""
+    return '%d.%d.%d' % (self.major, self.minor, self.patch)
+
 def mako_plugin(dictionary):
   """Expand version numbers:
      - for each language, ensure there's a language_version tag in
diff --git a/tools/buildgen/plugins/make_fuzzer_tests.py b/tools/buildgen/plugins/make_fuzzer_tests.py
new file mode 100644
index 0000000..9d00069
--- /dev/null
+++ b/tools/buildgen/plugins/make_fuzzer_tests.py
@@ -0,0 +1,58 @@
+# 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.
+
+"""Create tests for each fuzzer"""
+
+import copy
+import glob
+
+def mako_plugin(dictionary):
+  targets = dictionary['targets']
+  tests = dictionary['tests']
+  for tgt in targets:
+    if tgt['build'] == 'fuzzer':
+      new_target = copy.deepcopy(tgt)
+      new_target['build'] = 'test'
+      new_target['name'] += '_one_entry'
+      new_target['run'] = False
+      new_target['src'].append('test/core/util/one_corpus_entry_fuzzer.c')
+      new_target['own_src'].append('test/core/util/one_corpus_entry_fuzzer.c')
+      targets.append(new_target)
+      for corpus in new_target['corpus_dirs']:
+        for fn in sorted(glob.glob('%s/*' % corpus)):
+          tests.append({
+              'name': new_target['name'],
+              'args': [fn],
+              'exclude_configs': [],
+              'platforms': ['linux'],
+              'ci_platforms': ['linux'],
+              'flaky': False,
+              'language': 'c',
+              'cpu_cost': 0.1,
+          })
diff --git a/tools/buildgen/plugins/transitive_dependencies.py b/tools/buildgen/plugins/transitive_dependencies.py
index 01e7f61..176c8fa 100644
--- a/tools/buildgen/plugins/transitive_dependencies.py
+++ b/tools/buildgen/plugins/transitive_dependencies.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/codegen/core/gen_hpack_tables.c b/tools/codegen/core/gen_hpack_tables.c
index bae4e4c..33c68a2 100644
--- a/tools/codegen/core/gen_hpack_tables.c
+++ b/tools/codegen/core/gen_hpack_tables.c
@@ -33,13 +33,13 @@
 
 /* generates constant tables for hpack.c */
 
+#include <assert.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 
 #include <grpc/support/log.h>
-#include "src/core/transport/chttp2/huffsyms.h"
+#include "src/core/ext/transport/chttp2/transport/huffsyms.h"
 
 /*
  * first byte LUT generation
diff --git a/tools/codegen/core/gen_legal_metadata_characters.c b/tools/codegen/core/gen_legal_metadata_characters.c
index 10605d5..6ac3265 100644
--- a/tools/codegen/core/gen_legal_metadata_characters.c
+++ b/tools/codegen/core/gen_legal_metadata_characters.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2015, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/tools/codegen/core/gen_load_balancing_proto.sh b/tools/codegen/core/gen_load_balancing_proto.sh
deleted file mode 100755
index fb6a468..0000000
--- a/tools/codegen/core/gen_load_balancing_proto.sh
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-#
-# Example usage:
-#   tools/codegen/core/gen_load_balancing_proto.sh \
-#     src/proto/grpc/lb/v0/load_balancer.proto
-
-read -r -d '' COPYRIGHT <<'EOF'
-/*
- *
- * Copyright <YEAR>, 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.
- *
- */
-
-EOF
-
-CURRENT_YEAR=$(date +%Y)
-COPYRIGHT_FILE=$(mktemp)
-echo "${COPYRIGHT/<YEAR>/$CURRENT_YEAR}" > $COPYRIGHT_FILE
-
-set -ex
-if [ $# -eq 0 ]; then
-  echo "Usage: $0 <load_balancer.proto> [output dir]"
-  exit 1
-fi
-
-readonly GRPC_ROOT=$PWD
-
-OUTPUT_DIR="$GRPC_ROOT/src/core/proto/grpc/lb/v0"
-if [ $# -eq 2 ]; then
-  mkdir -p "$2"
-  if [ $? != 0 ]; then
-    echo "Error creating output directory $2"
-    exit 2
-  fi
-  OUTPUT_DIR="$2"
-fi
-
-readonly EXPECTED_OPTIONS_FILE_PATH="${1%.*}.options"
-
-if [[ ! -f "$1" ]]; then
-  echo "Input proto file '$1' doesn't exist."
-  exit 3
-fi
-if [[ ! -f "${EXPECTED_OPTIONS_FILE_PATH}" ]]; then
-  echo "Expected nanopb options file '${EXPECTED_OPTIONS_FILE_PATH}' missing"
-  exit 4
-fi
-
-readonly VENV_DIR=$(mktemp -d)
-readonly VENV_NAME="nanopb-$(date '+%Y%m%d_%H%M%S_%N')"
-pushd $VENV_DIR
-virtualenv $VENV_NAME
-. $VENV_NAME/bin/activate
-popd
-
-# this should be the same version as the submodule we compile against
-# ideally we'd update this as a template to ensure that
-pip install protobuf==3.0.0b2
-
-pushd "$(dirname $1)" > /dev/null
-
-protoc \
---plugin=protoc-gen-nanopb="$GRPC_ROOT/third_party/nanopb/generator/protoc-gen-nanopb" \
---nanopb_out='-T -L#include\ \"third_party/nanopb/pb.h\"'":$OUTPUT_DIR" \
-"$(basename $1)"
-
-readonly PROTO_BASENAME=$(basename $1 .proto)
-sed -i "s:$PROTO_BASENAME.pb.h:src/core/proto/grpc/lb/v0/$PROTO_BASENAME.pb.h:g" \
-    "$OUTPUT_DIR/$PROTO_BASENAME.pb.c"
-
-# prepend copyright
-TMPFILE=$(mktemp)
-cat $COPYRIGHT_FILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.c" > $TMPFILE
-mv -v $TMPFILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.c"
-cat $COPYRIGHT_FILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.h" > $TMPFILE
-mv -v $TMPFILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.h"
-
-deactivate
-rm -rf $VENV_DIR
-
-popd > /dev/null
diff --git a/tools/codegen/core/gen_nano_proto.sh b/tools/codegen/core/gen_nano_proto.sh
new file mode 100755
index 0000000..e2d2f67
--- /dev/null
+++ b/tools/codegen/core/gen_nano_proto.sh
@@ -0,0 +1,149 @@
+#!/bin/bash
+
+# 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.
+
+#
+# Example usage:
+#   tools/codegen/core/gen_nano_proto.sh \
+#     src/proto/grpc/lb/v0/load_balancer.proto
+#     $PWD/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0
+#
+# Exit statuses:
+# 1: Incorrect number of arguments
+# 2: Input proto file (1st argument) doesn't exist or is not a regular file.
+# 3: Options file for nanopb not found in same dir as the input proto file.
+# 4: Output dir not an absolute path.
+# 5: Couldn't create output directory (2nd argument).
+
+read -r -d '' COPYRIGHT <<'EOF'
+/*
+ *
+ * Copyright <YEAR>, 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.
+ *
+ */
+
+EOF
+
+CURRENT_YEAR=$(date +%Y)
+COPYRIGHT_FILE=$(mktemp)
+echo "${COPYRIGHT/<YEAR>/$CURRENT_YEAR}" > $COPYRIGHT_FILE
+
+set -ex
+if [ $# -lt 2 ] || [ $# -gt 3 ]; then
+  echo "Usage: $0 <input.proto> <absolute path to output dir> [grpc path]"
+  exit 1
+fi
+
+readonly GRPC_ROOT="$PWD"
+readonly INPUT_PROTO="$1"
+readonly OUTPUT_DIR="$2"
+readonly GRPC_OUTPUT_DIR="${3:-$OUTPUT_DIR}"
+readonly EXPECTED_OPTIONS_FILE_PATH="${1%.*}.options"
+
+if [[ ! -f "$INPUT_PROTO" ]]; then
+  echo "Input proto file '$INPUT_PROTO' doesn't exist."
+  exit 2
+fi
+if [[ ! -f "${EXPECTED_OPTIONS_FILE_PATH}" ]]; then
+  echo "Expected nanopb options file '${EXPECTED_OPTIONS_FILE_PATH}' missing"
+  exit 3
+fi
+
+if [[ "${OUTPUT_DIR:0:1}" != '/' ]]; then
+  echo "The output directory must be an absolute path. Got '$OUTPUT_DIR'"
+  exit 4
+fi
+
+mkdir -p "$OUTPUT_DIR"
+if [ $? != 0 ]; then
+  echo "Error creating output directory $OUTPUT_DIR"
+  exit 5
+fi
+
+readonly VENV_DIR=$(mktemp -d)
+readonly VENV_NAME="nanopb-$(date '+%Y%m%d_%H%M%S_%N')"
+pushd $VENV_DIR
+virtualenv $VENV_NAME
+. $VENV_NAME/bin/activate
+popd
+
+# this should be the same version as the submodule we compile against
+# ideally we'd update this as a template to ensure that
+pip install protobuf==3.0.0b2
+
+pushd "$(dirname $INPUT_PROTO)" > /dev/null
+
+protoc \
+--plugin=protoc-gen-nanopb="$GRPC_ROOT/third_party/nanopb/generator/protoc-gen-nanopb" \
+--nanopb_out='-T -L#include\ \"third_party/nanopb/pb.h\"'":$OUTPUT_DIR" \
+"$(basename $INPUT_PROTO)"
+
+readonly PROTO_BASENAME=$(basename $INPUT_PROTO .proto)
+sed -i "s:$PROTO_BASENAME.pb.h:${GRPC_OUTPUT_DIR}/$PROTO_BASENAME.pb.h:g" \
+  "$OUTPUT_DIR/$PROTO_BASENAME.pb.c"
+
+# prepend copyright
+TMPFILE=$(mktemp)
+cat $COPYRIGHT_FILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.c" > $TMPFILE
+mv -v $TMPFILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.c"
+cat $COPYRIGHT_FILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.h" > $TMPFILE
+mv -v $TMPFILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.h"
+
+deactivate
+rm -rf $VENV_DIR
+
+popd > /dev/null
diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py
index 593baec..b38555e 100755
--- a/tools/codegen/core/gen_static_metadata.py
+++ b/tools/codegen/core/gen_static_metadata.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2.7
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -69,6 +69,7 @@
     (':scheme', 'grpc'),
     (':authority', ''),
     (':method', 'GET'),
+    (':method', 'PUT'),
     (':path', '/'),
     (':path', '/index.html'),
     (':status', '204'),
@@ -204,6 +205,7 @@
 args = sys.argv[1:]
 H = None
 C = None
+D = None
 if args:
   if 'header' in args:
     H = sys.stdout
@@ -213,11 +215,17 @@
     C = sys.stdout
   else:
     C = open('/dev/null', 'w')
+  if 'dictionary' in args:
+    D = sys.stdout
+  else:
+    D = open('/dev/null', 'w')
 else:
   H = open(os.path.join(
-      os.path.dirname(sys.argv[0]), '../../../src/core/transport/static_metadata.h'), 'w')
+      os.path.dirname(sys.argv[0]), '../../../src/core/lib/transport/static_metadata.h'), 'w')
   C = open(os.path.join(
-      os.path.dirname(sys.argv[0]), '../../../src/core/transport/static_metadata.c'), 'w')
+      os.path.dirname(sys.argv[0]), '../../../src/core/lib/transport/static_metadata.c'), 'w')
+  D = open(os.path.join(
+      os.path.dirname(sys.argv[0]), '../../../test/core/end2end/fuzzers/hpack.dictionary'), 'w')
 
 # copy-paste copyright notice from this file
 with open(sys.argv[0]) as my_source:
@@ -232,25 +240,41 @@
     if line[0] != '#':
       break
     copyright.append(line)
-  put_banner([H,C], [line[1:].strip() for line in copyright])
+  put_banner([H,C], [line[2:].rstrip() for line in copyright])
+
+
+hex_bytes = [ord(c) for c in "abcdefABCDEF0123456789"]
+
+
+def esc_dict(line):
+  out = "\""
+  for c in line:
+    if 32 <= c < 127:
+      if c != ord('"'):
+        out += chr(c)
+      else:
+        out += "\\\""
+    else:
+      out += "\\x%02X" % c
+  return out + "\""
 
 put_banner([H,C],
 """WARNING: Auto-generated code.
 
-To make changes to this file, change tools/codegen/core/gen_static_metadata.py,
-and then re-run it.
+To make changes to this file, change
+tools/codegen/core/gen_static_metadata.py, and then re-run it.
 
-See metadata.h for an explanation of the interface here, and metadata.c for an
-explanation of what's going on.
+See metadata.h for an explanation of the interface here, and metadata.c for
+an explanation of what's going on.
 """.splitlines())
 
-print >>H, '#ifndef GRPC_INTERNAL_CORE_TRANSPORT_STATIC_METADATA_H'
-print >>H, '#define GRPC_INTERNAL_CORE_TRANSPORT_STATIC_METADATA_H'
+print >>H, '#ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
+print >>H, '#define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
 print >>H
-print >>H, '#include "src/core/transport/metadata.h"'
+print >>H, '#include "src/core/lib/transport/metadata.h"'
 print >>H
 
-print >>C, '#include "src/core/transport/static_metadata.h"'
+print >>C, '#include "src/core/lib/transport/static_metadata.h"'
 print >>C
 
 print >>H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
@@ -262,15 +286,22 @@
 print >>C, 'grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];'
 print >>C
 
+print >>D, '# hpack fuzzing dictionary'
+for i, elem in enumerate(all_strs):
+  print >>D, '%s' % (esc_dict([len(elem)] + [ord(c) for c in elem]))
+for i, elem in enumerate(all_elems):
+  print >>D, '%s' % (esc_dict([0, len(elem[0])] + [ord(c) for c in elem[0]] +
+                              [len(elem[1])] + [ord(c) for c in elem[1]]))
+
 print >>H, '#define GRPC_STATIC_MDELEM_COUNT %d' % len(all_elems)
 print >>H, 'extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];'
-print >>H, 'extern gpr_uintptr grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];'
+print >>H, 'extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];'
 for i, elem in enumerate(all_elems):
   print >>H, '/* "%s": "%s" */' % elem
   print >>H, '#define %s (&grpc_static_mdelem_table[%d])' % (mangle(elem).upper(), i)
 print >>H
 print >>C, 'grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];'
-print >>C, 'gpr_uintptr grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {'
+print >>C, 'uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {'
 print >>C, '  %s' % ','.join('%d' % static_userdata.get(elem, 0) for elem in all_elems)
 print >>C, '};'
 print >>C
@@ -285,8 +316,8 @@
     if m == m2:
       return i
 
-print >>H, 'extern const gpr_uint8 grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2];'
-print >>C, 'const gpr_uint8 grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2] = {'
+print >>H, 'extern const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2];'
+print >>C, 'const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2] = {'
 print >>C, ','.join('%d' % str_idx(x) for x in itertools.chain.from_iterable([a,b] for a, b in all_elems))
 print >>C, '};'
 print >>C
@@ -297,16 +328,15 @@
 print >>C, '};'
 print >>C
 
-print >>H, 'extern const gpr_uint8 grpc_static_accept_encoding_metadata[%d];' % (1 << len(COMPRESSION_ALGORITHMS))
-print >>C, 'const gpr_uint8 grpc_static_accept_encoding_metadata[%d] = {' % (1 << len(COMPRESSION_ALGORITHMS))
+print >>H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (1 << len(COMPRESSION_ALGORITHMS))
+print >>C, 'const uint8_t grpc_static_accept_encoding_metadata[%d] = {' % (1 << len(COMPRESSION_ALGORITHMS))
 print >>C, '0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems)
 print >>C, '};'
 print >>C
 
 print >>H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) (&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]])'
 
-print >>H, '#endif /* GRPC_INTERNAL_CORE_TRANSPORT_STATIC_METADATA_H */'
+print >>H, '#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */'
 
 H.close()
 C.close()
-
diff --git a/tools/distrib/build_ruby_environment_macos.sh b/tools/distrib/build_ruby_environment_macos.sh
index ff3a388..64fad7c 100644
--- a/tools/distrib/build_ruby_environment_macos.sh
+++ b/tools/distrib/build_ruby_environment_macos.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/distrib/check_copyright.py b/tools/distrib/check_copyright.py
index 5badbf4..68411c6 100755
--- a/tools/distrib/check_copyright.py
+++ b/tools/distrib/check_copyright.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2.7
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -155,23 +155,7 @@
     continue
   m = re.search(re_license, text)
   if m:
-    gdict = m.groupdict()
-    last_modified = int(subprocess.check_output('git log -1 --format="%ad" --date=short -- ' + filename, shell=True)[0:4])
-    latest_claimed = int(gdict['last_year'])
-    if last_modified > latest_claimed:
-      print '%s modified %d but copyright only extends to %d' % (filename, last_modified, latest_claimed)
-      ok = False
-      if args.fix:
-        span_start, span_end = m.span(2)
-        if not gdict['first_year']:
-          # prepend the old year to the current one.
-          text = '{}-{}{}'.format(text[:span_end], last_modified, text[span_end:])
-        else:  # already a year range
-          # simply update the last year
-          text = '{}{}{}'.format(text[:span_start], last_modified, text[span_end:])
-        save(filename, text)
-        print 'Fixed!'
-        ok = True
+    pass
   elif 'DO NOT EDIT' not in text and 'AssemblyInfo.cs' not in filename and filename != 'src/boringssl/err_data.c':
     log(1, 'copyright missing', filename)
     ok = False
diff --git a/tools/distrib/check_include_guards.py b/tools/distrib/check_include_guards.py
index 977f40e..897a899 100755
--- a/tools/distrib/check_include_guards.py
+++ b/tools/distrib/check_include_guards.py
@@ -95,6 +95,8 @@
     fcontents = load(fpath)
 
     match = self.ifndef_re.search(fcontents)
+    if not match:
+      print 'something drastically wrong with: %s' % fpath
     if match.lastindex is None:
       # No ifndef. Request manual addition with hints
       self.fail(fpath, match.re, match.string, '', '', False)
@@ -167,7 +169,7 @@
 args = argp.parse_args()
 
 KNOWN_BAD = set([
-    'src/core/proto/grpc/lb/v0/load_balancer.pb.h',
+    'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h',
 ])
 
 
diff --git a/tools/distrib/check_nanopb_output.sh b/tools/distrib/check_nanopb_output.sh
index 51c4d75..92cb8ec 100755
--- a/tools/distrib/check_nanopb_output.sh
+++ b/tools/distrib/check_nanopb_output.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -31,36 +31,42 @@
 set -ex
 
 readonly NANOPB_TMP_OUTPUT="$(mktemp -d)"
+readonly PROTOBUF_INSTALL_PREFIX="$(mktemp -d)"
 
 # install protoc version 3
 pushd third_party/protobuf
 ./autogen.sh
-./configure
+./configure --prefix="$PROTOBUF_INSTALL_PREFIX"
 make
 make install
-ldconfig
+#ldconfig
 popd
 
-if [ ! -x "/usr/local/bin/protoc" ]; then
-  echo "Error: protoc not found in path"
+readonly PROTOC_BIN_PATH="$PROTOBUF_INSTALL_PREFIX/bin"
+if [ ! -x "$PROTOBUF_INSTALL_PREFIX/bin/protoc" ]; then
+  echo "Error: protoc not found in temp install dir '$PROTOBUF_INSTALL_PREFIX'"
   exit 1
 fi
-readonly PROTOC_PATH='/usr/local/bin'
+
 # stack up and change to nanopb's proto generator directory
 pushd third_party/nanopb/generator/proto
-PATH="$PROTOC_PATH:$PATH" make
-
+export PATH="$PROTOC_BIN_PATH:$PATH"
+make
 # back to the root directory
 popd
 
-
+#
+# Checks for load_balancer.proto
+#
+readonly LOAD_BALANCER_GRPC_OUTPUT_PATH='src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0'
 # nanopb-compile the proto to a temp location
-PATH="$PROTOC_PATH:$PATH" ./tools/codegen/core/gen_load_balancing_proto.sh \
+./tools/codegen/core/gen_nano_proto.sh \
   src/proto/grpc/lb/v0/load_balancer.proto \
-  $NANOPB_TMP_OUTPUT
+  "$NANOPB_TMP_OUTPUT" \
+  "$LOAD_BALANCER_GRPC_OUTPUT_PATH"
 
 # compare outputs to checked compiled code
-if ! diff -r $NANOPB_TMP_OUTPUT src/core/proto/grpc/lb/v0; then
-  echo "Outputs differ: $NANOPB_TMP_OUTPUT vs src/core/proto/grpc/lb/v0"
+if ! diff -r $NANOPB_TMP_OUTPUT src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0; then
+  echo "Outputs differ: $NANOPB_TMP_OUTPUT vs $LOAD_BALANCER_GRPC_OUTPUT_PATH"
   exit 2
 fi
diff --git a/tools/distrib/check_vsprojects.py b/tools/distrib/check_vsprojects.py
new file mode 100755
index 0000000..96dd2e4
--- /dev/null
+++ b/tools/distrib/check_vsprojects.py
@@ -0,0 +1,84 @@
+#!/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 os
+import re
+import sys
+
+from lxml import etree
+
+
+def main():
+  root_dir = os.path.abspath(
+      os.path.join(os.path.dirname(sys.argv[0]), '../..'))
+  os.chdir(root_dir)
+
+  project_re = re.compile('Project\(.*\) = ".+", "(.+)", "(.+)"')
+
+  known_projects = {}
+  with open(os.path.join('vsprojects', 'grpc.sln')) as f:
+    for line in f.readlines():
+      m = project_re.match(line)
+      if not m:
+        continue
+
+      vcxproj_path, project_guid = m.groups()
+      if os.name != 'nt':
+        vcxproj_path = vcxproj_path.replace('\\', '/')
+
+      known_projects[project_guid] = vcxproj_path
+
+  ok = True
+  for vcxproj_path in known_projects.values():
+    with open(os.path.join(root_dir, 'vsprojects', vcxproj_path)) as f:
+      tree = etree.parse(f)
+
+    namespaces = {'ns': 'http://schemas.microsoft.com/developer/msbuild/2003'}
+    referenced_projects = tree.getroot().xpath('/ns:Project/ns:ItemGroup'
+                                               '/ns:ProjectReference'
+                                               '/ns:Project',
+                                               namespaces=namespaces)
+    for referenced_project in referenced_projects:
+      # Project tag under ProjectReference is a GUID reference.
+      if referenced_project.text not in known_projects:
+        target_vcxproj = referenced_project.getparent().attrib['Include']
+        guid = referenced_project.text
+        print ('In project "%s", dependency "%s" (with GUID "%s") is not in '
+               'grpc.sln' % (vcxproj_path, target_vcxproj, guid))
+        ok = False
+
+  if not ok:
+    exit(1)
+
+
+if __name__ == '__main__':
+  main()
+
diff --git a/tools/distrib/check_windows_dlls.sh b/tools/distrib/check_windows_dlls.sh
index efb66e9..65ac353 100755
--- a/tools/distrib/check_windows_dlls.sh
+++ b/tools/distrib/check_windows_dlls.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/distrib/clang_format_code.sh b/tools/distrib/clang_format_code.sh
index d904a84..858e074 100755
--- a/tools/distrib/clang_format_code.sh
+++ b/tools/distrib/clang_format_code.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/distrib/python/docgen.py b/tools/distrib/python/docgen.py
index 161d83e..72c65ad 100755
--- a/tools/distrib/python/docgen.py
+++ b/tools/distrib/python/docgen.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/distrib/python/submit.py b/tools/distrib/python/submit.py
index 9b012be..f581b77 100755
--- a/tools/distrib/python/submit.py
+++ b/tools/distrib/python/submit.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile
index 03b5b36..c917b29 100644
--- a/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_jessie_x64/Dockerfile
index 1cadba3..249095a 100644
--- a/tools/dockerfile/distribtest/csharp_jessie_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_jessie_x86/Dockerfile b/tools/dockerfile/distribtest/csharp_jessie_x86/Dockerfile
index be96282..9eda551 100644
--- a/tools/dockerfile/distribtest/csharp_jessie_x86/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_jessie_x86/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_ubuntu1404_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_ubuntu1404_x64/Dockerfile
index 3d04d03..85daea4 100644
--- a/tools/dockerfile/distribtest/csharp_ubuntu1404_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_ubuntu1404_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_ubuntu1504_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_ubuntu1504_x64/Dockerfile
index 5eec570..ec16105 100644
--- a/tools/dockerfile/distribtest/csharp_ubuntu1504_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_ubuntu1504_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_ubuntu1510_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_ubuntu1510_x64/Dockerfile
index a6d60fb..110aa2a 100644
--- a/tools/dockerfile/distribtest/csharp_ubuntu1510_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_ubuntu1510_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_ubuntu1604_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_ubuntu1604_x64/Dockerfile
index 6147270..4ef0766 100644
--- a/tools/dockerfile/distribtest/csharp_ubuntu1604_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_ubuntu1604_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/csharp_wheezy_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_wheezy_x64/Dockerfile
index 9039c3c..d9e64fe 100644
--- a/tools/dockerfile/distribtest/csharp_wheezy_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/csharp_wheezy_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/php_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/php_jessie_x64/Dockerfile
index d5d3fd6..e8cd6e7 100644
--- a/tools/dockerfile/distribtest/php_jessie_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/php_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_arch_x64/Dockerfile b/tools/dockerfile/distribtest/python_arch_x64/Dockerfile
index c4f2431..2f79cc3 100644
--- a/tools/dockerfile/distribtest/python_arch_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_arch_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_centos6_x64/Dockerfile b/tools/dockerfile/distribtest/python_centos6_x64/Dockerfile
index 79dae07..d4f4737 100644
--- a/tools/dockerfile/distribtest/python_centos6_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_centos6_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_centos7_x64/Dockerfile b/tools/dockerfile/distribtest/python_centos7_x64/Dockerfile
index 114957b..ca64fa7 100644
--- a/tools/dockerfile/distribtest/python_centos7_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_centos7_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile b/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile
index 5e6cb15..8b0f769 100644
--- a/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile b/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile
index f1b0e2f..fcbe053 100644
--- a/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_fedora22_x64/Dockerfile b/tools/dockerfile/distribtest/python_fedora22_x64/Dockerfile
index c641594..ddcacb4 100644
--- a/tools/dockerfile/distribtest/python_fedora22_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_fedora22_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_fedora23_x64/Dockerfile b/tools/dockerfile/distribtest/python_fedora23_x64/Dockerfile
index 6c834d2..d45195e 100644
--- a/tools/dockerfile/distribtest/python_fedora23_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_fedora23_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/python_jessie_x64/Dockerfile
index 5778d60..83df4ed 100644
--- a/tools/dockerfile/distribtest/python_jessie_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_jessie_x86/Dockerfile b/tools/dockerfile/distribtest/python_jessie_x86/Dockerfile
index e9cf991..19addb2 100644
--- a/tools/dockerfile/distribtest/python_jessie_x86/Dockerfile
+++ b/tools/dockerfile/distribtest/python_jessie_x86/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_opensuse_x64/Dockerfile b/tools/dockerfile/distribtest/python_opensuse_x64/Dockerfile
index ea5d4c7..fe1406b 100644
--- a/tools/dockerfile/distribtest/python_opensuse_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_opensuse_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_ubuntu1204_x64/Dockerfile b/tools/dockerfile/distribtest/python_ubuntu1204_x64/Dockerfile
index a48ce0e..4068fbe 100644
--- a/tools/dockerfile/distribtest/python_ubuntu1204_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_ubuntu1204_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_ubuntu1404_x64/Dockerfile b/tools/dockerfile/distribtest/python_ubuntu1404_x64/Dockerfile
index 18dbfd4..0858fb0 100644
--- a/tools/dockerfile/distribtest/python_ubuntu1404_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_ubuntu1404_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_ubuntu1504_x64/Dockerfile b/tools/dockerfile/distribtest/python_ubuntu1504_x64/Dockerfile
index 444a54d..ed6ffdd 100644
--- a/tools/dockerfile/distribtest/python_ubuntu1504_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_ubuntu1504_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_ubuntu1510_x64/Dockerfile b/tools/dockerfile/distribtest/python_ubuntu1510_x64/Dockerfile
index 245ffb9..9e3e0c2 100644
--- a/tools/dockerfile/distribtest/python_ubuntu1510_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_ubuntu1510_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_ubuntu1604_x64/Dockerfile b/tools/dockerfile/distribtest/python_ubuntu1604_x64/Dockerfile
index a1ac305..5098da8 100644
--- a/tools/dockerfile/distribtest/python_ubuntu1604_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_ubuntu1604_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/python_wheezy_x64/Dockerfile b/tools/dockerfile/distribtest/python_wheezy_x64/Dockerfile
index 46353b9..66165ee 100644
--- a/tools/dockerfile/distribtest/python_wheezy_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_wheezy_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
index b943b67..dcfc07a 100644
--- a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile
index 8565020..056bd45 100644
--- a/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
index 437337e..f4151e7 100644
--- a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
index b567c5b..78d7575 100644
--- a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
index 58d3d93..f574c62 100644
--- a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
index 9f07f51..fe6c72a 100644
--- a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x64/Dockerfile
index cc377b7..57f98ef 100644
--- a/tools/dockerfile/distribtest/ruby_jessie_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_jessie_x86/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x86/Dockerfile
index 3fe3e2b..938bc5e 100644
--- a/tools/dockerfile/distribtest/ruby_jessie_x86/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_jessie_x86/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_opensuse_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_opensuse_x64/Dockerfile
index c98d691..c5b0113 100644
--- a/tools/dockerfile/distribtest/ruby_opensuse_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_opensuse_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_ubuntu1204_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_ubuntu1204_x64/Dockerfile
index 782368b..0aab241 100644
--- a/tools/dockerfile/distribtest/ruby_ubuntu1204_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_ubuntu1204_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_ubuntu1404_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_ubuntu1404_x64/Dockerfile
index 53fb4d5..324f51e 100644
--- a/tools/dockerfile/distribtest/ruby_ubuntu1404_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_ubuntu1404_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_ubuntu1504_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_ubuntu1504_x64/Dockerfile
index 3225166..762734b 100644
--- a/tools/dockerfile/distribtest/ruby_ubuntu1504_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_ubuntu1504_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_ubuntu1510_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_ubuntu1510_x64/Dockerfile
index df93360..3ac61a0 100644
--- a/tools/dockerfile/distribtest/ruby_ubuntu1510_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_ubuntu1510_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_ubuntu1604_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_ubuntu1604_x64/Dockerfile
index f0c2e80..40fc6be 100644
--- a/tools/dockerfile/distribtest/ruby_ubuntu1604_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_ubuntu1604_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/distribtest/ruby_wheezy_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_wheezy_x64/Dockerfile
index ee4e0fc..9ae2ee2 100644
--- a/tools/dockerfile/distribtest/ruby_wheezy_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_wheezy_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_clang_format/Dockerfile b/tools/dockerfile/grpc_clang_format/Dockerfile
index 4b101f6..41239e9 100644
--- a/tools/dockerfile/grpc_clang_format/Dockerfile
+++ b/tools/dockerfile/grpc_clang_format/Dockerfile
@@ -27,9 +27,13 @@
 # (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 ubuntu:vivid
+FROM ubuntu:wily
 RUN apt-get update
-RUN apt-get -y install clang-format-3.6
+RUN apt-get -y install wget
+RUN echo deb http://llvm.org/apt/wily/ llvm-toolchain-wily main >> /etc/apt/sources.list
+RUN echo deb-src http://llvm.org/apt/wily/ llvm-toolchain-wily main >> /etc/apt/sources.list
+RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key| apt-key add -
+RUN apt-get update
+RUN apt-get -y install clang-format-3.8
 ADD clang_format_all_the_things.sh /
 CMD ["echo 'Run with tools/distrib/clang_format_code.sh'"]
-
diff --git a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
index d56bc01..6f41559 100755
--- a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
+++ b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -31,13 +31,13 @@
 set -e
 
 # directories to run against
-DIRS="src/core src/cpp test/core test/cpp include"
+DIRS="src/core/lib src/core/ext src/cpp test/core test/cpp include"
 
 # file matching patterns to check
 GLOB="*.h *.c *.cc"
 
 # clang format command
-CLANG_FORMAT=clang-format-3.6
+CLANG_FORMAT=clang-format-3.8
 
 files=
 for dir in $DIRS
diff --git a/tools/dockerfile/grpc_interop_csharp/Dockerfile b/tools/dockerfile/grpc_interop_csharp/Dockerfile
index c3c7948..93cd250 100644
--- a/tools/dockerfile/grpc_interop_csharp/Dockerfile
+++ b/tools/dockerfile/grpc_interop_csharp/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -80,13 +80,9 @@
 # Install dependencies
 RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \
     mono-devel \
-    nunit \
-    nunit-console \
-    monodevelop
-
-# Download NuGet
-RUN cd /var/local && wget www.nuget.org/NuGet.exe
-ENV NUGET mono /var/local/NuGet.exe
+    ca-certificates-mono \
+    nuget \
+    && apt-get clean
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/grpc_interop_csharp/build_interop.sh b/tools/dockerfile/grpc_interop_csharp/build_interop.sh
index 5ad525f..fd5436c 100755
--- a/tools/dockerfile/grpc_interop_csharp/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_csharp/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,4 @@
 cd /var/local/git/grpc
 
 # build C# interop client & server
-make CONFIG=dbg grpc_csharp_ext
-(cd src/csharp && mono /var/local/NuGet.exe restore Grpc.sln)
-(cd src/csharp && xbuild Grpc.sln)
+tools/run_tests/run_tests.py -l csharp -c dbg --build_only
diff --git a/tools/dockerfile/grpc_interop_cxx/Dockerfile b/tools/dockerfile/grpc_interop_cxx/Dockerfile
index 58a8c32..1fa1907 100644
--- a/tools/dockerfile/grpc_interop_cxx/Dockerfile
+++ b/tools/dockerfile/grpc_interop_cxx/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_cxx/build_interop.sh b/tools/dockerfile/grpc_interop_cxx/build_interop.sh
index 903c31b..1c0828d 100755
--- a/tools/dockerfile/grpc_interop_cxx/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_cxx/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_go/Dockerfile b/tools/dockerfile/grpc_interop_go/Dockerfile
index f83e18c..ec71a53 100644
--- a/tools/dockerfile/grpc_interop_go/Dockerfile
+++ b/tools/dockerfile/grpc_interop_go/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -27,10 +27,10 @@
 # (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 golang:1.4
+FROM golang:1.5
 
 # Using login shell removes Go from path, so we add it.
-RUN ln -s /usr/src/go/bin/go /usr/local/bin
+RUN ln -s /usr/local/go/bin/go /usr/local/bin
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/grpc_interop_go/build_interop.sh b/tools/dockerfile/grpc_interop_go/build_interop.sh
index 224b004..e891549 100755
--- a/tools/dockerfile/grpc_interop_go/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_go/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_http2/Dockerfile b/tools/dockerfile/grpc_interop_http2/Dockerfile
index f83e18c..ec71a53 100644
--- a/tools/dockerfile/grpc_interop_http2/Dockerfile
+++ b/tools/dockerfile/grpc_interop_http2/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -27,10 +27,10 @@
 # (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 golang:1.4
+FROM golang:1.5
 
 # Using login shell removes Go from path, so we add it.
-RUN ln -s /usr/src/go/bin/go /usr/local/bin
+RUN ln -s /usr/local/go/bin/go /usr/local/bin
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/grpc_interop_http2/build_interop.sh b/tools/dockerfile/grpc_interop_http2/build_interop.sh
index 5f701e3..46ddaf9 100755
--- a/tools/dockerfile/grpc_interop_http2/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_http2/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_java/Dockerfile b/tools/dockerfile/grpc_interop_java/Dockerfile
index 8bfb796..370657b 100644
--- a/tools/dockerfile/grpc_interop_java/Dockerfile
+++ b/tools/dockerfile/grpc_interop_java/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_java/build_interop.sh b/tools/dockerfile/grpc_interop_java/build_interop.sh
index 9c9591a..9997c63 100755
--- a/tools/dockerfile/grpc_interop_java/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_java/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_node/Dockerfile b/tools/dockerfile/grpc_interop_node/Dockerfile
index 3f0f918..db5aff8 100644
--- a/tools/dockerfile/grpc_interop_node/Dockerfile
+++ b/tools/dockerfile/grpc_interop_node/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_node/build_interop.sh b/tools/dockerfile/grpc_interop_node/build_interop.sh
index 526dd61..4d4290d 100755
--- a/tools/dockerfile/grpc_interop_node/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_node/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_php/Dockerfile b/tools/dockerfile/grpc_interop_php/Dockerfile
index 4f5b3fc..cf3e791 100644
--- a/tools/dockerfile/grpc_interop_php/Dockerfile
+++ b/tools/dockerfile/grpc_interop_php/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_php/build_interop.sh b/tools/dockerfile/grpc_interop_php/build_interop.sh
index 2bffbd8..87262f1 100755
--- a/tools/dockerfile/grpc_interop_php/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_php/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_python/Dockerfile b/tools/dockerfile/grpc_interop_python/Dockerfile
index ef4432d..047604b 100644
--- a/tools/dockerfile/grpc_interop_python/Dockerfile
+++ b/tools/dockerfile/grpc_interop_python/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_python/build_interop.sh b/tools/dockerfile/grpc_interop_python/build_interop.sh
index ed73680..6454a4f 100755
--- a/tools/dockerfile/grpc_interop_python/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_python/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_ruby/Dockerfile b/tools/dockerfile/grpc_interop_ruby/Dockerfile
index b3383af..ff201fa 100644
--- a/tools/dockerfile/grpc_interop_ruby/Dockerfile
+++ b/tools/dockerfile/grpc_interop_ruby/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_ruby/build_interop.sh b/tools/dockerfile/grpc_interop_ruby/build_interop.sh
index 84fd499..685397b 100755
--- a/tools/dockerfile/grpc_interop_ruby/build_interop.sh
+++ b/tools/dockerfile/grpc_interop_ruby/build_interop.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile b/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
deleted file mode 100644
index 4123cc1..0000000
--- a/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
+++ /dev/null
@@ -1,80 +0,0 @@
-# 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.
-
-# A work-in-progress Dockerfile that allows running gRPC test suites
-# inside a docker container.
-
-FROM debian:jessie
-
-# Install Git.
-RUN apt-get update && apt-get install -y \
-  autoconf \
-  autotools-dev \
-  build-essential \
-  bzip2 \
-  ccache \
-  curl \
-  gcc \
-  gcc-multilib \
-  git \
-  gyp \
-  libc6 \
-  libc6-dbg \
-  libc6-dev \
-  libgtest-dev \
-  libtool \
-  make \
-  strace \
-  python-dev \
-  python-setuptools \
-  python-yaml \
-  telnet \
-  unzip \
-  wget \
-  zip && apt-get clean
-
-RUN easy_install -U pip
-
-# Prepare ccache
-RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
-RUN ln -s /usr/bin/ccache /usr/local/bin/g++
-RUN ln -s /usr/bin/ccache /usr/local/bin/cc
-RUN ln -s /usr/bin/ccache /usr/local/bin/c++
-RUN ln -s /usr/bin/ccache /usr/local/bin/clang
-RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
-
-##################
-# C++ dependencies
-RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang
-
-# Google Cloud platform API libraries (for BigQuery)
-RUN pip install --upgrade google-api-python-client
-
-# Define the default command.
-CMD ["bash"]
diff --git a/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh b/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
deleted file mode 100755
index 392bdfc..0000000
--- a/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash
-# 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.
-#
-# Builds C++ interop server and client in a base image.
-set -e
-
-mkdir -p /var/local/git
-git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
-
-# copy service account keys if available
-cp -r /var/local/jenkins/service_account $HOME || true
-
-cd /var/local/git/grpc
-
-make install-certs
-
-# build C++ interop stress client, interop client and server
-make stress_test metrics_client interop_client interop_server
diff --git a/tools/dockerfile/grpc_linuxbrew/Dockerfile b/tools/dockerfile/grpc_linuxbrew/Dockerfile
index 8c179da..848489e 100644
--- a/tools/dockerfile/grpc_linuxbrew/Dockerfile
+++ b/tools/dockerfile/grpc_linuxbrew/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile
new file mode 100644
index 0000000..556a26e
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile
@@ -0,0 +1,117 @@
+# 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.
+
+FROM debian:jessie
+
+# Install Git and basic packages.
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  golang \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  perl \
+  strace \
+  python-dev \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip && apt-get clean
+
+#================
+# Build profiling
+RUN apt-get update && apt-get install -y time && apt-get clean
+
+# Prepare ccache
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+#=================
+# C++ dependencies
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
+
+# Google Cloud platform API libraries
+RUN apt-get update && apt-get install -y python-pip && apt-get clean
+RUN pip install --upgrade google-api-python-client
+
+
+#=================
+# Update clang to a version with improved tsan and fuzzing capabilities
+
+RUN apt-get update && apt-get -y install python cmake && apt-get clean
+
+RUN git clone -n -b release_38 http://llvm.org/git/llvm.git && \
+  cd llvm && git checkout ad57503 && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/clang.git && \
+  cd clang && git checkout ad2c56e && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/compiler-rt.git && \
+  cd compiler-rt && git checkout 3176922 && cd ..
+RUN git clone -n -b release_38 \
+  http://llvm.org/git/clang-tools-extra.git && cd clang-tools-extra && \
+  git checkout c288525 && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/libcxx.git && \
+  cd libcxx && git checkout fda3549  && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/libcxxabi.git && \
+  cd libcxxabi && git checkout 8d4e51d && cd ..
+
+RUN mv clang llvm/tools
+RUN mv compiler-rt llvm/projects
+RUN mv clang-tools-extra llvm/tools/clang/tools
+RUN mv libcxx llvm/projects
+RUN mv libcxxabi llvm/projects
+
+RUN mkdir llvm-build
+RUN cd llvm-build && cmake \
+  -DCMAKE_BUILD_TYPE:STRING=Release \
+  -DCMAKE_INSTALL_PREFIX:STRING=/usr \
+  -DLLVM_TARGETS_TO_BUILD:STRING=X86 \
+  ../llvm
+RUN make -C llvm-build -j 12 && make -C llvm-build install && rm -rf llvm-build
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_cxx/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_cxx/build_interop_stress.sh
new file mode 100755
index 0000000..b67b1a1
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_cxx/build_interop_stress.sh
@@ -0,0 +1,47 @@
+#!/bin/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.
+#
+# Builds C++ interop server and client in a base image.
+set -e
+
+mkdir -p /var/local/git
+git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+cd /var/local/git/grpc
+
+make install-certs
+
+BUILD_TYPE=${BUILD_TYPE:=opt}
+
+# build C++ interop stress client, interop client and server
+make CONFIG=$BUILD_TYPE stress_test metrics_client interop_client interop_server
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile
new file mode 100644
index 0000000..2a875f5
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile
@@ -0,0 +1,41 @@
+# 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.
+
+FROM golang:1.5
+
+# Google Cloud platform API libraries
+RUN apt-get update && apt-get install -y python-pip && apt-get clean
+RUN pip install --upgrade google-api-python-client
+
+
+# Using login shell removes Go from path, so we add it.
+RUN ln -s /usr/local/go/bin/go /usr/local/bin
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_go/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_go/build_interop_stress.sh
new file mode 100755
index 0000000..919d885
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_go/build_interop_stress.sh
@@ -0,0 +1,58 @@
+#!/bin/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.
+#
+# Builds Go interop server, Stress client and metrics client in a base image.
+set -e
+
+# Clone just the grpc-go source code without any dependencies.
+# We are cloning from a local git repo that contains the right revision
+# to test instead of using "go get" to download from Github directly.
+git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc
+
+# Clone the 'grpc' repo. We just need this for the wrapper scripts under
+# grpc/tools/gcp/stress_tests
+git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# Get dependencies from GitHub
+# NOTE: once grpc-go dependencies change, this needs to be updated manually
+# but we don't expect this to happen any time soon.
+go get github.com/golang/protobuf/proto
+go get golang.org/x/net/context
+go get golang.org/x/net/trace
+go get golang.org/x/oauth2
+go get google.golang.org/cloud
+
+# Build the interop server, stress client and stress metrics client
+(cd src/google.golang.org/grpc/interop/server && go install)
+(cd src/google.golang.org/grpc/stress/client && go install)
+(cd src/google.golang.org/grpc/stress/metrics_client && go install)
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile
new file mode 100644
index 0000000..69bef14
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile
@@ -0,0 +1,102 @@
+# 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.
+
+FROM debian:jessie
+
+# Install Git and basic packages.
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  golang \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  perl \
+  strace \
+  python-dev \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip && apt-get clean
+
+#================
+# Build profiling
+RUN apt-get update && apt-get install -y time && apt-get clean
+
+# Prepare ccache
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+#=================
+# C++ dependencies
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
+
+# Google Cloud platform API libraries
+RUN apt-get update && apt-get install -y python-pip && apt-get clean
+RUN pip install --upgrade google-api-python-client
+
+
+# Install JDK 8 and Git
+#
+RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \
+  echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && \
+  echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && \
+  apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
+
+RUN apt-get update && apt-get -y install \
+      git \
+      libapr1 \
+      oracle-java8-installer \
+      && \
+    apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
+
+ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
+ENV PATH $PATH:$JAVA_HOME/bin
+
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_java/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_java/build_interop_stress.sh
new file mode 100755
index 0000000..d4fdfbb
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_java/build_interop_stress.sh
@@ -0,0 +1,51 @@
+#!/bin/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.
+#
+# Builds C++ interop server and client in a base image.
+set -e
+
+mkdir -p /var/local/git
+# grpc-java repo
+git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java
+
+# grpc repo (for metrics client and for the stress test wrapper scripts)
+git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
+
+# Copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# First build the metrics client in grpc repo
+cd /var/local/git/grpc
+make metrics_client
+
+# Build all interop test targets (which includes interop server and stress test
+# client) in grpc-java repo
+cd /var/local/git/grpc-java
+./gradlew :grpc-interop-testing:installDist -PskipCodegen=true
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile
new file mode 100644
index 0000000..f70add4
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile
@@ -0,0 +1,95 @@
+# 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.
+
+FROM debian:jessie
+
+# Install Git and basic packages.
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  golang \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  perl \
+  strace \
+  python-dev \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip && apt-get clean
+
+#================
+# Build profiling
+RUN apt-get update && apt-get install -y time && apt-get clean
+
+#==================
+# Node dependencies
+
+# Install nvm
+RUN touch .profile
+RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
+RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache"
+
+# Google Cloud platform API libraries
+RUN apt-get update && apt-get install -y python-pip && apt-get clean
+RUN pip install --upgrade google-api-python-client
+
+
+# Prepare ccache
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+#======================
+# Zookeeper dependencies
+# TODO(jtattermusch): is zookeeper still needed?
+RUN apt-get install -y libzookeeper-mt-dev
+
+RUN mkdir /var/local/jenkins
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh
new file mode 100755
index 0000000..b99fd44
--- /dev/null
+++ b/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh
@@ -0,0 +1,46 @@
+#!/bin/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.
+#
+# Builds Node interop server and client in a base image.
+set -e
+
+mkdir -p /var/local/git
+git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+cd /var/local/git/grpc
+nvm use 0.12
+nvm alias default 0.12  # prevent the need to run 'nvm use' in every shell
+
+# build Node interop client & server
+npm install -g node-gyp
+npm install --unsafe-perm --build-from-source
diff --git a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
index 0052de6..baab2f5 100644
--- a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
index b848f23..6492158 100644
--- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -68,7 +68,7 @@
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
 
 #=================
-# Update clang to a version with improved tsan
+# Update clang to a version with improved tsan and fuzzing capabilities
 
 RUN apt-get update && apt-get -y install python cmake && apt-get clean
 
@@ -98,7 +98,7 @@
   -DCMAKE_INSTALL_PREFIX:STRING=/usr \
   -DLLVM_TARGETS_TO_BUILD:STRING=X86 \
   ../llvm
-RUN make -C llvm-build && make -C llvm-build install && rm -rf llvm-build
+RUN make -C llvm-build -j 12 && make -C llvm-build install && rm -rf llvm-build
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
index 9a8f2b1..92c9c4c 100644
--- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
+++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
index e8dab1b..1e43e6b 100644
--- a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
index c6fe79b..02d3c0d 100644
--- a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile
new file mode 100644
index 0000000..6ba3111
--- /dev/null
+++ b/tools/dockerfile/test/fuzzer/Dockerfile
@@ -0,0 +1,123 @@
+# 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.
+
+FROM debian:jessie
+
+# Install Git and basic packages.
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  golang \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  perl \
+  strace \
+  python-dev \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip && apt-get clean
+
+#================
+# Build profiling
+RUN apt-get update && apt-get install -y time && apt-get clean
+
+#=================
+# C++ dependencies
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
+
+#=================
+# Update clang to a version with improved tsan and fuzzing capabilities
+
+RUN apt-get update && apt-get -y install python cmake && apt-get clean
+
+RUN git clone -n -b release_38 http://llvm.org/git/llvm.git && \
+  cd llvm && git checkout ad57503 && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/clang.git && \
+  cd clang && git checkout ad2c56e && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/compiler-rt.git && \
+  cd compiler-rt && git checkout 3176922 && cd ..
+RUN git clone -n -b release_38 \
+  http://llvm.org/git/clang-tools-extra.git && cd clang-tools-extra && \
+  git checkout c288525 && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/libcxx.git && \
+  cd libcxx && git checkout fda3549  && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/libcxxabi.git && \
+  cd libcxxabi && git checkout 8d4e51d && cd ..
+
+RUN mv clang llvm/tools
+RUN mv compiler-rt llvm/projects
+RUN mv clang-tools-extra llvm/tools/clang/tools
+RUN mv libcxx llvm/projects
+RUN mv libcxxabi llvm/projects
+
+RUN mkdir llvm-build
+RUN cd llvm-build && cmake \
+  -DCMAKE_BUILD_TYPE:STRING=Release \
+  -DCMAKE_INSTALL_PREFIX:STRING=/usr \
+  -DLLVM_TARGETS_TO_BUILD:STRING=X86 \
+  ../llvm
+RUN make -C llvm-build -j 12 && make -C llvm-build install && rm -rf llvm-build
+
+# Prepare ccache
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+#======================
+# Zookeeper dependencies
+# TODO(jtattermusch): is zookeeper still needed?
+RUN apt-get install -y libzookeeper-mt-dev
+
+RUN mkdir /var/local/jenkins
+
+RUN clang++ -c -g -O2 -std=c++11 llvm/lib/Fuzzer/*.cpp -IFuzzer
+RUN ar ruv libFuzzer.a Fuzzer*.o
+RUN mv libFuzzer.a /usr/lib
+RUN rm -f Fuzzer*.o
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile
index 0655bf7..64314f8 100644
--- a/tools/dockerfile/test/node_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile
index 43081e7..d8d2784 100644
--- a/tools/dockerfile/test/php_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/python_jessie_x64/Dockerfile b/tools/dockerfile/test/python_jessie_x64/Dockerfile
index 7ed8b4c..071fb2c 100644
--- a/tools/dockerfile/test/python_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/python_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
index 91af772..df8eef5 100644
--- a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile
index 4a69cd8..3146a92 100644
--- a/tools/dockerfile/test/sanity/Dockerfile
+++ b/tools/dockerfile/test/sanity/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,8 @@
       automake \
       libtool \
       curl \
-      python-virtualenv
+      python-virtualenv \
+      python-lxml
 RUN pip install simplejson mako
 
 #===================
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index 253262c..7dc0496 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -795,8 +795,6 @@
 include/grpc++/support/async_unary_call.h \
 include/grpc++/support/byte_buffer.h \
 include/grpc++/support/channel_arguments.h \
-include/grpc++/support/config.h \
-include/grpc++/support/config_protobuf.h \
 include/grpc++/support/slice.h \
 include/grpc++/support/status.h \
 include/grpc++/support/status_code_enum.h \
@@ -813,9 +811,8 @@
 include/grpc++/impl/codegen/client_unary_call.h \
 include/grpc++/impl/codegen/completion_queue.h \
 include/grpc++/impl/codegen/completion_queue_tag.h \
-include/grpc++/impl/codegen/config.h \
-include/grpc++/impl/codegen/config_protobuf.h \
 include/grpc++/impl/codegen/core_codegen_interface.h \
+include/grpc++/impl/codegen/create_auth_context.h \
 include/grpc++/impl/codegen/grpc_library.h \
 include/grpc++/impl/codegen/method_handler_impl.h \
 include/grpc++/impl/codegen/proto_utils.h \
@@ -834,7 +831,31 @@
 include/grpc++/impl/codegen/sync_cxx11.h \
 include/grpc++/impl/codegen/sync_no_cxx11.h \
 include/grpc++/impl/codegen/sync_stream.h \
-include/grpc++/impl/codegen/time.h
+include/grpc++/impl/codegen/time.h \
+include/grpc/impl/codegen/byte_buffer.h \
+include/grpc/impl/codegen/compression_types.h \
+include/grpc/impl/codegen/connectivity_state.h \
+include/grpc/impl/codegen/grpc_types.h \
+include/grpc/impl/codegen/propagation_bits.h \
+include/grpc/impl/codegen/status.h \
+include/grpc/impl/codegen/alloc.h \
+include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm_gcc_atomic.h \
+include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_win32.h \
+include/grpc/impl/codegen/log.h \
+include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/slice_buffer.h \
+include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync_generic.h \
+include/grpc/impl/codegen/sync_posix.h \
+include/grpc/impl/codegen/sync_win32.h \
+include/grpc/impl/codegen/time.h \
+include/grpc++/impl/codegen/config.h \
+include/grpc++/impl/codegen/config_protobuf.h \
+include/grpc++/support/config.h \
+include/grpc++/support/config_protobuf.h
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 134b16f..312fd17 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -795,8 +795,6 @@
 include/grpc++/support/async_unary_call.h \
 include/grpc++/support/byte_buffer.h \
 include/grpc++/support/channel_arguments.h \
-include/grpc++/support/config.h \
-include/grpc++/support/config_protobuf.h \
 include/grpc++/support/slice.h \
 include/grpc++/support/status.h \
 include/grpc++/support/status_code_enum.h \
@@ -813,9 +811,8 @@
 include/grpc++/impl/codegen/client_unary_call.h \
 include/grpc++/impl/codegen/completion_queue.h \
 include/grpc++/impl/codegen/completion_queue_tag.h \
-include/grpc++/impl/codegen/config.h \
-include/grpc++/impl/codegen/config_protobuf.h \
 include/grpc++/impl/codegen/core_codegen_interface.h \
+include/grpc++/impl/codegen/create_auth_context.h \
 include/grpc++/impl/codegen/grpc_library.h \
 include/grpc++/impl/codegen/method_handler_impl.h \
 include/grpc++/impl/codegen/proto_utils.h \
@@ -835,13 +832,35 @@
 include/grpc++/impl/codegen/sync_no_cxx11.h \
 include/grpc++/impl/codegen/sync_stream.h \
 include/grpc++/impl/codegen/time.h \
+include/grpc/impl/codegen/byte_buffer.h \
+include/grpc/impl/codegen/compression_types.h \
+include/grpc/impl/codegen/connectivity_state.h \
+include/grpc/impl/codegen/grpc_types.h \
+include/grpc/impl/codegen/propagation_bits.h \
+include/grpc/impl/codegen/status.h \
+include/grpc/impl/codegen/alloc.h \
+include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm_gcc_atomic.h \
+include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_win32.h \
+include/grpc/impl/codegen/log.h \
+include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/slice_buffer.h \
+include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync_generic.h \
+include/grpc/impl/codegen/sync_posix.h \
+include/grpc/impl/codegen/sync_win32.h \
+include/grpc/impl/codegen/time.h \
+include/grpc++/impl/codegen/config.h \
+include/grpc++/impl/codegen/config_protobuf.h \
+include/grpc++/support/config.h \
+include/grpc++/support/config_protobuf.h \
 src/cpp/client/secure_credentials.h \
 src/cpp/common/core_codegen.h \
 src/cpp/common/secure_auth_context.h \
 src/cpp/server/secure_server_credentials.h \
 src/cpp/client/create_channel_internal.h \
-src/cpp/common/core_codegen.h \
-src/cpp/common/create_auth_context.h \
 src/cpp/server/dynamic_thread_pool.h \
 src/cpp/server/thread_pool_interface.h \
 src/cpp/client/secure_credentials.cc \
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index e326adc..034d9c6 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -760,8 +760,7 @@
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = include/grpc/grpc_security.h \
-include/grpc/byte_buffer.h \
+INPUT                  = include/grpc/byte_buffer.h \
 include/grpc/byte_buffer_reader.h \
 include/grpc/compression.h \
 include/grpc/grpc.h \
@@ -772,6 +771,22 @@
 include/grpc/impl/codegen/grpc_types.h \
 include/grpc/impl/codegen/propagation_bits.h \
 include/grpc/impl/codegen/status.h \
+include/grpc/impl/codegen/alloc.h \
+include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm_gcc_atomic.h \
+include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_win32.h \
+include/grpc/impl/codegen/log.h \
+include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/slice_buffer.h \
+include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync_generic.h \
+include/grpc/impl/codegen/sync_posix.h \
+include/grpc/impl/codegen/sync_win32.h \
+include/grpc/impl/codegen/time.h \
+include/grpc/grpc_security.h \
+include/grpc/grpc_security_constants.h \
 include/grpc/census.h \
 include/grpc/support/alloc.h \
 include/grpc/support/atm.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 4fcfba3..3a774a7 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -760,8 +760,7 @@
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = include/grpc/grpc_security.h \
-include/grpc/byte_buffer.h \
+INPUT                  = include/grpc/byte_buffer.h \
 include/grpc/byte_buffer_reader.h \
 include/grpc/compression.h \
 include/grpc/grpc.h \
@@ -772,311 +771,324 @@
 include/grpc/impl/codegen/grpc_types.h \
 include/grpc/impl/codegen/propagation_bits.h \
 include/grpc/impl/codegen/status.h \
+include/grpc/impl/codegen/alloc.h \
+include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm_gcc_atomic.h \
+include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_win32.h \
+include/grpc/impl/codegen/log.h \
+include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/slice_buffer.h \
+include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync_generic.h \
+include/grpc/impl/codegen/sync_posix.h \
+include/grpc/impl/codegen/sync_win32.h \
+include/grpc/impl/codegen/time.h \
+include/grpc/grpc_security.h \
+include/grpc/grpc_security_constants.h \
 include/grpc/census.h \
-src/core/census/grpc_filter.h \
-src/core/census/grpc_plugin.h \
-src/core/channel/channel_args.h \
-src/core/channel/channel_stack.h \
-src/core/channel/channel_stack_builder.h \
-src/core/channel/client_channel.h \
-src/core/channel/client_uchannel.h \
-src/core/channel/compress_filter.h \
-src/core/channel/connected_channel.h \
-src/core/channel/context.h \
-src/core/channel/http_client_filter.h \
-src/core/channel/http_server_filter.h \
-src/core/channel/subchannel_call_holder.h \
-src/core/client_config/client_config.h \
-src/core/client_config/connector.h \
-src/core/client_config/initial_connect_string.h \
-src/core/client_config/lb_policies/load_balancer_api.h \
-src/core/client_config/lb_policies/pick_first.h \
-src/core/client_config/lb_policies/round_robin.h \
-src/core/client_config/lb_policy.h \
-src/core/client_config/lb_policy_factory.h \
-src/core/client_config/lb_policy_registry.h \
-src/core/client_config/resolver.h \
-src/core/client_config/resolver_factory.h \
-src/core/client_config/resolver_registry.h \
-src/core/client_config/resolvers/dns_resolver.h \
-src/core/client_config/resolvers/sockaddr_resolver.h \
-src/core/client_config/subchannel.h \
-src/core/client_config/subchannel_factory.h \
-src/core/client_config/subchannel_index.h \
-src/core/client_config/uri_parser.h \
-src/core/compression/algorithm_metadata.h \
-src/core/compression/message_compress.h \
-src/core/debug/trace.h \
-src/core/httpcli/format_request.h \
-src/core/httpcli/httpcli.h \
-src/core/httpcli/parser.h \
-src/core/iomgr/closure.h \
-src/core/iomgr/endpoint.h \
-src/core/iomgr/endpoint_pair.h \
-src/core/iomgr/exec_ctx.h \
-src/core/iomgr/executor.h \
-src/core/iomgr/fd_posix.h \
-src/core/iomgr/iocp_windows.h \
-src/core/iomgr/iomgr.h \
-src/core/iomgr/iomgr_internal.h \
-src/core/iomgr/iomgr_posix.h \
-src/core/iomgr/pollset.h \
-src/core/iomgr/pollset_posix.h \
-src/core/iomgr/pollset_set.h \
-src/core/iomgr/pollset_set_posix.h \
-src/core/iomgr/pollset_set_windows.h \
-src/core/iomgr/pollset_windows.h \
-src/core/iomgr/resolve_address.h \
-src/core/iomgr/sockaddr.h \
-src/core/iomgr/sockaddr_posix.h \
-src/core/iomgr/sockaddr_utils.h \
-src/core/iomgr/sockaddr_win32.h \
-src/core/iomgr/socket_utils_posix.h \
-src/core/iomgr/socket_windows.h \
-src/core/iomgr/tcp_client.h \
-src/core/iomgr/tcp_posix.h \
-src/core/iomgr/tcp_server.h \
-src/core/iomgr/tcp_windows.h \
-src/core/iomgr/time_averaged_stats.h \
-src/core/iomgr/timer.h \
-src/core/iomgr/timer_heap.h \
-src/core/iomgr/udp_server.h \
-src/core/iomgr/wakeup_fd_pipe.h \
-src/core/iomgr/wakeup_fd_posix.h \
-src/core/iomgr/workqueue.h \
-src/core/iomgr/workqueue_posix.h \
-src/core/iomgr/workqueue_windows.h \
-src/core/json/json.h \
-src/core/json/json_common.h \
-src/core/json/json_reader.h \
-src/core/json/json_writer.h \
-src/core/proto/grpc/lb/v0/load_balancer.pb.h \
-src/core/statistics/census_interface.h \
-src/core/statistics/census_rpc_stats.h \
-src/core/surface/api_trace.h \
-src/core/surface/call.h \
-src/core/surface/call_test_only.h \
-src/core/surface/channel.h \
-src/core/surface/channel_init.h \
-src/core/surface/channel_stack_type.h \
-src/core/surface/completion_queue.h \
-src/core/surface/event_string.h \
-src/core/surface/init.h \
-src/core/surface/lame_client.h \
-src/core/surface/server.h \
-src/core/surface/surface_trace.h \
-src/core/transport/byte_stream.h \
-src/core/transport/chttp2/alpn.h \
-src/core/transport/chttp2/bin_encoder.h \
-src/core/transport/chttp2/frame.h \
-src/core/transport/chttp2/frame_data.h \
-src/core/transport/chttp2/frame_goaway.h \
-src/core/transport/chttp2/frame_ping.h \
-src/core/transport/chttp2/frame_rst_stream.h \
-src/core/transport/chttp2/frame_settings.h \
-src/core/transport/chttp2/frame_window_update.h \
-src/core/transport/chttp2/hpack_encoder.h \
-src/core/transport/chttp2/hpack_parser.h \
-src/core/transport/chttp2/hpack_table.h \
-src/core/transport/chttp2/http2_errors.h \
-src/core/transport/chttp2/huffsyms.h \
-src/core/transport/chttp2/incoming_metadata.h \
-src/core/transport/chttp2/internal.h \
-src/core/transport/chttp2/status_conversion.h \
-src/core/transport/chttp2/stream_map.h \
-src/core/transport/chttp2/timeout_encoding.h \
-src/core/transport/chttp2/varint.h \
-src/core/transport/chttp2_transport.h \
-src/core/transport/connectivity_state.h \
-src/core/transport/metadata.h \
-src/core/transport/metadata_batch.h \
-src/core/transport/static_metadata.h \
-src/core/transport/transport.h \
-src/core/transport/transport_impl.h \
-src/core/security/auth_filters.h \
-src/core/security/b64.h \
-src/core/security/credentials.h \
-src/core/security/handshake.h \
-src/core/security/json_token.h \
-src/core/security/jwt_verifier.h \
-src/core/security/secure_endpoint.h \
-src/core/security/security_connector.h \
-src/core/security/security_context.h \
-src/core/tsi/fake_transport_security.h \
-src/core/tsi/ssl_transport_security.h \
-src/core/tsi/ssl_types.h \
-src/core/tsi/transport_security.h \
-src/core/tsi/transport_security_interface.h \
-src/core/census/aggregation.h \
-src/core/census/mlog.h \
-src/core/census/rpc_metric_id.h \
+src/core/lib/channel/channel_args.h \
+src/core/lib/channel/channel_stack.h \
+src/core/lib/channel/channel_stack_builder.h \
+src/core/lib/channel/compress_filter.h \
+src/core/lib/channel/connected_channel.h \
+src/core/lib/channel/context.h \
+src/core/lib/channel/http_client_filter.h \
+src/core/lib/channel/http_server_filter.h \
+src/core/lib/compression/algorithm_metadata.h \
+src/core/lib/compression/message_compress.h \
+src/core/lib/debug/trace.h \
+src/core/lib/http/format_request.h \
+src/core/lib/http/httpcli.h \
+src/core/lib/http/parser.h \
+src/core/lib/iomgr/closure.h \
+src/core/lib/iomgr/endpoint.h \
+src/core/lib/iomgr/endpoint_pair.h \
+src/core/lib/iomgr/ev_poll_and_epoll_posix.h \
+src/core/lib/iomgr/ev_posix.h \
+src/core/lib/iomgr/exec_ctx.h \
+src/core/lib/iomgr/executor.h \
+src/core/lib/iomgr/iocp_windows.h \
+src/core/lib/iomgr/iomgr.h \
+src/core/lib/iomgr/iomgr_internal.h \
+src/core/lib/iomgr/iomgr_posix.h \
+src/core/lib/iomgr/pollset.h \
+src/core/lib/iomgr/pollset_set.h \
+src/core/lib/iomgr/pollset_set_windows.h \
+src/core/lib/iomgr/pollset_windows.h \
+src/core/lib/iomgr/resolve_address.h \
+src/core/lib/iomgr/sockaddr.h \
+src/core/lib/iomgr/sockaddr_posix.h \
+src/core/lib/iomgr/sockaddr_utils.h \
+src/core/lib/iomgr/sockaddr_win32.h \
+src/core/lib/iomgr/socket_utils_posix.h \
+src/core/lib/iomgr/socket_windows.h \
+src/core/lib/iomgr/tcp_client.h \
+src/core/lib/iomgr/tcp_posix.h \
+src/core/lib/iomgr/tcp_server.h \
+src/core/lib/iomgr/tcp_windows.h \
+src/core/lib/iomgr/time_averaged_stats.h \
+src/core/lib/iomgr/timer.h \
+src/core/lib/iomgr/timer_heap.h \
+src/core/lib/iomgr/udp_server.h \
+src/core/lib/iomgr/unix_sockets_posix.h \
+src/core/lib/iomgr/wakeup_fd_pipe.h \
+src/core/lib/iomgr/wakeup_fd_posix.h \
+src/core/lib/iomgr/workqueue.h \
+src/core/lib/iomgr/workqueue_posix.h \
+src/core/lib/iomgr/workqueue_windows.h \
+src/core/lib/json/json.h \
+src/core/lib/json/json_common.h \
+src/core/lib/json/json_reader.h \
+src/core/lib/json/json_writer.h \
+src/core/lib/surface/api_trace.h \
+src/core/lib/surface/call.h \
+src/core/lib/surface/call_test_only.h \
+src/core/lib/surface/channel.h \
+src/core/lib/surface/channel_init.h \
+src/core/lib/surface/channel_stack_type.h \
+src/core/lib/surface/completion_queue.h \
+src/core/lib/surface/event_string.h \
+src/core/lib/surface/init.h \
+src/core/lib/surface/lame_client.h \
+src/core/lib/surface/server.h \
+src/core/lib/surface/surface_trace.h \
+src/core/lib/transport/byte_stream.h \
+src/core/lib/transport/connectivity_state.h \
+src/core/lib/transport/metadata.h \
+src/core/lib/transport/metadata_batch.h \
+src/core/lib/transport/static_metadata.h \
+src/core/lib/transport/transport.h \
+src/core/lib/transport/transport_impl.h \
+src/core/ext/transport/chttp2/transport/bin_encoder.h \
+src/core/ext/transport/chttp2/transport/chttp2_transport.h \
+src/core/ext/transport/chttp2/transport/frame.h \
+src/core/ext/transport/chttp2/transport/frame_data.h \
+src/core/ext/transport/chttp2/transport/frame_goaway.h \
+src/core/ext/transport/chttp2/transport/frame_ping.h \
+src/core/ext/transport/chttp2/transport/frame_rst_stream.h \
+src/core/ext/transport/chttp2/transport/frame_settings.h \
+src/core/ext/transport/chttp2/transport/frame_window_update.h \
+src/core/ext/transport/chttp2/transport/hpack_encoder.h \
+src/core/ext/transport/chttp2/transport/hpack_parser.h \
+src/core/ext/transport/chttp2/transport/hpack_table.h \
+src/core/ext/transport/chttp2/transport/http2_errors.h \
+src/core/ext/transport/chttp2/transport/huffsyms.h \
+src/core/ext/transport/chttp2/transport/incoming_metadata.h \
+src/core/ext/transport/chttp2/transport/internal.h \
+src/core/ext/transport/chttp2/transport/status_conversion.h \
+src/core/ext/transport/chttp2/transport/stream_map.h \
+src/core/ext/transport/chttp2/transport/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/tsi/fake_transport_security.h \
+src/core/lib/tsi/ssl_transport_security.h \
+src/core/lib/tsi/ssl_types.h \
+src/core/lib/tsi/transport_security.h \
+src/core/lib/tsi/transport_security_interface.h \
+src/core/ext/client_config/client_channel.h \
+src/core/ext/client_config/client_channel_factory.h \
+src/core/ext/client_config/client_config.h \
+src/core/ext/client_config/connector.h \
+src/core/ext/client_config/initial_connect_string.h \
+src/core/ext/client_config/lb_policy.h \
+src/core/ext/client_config/lb_policy_factory.h \
+src/core/ext/client_config/lb_policy_registry.h \
+src/core/ext/client_config/parse_address.h \
+src/core/ext/client_config/resolver.h \
+src/core/ext/client_config/resolver_factory.h \
+src/core/ext/client_config/resolver_registry.h \
+src/core/ext/client_config/subchannel.h \
+src/core/ext/client_config/subchannel_call_holder.h \
+src/core/ext/client_config/subchannel_index.h \
+src/core/ext/client_config/uri_parser.h \
+src/core/ext/lb_policy/grpclb/load_balancer_api.h \
+src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h \
 third_party/nanopb/pb.h \
 third_party/nanopb/pb_common.h \
 third_party/nanopb/pb_decode.h \
 third_party/nanopb/pb_encode.h \
-src/core/census/grpc_context.c \
-src/core/census/grpc_filter.c \
-src/core/census/grpc_plugin.c \
-src/core/channel/channel_args.c \
-src/core/channel/channel_stack.c \
-src/core/channel/channel_stack_builder.c \
-src/core/channel/client_channel.c \
-src/core/channel/client_uchannel.c \
-src/core/channel/compress_filter.c \
-src/core/channel/connected_channel.c \
-src/core/channel/http_client_filter.c \
-src/core/channel/http_server_filter.c \
-src/core/channel/subchannel_call_holder.c \
-src/core/client_config/client_config.c \
-src/core/client_config/connector.c \
-src/core/client_config/default_initial_connect_string.c \
-src/core/client_config/initial_connect_string.c \
-src/core/client_config/lb_policies/load_balancer_api.c \
-src/core/client_config/lb_policies/pick_first.c \
-src/core/client_config/lb_policies/round_robin.c \
-src/core/client_config/lb_policy.c \
-src/core/client_config/lb_policy_factory.c \
-src/core/client_config/lb_policy_registry.c \
-src/core/client_config/resolver.c \
-src/core/client_config/resolver_factory.c \
-src/core/client_config/resolver_registry.c \
-src/core/client_config/resolvers/dns_resolver.c \
-src/core/client_config/resolvers/sockaddr_resolver.c \
-src/core/client_config/subchannel.c \
-src/core/client_config/subchannel_factory.c \
-src/core/client_config/subchannel_index.c \
-src/core/client_config/uri_parser.c \
-src/core/compression/compression_algorithm.c \
-src/core/compression/message_compress.c \
-src/core/debug/trace.c \
-src/core/httpcli/format_request.c \
-src/core/httpcli/httpcli.c \
-src/core/httpcli/parser.c \
-src/core/iomgr/closure.c \
-src/core/iomgr/endpoint.c \
-src/core/iomgr/endpoint_pair_posix.c \
-src/core/iomgr/endpoint_pair_windows.c \
-src/core/iomgr/exec_ctx.c \
-src/core/iomgr/executor.c \
-src/core/iomgr/fd_posix.c \
-src/core/iomgr/iocp_windows.c \
-src/core/iomgr/iomgr.c \
-src/core/iomgr/iomgr_posix.c \
-src/core/iomgr/iomgr_windows.c \
-src/core/iomgr/pollset_multipoller_with_epoll.c \
-src/core/iomgr/pollset_multipoller_with_poll_posix.c \
-src/core/iomgr/pollset_posix.c \
-src/core/iomgr/pollset_set_posix.c \
-src/core/iomgr/pollset_set_windows.c \
-src/core/iomgr/pollset_windows.c \
-src/core/iomgr/resolve_address_posix.c \
-src/core/iomgr/resolve_address_windows.c \
-src/core/iomgr/sockaddr_utils.c \
-src/core/iomgr/socket_utils_common_posix.c \
-src/core/iomgr/socket_utils_linux.c \
-src/core/iomgr/socket_utils_posix.c \
-src/core/iomgr/socket_windows.c \
-src/core/iomgr/tcp_client_posix.c \
-src/core/iomgr/tcp_client_windows.c \
-src/core/iomgr/tcp_posix.c \
-src/core/iomgr/tcp_server_posix.c \
-src/core/iomgr/tcp_server_windows.c \
-src/core/iomgr/tcp_windows.c \
-src/core/iomgr/time_averaged_stats.c \
-src/core/iomgr/timer.c \
-src/core/iomgr/timer_heap.c \
-src/core/iomgr/udp_server.c \
-src/core/iomgr/wakeup_fd_eventfd.c \
-src/core/iomgr/wakeup_fd_nospecial.c \
-src/core/iomgr/wakeup_fd_pipe.c \
-src/core/iomgr/wakeup_fd_posix.c \
-src/core/iomgr/workqueue_posix.c \
-src/core/iomgr/workqueue_windows.c \
-src/core/json/json.c \
-src/core/json/json_reader.c \
-src/core/json/json_string.c \
-src/core/json/json_writer.c \
-src/core/proto/grpc/lb/v0/load_balancer.pb.c \
-src/core/surface/alarm.c \
-src/core/surface/api_trace.c \
-src/core/surface/byte_buffer.c \
-src/core/surface/byte_buffer_reader.c \
-src/core/surface/call.c \
-src/core/surface/call_details.c \
-src/core/surface/call_log_batch.c \
-src/core/surface/channel.c \
-src/core/surface/channel_connectivity.c \
-src/core/surface/channel_create.c \
-src/core/surface/channel_init.c \
-src/core/surface/channel_ping.c \
-src/core/surface/channel_stack_type.c \
-src/core/surface/completion_queue.c \
-src/core/surface/event_string.c \
-src/core/surface/init.c \
-src/core/surface/lame_client.c \
-src/core/surface/metadata_array.c \
-src/core/surface/server.c \
-src/core/surface/server_chttp2.c \
-src/core/surface/validate_metadata.c \
-src/core/surface/version.c \
-src/core/transport/byte_stream.c \
-src/core/transport/chttp2/alpn.c \
-src/core/transport/chttp2/bin_encoder.c \
-src/core/transport/chttp2/frame_data.c \
-src/core/transport/chttp2/frame_goaway.c \
-src/core/transport/chttp2/frame_ping.c \
-src/core/transport/chttp2/frame_rst_stream.c \
-src/core/transport/chttp2/frame_settings.c \
-src/core/transport/chttp2/frame_window_update.c \
-src/core/transport/chttp2/hpack_encoder.c \
-src/core/transport/chttp2/hpack_parser.c \
-src/core/transport/chttp2/hpack_table.c \
-src/core/transport/chttp2/huffsyms.c \
-src/core/transport/chttp2/incoming_metadata.c \
-src/core/transport/chttp2/parsing.c \
-src/core/transport/chttp2/status_conversion.c \
-src/core/transport/chttp2/stream_lists.c \
-src/core/transport/chttp2/stream_map.c \
-src/core/transport/chttp2/timeout_encoding.c \
-src/core/transport/chttp2/varint.c \
-src/core/transport/chttp2/writing.c \
-src/core/transport/chttp2_transport.c \
-src/core/transport/connectivity_state.c \
-src/core/transport/metadata.c \
-src/core/transport/metadata_batch.c \
-src/core/transport/static_metadata.c \
-src/core/transport/transport.c \
-src/core/transport/transport_op_string.c \
-src/core/httpcli/httpcli_security_connector.c \
-src/core/security/b64.c \
-src/core/security/client_auth_filter.c \
-src/core/security/credentials.c \
-src/core/security/credentials_metadata.c \
-src/core/security/credentials_posix.c \
-src/core/security/credentials_win32.c \
-src/core/security/google_default_credentials.c \
-src/core/security/handshake.c \
-src/core/security/json_token.c \
-src/core/security/jwt_verifier.c \
-src/core/security/secure_endpoint.c \
-src/core/security/security_connector.c \
-src/core/security/security_context.c \
-src/core/security/server_auth_filter.c \
-src/core/security/server_secure_chttp2.c \
-src/core/surface/init_secure.c \
-src/core/surface/secure_channel_create.c \
-src/core/tsi/fake_transport_security.c \
-src/core/tsi/ssl_transport_security.c \
-src/core/tsi/transport_security.c \
-src/core/census/context.c \
-src/core/census/initialize.c \
-src/core/census/mlog.c \
-src/core/census/operation.c \
-src/core/census/placeholders.c \
-src/core/census/tracing.c \
+src/core/ext/census/aggregation.h \
+src/core/ext/census/census_interface.h \
+src/core/ext/census/census_rpc_stats.h \
+src/core/ext/census/grpc_filter.h \
+src/core/ext/census/mlog.h \
+src/core/ext/census/rpc_metric_id.h \
+src/core/lib/surface/init.c \
+src/core/lib/channel/channel_args.c \
+src/core/lib/channel/channel_stack.c \
+src/core/lib/channel/channel_stack_builder.c \
+src/core/lib/channel/compress_filter.c \
+src/core/lib/channel/connected_channel.c \
+src/core/lib/channel/http_client_filter.c \
+src/core/lib/channel/http_server_filter.c \
+src/core/lib/compression/compression_algorithm.c \
+src/core/lib/compression/message_compress.c \
+src/core/lib/debug/trace.c \
+src/core/lib/http/format_request.c \
+src/core/lib/http/httpcli.c \
+src/core/lib/http/parser.c \
+src/core/lib/iomgr/closure.c \
+src/core/lib/iomgr/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_posix.c \
+src/core/lib/iomgr/exec_ctx.c \
+src/core/lib/iomgr/executor.c \
+src/core/lib/iomgr/iocp_windows.c \
+src/core/lib/iomgr/iomgr.c \
+src/core/lib/iomgr/iomgr_posix.c \
+src/core/lib/iomgr/iomgr_windows.c \
+src/core/lib/iomgr/pollset_set_windows.c \
+src/core/lib/iomgr/pollset_windows.c \
+src/core/lib/iomgr/resolve_address_posix.c \
+src/core/lib/iomgr/resolve_address_windows.c \
+src/core/lib/iomgr/sockaddr_utils.c \
+src/core/lib/iomgr/socket_utils_common_posix.c \
+src/core/lib/iomgr/socket_utils_linux.c \
+src/core/lib/iomgr/socket_utils_posix.c \
+src/core/lib/iomgr/socket_windows.c \
+src/core/lib/iomgr/tcp_client_posix.c \
+src/core/lib/iomgr/tcp_client_windows.c \
+src/core/lib/iomgr/tcp_posix.c \
+src/core/lib/iomgr/tcp_server_posix.c \
+src/core/lib/iomgr/tcp_server_windows.c \
+src/core/lib/iomgr/tcp_windows.c \
+src/core/lib/iomgr/time_averaged_stats.c \
+src/core/lib/iomgr/timer.c \
+src/core/lib/iomgr/timer_heap.c \
+src/core/lib/iomgr/udp_server.c \
+src/core/lib/iomgr/unix_sockets_posix.c \
+src/core/lib/iomgr/unix_sockets_posix_noop.c \
+src/core/lib/iomgr/wakeup_fd_eventfd.c \
+src/core/lib/iomgr/wakeup_fd_nospecial.c \
+src/core/lib/iomgr/wakeup_fd_pipe.c \
+src/core/lib/iomgr/wakeup_fd_posix.c \
+src/core/lib/iomgr/workqueue_posix.c \
+src/core/lib/iomgr/workqueue_windows.c \
+src/core/lib/json/json.c \
+src/core/lib/json/json_reader.c \
+src/core/lib/json/json_string.c \
+src/core/lib/json/json_writer.c \
+src/core/lib/surface/alarm.c \
+src/core/lib/surface/api_trace.c \
+src/core/lib/surface/byte_buffer.c \
+src/core/lib/surface/byte_buffer_reader.c \
+src/core/lib/surface/call.c \
+src/core/lib/surface/call_details.c \
+src/core/lib/surface/call_log_batch.c \
+src/core/lib/surface/channel.c \
+src/core/lib/surface/channel_init.c \
+src/core/lib/surface/channel_ping.c \
+src/core/lib/surface/channel_stack_type.c \
+src/core/lib/surface/completion_queue.c \
+src/core/lib/surface/event_string.c \
+src/core/lib/surface/lame_client.c \
+src/core/lib/surface/metadata_array.c \
+src/core/lib/surface/server.c \
+src/core/lib/surface/validate_metadata.c \
+src/core/lib/surface/version.c \
+src/core/lib/transport/byte_stream.c \
+src/core/lib/transport/connectivity_state.c \
+src/core/lib/transport/metadata.c \
+src/core/lib/transport/metadata_batch.c \
+src/core/lib/transport/static_metadata.c \
+src/core/lib/transport/transport.c \
+src/core/lib/transport/transport_op_string.c \
+src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \
+src/core/ext/transport/chttp2/transport/bin_encoder.c \
+src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
+src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+src/core/ext/transport/chttp2/transport/frame_data.c \
+src/core/ext/transport/chttp2/transport/frame_goaway.c \
+src/core/ext/transport/chttp2/transport/frame_ping.c \
+src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+src/core/ext/transport/chttp2/transport/frame_settings.c \
+src/core/ext/transport/chttp2/transport/frame_window_update.c \
+src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+src/core/ext/transport/chttp2/transport/hpack_parser.c \
+src/core/ext/transport/chttp2/transport/hpack_table.c \
+src/core/ext/transport/chttp2/transport/huffsyms.c \
+src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+src/core/ext/transport/chttp2/transport/parsing.c \
+src/core/ext/transport/chttp2/transport/status_conversion.c \
+src/core/ext/transport/chttp2/transport/stream_lists.c \
+src/core/ext/transport/chttp2/transport/stream_map.c \
+src/core/ext/transport/chttp2/transport/timeout_encoding.c \
+src/core/ext/transport/chttp2/transport/varint.c \
+src/core/ext/transport/chttp2/transport/writing.c \
+src/core/ext/transport/chttp2/alpn/alpn.c \
+src/core/lib/http/httpcli_security_connector.c \
+src/core/lib/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/surface/init_secure.c \
+src/core/lib/tsi/fake_transport_security.c \
+src/core/lib/tsi/ssl_transport_security.c \
+src/core/lib/tsi/transport_security.c \
+src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \
+src/core/ext/client_config/channel_connectivity.c \
+src/core/ext/client_config/client_channel.c \
+src/core/ext/client_config/client_channel_factory.c \
+src/core/ext/client_config/client_config.c \
+src/core/ext/client_config/client_config_plugin.c \
+src/core/ext/client_config/connector.c \
+src/core/ext/client_config/default_initial_connect_string.c \
+src/core/ext/client_config/initial_connect_string.c \
+src/core/ext/client_config/lb_policy.c \
+src/core/ext/client_config/lb_policy_factory.c \
+src/core/ext/client_config/lb_policy_registry.c \
+src/core/ext/client_config/parse_address.c \
+src/core/ext/client_config/resolver.c \
+src/core/ext/client_config/resolver_factory.c \
+src/core/ext/client_config/resolver_registry.c \
+src/core/ext/client_config/subchannel.c \
+src/core/ext/client_config/subchannel_call_holder.c \
+src/core/ext/client_config/subchannel_index.c \
+src/core/ext/client_config/uri_parser.c \
+src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
+src/core/ext/transport/chttp2/client/insecure/channel_create.c \
+src/core/ext/lb_policy/grpclb/load_balancer_api.c \
+src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \
 third_party/nanopb/pb_common.c \
 third_party/nanopb/pb_decode.c \
 third_party/nanopb/pb_encode.c \
+src/core/ext/lb_policy/pick_first/pick_first.c \
+src/core/ext/lb_policy/round_robin/round_robin.c \
+src/core/ext/resolver/dns/native/dns_resolver.c \
+src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
+src/core/ext/census/context.c \
+src/core/ext/census/grpc_context.c \
+src/core/ext/census/grpc_filter.c \
+src/core/ext/census/grpc_plugin.c \
+src/core/ext/census/initialize.c \
+src/core/ext/census/mlog.c \
+src/core/ext/census/operation.c \
+src/core/ext/census/placeholders.c \
+src/core/ext/census/tracing.c \
+src/core/plugin_registry/grpc_plugin_registry.c \
 include/grpc/support/alloc.h \
 include/grpc/support/atm.h \
 include/grpc/support/atm_gcc_atomic.h \
@@ -1119,62 +1131,62 @@
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_win32.h \
 include/grpc/impl/codegen/time.h \
-src/core/profiling/timers.h \
-src/core/support/backoff.h \
-src/core/support/block_annotate.h \
-src/core/support/env.h \
-src/core/support/load_file.h \
-src/core/support/murmur_hash.h \
-src/core/support/stack_lockfree.h \
-src/core/support/string.h \
-src/core/support/string_win32.h \
-src/core/support/thd_internal.h \
-src/core/support/time_precise.h \
-src/core/support/tmpfile.h \
-src/core/profiling/basic_timers.c \
-src/core/profiling/stap_timers.c \
-src/core/support/alloc.c \
-src/core/support/avl.c \
-src/core/support/backoff.c \
-src/core/support/cmdline.c \
-src/core/support/cpu_iphone.c \
-src/core/support/cpu_linux.c \
-src/core/support/cpu_posix.c \
-src/core/support/cpu_windows.c \
-src/core/support/env_linux.c \
-src/core/support/env_posix.c \
-src/core/support/env_win32.c \
-src/core/support/histogram.c \
-src/core/support/host_port.c \
-src/core/support/load_file.c \
-src/core/support/log.c \
-src/core/support/log_android.c \
-src/core/support/log_linux.c \
-src/core/support/log_posix.c \
-src/core/support/log_win32.c \
-src/core/support/murmur_hash.c \
-src/core/support/slice.c \
-src/core/support/slice_buffer.c \
-src/core/support/stack_lockfree.c \
-src/core/support/string.c \
-src/core/support/string_posix.c \
-src/core/support/string_win32.c \
-src/core/support/subprocess_posix.c \
-src/core/support/subprocess_windows.c \
-src/core/support/sync.c \
-src/core/support/sync_posix.c \
-src/core/support/sync_win32.c \
-src/core/support/thd.c \
-src/core/support/thd_posix.c \
-src/core/support/thd_win32.c \
-src/core/support/time.c \
-src/core/support/time_posix.c \
-src/core/support/time_precise.c \
-src/core/support/time_win32.c \
-src/core/support/tls_pthread.c \
-src/core/support/tmpfile_posix.c \
-src/core/support/tmpfile_win32.c \
-src/core/support/wrap_memcpy.c
+src/core/lib/profiling/timers.h \
+src/core/lib/support/backoff.h \
+src/core/lib/support/block_annotate.h \
+src/core/lib/support/env.h \
+src/core/lib/support/load_file.h \
+src/core/lib/support/murmur_hash.h \
+src/core/lib/support/stack_lockfree.h \
+src/core/lib/support/string.h \
+src/core/lib/support/string_win32.h \
+src/core/lib/support/thd_internal.h \
+src/core/lib/support/time_precise.h \
+src/core/lib/support/tmpfile.h \
+src/core/lib/profiling/basic_timers.c \
+src/core/lib/profiling/stap_timers.c \
+src/core/lib/support/alloc.c \
+src/core/lib/support/avl.c \
+src/core/lib/support/backoff.c \
+src/core/lib/support/cmdline.c \
+src/core/lib/support/cpu_iphone.c \
+src/core/lib/support/cpu_linux.c \
+src/core/lib/support/cpu_posix.c \
+src/core/lib/support/cpu_windows.c \
+src/core/lib/support/env_linux.c \
+src/core/lib/support/env_posix.c \
+src/core/lib/support/env_win32.c \
+src/core/lib/support/histogram.c \
+src/core/lib/support/host_port.c \
+src/core/lib/support/load_file.c \
+src/core/lib/support/log.c \
+src/core/lib/support/log_android.c \
+src/core/lib/support/log_linux.c \
+src/core/lib/support/log_posix.c \
+src/core/lib/support/log_win32.c \
+src/core/lib/support/murmur_hash.c \
+src/core/lib/support/slice.c \
+src/core/lib/support/slice_buffer.c \
+src/core/lib/support/stack_lockfree.c \
+src/core/lib/support/string.c \
+src/core/lib/support/string_posix.c \
+src/core/lib/support/string_win32.c \
+src/core/lib/support/subprocess_posix.c \
+src/core/lib/support/subprocess_windows.c \
+src/core/lib/support/sync.c \
+src/core/lib/support/sync_posix.c \
+src/core/lib/support/sync_win32.c \
+src/core/lib/support/thd.c \
+src/core/lib/support/thd_posix.c \
+src/core/lib/support/thd_win32.c \
+src/core/lib/support/time.c \
+src/core/lib/support/time_posix.c \
+src/core/lib/support/time_precise.c \
+src/core/lib/support/time_win32.c \
+src/core/lib/support/tls_pthread.c \
+src/core/lib/support/tmpfile_posix.c \
+src/core/lib/support/tmpfile_win32.c \
+src/core/lib/support/wrap_memcpy.c
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/tools/fuzzer/build_and_run_fuzzer.sh b/tools/fuzzer/build_and_run_fuzzer.sh
new file mode 100755
index 0000000..7139097
--- /dev/null
+++ b/tools/fuzzer/build_and_run_fuzzer.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# 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.
+#
+
+set -ex
+
+cd $(dirname $0)/../..
+make CONFIG=$config $1 -j3
+mkdir -p fuzzer_output
+export ASAN_OPTIONS=handle_abort=1
+. tools/fuzzer/runners/$1.sh
diff --git a/tools/fuzzer/runners/api_fuzzer.sh b/tools/fuzzer/runners/api_fuzzer.sh
new file mode 100644
index 0000000..d1c1e7d
--- /dev/null
+++ b/tools/fuzzer/runners/api_fuzzer.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
+
+flags="$flags -dict=test/core/end2end/fuzzers/api_fuzzer.dictionary"
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/api_fuzzer $flags fuzzer_output test/core/end2end/fuzzers/api_fuzzer_corpus
diff --git a/tools/fuzzer/runners/client_fuzzer.sh b/tools/fuzzer/runners/client_fuzzer.sh
new file mode 100644
index 0000000..df03e27
--- /dev/null
+++ b/tools/fuzzer/runners/client_fuzzer.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
+
+flags="$flags -dict=test/core/end2end/fuzzers/hpack.dictionary"
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/client_fuzzer $flags fuzzer_output test/core/end2end/fuzzers/client_fuzzer_corpus
diff --git a/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh b/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh
new file mode 100644
index 0000000..e49c082
--- /dev/null
+++ b/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=512 -timeout=120"
+
+flags="$flags -dict=test/core/end2end/fuzzers/hpack.dictionary"
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/hpack_parser_fuzzer_test $flags fuzzer_output test/core/transport/chttp2/hpack_parser_corpus
diff --git a/tools/fuzzer/runners/http_fuzzer_test.sh b/tools/fuzzer/runners/http_fuzzer_test.sh
new file mode 100644
index 0000000..d8dde14
--- /dev/null
+++ b/tools/fuzzer/runners/http_fuzzer_test.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
+
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/http_fuzzer_test $flags fuzzer_output test/core/http/corpus
diff --git a/tools/fuzzer/runners/json_fuzzer_test.sh b/tools/fuzzer/runners/json_fuzzer_test.sh
new file mode 100644
index 0000000..9eaef87
--- /dev/null
+++ b/tools/fuzzer/runners/json_fuzzer_test.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=512 -timeout=120"
+
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/json_fuzzer_test $flags fuzzer_output test/core/json/corpus
diff --git a/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh b/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh
new file mode 100644
index 0000000..9db425b
--- /dev/null
+++ b/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128 -timeout=120"
+
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/nanopb_fuzzer_response_test $flags fuzzer_output test/core/nanopb/corpus_response
diff --git a/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh b/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh
new file mode 100644
index 0000000..33cfe67
--- /dev/null
+++ b/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128 -timeout=120"
+
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/nanopb_fuzzer_serverlist_test $flags fuzzer_output test/core/nanopb/corpus_serverlist
diff --git a/tools/fuzzer/runners/server_fuzzer.sh b/tools/fuzzer/runners/server_fuzzer.sh
new file mode 100644
index 0000000..337307a
--- /dev/null
+++ b/tools/fuzzer/runners/server_fuzzer.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
+
+flags="$flags -dict=test/core/end2end/fuzzers/hpack.dictionary"
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/server_fuzzer $flags fuzzer_output test/core/end2end/fuzzers/server_fuzzer_corpus
diff --git a/tools/fuzzer/runners/uri_fuzzer_test.sh b/tools/fuzzer/runners/uri_fuzzer_test.sh
new file mode 100644
index 0000000..84d63bf
--- /dev/null
+++ b/tools/fuzzer/runners/uri_fuzzer_test.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128 -timeout=120"
+
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/uri_fuzzer_test $flags fuzzer_output test/core/client_config/uri_corpus
diff --git a/tools/gce/create_interop_worker.sh b/tools/gce/create_interop_worker.sh
new file mode 100755
index 0000000..9170d82
--- /dev/null
+++ b/tools/gce/create_interop_worker.sh
@@ -0,0 +1,64 @@
+#!/bin/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.
+
+# Creates an interop worker on GCE.
+# IMPORTANT: After this script finishes, there are still some manual
+# steps needed there are hard to automatize.
+# See go/grpc-jenkins-setup for followup instructions.
+
+set -ex
+
+cd $(dirname $0)
+
+CLOUD_PROJECT=grpc-testing
+ZONE=us-east1-a  # canary gateway is reachable from this zone
+
+INSTANCE_NAME="${1:-grpc-canary-interop2}"
+
+gcloud compute instances create $INSTANCE_NAME \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    --machine-type n1-standard-16 \
+    --image ubuntu-15-10 \
+    --boot-disk-size 1000 \
+    --scopes https://www.googleapis.com/auth/xapi.zoo
+
+echo 'Created GCE instance, waiting 60 seconds for it to come online.'
+sleep 60
+
+gcloud compute copy-files \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    jenkins_master.pub linux_worker_init.sh ${INSTANCE_NAME}:~
+
+gcloud compute ssh \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    $INSTANCE_NAME --command "./linux_worker_init.sh"
diff --git a/tools/gce/create_linux_performance_worker.sh b/tools/gce/create_linux_performance_worker.sh
new file mode 100755
index 0000000..8c9cc46
--- /dev/null
+++ b/tools/gce/create_linux_performance_worker.sh
@@ -0,0 +1,65 @@
+#!/bin/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.
+
+# Creates a performance worker on GCE.
+# IMPORTANT: After creating the worker, one needs to manually add the pubkey
+# of jenkins@the-machine-where-jenkins-starts-perf-tests
+# to ~/.ssh/authorized_keys so that multi-machine scenarios can work.
+# See tools/run_tests/run_performance_tests.py for details.
+
+set -ex
+
+cd $(dirname $0)
+
+CLOUD_PROJECT=grpc-testing
+ZONE=us-central1-b  # this zone allows 32core machines
+
+INSTANCE_NAME="${1:-grpc-performance-server1}"
+MACHINE_TYPE=n1-standard-32
+
+gcloud compute instances create $INSTANCE_NAME \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    --machine-type $MACHINE_TYPE \
+    --image ubuntu-15-10 \
+    --boot-disk-size 300
+
+echo 'Created GCE instance, waiting 60 seconds for it to come online.'
+sleep 60
+
+gcloud compute copy-files \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    jenkins_master.pub linux_performance_worker_init.sh jenkins@${INSTANCE_NAME}:~
+
+gcloud compute ssh \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    jenkins@${INSTANCE_NAME} --command "./linux_performance_worker_init.sh"
diff --git a/tools/gce/create_linux_worker.sh b/tools/gce/create_linux_worker.sh
index 399e3ec..dff0b1c 100755
--- a/tools/gce/create_linux_worker.sh
+++ b/tools/gce/create_linux_worker.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/gce/linux_performance_worker_init.sh b/tools/gce/linux_performance_worker_init.sh
new file mode 100755
index 0000000..478e04e
--- /dev/null
+++ b/tools/gce/linux_performance_worker_init.sh
@@ -0,0 +1,112 @@
+#!/bin/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.
+
+# Initializes a fresh GCE VM to become a jenkins linux performance worker.
+# You shouldn't run this script on your own,
+# use create_linux_performance_worker.sh instead.
+
+set -ex
+
+sudo apt-get update
+
+# Install Java 8 JDK (to build gRPC Java)
+sudo apt-get install -y openjdk-8-jdk
+sudo apt-get install -y unzip lsof
+
+# Add pubkey of jenkins@grpc-jenkins-master to authorized keys of jenkins@
+# This needs to happen as the last step to prevent Jenkins master from connecting
+# to a machine that hasn't been properly setup yet.
+cat jenkins_master.pub | sudo tee --append ~jenkins/.ssh/authorized_keys
+
+sudo apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  strace \
+  pypy \
+  python-dev \
+  python-pip \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip
+
+# perftools
+sudo apt-get install -y google-perftools libgoogle-perftools-dev
+
+# C++ dependencies
+sudo apt-get install -y libgflags-dev libgtest-dev libc++-dev clang
+
+# Python dependencies
+sudo pip install tabulate
+sudo pip install google-api-python-client
+
+curl -O https://bootstrap.pypa.io/get-pip.py
+sudo pypy get-pip.py
+sudo pypy -m pip install tabulate
+sudo pip install google-api-python-client
+
+# Node dependencies (nvm has to be installed under user jenkins)
+touch .profile
+curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
+nvm install 0.12 && npm config set cache /tmp/npm-cache
+
+# C# dependencies (http://www.mono-project.com/docs/getting-started/install/linux/#debian-ubuntu-and-derivatives)
+
+sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
+sudo apt-get update
+sudo apt-get install -y mono-devel nuget
+
+# Ruby dependencies
+gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
+curl -sSL https://get.rvm.io | bash -s stable --ruby
+
+# Install bundler (prerequisite for gRPC Ruby)
+source ~/.rvm/scripts/rvm
+gem install bundler
+
+# Java dependencies - nothing as we already have Java JDK 8
diff --git a/tools/gce/linux_worker_init.sh b/tools/gce/linux_worker_init.sh
index f56cac0..ef6a5d1 100755
--- a/tools/gce/linux_worker_init.sh
+++ b/tools/gce/linux_worker_init.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/gcp/stress_test/run_client.py b/tools/gcp/stress_test/run_client.py
index 0fa1bf1..2004bf6 100755
--- a/tools/gcp/stress_test/run_client.py
+++ b/tools/gcp/stress_test/run_client.py
@@ -31,6 +31,7 @@
 import datetime
 import os
 import re
+import resource
 import select
 import subprocess
 import sys
@@ -89,11 +90,16 @@
                examining logs). This is the reason why the script waits forever
                in case of failures
   """
+  # Set the 'core file' size to 'unlimited' so that 'core' files are generated
+  # if the client crashes (Note: This is not relevant for Java and Go clients)
+  resource.setrlimit(resource.RLIMIT_CORE,
+                     (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
+
   env = dict(os.environ)
   image_type = env['STRESS_TEST_IMAGE_TYPE']
-  image_name = env['STRESS_TEST_IMAGE']
+  stress_client_cmd = env['STRESS_TEST_CMD'].split()
   args_str = env['STRESS_TEST_ARGS_STR']
-  metrics_client_image = env['METRICS_CLIENT_IMAGE']
+  metrics_client_cmd = env['METRICS_CLIENT_CMD'].split()
   metrics_client_args_str = env['METRICS_CLIENT_ARGS_STR']
   run_id = env['RUN_ID']
   pod_name = env['POD_NAME']
@@ -103,6 +109,11 @@
   dataset_id = env['DATASET_ID']
   summary_table_id = env['SUMMARY_TABLE_ID']
   qps_table_id = env['QPS_TABLE_ID']
+  # The following parameter is to inform us whether the stress client runs
+  # forever until forcefully stopped or will it naturally stop after sometime.
+  # This way, we know that the stress client process should not terminate (even
+  # if it does with a success exit code) and flag the termination as a failure
+  will_run_forever = env.get('WILL_RUN_FOREVER', '1')
 
   bq_helper = BigQueryHelper(run_id, image_type, pod_name, project_id,
                              dataset_id, summary_table_id, qps_table_id)
@@ -125,9 +136,8 @@
   # Update status that the test is starting (in the status table)
   bq_helper.insert_summary_row(EventType.STARTING, details)
 
-  metrics_cmd = [metrics_client_image
-                ] + [x for x in metrics_client_args_str.split()]
-  stress_cmd = [image_name] + [x for x in args_str.split()]
+  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,
@@ -141,11 +151,12 @@
   while True:
     # Check if stress_client is still running. If so, collect metrics and upload
     # to BigQuery status table
+    # If stress_p.poll() is not None, it means that the stress client terminated
     if stress_p.poll() is not None:
       end_time = datetime.datetime.now().isoformat()
       event_type = EventType.SUCCESS
       details = 'End time: %s' % end_time
-      if stress_p.returncode != 0:
+      if will_run_forever == '1' or stress_p.returncode != 0:
         event_type = EventType.FAILURE
         details = 'Return code = %d. End time: %s' % (stress_p.returncode,
                                                       end_time)
diff --git a/tools/gcp/stress_test/run_node.sh b/tools/gcp/stress_test/run_node.sh
new file mode 100755
index 0000000..4a4da6f
--- /dev/null
+++ b/tools/gcp/stress_test/run_node.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# 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.
+
+# This is a wrapper script that was created to help run_server.py and
+# run_client.py to launch 'node js' stress clients and stress servers
+source ~/.nvm/nvm.sh
+
+set -ex
+
+$@
diff --git a/tools/gcp/stress_test/run_server.py b/tools/gcp/stress_test/run_server.py
index 64322f6..a666ae2 100755
--- a/tools/gcp/stress_test/run_server.py
+++ b/tools/gcp/stress_test/run_server.py
@@ -30,6 +30,7 @@
 
 import datetime
 import os
+import resource
 import select
 import subprocess
 import sys
@@ -56,26 +57,36 @@
          might want to connect to the pod for examining logs). This is the
          reason why the script waits forever in case of failures.
   """
+  # Set the 'core file' size to 'unlimited' so that 'core' files are generated
+  # if the server crashes (Note: This is not relevant for Java and Go servers)
+  resource.setrlimit(resource.RLIMIT_CORE,
+                     (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
 
   # Read the parameters from environment variables
   env = dict(os.environ)
 
   run_id = env['RUN_ID']  # The unique run id for this test
   image_type = env['STRESS_TEST_IMAGE_TYPE']
-  image_name = env['STRESS_TEST_IMAGE']
+  stress_server_cmd = env['STRESS_TEST_CMD'].split()
   args_str = env['STRESS_TEST_ARGS_STR']
   pod_name = env['POD_NAME']
   project_id = env['GCP_PROJECT_ID']
   dataset_id = env['DATASET_ID']
   summary_table_id = env['SUMMARY_TABLE_ID']
   qps_table_id = env['QPS_TABLE_ID']
+  # The following parameter is to inform us whether the server runs forever
+  # until forcefully stopped or will it naturally stop after sometime.
+  # This way, we know that the process should not terminate (even if it does
+  # with a success exit code) and flag any termination as a failure.
+  will_run_forever = env.get('WILL_RUN_FOREVER', '1')
 
   logfile_name = env.get('LOGFILE_NAME')
 
   print('pod_name: %s, project_id: %s, run_id: %s, dataset_id: %s, '
-        'summary_table_id: %s, qps_table_id: %s') % (
-            pod_name, project_id, run_id, dataset_id, summary_table_id,
-            qps_table_id)
+        'summary_table_id: %s, qps_table_id: %s') % (pod_name, project_id,
+                                                     run_id, dataset_id,
+                                                     summary_table_id,
+                                                     qps_table_id)
 
   bq_helper = BigQueryHelper(run_id, image_type, pod_name, project_id,
                              dataset_id, summary_table_id, qps_table_id)
@@ -98,7 +109,7 @@
   # Update status that the test is starting (in the status table)
   bq_helper.insert_summary_row(EventType.STARTING, details)
 
-  stress_cmd = [image_name] + [x for x in args_str.split()]
+  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,
@@ -106,7 +117,8 @@
                               stderr=subprocess.STDOUT)
 
   returncode = stress_p.wait()
-  if returncode != 0:
+
+  if will_run_forever == '1' or returncode != 0:
     end_time = datetime.datetime.now().isoformat()
     event_type = EventType.FAILURE
     details = 'Returncode: %d; End time: %s' % (returncode, end_time)
diff --git a/tools/gcp/stress_test/stress_test_utils.py b/tools/gcp/stress_test/stress_test_utils.py
index c4b437e..19d59c0 100755
--- a/tools/gcp/stress_test/stress_test_utils.py
+++ b/tools/gcp/stress_test/stress_test_utils.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -103,16 +103,32 @@
     return bq_utils.insert_rows(self.bq, self.project_id, self.dataset_id,
                                 self.qps_table_id, [row])
 
-  def check_if_any_tests_failed(self, num_query_retries=3):
+  def check_if_any_tests_failed(self, num_query_retries=3, timeout_msec=30000):
     query = ('SELECT event_type FROM %s.%s WHERE run_id = \'%s\' AND '
              'event_type="%s"') % (self.dataset_id, self.summary_table_id,
                                    self.run_id, EventType.FAILURE)
-    query_job = bq_utils.sync_query_job(self.bq, self.project_id, query)
-    page = self.bq.jobs().getQueryResults(**query_job['jobReference']).execute(
-        num_retries=num_query_retries)
-    num_failures = int(page['totalRows'])
-    print 'num rows: ', num_failures
-    return num_failures > 0
+    page = None
+    try:
+      query_job = bq_utils.sync_query_job(self.bq, self.project_id, query)
+      job_id = query_job['jobReference']['jobId']
+      project_id = query_job['jobReference']['projectId']
+      page = self.bq.jobs().getQueryResults(
+          projectId=project_id,
+          jobId=job_id,
+          timeoutMs=timeout_msec).execute(num_retries=num_query_retries)
+
+      if not page['jobComplete']:
+        print('TIMEOUT ERROR: The query %s timed out. Current timeout value is'
+              ' %d msec. Returning False (i.e assuming there are no failures)'
+             ) % (query, timeoout_msec)
+        return False
+
+      num_failures = int(page['totalRows'])
+      print 'num rows: ', num_failures
+      return num_failures > 0
+    except:
+      print 'Exception in check_if_any_tests_failed(). Info: ', sys.exc_info()
+      print 'Query: ', query
 
   def print_summary_records(self, num_query_retries=3):
     line = '-' * 120
@@ -126,8 +142,9 @@
                  self.dataset_id, self.summary_table_id, self.run_id)
     query_job = bq_utils.sync_query_job(self.bq, self.project_id, query)
 
-    print '{:<25} {:<12} {:<12} {:<30} {}'.format(
-        'Pod name', 'Image type', 'Event type', 'Date', 'Details')
+    print '{:<25} {:<12} {:<12} {:<30} {}'.format('Pod name', 'Image type',
+                                                  'Event type', 'Date',
+                                                  'Details')
     print line
     page_token = None
     while True:
@@ -136,9 +153,11 @@
           **query_job['jobReference']).execute(num_retries=num_query_retries)
       rows = page.get('rows', [])
       for row in rows:
-        print '{:<25} {:<12} {:<12} {:<30} {}'.format(
-            row['f'][0]['v'], row['f'][1]['v'], row['f'][2]['v'],
-            row['f'][3]['v'], row['f'][4]['v'])
+        print '{:<25} {:<12} {:<12} {:<30} {}'.format(row['f'][0]['v'],
+                                                      row['f'][1]['v'],
+                                                      row['f'][2]['v'],
+                                                      row['f'][3]['v'],
+                                                      row['f'][4]['v'])
       page_token = page.get('pageToken')
       if not page_token:
         break
diff --git a/tools/gcp/utils/big_query_utils.py b/tools/gcp/utils/big_query_utils.py
index 7bb1e14..9dbc69c 100755
--- a/tools/gcp/utils/big_query_utils.py
+++ b/tools/gcp/utils/big_query_utils.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -71,16 +71,22 @@
 
 def create_table(big_query, project_id, dataset_id, table_id, table_schema,
                  description):
+  fields = [{'name': field_name,
+             'type': field_type,
+             'description': field_description
+             } for (field_name, field_type, field_description) in table_schema]
+  return create_table2(big_query, project_id, dataset_id, table_id,
+                       fields, description)
+
+
+def create_table2(big_query, project_id, dataset_id, table_id, fields_schema,
+                 description):
   is_success = True
 
   body = {
       'description': description,
       'schema': {
-          'fields': [{
-              'name': field_name,
-              'type': field_type,
-              'description': field_description
-          } for (field_name, field_type, field_description) in table_schema]
+          'fields': fields_schema
       },
       'tableReference': {
           'datasetId': dataset_id,
@@ -112,12 +118,14 @@
                                                  datasetId=dataset_id,
                                                  tableId=table_id,
                                                  body=body)
-    print body
     res = insert_req.execute(num_retries=NUM_RETRIES)
-    print res
+    if res.get('insertErrors', None):
+      print 'Error inserting rows! Response: %s' % res
+      is_success = False
   except HttpError as http_error:
-    print 'Error in inserting rows in the table %s' % table_id
+    print 'Error inserting rows to the table %s' % table_id
     is_success = False
+
   return is_success
 
 
diff --git a/tools/gcp/utils/kubernetes_api.py b/tools/gcp/utils/kubernetes_api.py
index e8ddd2f..a8a4aad 100755
--- a/tools/gcp/utils/kubernetes_api.py
+++ b/tools/gcp/utils/kubernetes_api.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/gource/gource.sh b/tools/gource/gource.sh
new file mode 100755
index 0000000..0199609
--- /dev/null
+++ b/tools/gource/gource.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# 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.
+
+gource --multi-sampling -c 4 -s 0.1 --max-file-lag 0.05 --max-files 0 -e 0.05 --hide filenames,dirnames $*
+
diff --git a/tools/http2_interop/http2interop.go b/tools/http2_interop/http2interop.go
index 1276a71..fa11396 100644
--- a/tools/http2_interop/http2interop.go
+++ b/tools/http2_interop/http2interop.go
@@ -150,7 +150,8 @@
 	}
 
 	// Write a bunch of invalid frame types.
-	for ft := ContinuationFrameType + 1; ft != 0; ft++ {
+	// Frame number 11 is the upcoming ALTSVC frame, and should not be tested.
+	for ft := ContinuationFrameType + 2; ft != 0; ft++ {
 		fh := &UnknownFrame{
 			Header: FrameHeader{
 				Type: ft,
diff --git a/tools/http2_interop/http2interop_test.go b/tools/http2_interop/http2interop_test.go
index fb314da..305125f 100644
--- a/tools/http2_interop/http2interop_test.go
+++ b/tools/http2_interop/http2interop_test.go
@@ -49,7 +49,7 @@
 
 	if ctx.UseTestCa {
 		// It would be odd if useTestCa was true, but not useTls.  meh
-		certData, err := ioutil.ReadFile("src/core/tsi/test_creds/ca.pem")
+		certData, err := ioutil.ReadFile("src/core/lib/tsi/test_creds/ca.pem")
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/tools/jenkins/build_docker_and_run_tests.sh b/tools/jenkins/build_docker_and_run_tests.sh
index 458e8ca..5779e63 100755
--- a/tools/jenkins/build_docker_and_run_tests.sh
+++ b/tools/jenkins/build_docker_and_run_tests.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/jenkins/build_interop_image.sh b/tools/jenkins/build_interop_image.sh
index 28d5f31..26687a5 100755
--- a/tools/jenkins/build_interop_image.sh
+++ b/tools/jenkins/build_interop_image.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/jenkins/build_interop_stress_image.sh b/tools/jenkins/build_interop_stress_image.sh
index 501dc5b..31ffa75 100755
--- a/tools/jenkins/build_interop_stress_image.sh
+++ b/tools/jenkins/build_interop_stress_image.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -34,10 +34,12 @@
 set -x
 
 # Params:
-#  INTEROP_IMAGE - name of tag of the final interop image
-#  INTEROP_IMAGE_TAG - Optional. If set, the created image will be tagged using
+#  INTEROP_IMAGE - Name of tag of the final interop image
+#  INTEROP_IMAGE_REPOSITORY_TAG - Optional. If set, the created image will be tagged using
 #    the command: 'docker tag $INTEROP_IMAGE $INTEROP_IMAGE_REPOSITORY_TAG'
-#  BASE_NAME - base name used to locate the base Dockerfile and build script
+#  BASE_NAME - Base name used to locate the base Dockerfile and build script
+#  BUILD_TYPE - The 'CONFIG' variable passed to the 'make' command (example:
+#  asan, tsan. Default value: opt).
 #  TTY_FLAG - optional -t flag to make docker allocate tty
 #  BUILD_INTEROP_DOCKER_EXTRA_ARGS - optional args to be passed to the
 #    docker run command
@@ -46,6 +48,22 @@
 GRPC_ROOT=`pwd`
 MOUNT_ARGS="-v $GRPC_ROOT:/var/local/jenkins/grpc:ro"
 
+GRPC_JAVA_ROOT=`cd ../grpc-java && pwd`
+if [ "$GRPC_JAVA_ROOT" != "" ]
+then
+  MOUNT_ARGS+=" -v $GRPC_JAVA_ROOT:/var/local/jenkins/grpc-java:ro"
+else
+  echo "WARNING: grpc-java not found, it won't be mounted to the docker container."
+fi
+
+GRPC_GO_ROOT=`cd ../grpc-go && pwd`
+if [ "$GRPC_GO_ROOT" != "" ]
+then
+  MOUNT_ARGS+=" -v $GRPC_GO_ROOT:/var/local/jenkins/grpc-go:ro"
+else
+  echo "WARNING: grpc-go not found, it won't be mounted to the docker container."
+fi
+
 mkdir -p /tmp/ccache
 
 # Mount service account dir if available.
@@ -57,10 +75,10 @@
 fi
 
 # Use image name based on Dockerfile checksum
-BASE_IMAGE=${BASE_NAME}_base:`sha1sum tools/dockerfile/$BASE_NAME/Dockerfile | cut -f1 -d\ `
+BASE_IMAGE=${BASE_NAME}_base:`sha1sum tools/dockerfile/stress_test/$BASE_NAME/Dockerfile | cut -f1 -d\ `
 
 # Make sure base docker image has been built. Should be instantaneous if so.
-docker build -t $BASE_IMAGE --force-rm=true tools/dockerfile/$BASE_NAME || exit $?
+docker build -t $BASE_IMAGE --force-rm=true tools/dockerfile/stress_test/$BASE_NAME || exit $?
 
 # Create a local branch so the child Docker script won't complain
 git branch -f jenkins-docker
@@ -71,13 +89,14 @@
 (docker run \
   -e CCACHE_DIR=/tmp/ccache \
   -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \
+  -e BUILD_TYPE=${BUILD_TYPE:=opt} \
   -i $TTY_FLAG \
   $MOUNT_ARGS \
   $BUILD_INTEROP_DOCKER_EXTRA_ARGS \
   -v /tmp/ccache:/tmp/ccache \
   --name=$CONTAINER_NAME \
   $BASE_IMAGE \
-  bash -l /var/local/jenkins/grpc/tools/dockerfile/$BASE_NAME/build_interop_stress.sh \
+  bash -l /var/local/jenkins/grpc/tools/dockerfile/stress_test/$BASE_NAME/build_interop_stress.sh \
   && docker commit $CONTAINER_NAME $INTEROP_IMAGE \
   && ( if [ -n "$INTEROP_IMAGE_REPOSITORY_TAG" ]; then docker tag -f $INTEROP_IMAGE $INTEROP_IMAGE_REPOSITORY_TAG ; fi ) \
   && echo "Successfully built image $INTEROP_IMAGE")
diff --git a/tools/jenkins/docker_run_tests.sh b/tools/jenkins/docker_run_tests.sh
index 8d6c42c..2fc66c2 100755
--- a/tools/jenkins/docker_run_tests.sh
+++ b/tools/jenkins/docker_run_tests.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
 set -e
 
 export CONFIG=$config
-export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.5
+export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
 
 # Ensure that programs depending on current-user-ownership of cache directories
 # are satisfied (it's being mounted from outside the image).
diff --git a/tools/jenkins/run_distribution.sh b/tools/jenkins/run_distribution.sh
index 446ce16..306b85b 100755
--- a/tools/jenkins/run_distribution.sh
+++ b/tools/jenkins/run_distribution.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/jenkins/run_fuzzer.sh b/tools/jenkins/run_fuzzer.sh
new file mode 100755
index 0000000..3f25a93
--- /dev/null
+++ b/tools/jenkins/run_fuzzer.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# 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.
+#
+# Builds and runs a fuzzer (specified by the first command line argument)
+
+set -ex
+
+export RUN_COMMAND="tools/fuzzer/build_and_run_fuzzer.sh $1"
+export DOCKER_RUN_SCRIPT=tools/jenkins/docker_run.sh
+export DOCKERFILE_DIR=tools/dockerfile/test/fuzzer
+export OUTPUT_DIR=fuzzer_output
+
+runtime=${runtime:-3600}
+jobs=${jobs:-3}
+
+tools/jenkins/build_and_run_docker.sh \
+  -e RUN_COMMAND="$RUN_COMMAND" \
+  -e OUTPUT_DIR="$OUTPUT_DIR" \
+  -e config="$config" \
+  -e runtime="$runtime" \
+  -e jobs="$jobs"
diff --git a/tools/jenkins/run_interop_stress.sh b/tools/jenkins/run_interop_stress.sh
index 8166f34..22d81db 100755
--- a/tools/jenkins/run_interop_stress.sh
+++ b/tools/jenkins/run_interop_stress.sh
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/jenkins/run_jenkins.sh b/tools/jenkins/run_jenkins.sh
index da6ca69..7a6dfe3 100755
--- a/tools/jenkins/run_jenkins.sh
+++ b/tools/jenkins/run_jenkins.sh
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/jenkins/run_performance.sh b/tools/jenkins/run_performance.sh
index fbc0783..903a144 100755
--- a/tools/jenkins/run_performance.sh
+++ b/tools/jenkins/run_performance.sh
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -34,103 +34,4 @@
 # Enter the gRPC repo root
 cd $(dirname $0)/../..
 
-[[ $* =~ '--latency_profile' ]] \
-	&& tools/profiling/latency_profile/run_latency_profile.sh \
-	|| true
-
-config=opt
-
-make CONFIG=$config qps_worker qps_driver -j8
-
-bins/$config/qps_worker -driver_port 10000 &
-PID1=$!
-bins/$config/qps_worker -driver_port 10010 &
-PID2=$!
-
-#
-# Put a timeout on these tests
-#
-((sleep 900; kill $$ && killall qps_worker && rm -f /tmp/qps-test.$$ )&)
-
-export QPS_WORKERS="localhost:10000,localhost:10010"
-
-# big is the size in bytes of large messages (0 is the size otherwise)
-big=65536
-
-# wide is the number of client channels in multi-channel tests (1 otherwise)
-wide=64
-
-# deep is the number of RPCs outstanding on a channel in non-ping-pong tests
-# (the value used is 1 otherwise)
-deep=100
-
-#
-# Get total core count
-cores=`grep -c ^processor /proc/cpuinfo`
-halfcores=`expr $cores / 2`
-
-for secure in true false; do
-  # Scenario 1: generic async streaming ping-pong (contentionless latency)
-  bins/$config/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=1 --bbuf_req_size=0 --bbuf_resp_size=0 \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1 \
-    --server_core_limit=$halfcores --client_core_limit=0
-
-  # Scenario 2: generic async streaming "unconstrained" (QPS)
-  bins/$config/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=0 \
-    --server_core_limit=$halfcores --client_core_limit=0 |& tee /tmp/qps-test.$$
-
-  # Scenario 2b: QPS with a single server core
-  bins/$config/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=0 --server_core_limit=1 --client_core_limit=0
-
-  # Scenario 2c: protobuf-based QPS
-  bins/$config/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=$wide --simple_req_size=0 --simple_resp_size=0 \
-    --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=0 \
-    --server_core_limit=$halfcores --client_core_limit=0
-
-  # Scenario 3: Latency at sub-peak load (all clients equally loaded)
-  for loadfactor in 0.7; do
-    bins/$config/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-      --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-      --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
-      --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-      --num_servers=1 --num_clients=0 --poisson_load=`awk -v lf=$loadfactor \
-      '$5 == "QPS:" {print int(lf * $6); exit}' /tmp/qps-test.$$` \
-      --server_core_limit=$halfcores --client_core_limit=0
-  done
-
-  rm /tmp/qps-test.$$
-
-  # Scenario 4: Single-channel bidirectional throughput test (like TCP_STREAM).
-  bins/$config/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
-    --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
-    --client_channels=1 --bbuf_req_size=$big --bbuf_resp_size=$big \
-    --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \
-    --num_servers=1 --num_clients=1 \
-    --server_core_limit=$halfcores --client_core_limit=0
-
-  # Scenario 5: Sync unary ping-pong with protobufs
-  bins/$config/qps_driver --rpc_type=UNARY --client_type=SYNC_CLIENT \
-    --server_type=SYNC_SERVER --outstanding_rpcs_per_channel=1 \
-    --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \
-    --secure_test=$secure --num_servers=1 --num_clients=1 \
-    --server_core_limit=$halfcores --client_core_limit=0
-
-done
-
-bins/$config/qps_driver --quit=true
-
-wait
+tools/run_tests/run_performance_tests.py -l c++ node ruby csharp
diff --git a/tools/jenkins/run_portability.sh b/tools/jenkins/run_portability.sh
index 6f15da7..18d34cc8 100755
--- a/tools/jenkins/run_portability.sh
+++ b/tools/jenkins/run_portability.sh
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/openssl/use_openssl.sh b/tools/openssl/use_openssl.sh
index 9318b34..09d8676 100755
--- a/tools/openssl/use_openssl.sh
+++ b/tools/openssl/use_openssl.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/build_artifact_node.sh b/tools/run_tests/build_artifact_node.sh
index 6aa4824..ef3476a 100755
--- a/tools/run_tests/build_artifact_node.sh
+++ b/tools/run_tests/build_artifact_node.sh
@@ -30,9 +30,9 @@
 
 NODE_TARGET_ARCH=$1
 source ~/.nvm/nvm.sh
-set -ex
 
 nvm use 4
+set -ex
 
 cd $(dirname $0)/../..
 
diff --git a/tools/run_tests/build_artifact_python.sh b/tools/run_tests/build_artifact_python.sh
index 7ba04d7..1f23f9f 100755
--- a/tools/run_tests/build_artifact_python.sh
+++ b/tools/run_tests/build_artifact_python.sh
@@ -35,15 +35,18 @@
 if [ "$SKIP_PIP_INSTALL" == "" ]
 then
   pip install --upgrade six
-  pip install --upgrade setuptools
+  # There's a bug in newer versions of setuptools (see
+  # https://bitbucket.org/pypa/setuptools/issues/503/pkg_resources_vendorpackagingrequirementsi)
+  pip install --upgrade 'setuptools==18'
   pip install -rrequirements.txt
 fi
 
+export GRPC_PYTHON_USE_CUSTOM_BDIST=0
+export GRPC_PYTHON_BUILD_WITH_CYTHON=1
+
 # Build the source distribution first because MANIFEST.in cannot override
 # exclusion of built shared objects among package resources (for some
 # inexplicable reason).
-GRPC_PYTHON_USE_CUSTOM_BDIST=0  \
-GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
 ${SETARCH_CMD} python setup.py  \
     sdist
 
@@ -51,15 +54,11 @@
 # and thus ought to be run in a shell command separate of others. Further, it
 # trashes the actual bdist_wheel output, so it should be run first so that
 # bdist_wheel may be run unmolested.
-GRPC_PYTHON_USE_CUSTOM_BDIST=0  \
-GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
 ${SETARCH_CMD} python setup.py  \
     build_tagged_ext
 
 # Wheel has a bug where directories don't get excluded.
 # https://bitbucket.org/pypa/wheel/issues/99/cannot-exclude-directory
-GRPC_PYTHON_USE_CUSTOM_BDIST=0  \
-GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
 ${SETARCH_CMD} python setup.py  \
     bdist_wheel
 
diff --git a/tools/run_tests/build_csharp.sh b/tools/run_tests/build_csharp.sh
index aadd11e..48ce11a 100755
--- a/tools/run_tests/build_csharp.sh
+++ b/tools/run_tests/build_csharp.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/build_node.sh b/tools/run_tests/build_node.sh
index 9c4af07..d9292fd 100755
--- a/tools/run_tests/build_node.sh
+++ b/tools/run_tests/build_node.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -31,9 +31,9 @@
 
 NODE_VERSION=$1
 source ~/.nvm/nvm.sh
-set -ex
 
 nvm use $NODE_VERSION
+set -ex
 
 CONFIG=${CONFIG:-opt}
 
diff --git a/tools/run_tests/build_package_node.sh b/tools/run_tests/build_package_node.sh
index aca90a3..540c826 100755
--- a/tools/run_tests/build_package_node.sh
+++ b/tools/run_tests/build_package_node.sh
@@ -29,9 +29,9 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 source ~/.nvm/nvm.sh
-set -ex
 
 nvm use 4
+set -ex
 
 cd $(dirname $0)/../..
 
diff --git a/tools/run_tests/build_php.sh b/tools/run_tests/build_php.sh
index 0f9cfe5..77a8abc 100755
--- a/tools/run_tests/build_php.sh
+++ b/tools/run_tests/build_php.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh
index 79a148f..30d1210 100755
--- a/tools/run_tests/build_python.sh
+++ b/tools/run_tests/build_python.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
 export CFLAGS="-I$ROOT/include -std=gnu99"
 export LDFLAGS="-L$ROOT/libs/$CONFIG"
 export GRPC_PYTHON_BUILD_WITH_CYTHON=1
+export GRPC_PYTHON_USE_PRECOMPILED_BINARIES=0
 
 if [ "$CONFIG" = "gcov" ]
 then
diff --git a/tools/run_tests/build_ruby.sh b/tools/run_tests/build_ruby.sh
index ebd27f6..10343fc 100755
--- a/tools/run_tests/build_ruby.sh
+++ b/tools/run_tests/build_ruby.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/configs.json b/tools/run_tests/configs.json
index a858170..325e9aa 100644
--- a/tools/run_tests/configs.json
+++ b/tools/run_tests/configs.json
@@ -3,6 +3,14 @@
     "config": "opt"
   }, 
   {
+    "config": "asan-trace-cmp", 
+    "environ": {
+      "ASAN_OPTIONS": "detect_leaks=1:color=always", 
+      "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
+    }, 
+    "timeout_multiplier": 3
+  }, 
+  {
     "config": "dbg"
   }, 
   {
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index a3b246d..e9675fb 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -151,7 +151,8 @@
 
   def __init__(self, cmdline, shortname=None, environ=None, hash_targets=None,
                cwd=None, shell=False, timeout_seconds=5*60, flake_retries=0,
-               timeout_retries=0, kill_handler=None, cpu_cost=1.0):
+               timeout_retries=0, kill_handler=None, cpu_cost=1.0,
+               verbose_success=False):
     """
     Arguments:
       cmdline: a list of arguments to pass as the command line
@@ -176,6 +177,7 @@
     self.timeout_retries = timeout_retries
     self.kill_handler = kill_handler
     self.cpu_cost = cpu_cost
+    self.verbose_success = verbose_success
 
   def identity(self):
     return '%r %r %r' % (self.cmdline, self.environ, self.hash_targets)
@@ -287,7 +289,8 @@
             cores = (user + sys) / real
             measurement = '; cpu_cost=%.01f; estimated=%.01f' % (cores, self._spec.cpu_cost)
         message('PASSED', '%s [time=%.1fsec; retries=%d:%d%s]' % (
-                    self._spec.shortname, elapsed, self._retries, self._timeout_retries, measurement),
+            self._spec.shortname, elapsed, self._retries, self._timeout_retries, measurement),
+            stdout() if self._spec.verbose_success else None,
             do_newline=self._newline_on_success or self._travis)
         self.result.state = 'PASSED'
         if self._bin_hash:
diff --git a/tools/run_tests/performance/__init__.py b/tools/run_tests/performance/__init__.py
new file mode 100644
index 0000000..100a624
--- /dev/null
+++ b/tools/run_tests/performance/__init__.py
@@ -0,0 +1,28 @@
+# 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.
diff --git a/tools/run_tests/performance/bq_upload_result.py b/tools/run_tests/performance/bq_upload_result.py
new file mode 100755
index 0000000..ebd28f7
--- /dev/null
+++ b/tools/run_tests/performance/bq_upload_result.py
@@ -0,0 +1,135 @@
+#!/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.
+
+# Uploads performance benchmark result file to bigquery.
+
+import argparse
+import calendar
+import json
+import os
+import sys
+import time
+import uuid
+
+
+gcp_utils_dir = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '../../gcp/utils'))
+sys.path.append(gcp_utils_dir)
+import big_query_utils
+
+
+_PROJECT_ID='grpc-testing'
+
+
+def _upload_scenario_result_to_bigquery(dataset_id, table_id, result_file):
+  bq = big_query_utils.create_big_query()
+  _create_results_table(bq, dataset_id, table_id)
+
+  with open(result_file, 'r') as f:
+    scenario_result = json.loads(f.read())
+
+  if not _insert_result(bq, dataset_id, table_id, scenario_result):
+    print 'Error uploading result to bigquery.'
+    sys.exit(1)
+
+
+def _insert_result(bq, dataset_id, table_id, scenario_result):
+  _flatten_result_inplace(scenario_result)
+  _populate_metadata_inplace(scenario_result)
+  row = big_query_utils.make_row(str(uuid.uuid4()), scenario_result)
+  return big_query_utils.insert_rows(bq,
+                                     _PROJECT_ID,
+                                     dataset_id,
+                                     table_id,
+                                     [row])
+
+
+def _create_results_table(bq, dataset_id, table_id):
+  with open(os.path.dirname(__file__) + '/scenario_result_schema.json', 'r') as f:
+    table_schema = json.loads(f.read())
+  desc = 'Results of performance benchmarks.'
+  return big_query_utils.create_table2(bq, _PROJECT_ID, dataset_id,
+                               table_id, table_schema, desc)
+
+
+def _flatten_result_inplace(scenario_result):
+  """Bigquery is not really great for handling deeply nested data
+  and repeated fields. To maintain values of some fields while keeping
+  the schema relatively simple, we artificially leave some of the fields
+  as JSON strings.
+  """
+  scenario_result['scenario']['clientConfig'] = json.dumps(scenario_result['scenario']['clientConfig'])
+  scenario_result['scenario']['serverConfig'] = json.dumps(scenario_result['scenario']['serverConfig'])
+  scenario_result['latencies'] = json.dumps(scenario_result['latencies'])
+  for stats in scenario_result['clientStats']:
+    stats['latencies'] = json.dumps(stats['latencies'])
+  scenario_result['serverCores'] = json.dumps(scenario_result['serverCores'])
+
+
+def _populate_metadata_inplace(scenario_result):
+  """Populates metadata based on environment variables set by Jenkins."""
+  # NOTE: Grabbing the Jenkins environment variables will only work if the
+  # driver is running locally on the same machine where Jenkins has started
+  # the job. For our setup, this is currently the case, so just assume that.
+  build_number = os.getenv('BUILD_NUMBER')
+  build_url = os.getenv('BUILD_URL')
+  job_name = os.getenv('JOB_NAME')
+  git_commit = os.getenv('GIT_COMMIT')
+  # actual commit is the actual head of PR that is getting tested
+  git_actual_commit = os.getenv('ghprbActualCommit')
+
+  utc_timestamp = str(calendar.timegm(time.gmtime()))
+  metadata = {'created': utc_timestamp}
+
+  if build_number:
+    metadata['buildNumber'] = build_number
+  if build_url:
+    metadata['buildUrl'] = build_url
+  if job_name:
+    metadata['jobName'] = job_name
+  if git_commit:
+    metadata['gitCommit'] = git_commit
+  if git_actual_commit:
+    metadata['gitActualCommit'] = git_actual_commit
+
+  scenario_result['metadata'] = metadata
+
+
+argp = argparse.ArgumentParser(description='Upload result to big query.')
+argp.add_argument('--bq_result_table', required=True, default=None, type=str,
+                  help='Bigquery "dataset.table" to upload results to.')
+argp.add_argument('--file_to_upload', default='scenario_result.json', type=str,
+                  help='Report file to upload.')
+
+args = argp.parse_args()
+
+dataset_id, table_id = args.bq_result_table.split('.', 2)
+_upload_scenario_result_to_bigquery(dataset_id, table_id, args.file_to_upload)
+print 'Successfully uploaded %s to BigQuery.\n' % args.file_to_upload
diff --git a/tools/run_tests/performance/build_performance.sh b/tools/run_tests/performance/build_performance.sh
new file mode 100755
index 0000000..8cfe1c4
--- /dev/null
+++ b/tools/run_tests/performance/build_performance.sh
@@ -0,0 +1,60 @@
+#!/bin/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.
+
+source ~/.rvm/scripts/rvm
+set -ex
+
+cd $(dirname $0)/../../..
+
+#TODO(jtattermusch): add support for more languages
+
+CONFIG=${CONFIG:-opt}
+
+# build C++ qps worker & driver always - we need at least the driver to
+# run any of the scenarios.
+# TODO(jtattermusch): not embedding OpenSSL breaks the C# build because
+# grpc_csharp_ext needs OpenSSL embedded and some intermediate files from
+# this build will be reused.
+make CONFIG=${CONFIG} EMBED_OPENSSL=true EMBED_ZLIB=true qps_worker qps_json_driver -j8
+
+for language in $@
+do
+  case "$language" in
+  "c++")
+    ;;  # C++ has already been built.
+  "java")
+    (cd ../grpc-java/ &&
+      ./gradlew -PskipCodegen=true :grpc-benchmarks:installDist)
+    ;;
+  *)
+    tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8
+    ;;
+  esac
+done
diff --git a/tools/run_tests/performance/remote_host_build.sh b/tools/run_tests/performance/remote_host_build.sh
new file mode 100755
index 0000000..b888608
--- /dev/null
+++ b/tools/run_tests/performance/remote_host_build.sh
@@ -0,0 +1,36 @@
+#!/bin/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.
+
+set -ex
+
+cd $(dirname $0)/../../..
+
+# execute the build script remotely
+ssh "${USER_AT_HOST}" "CONFIG=${CONFIG} ~/performance_workspace/grpc/tools/run_tests/performance/build_performance.sh $*"
diff --git a/tools/run_tests/performance/remote_host_prepare.sh b/tools/run_tests/performance/remote_host_prepare.sh
new file mode 100755
index 0000000..17cfa1a
--- /dev/null
+++ b/tools/run_tests/performance/remote_host_prepare.sh
@@ -0,0 +1,50 @@
+#!/bin/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.
+
+set -ex
+
+cd $(dirname $0)/../../..
+
+# cleanup after previous builds
+ssh "${USER_AT_HOST}" "rm -rf ~/performance_workspace && mkdir -p ~/performance_workspace"
+
+# TODO(jtattermusch): To be sure there are no running processes that would
+# mess with the results, be rough and reboot the slave here
+# and wait for it to come back online.
+# could also kill jenkins.
+ssh "${USER_AT_HOST}" "killall -9 qps_worker mono node ruby || true"
+
+# Kill all java LoadWorker processes. We can't just killall java
+# as one of the processes might be jenkins.
+ssh "${USER_AT_HOST}" 'kill -9 $(jps | grep LoadWorker | cut -f1 -d" ") || true'
+
+# push the current sources to the slave and unpack it.
+scp ../grpc.tar "${USER_AT_HOST}:~/performance_workspace"
+ssh "${USER_AT_HOST}" "tar -xf ~/performance_workspace/grpc.tar -C ~/performance_workspace"
diff --git a/tools/run_tests/performance/run_qps_driver.sh b/tools/run_tests/performance/run_qps_driver.sh
new file mode 100755
index 0000000..c8c6890
--- /dev/null
+++ b/tools/run_tests/performance/run_qps_driver.sh
@@ -0,0 +1,40 @@
+#!/bin/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.
+
+set -ex
+
+cd $(dirname $0)/../../..
+
+bins/opt/qps_json_driver "$@"
+
+if [ "$BQ_RESULT_TABLE" != "" ]
+then
+  tools/run_tests/performance/bq_upload_result.py --bq_result_table="$BQ_RESULT_TABLE"
+fi
diff --git a/tools/run_tests/performance/run_worker_csharp.sh b/tools/run_tests/performance/run_worker_csharp.sh
new file mode 100755
index 0000000..b91df09
--- /dev/null
+++ b/tools/run_tests/performance/run_worker_csharp.sh
@@ -0,0 +1,38 @@
+#!/bin/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.
+
+set -ex
+
+cd $(dirname $0)/../../..
+
+# needed to correctly locate testca
+cd src/csharp/Grpc.IntegrationTesting.QpsWorker/bin/Release
+
+mono Grpc.IntegrationTesting.QpsWorker.exe $@
diff --git a/tools/run_tests/performance/run_worker_java.sh b/tools/run_tests/performance/run_worker_java.sh
new file mode 100755
index 0000000..d5503a1
--- /dev/null
+++ b/tools/run_tests/performance/run_worker_java.sh
@@ -0,0 +1,39 @@
+#!/bin/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.
+
+set -ex
+
+# Enter repo root
+cd $(dirname $0)/../../..
+
+# Enter the grpc-java repo root (expected to be next to grpc repo root)
+cd ../grpc-java
+
+benchmarks/build/install/grpc-benchmarks/bin/benchmark_worker $@
diff --git a/tools/run_tests/performance/run_worker_node.sh b/tools/run_tests/performance/run_worker_node.sh
new file mode 100755
index 0000000..46b6ff0
--- /dev/null
+++ b/tools/run_tests/performance/run_worker_node.sh
@@ -0,0 +1,38 @@
+#!/bin/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.
+
+source ~/.nvm/nvm.sh
+nvm use 0.12
+
+set -ex
+
+cd $(dirname $0)/../../..
+
+node src/node/performance/worker.js $@
diff --git a/tools/run_tests/performance/run_worker_ruby.sh b/tools/run_tests/performance/run_worker_ruby.sh
new file mode 100755
index 0000000..4318734
--- /dev/null
+++ b/tools/run_tests/performance/run_worker_ruby.sh
@@ -0,0 +1,36 @@
+#!/bin/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.
+
+source ~/.rvm/scripts/rvm
+set -ex
+
+cd $(dirname $0)/../../..
+
+ruby src/ruby/qps/worker.rb $@
diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py
new file mode 100644
index 0000000..55657f8
--- /dev/null
+++ b/tools/run_tests/performance/scenario_config.py
@@ -0,0 +1,565 @@
+# 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.
+
+# performance scenario configuration for various languages
+
+SINGLE_MACHINE_CORES=8
+WARMUP_SECONDS=5
+JAVA_WARMUP_SECONDS=15  # Java needs more warmup time for JIT to kick in.
+BENCHMARK_SECONDS=30
+
+SECURE_SECARGS = {'use_test_ca': True,
+                  'server_host_override': 'foo.test.google.fr'}
+
+HISTOGRAM_PARAMS = {
+  'resolution': 0.01,
+  'max_possible': 60e9,
+}
+
+EMPTY_GENERIC_PAYLOAD = {
+  'bytebuf_params': {
+    'req_size': 0,
+    'resp_size': 0,
+  }
+}
+EMPTY_PROTO_PAYLOAD = {
+  'simple_params': {
+    'req_size': 0,
+    'resp_size': 0,
+  }
+}
+BIG_GENERIC_PAYLOAD = {
+  'bytebuf_params': {
+    'req_size': 65536,
+    'resp_size': 65536,
+  }
+}
+
+# deep is the number of RPCs outstanding on a channel in non-ping-pong tests
+# (the value used is 1 otherwise)
+DEEP=100
+
+# wide is the number of client channels in multi-channel tests (1 otherwise)
+WIDE=64
+
+
+class CXXLanguage:
+
+  def __init__(self):
+    self.safename = 'cxx'
+
+  def worker_cmdline(self):
+    return ['bins/opt/qps_worker']
+
+  def worker_port_offset(self):
+    return 0
+
+  def scenarios(self):
+    # TODO(ctiller): add 70% load latency test
+    for secure in [True, False]:
+      if secure:
+        secstr = 'secure'
+        secargs = SECURE_SECARGS
+      else:
+        secstr = 'insecure'
+        secargs = None
+
+      yield {
+          'name': 'cpp_generic_async_streaming_ping_pong_%s'
+                  % secstr,
+          'num_servers': 1,
+          'num_clients': 1,
+          'client_config': {
+            'client_type': 'ASYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': 1,
+            'client_channels': 1,
+            'async_client_threads': 1,
+            'rpc_type': 'STREAMING',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_GENERIC_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'ASYNC_GENERIC_SERVER',
+            'security_params': secargs,
+            'core_limit': 1,
+            'async_server_threads': 1,
+            'payload_config': EMPTY_GENERIC_PAYLOAD,
+          },
+          'warmup_seconds': WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+      yield {
+          'name': 'cpp_generic_async_streaming_qps_unconstrained_%s'
+                  % secstr,
+          'num_servers': 1,
+          'num_clients': 0,
+          'client_config': {
+            'client_type': 'ASYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': DEEP,
+            'client_channels': WIDE,
+            'async_client_threads': 0,
+            'rpc_type': 'STREAMING',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_GENERIC_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'ASYNC_GENERIC_SERVER',
+            'security_params': secargs,
+            'core_limit': SINGLE_MACHINE_CORES/2,
+            'async_server_threads': 0,
+            'payload_config': EMPTY_GENERIC_PAYLOAD,
+          },
+          'warmup_seconds': WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+      yield {
+          'name': 'cpp_generic_async_streaming_qps_one_server_core_%s'
+                  % secstr,
+          'num_servers': 1,
+          'num_clients': 0,
+          'client_config': {
+            'client_type': 'ASYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': DEEP,
+            'client_channels': WIDE,
+            'async_client_threads': 0,
+            'rpc_type': 'STREAMING',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_GENERIC_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'ASYNC_GENERIC_SERVER',
+            'security_params': secargs,
+            'core_limit': 1,
+            'async_server_threads': 1,
+            'payload_config': EMPTY_GENERIC_PAYLOAD,
+          },
+          'warmup_seconds': WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+      yield {
+          'name': 'cpp_protobuf_async_streaming_qps_unconstrained_%s'
+                  % secstr,
+          'num_servers': 1,
+          'num_clients': 0,
+          'client_config': {
+            'client_type': 'ASYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': DEEP,
+            'client_channels': WIDE,
+            'async_client_threads': 0,
+            'rpc_type': 'STREAMING',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_PROTO_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'ASYNC_SERVER',
+            'security_params': secargs,
+            'core_limit': SINGLE_MACHINE_CORES/2,
+            'async_server_threads': 0,
+          },
+          'warmup_seconds': WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+      yield {
+          'name': 'cpp_protobuf_async_streaming_ping_pong_%s'
+                  % secstr,
+          'num_servers': 1,
+          'num_clients': 1,
+          'client_config': {
+            'client_type': 'ASYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': 1,
+            'client_channels': 1,
+            'async_client_threads': 1,
+            'rpc_type': 'STREAMING',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_PROTO_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'ASYNC_SERVER',
+            'security_params': secargs,
+            'core_limit': 1,
+            'async_server_threads': 1,
+          },
+          'warmup_seconds': WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+      yield {
+          'name': 'cpp_protobuf_sync_unary_ping_pong_%s'
+                  % secstr,
+          'num_servers': 1,
+          'num_clients': 1,
+          'client_config': {
+            'client_type': 'SYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': 1,
+            'client_channels': 1,
+            'async_client_threads': 0,
+            'rpc_type': 'UNARY',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_PROTO_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'SYNC_SERVER',
+            'security_params': secargs,
+            'core_limit': 1,
+            'async_server_threads': 0,
+          },
+          'warmup_seconds': WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+      yield {
+          'name': 'cpp_protobuf_async_unary_ping_pong_%s'
+                  % secstr,
+          'num_servers': 1,
+          'num_clients': 1,
+          'client_config': {
+            'client_type': 'ASYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': 1,
+            'client_channels': 1,
+            'async_client_threads': 1,
+            'rpc_type': 'UNARY',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_PROTO_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'ASYNC_SERVER',
+            'security_params': secargs,
+            'core_limit': 1,
+            'async_server_threads': 1,
+          },
+          'warmup_seconds': WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+
+  def __str__(self):
+    return 'c++'
+
+
+class CSharpLanguage:
+
+  def __init__(self):
+    self.safename = str(self)
+
+  def worker_cmdline(self):
+    return ['tools/run_tests/performance/run_worker_csharp.sh']
+
+  def worker_port_offset(self):
+    return 100
+
+  def scenarios(self):
+    secargs = SECURE_SECARGS
+    yield {
+        'name': 'csharp_generic_async_streaming_ping_pong',
+        'num_servers': 1,
+        'num_clients': 1,
+        'client_config': {
+          'client_type': 'ASYNC_CLIENT',
+          'security_params': secargs,
+          'outstanding_rpcs_per_channel': 1,
+          'client_channels': 1,
+          'async_client_threads': 1,
+          'rpc_type': 'STREAMING',
+          'load_params': {
+            'closed_loop': {}
+          },
+          'payload_config': EMPTY_GENERIC_PAYLOAD,
+          'histogram_params': HISTOGRAM_PARAMS,
+        },
+        'server_config': {
+          'server_type': 'ASYNC_GENERIC_SERVER',
+          'security_params': secargs,
+          'core_limit': 0,
+          'async_server_threads': 0,
+          'payload_config': EMPTY_GENERIC_PAYLOAD,
+        },
+        'warmup_seconds': WARMUP_SECONDS,
+        'benchmark_seconds': BENCHMARK_SECONDS
+    }
+    yield {
+        'name': 'csharp_protobuf_async_unary_ping_pong',
+        'num_servers': 1,
+        'num_clients': 1,
+        'client_config': {
+          'client_type': 'ASYNC_CLIENT',
+          'security_params': secargs,
+          'outstanding_rpcs_per_channel': 1,
+          'client_channels': 1,
+          'async_client_threads': 1,
+          'rpc_type': 'UNARY',
+          'load_params': {
+            'closed_loop': {}
+          },
+          'payload_config': EMPTY_PROTO_PAYLOAD,
+          'histogram_params': HISTOGRAM_PARAMS,
+        },
+        'server_config': {
+          'server_type': 'ASYNC_SERVER',
+          'security_params': secargs,
+          'core_limit': 0,
+          'async_server_threads': 0,
+        },
+        'warmup_seconds': WARMUP_SECONDS,
+        'benchmark_seconds': BENCHMARK_SECONDS
+    }
+    yield {
+        'name': 'csharp_protobuf_sync_to_async_unary_ping_pong',
+        'num_servers': 1,
+        'num_clients': 1,
+        'client_config': {
+          'client_type': 'SYNC_CLIENT',
+          'security_params': secargs,
+          'outstanding_rpcs_per_channel': 1,
+          'client_channels': 1,
+          'async_client_threads': 1,
+          'rpc_type': 'UNARY',
+          'load_params': {
+            'closed_loop': {}
+          },
+          'payload_config': EMPTY_PROTO_PAYLOAD,
+          'histogram_params': HISTOGRAM_PARAMS,
+        },
+        'server_config': {
+          'server_type': 'ASYNC_SERVER',
+          'security_params': secargs,
+          'core_limit': 0,
+          'async_server_threads': 0,
+        },
+        'warmup_seconds': WARMUP_SECONDS,
+        'benchmark_seconds': BENCHMARK_SECONDS
+    }
+    yield {
+        'name': 'csharp_to_cpp_protobuf_sync_unary_ping_pong',
+        'num_servers': 1,
+        'num_clients': 1,
+        'client_config': {
+          'client_type': 'SYNC_CLIENT',
+          'security_params': secargs,
+          'outstanding_rpcs_per_channel': 1,
+          'client_channels': 1,
+          'async_client_threads': 1,
+          'rpc_type': 'UNARY',
+          'load_params': {
+            'closed_loop': {}
+          },
+          'payload_config': EMPTY_PROTO_PAYLOAD,
+          'histogram_params': HISTOGRAM_PARAMS,
+        },
+        'server_config': {
+          'server_type': 'SYNC_SERVER',
+          'security_params': secargs,
+          'core_limit': 1,
+          'async_server_threads': 1,
+        },
+        'warmup_seconds': WARMUP_SECONDS,
+        'benchmark_seconds': BENCHMARK_SECONDS,
+        'SERVER_LANGUAGE': 'c++'  # recognized by run_performance_tests.py
+    }
+
+  def __str__(self):
+    return 'csharp'
+
+
+class NodeLanguage:
+
+  def __init__(self):
+    pass
+    self.safename = str(self)
+
+  def worker_cmdline(self):
+    return ['tools/run_tests/performance/run_worker_node.sh']
+
+  def worker_port_offset(self):
+    return 200
+
+  def scenarios(self):
+    # TODO(jtattermusch): add more scenarios
+    secargs = SECURE_SECARGS
+    yield {
+        'name': 'node_protobuf_unary_ping_pong',
+        'num_servers': 1,
+        'num_clients': 1,
+        'client_config': {
+          'client_type': 'ASYNC_CLIENT',
+          'security_params': secargs,
+          'outstanding_rpcs_per_channel': 1,
+          'client_channels': 1,
+          'async_client_threads': 1,
+          'rpc_type': 'UNARY',
+          'load_params': {
+            'closed_loop': {}
+          },
+          'payload_config': EMPTY_PROTO_PAYLOAD,
+          'histogram_params': HISTOGRAM_PARAMS,
+        },
+        'server_config': {
+          'server_type': 'ASYNC_SERVER',
+          'security_params': secargs,
+          'core_limit': 0,
+          'async_server_threads': 1,
+        },
+        'warmup_seconds': WARMUP_SECONDS,
+        'benchmark_seconds': BENCHMARK_SECONDS
+    }
+
+  def __str__(self):
+    return 'node'
+
+
+class RubyLanguage:
+
+  def __init__(self):
+    pass
+    self.safename = str(self)
+
+  def worker_cmdline(self):
+    return ['tools/run_tests/performance/run_worker_ruby.sh']
+
+  def worker_port_offset(self):
+    return 300
+
+  def scenarios(self):
+    # TODO(jtattermusch): add more scenarios
+    secargs = SECURE_SECARGS
+    yield {
+        'name': 'ruby_protobuf_unary_ping_pong',
+        'num_servers': 1,
+        'num_clients': 1,
+        'client_config': {
+          'client_type': 'SYNC_CLIENT',
+          'security_params': secargs,
+          'outstanding_rpcs_per_channel': 1,
+          'client_channels': 1,
+          'async_client_threads': 1,
+          'rpc_type': 'UNARY',
+          'load_params': {
+            'closed_loop': {}
+          },
+          'payload_config': EMPTY_PROTO_PAYLOAD,
+          'histogram_params': HISTOGRAM_PARAMS,
+        },
+        'server_config': {
+          'server_type': 'SYNC_SERVER',
+          'security_params': secargs,
+          'core_limit': 0,
+          'async_server_threads': 1,
+        },
+        'warmup_seconds': WARMUP_SECONDS,
+        'benchmark_seconds': BENCHMARK_SECONDS
+    }
+
+  def __str__(self):
+    return 'ruby'
+
+
+class JavaLanguage:
+
+  def __init__(self):
+    pass
+    self.safename = str(self)
+
+  def worker_cmdline(self):
+    return ['tools/run_tests/performance/run_worker_java.sh']
+
+  def worker_port_offset(self):
+    return 400
+
+  def scenarios(self):
+    # TODO(jtattermusch): add more scenarios
+    for secure in [True, False]:
+      if secure:
+        secstr = 'secure'
+        secargs = SECURE_SECARGS
+      else:
+        secstr = 'insecure'
+        secargs = None
+
+      yield {
+          'name': 'java_protobuf_unary_ping_pong_%s' % secstr,
+          'num_servers': 1,
+          'num_clients': 1,
+          'client_config': {
+            'client_type': 'SYNC_CLIENT',
+            'security_params': secargs,
+            'outstanding_rpcs_per_channel': 1,
+            'client_channels': 1,
+            'async_client_threads': 1,
+            'rpc_type': 'UNARY',
+            'load_params': {
+              'closed_loop': {}
+            },
+            'payload_config': EMPTY_PROTO_PAYLOAD,
+            'histogram_params': HISTOGRAM_PARAMS,
+          },
+          'server_config': {
+            'server_type': 'SYNC_SERVER',
+            'security_params': secargs,
+            'core_limit': 0,
+            'async_server_threads': 1,
+          },
+          'warmup_seconds': JAVA_WARMUP_SECONDS,
+          'benchmark_seconds': BENCHMARK_SECONDS
+      }
+
+  def __str__(self):
+    return 'java'
+
+
+LANGUAGES = {
+    'c++' : CXXLanguage(),
+    'csharp' : CSharpLanguage(),
+    'node' : NodeLanguage(),
+    'ruby' : RubyLanguage(),
+    'java' : JavaLanguage(),
+}
diff --git a/tools/run_tests/performance/scenario_result_schema.json b/tools/run_tests/performance/scenario_result_schema.json
new file mode 100644
index 0000000..0325414
--- /dev/null
+++ b/tools/run_tests/performance/scenario_result_schema.json
@@ -0,0 +1,202 @@
+[
+  {
+    "name": "metadata",
+    "type": "RECORD",
+    "mode": "NULLABLE",
+    "fields": [
+      {
+        "name": "buildNumber",
+        "type": "INTEGER",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "buildUrl",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "jobName",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "gitCommit",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "gitActualCommit",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "created",
+        "type": "TIMESTAMP",
+        "mode": "NULLABLE"
+      }
+    ]
+  },
+  {
+    "name": "scenario",
+    "type": "RECORD",
+    "mode": "NULLABLE",
+    "fields": [
+      {
+        "name": "name",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "clientConfig",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "numClients",
+        "type": "INTEGER",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "serverConfig",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "numServers",
+        "type": "INTEGER",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "warmupSeconds",
+        "type": "INTEGER",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "benchmarkSeconds",
+        "type": "INTEGER",
+        "mode": "NULLABLE"
+      }
+    ]
+  },
+  {
+    "name": "latencies",
+    "type": "STRING",
+    "mode": "NULLABLE"
+  },
+  {
+    "name": "clientStats",
+    "type": "RECORD",
+    "mode": "REPEATED",
+    "fields": [
+      {
+        "name": "latencies",
+        "type": "STRING",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "timeElapsed",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "timeUser",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "timeSystem",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      }
+    ]
+  },
+  {
+    "name": "serverStats",
+    "type": "RECORD",
+    "mode": "REPEATED",
+    "fields": [
+      {
+        "name": "timeElapsed",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "timeUser",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "timeSystem",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      }
+    ]
+  },
+  {
+    "name": "serverCores",
+    "type": "STRING",
+    "mode": "NULLABLE"
+  },
+  {
+    "name": "summary",
+    "type": "RECORD",
+    "mode": "NULLABLE",
+    "fields": [
+      {
+        "name": "qps",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "qpsPerServerCore",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "serverSystemTime",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "serverUserTime",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "clientSystemTime",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "clientUserTime",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "latency50",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "latency90",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "latency95",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "latency99",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "latency999",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      }
+    ]
+  }
+]
diff --git a/tools/run_tests/post_tests_csharp.bat b/tools/run_tests/post_tests_csharp.bat
new file mode 100644
index 0000000..7851b91
--- /dev/null
+++ b/tools/run_tests/post_tests_csharp.bat
@@ -0,0 +1,25 @@
+@rem Runs C# tests for given assembly from command line. The Grpc.sln solution needs to be built before running the tests.
+
+setlocal
+
+if not "%CONFIG%" == "gcov" (
+  goto :EOF
+)
+
+@rem enter src/csharp directory
+cd /d %~dp0\..\..\src\csharp
+
+@rem Generate code coverage report
+@rem TODO(jtattermusch): currently the report list is hardcoded
+packages\ReportGenerator.2.4.4.0\tools\ReportGenerator.exe -reports:"coverage_csharp_*.xml" -targetdir:"..\..\reports\csharp_coverage" -reporttypes:"Html;TextSummary" || goto :error
+
+@rem Generate the index.html file
+echo ^<html^>^<head^>^</head^>^<body^>^<a href='csharp_coverage/index.htm'^>csharp coverage^</a^>^<br/^>^</body^>^</html^> >..\..\reports\index.html
+
+endlocal
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%
diff --git a/tools/run_tests/post_tests_csharp.sh b/tools/run_tests/post_tests_csharp.sh
new file mode 100755
index 0000000..bb6f5c6
--- /dev/null
+++ b/tools/run_tests/post_tests_csharp.sh
@@ -0,0 +1,44 @@
+#!/bin/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.
+
+set -ex
+
+if [ "$CONFIG" != "gcov" ] ; then exit ; fi
+
+# change to gRPC repo root
+cd $(dirname $0)/../..
+
+# Generate the csharp extension coverage report
+gcov objs/gcov/src/csharp/ext/*.o
+lcov --base-directory . --directory . -c -o coverage.info
+lcov -e coverage.info '**/src/csharp/ext/*' -o coverage.info
+genhtml -o reports/csharp_ext_coverage --num-spaces 2 \
+  -t 'gRPC C# native extension test coverage' coverage.info \
+  --rc genhtml_hi_limit=95 --rc genhtml_med_limit=80 --no-prefix
diff --git a/tools/run_tests/post_tests_php.sh b/tools/run_tests/post_tests_php.sh
index 01a44d0..b409806 100755
--- a/tools/run_tests/post_tests_php.sh
+++ b/tools/run_tests/post_tests_php.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/post_tests_ruby.sh b/tools/run_tests/post_tests_ruby.sh
index 1a02e56..0877e44 100755
--- a/tools/run_tests/post_tests_ruby.sh
+++ b/tools/run_tests/post_tests_ruby.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/pre_build_csharp.sh b/tools/run_tests/pre_build_csharp.sh
index 32466c2..3ff1a4e 100755
--- a/tools/run_tests/pre_build_csharp.sh
+++ b/tools/run_tests/pre_build_csharp.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/pre_build_node.sh b/tools/run_tests/pre_build_node.sh
index 11f46d6..4879e7a 100755
--- a/tools/run_tests/pre_build_node.sh
+++ b/tools/run_tests/pre_build_node.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -31,9 +31,9 @@
 
 NODE_VERSION=$1
 source ~/.nvm/nvm.sh
-set -ex
 
 nvm use $NODE_VERSION
+set -ex
 
 export GRPC_CONFIG=${CONFIG:-opt}
 
diff --git a/tools/run_tests/pre_build_ruby.sh b/tools/run_tests/pre_build_ruby.sh
index 569a1d0..e7074c4 100755
--- a/tools/run_tests/pre_build_ruby.sh
+++ b/tools/run_tests/pre_build_ruby.sh
@@ -33,7 +33,7 @@
 
 export GRPC_CONFIG=${CONFIG:-opt}
 
-# change to grpc's ruby directory
-cd $(dirname $0)/../../src/ruby
+# change to grpc repo root
+cd $(dirname $0)/../..
 
 bundle install
diff --git a/tools/run_tests/report_utils.py b/tools/run_tests/report_utils.py
index df114e5..35dcaca 100644
--- a/tools/run_tests/report_utils.py
+++ b/tools/run_tests/report_utils.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/run_csharp.bat b/tools/run_tests/run_csharp.bat
deleted file mode 100644
index 82eb585..0000000
--- a/tools/run_tests/run_csharp.bat
+++ /dev/null
@@ -1,27 +0,0 @@
-@rem Runs C# tests for given assembly from command line. The Grpc.sln solution needs to be built before running the tests.
-
-setlocal
-
-@rem enter src/csharp directory
-cd /d %~dp0\..\..\src\csharp
-
-if not "%CONFIG%" == "gcov" (
-  packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe %* || goto :error
-) else (
-  @rem Run all tests with code coverage
-
-  packages\OpenCover.4.6.166\tools\OpenCover.Console.exe -target:"packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe" -targetdir:"." -targetargs:"%*" -filter:"+[Grpc.Core]*"  -register:user -output:coverage_results.xml || goto :error
-
-  packages\ReportGenerator.2.3.2.0\tools\ReportGenerator.exe -reports:"coverage_results.xml" -targetdir:"..\..\reports\csharp_coverage" -reporttypes:"Html;TextSummary" || goto :error
-
-  @rem Generate the index.html file
-  echo ^<html^>^<head^>^</head^>^<body^>^<a href='csharp_coverage/index.htm'^>csharp coverage^</a^>^<br/^>^</body^>^</html^> >..\..\reports\index.html
-)
-
-endlocal
-
-goto :EOF
-
-:error
-echo Failed!
-exit /b %errorlevel%
diff --git a/tools/run_tests/run_csharp.sh b/tools/run_tests/run_csharp.sh
deleted file mode 100755
index 10f1c28..0000000
--- a/tools/run_tests/run_csharp.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-# 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.
-
-set -ex
-
-CONFIG=${CONFIG:-opt}
-NUNIT_CONSOLE="mono packages/NUnit.Runners.2.6.4/tools/nunit-console.exe"
-
-# change to gRPC repo root
-cd $(dirname $0)/../..
-
-(cd src/csharp; $NUNIT_CONSOLE $@)
-
-if [ "$CONFIG" = "gcov" ]
-then
-  # Generate the csharp extension coverage report
-  gcov objs/gcov/src/csharp/ext/*.o
-  lcov --base-directory . --directory . -c -o coverage.info
-  lcov -e coverage.info '**/src/csharp/ext/*' -o coverage.info
-  genhtml -o reports/csharp_ext_coverage --num-spaces 2 \
-    -t 'gRPC C# native extension test coverage' coverage.info \
-    --rc genhtml_hi_limit=95 --rc genhtml_med_limit=80 --no-prefix
-fi
-
-
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 86eb52b..220d0e6 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -270,13 +270,13 @@
     self.safename = str(self)
 
   def client_cmd(self, args):
-    return ['ruby', 'src/ruby/bin/interop/interop_client.rb'] + args
+    return ['ruby', 'src/ruby/pb/test/client.rb'] + args
 
   def cloud_to_prod_env(self):
     return {}
 
   def server_cmd(self, args):
-    return ['ruby', 'src/ruby/bin/interop/interop_server.rb', '--use_tls=true'] + args
+    return ['ruby', 'src/ruby/pb/test/server.rb', '--use_tls=true'] + args
 
   def global_env(self):
     return {}
@@ -590,8 +590,8 @@
                       False),
     'cloud_gateway_v2': ('216.239.32.255', 'grpc-test2.sandbox.googleapis.com',
                          True),
-    'gateway_v4': ('grpc-test4.sandbox.googleapis.com', 
-                   'grpc-test4.sandbox.googleapis.com', True), 
+    'gateway_v4': ('grpc-test4.sandbox.googleapis.com',
+                   'grpc-test4.sandbox.googleapis.com', True),
     'cloud_gateway_v4': ('216.239.32.255', 'grpc-test4.sandbox.googleapis.com',
                          True),
 }
diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh
index d338900..44f7564 100755
--- a/tools/run_tests/run_node.sh
+++ b/tools/run_tests/run_node.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -30,9 +30,9 @@
 
 NODE_VERSION=$1
 source ~/.nvm/nvm.sh
-set -ex
 
 nvm use $NODE_VERSION
+set -ex
 
 CONFIG=${CONFIG:-opt}
 
@@ -48,6 +48,7 @@
 then
   ./node_modules/.bin/istanbul cover --dir reports/node_coverage \
     -x **/interop/* ./node_modules/.bin/_mocha -- --timeout $timeout $test_directory
+  cp -r reports/node_coverage/lcov-report/* reports/node_coverage/
   cd build
   gcov Release/obj.target/grpc/ext/*.o
   lcov --base-directory . --directory . -c -o coverage.info
@@ -55,8 +56,6 @@
   genhtml -o ../reports/node_ext_coverage --num-spaces 2 \
     -t 'Node gRPC test coverage' coverage.info --rc genhtml_hi_limit=95 \
     --rc genhtml_med_limit=80 --no-prefix
-  echo '<html><head><meta http-equiv="refresh" content="0;URL=lcov-report/index.html"></head></html>' > \
-    ../reports/node_coverage/index.html
 else
   JUNIT_REPORT_PATH=src/node/report.xml JUNIT_REPORT_STACK=1 \
     ./node_modules/.bin/mocha --timeout $timeout \
diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py
new file mode 100755
index 0000000..ada341a
--- /dev/null
+++ b/tools/run_tests/run_performance_tests.py
@@ -0,0 +1,366 @@
+#!/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.
+
+"""Run performance tests locally or remotely."""
+
+import argparse
+import itertools
+import jobset
+import json
+import multiprocessing
+import os
+import pipes
+import re
+import subprocess
+import sys
+import tempfile
+import time
+import traceback
+import uuid
+import performance.scenario_config as scenario_config
+
+
+_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
+os.chdir(_ROOT)
+
+
+_REMOTE_HOST_USERNAME = 'jenkins'
+
+
+class QpsWorkerJob:
+  """Encapsulates a qps worker server job."""
+
+  def __init__(self, spec, language, host_and_port):
+    self._spec = spec
+    self.language = language
+    self.host_and_port = host_and_port
+    self._job = jobset.Job(spec, bin_hash=None, newline_on_success=True, travis=True, add_env={})
+
+  def is_running(self):
+    """Polls a job and returns True if given job is still running."""
+    return self._job.state(jobset.NoCache()) == jobset._RUNNING
+
+  def kill(self):
+    return self._job.kill()
+
+
+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)
+    cmdline = ['ssh',
+               str(user_at_host),
+               'cd ~/performance_workspace/grpc/ && %s' % ' '.join(cmdline)]
+    host_and_port='%s:%s' % (remote_host, port)
+  else:
+    host_and_port='localhost:%s' % port
+
+  # TODO(jtattermusch): with some care, we can calculate the right timeout
+  # of a worker from the sum of warmup + benchmark times for all the scenarios
+  jobspec = jobset.JobSpec(
+      cmdline=cmdline,
+      shortname=shortname,
+      timeout_seconds=30*60)
+  return QpsWorkerJob(jobspec, language, host_and_port)
+
+
+def create_scenario_jobspec(scenario_json, workers, remote_host=None,
+                            bq_result_table=None):
+  """Runs one scenario using QPS driver."""
+  # setting QPS_WORKERS env variable here makes sure it works with SSH too.
+  cmd = 'QPS_WORKERS="%s" ' % ','.join(workers)
+  if bq_result_table:
+    cmd += 'BQ_RESULT_TABLE="%s" ' % bq_result_table
+  cmd += 'tools/run_tests/performance/run_qps_driver.sh '
+  cmd += '--scenarios_json=%s ' % pipes.quote(json.dumps({'scenarios': [scenario_json]}))
+  cmd += '--scenario_result_file=scenario_result.json'
+  if remote_host:
+    user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host)
+    cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (user_at_host, pipes.quote(cmd))
+
+  return jobset.JobSpec(
+      cmdline=[cmd],
+      shortname='qps_json_driver.%s' % scenario_json['name'],
+      timeout_seconds=3*60,
+      shell=True,
+      verbose_success=True)
+
+
+def create_quit_jobspec(workers, remote_host=None):
+  """Runs quit using QPS driver."""
+  # setting QPS_WORKERS env variable here makes sure it works with SSH too.
+  cmd = 'QPS_WORKERS="%s" bins/opt/qps_json_driver --quit' % ','.join(workers)
+  if remote_host:
+    user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host)
+    cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (user_at_host, pipes.quote(cmd))
+
+  return jobset.JobSpec(
+      cmdline=[cmd],
+      shortname='qps_json_driver.quit',
+      timeout_seconds=3*60,
+      shell=True,
+      verbose_success=True)
+
+
+def archive_repo(languages):
+  """Archives local version of repo including submodules."""
+  cmdline=['tar', '-cf', '../grpc.tar', '../grpc/']
+  if 'java' in languages:
+    cmdline.append('../grpc-java')
+  if 'go' in languages:
+    cmdline.append('../grpc-go')
+
+  archive_job = jobset.JobSpec(
+      cmdline=cmdline,
+      shortname='archive_repo',
+      timeout_seconds=3*60)
+
+  jobset.message('START', 'Archiving local repository.', do_newline=True)
+  num_failures, _ = jobset.run(
+      [archive_job], newline_on_success=True, maxjobs=1)
+  if num_failures == 0:
+    jobset.message('SUCCESS',
+                   'Archive with local repository created successfully.',
+                   do_newline=True)
+  else:
+    jobset.message('FAILED', 'Failed to archive local repository.',
+                   do_newline=True)
+    sys.exit(1)
+
+
+def prepare_remote_hosts(hosts):
+  """Prepares remote hosts."""
+  prepare_jobs = []
+  for host in hosts:
+    user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, host)
+    prepare_jobs.append(
+        jobset.JobSpec(
+            cmdline=['tools/run_tests/performance/remote_host_prepare.sh'],
+            shortname='remote_host_prepare.%s' % host,
+            environ = {'USER_AT_HOST': user_at_host},
+            timeout_seconds=5*60))
+  jobset.message('START', 'Preparing remote hosts.', do_newline=True)
+  num_failures, _ = jobset.run(
+      prepare_jobs, newline_on_success=True, maxjobs=10)
+  if num_failures == 0:
+    jobset.message('SUCCESS',
+                   'Remote hosts ready to start build.',
+                   do_newline=True)
+  else:
+    jobset.message('FAILED', 'Failed to prepare remote hosts.',
+                   do_newline=True)
+    sys.exit(1)
+
+
+def build_on_remote_hosts(hosts, languages=scenario_config.LANGUAGES.keys(), build_local=False):
+  """Builds performance worker on remote hosts (and maybe also locally)."""
+  build_timeout = 15*60
+  build_jobs = []
+  for host in hosts:
+    user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, host)
+    build_jobs.append(
+        jobset.JobSpec(
+            cmdline=['tools/run_tests/performance/remote_host_build.sh'] + languages,
+            shortname='remote_host_build.%s' % host,
+            environ = {'USER_AT_HOST': user_at_host, 'CONFIG': 'opt'},
+            timeout_seconds=build_timeout))
+  if build_local:
+    # Build locally as well
+    build_jobs.append(
+        jobset.JobSpec(
+            cmdline=['tools/run_tests/performance/build_performance.sh'] + languages,
+            shortname='local_build',
+            environ = {'CONFIG': 'opt'},
+            timeout_seconds=build_timeout))
+  jobset.message('START', 'Building.', do_newline=True)
+  num_failures, _ = jobset.run(
+      build_jobs, newline_on_success=True, maxjobs=10)
+  if num_failures == 0:
+    jobset.message('SUCCESS',
+                   'Built successfully.',
+                   do_newline=True)
+  else:
+    jobset.message('FAILED', 'Build failed.',
+                   do_newline=True)
+    sys.exit(1)
+
+
+def start_qpsworkers(languages, worker_hosts):
+  """Starts QPS workers as background jobs."""
+  if not worker_hosts:
+    # run two workers locally (for each language)
+    workers=[(None, 10000), (None, 10010)]
+  elif len(worker_hosts) == 1:
+    # run two workers on the remote host (for each language)
+    workers=[(worker_hosts[0], 10000), (worker_hosts[0], 10010)]
+  else:
+    # run one worker per each remote host (for each language)
+    workers=[(worker_host, 10000) for worker_host in worker_hosts]
+
+  return [create_qpsworker_job(language,
+                               shortname= 'qps_worker_%s_%s' % (language,
+                                                                worker_idx),
+                               port=worker[1] + language.worker_port_offset(),
+                               remote_host=worker[0])
+          for language in languages
+          for worker_idx, worker in enumerate(workers)]
+
+
+def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*',
+                     bq_result_table=None):
+  """Create jobspecs for scenarios to run."""
+  scenarios = []
+  for language in languages:
+    for scenario_json in language.scenarios():
+      if re.search(args.regex, scenario_json['name']):
+        workers = workers_by_lang[str(language)]
+        # 'SERVER_LANGUAGE' is an indicator for this script to pick
+        # a server in different language. It doesn't belong to the Scenario
+        # schema, so we also need to remove it.
+        custom_server_lang = scenario_json.pop('SERVER_LANGUAGE', None)
+        if custom_server_lang:
+          if not workers_by_lang.get(custom_server_lang, []):
+            print 'Warning: Skipping scenario %s as' % scenario_json['name']
+            print('SERVER_LANGUAGE is set to %s yet the language has '
+                  'not been selected with -l' % custom_server_lang)
+            continue
+          for idx in range(0, scenario_json['num_servers']):
+            # replace first X workers by workers of a different language
+            workers[idx] = workers_by_lang[custom_server_lang][idx]
+        scenario = create_scenario_jobspec(scenario_json,
+                                           workers,
+                                           remote_host=remote_host,
+                                           bq_result_table=bq_result_table)
+        scenarios.append(scenario)
+
+  # the very last scenario requests shutting down the workers.
+  all_workers = [worker
+                 for workers in workers_by_lang.values()
+                 for worker in workers]
+  scenarios.append(create_quit_jobspec(all_workers, remote_host=remote_host))
+  return scenarios
+
+
+def finish_qps_workers(jobs):
+  """Waits for given jobs to finish and eventually kills them."""
+  retries = 0
+  while any(job.is_running() for job in jobs):
+    for job in qpsworker_jobs:
+      if job.is_running():
+        print 'QPS worker "%s" is still running.' % job.host_and_port
+    if retries > 10:
+      print 'Killing all QPS workers.'
+      for job in jobs:
+        job.kill()
+    retries += 1
+    time.sleep(3)
+  print 'All QPS workers finished.'
+
+
+argp = argparse.ArgumentParser(description='Run performance tests.')
+argp.add_argument('-l', '--language',
+                  choices=['all'] + sorted(scenario_config.LANGUAGES.keys()),
+                  nargs='+',
+                  default=['all'],
+                  help='Languages to benchmark.')
+argp.add_argument('--remote_driver_host',
+                  default=None,
+                  help='Run QPS driver on given host. By default, QPS driver is run locally.')
+argp.add_argument('--remote_worker_host',
+                  nargs='+',
+                  default=[],
+                  help='Worker hosts where to start QPS workers.')
+argp.add_argument('-r', '--regex', default='.*', type=str,
+                  help='Regex to select scenarios to run.')
+argp.add_argument('--bq_result_table', default=None, type=str,
+                  help='Bigquery "dataset.table" to upload results to.')
+
+args = argp.parse_args()
+
+languages = set(scenario_config.LANGUAGES[l]
+                for l in itertools.chain.from_iterable(
+                      scenario_config.LANGUAGES.iterkeys() if x == 'all' else [x]
+                      for x in args.language))
+
+
+# Put together set of remote hosts where to run and build
+remote_hosts = set()
+if args.remote_worker_host:
+  for host in args.remote_worker_host:
+    remote_hosts.add(host)
+if args.remote_driver_host:
+  remote_hosts.add(args.remote_driver_host)
+
+if remote_hosts:
+  archive_repo(languages=[str(l) for l in languages])
+  prepare_remote_hosts(remote_hosts)
+
+build_local = False
+if not args.remote_driver_host:
+  build_local = True
+build_on_remote_hosts(remote_hosts, languages=[str(l) for l in languages], build_local=build_local)
+
+qpsworker_jobs = start_qpsworkers(languages, args.remote_worker_host)
+
+# TODO(jtattermusch): see https://github.com/grpc/grpc/issues/6174
+time.sleep(5)
+
+# get list of worker addresses for each language.
+worker_addresses = dict([(str(language), []) for language in languages])
+for job in qpsworker_jobs:
+  worker_addresses[str(job.language)].append(job.host_and_port)
+
+try:
+  scenarios = create_scenarios(languages,
+                               workers_by_lang=worker_addresses,
+                               remote_host=args.remote_driver_host,
+                               regex=args.regex,
+                               bq_result_table=args.bq_result_table)
+  if not scenarios:
+    raise Exception('No scenarios to run')
+
+  jobset.message('START', 'Running scenarios.', do_newline=True)
+  num_failures, _ = jobset.run(
+      scenarios, newline_on_success=True, maxjobs=1)
+  if num_failures == 0:
+    jobset.message('SUCCESS',
+                   'All scenarios finished successfully.',
+                   do_newline=True)
+  else:
+    jobset.message('FAILED', 'Some of the scenarios failed.',
+                   do_newline=True)
+    sys.exit(1)
+except:
+  traceback.print_exc()
+  raise
+finally:
+  finish_qps_workers(qpsworker_jobs)
diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh
index d4b7250..a93ef25 100755
--- a/tools/run_tests/run_python.sh
+++ b/tools/run_tests/run_python.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
 export CFLAGS="-I$ROOT/include -std=c89"
 export LDFLAGS="-L$ROOT/libs/$CONFIG"
 export GRPC_PYTHON_BUILD_WITH_CYTHON=1
+export GRPC_PYTHON_USE_PRECOMPILED_BINARIES=0
 
 if [ "$CONFIG" = "gcov" ]
 then
diff --git a/tools/run_tests/run_stress_tests.py b/tools/run_tests/run_stress_tests.py
index d1faf7d..0ba8f51 100755
--- a/tools/run_tests/run_stress_tests.py
+++ b/tools/run_tests/run_stress_tests.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index dc11c0b..9dff686 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -120,7 +120,12 @@
 
 def _check_compiler(compiler, supported_compilers):
   if compiler not in supported_compilers:
-    raise Exception('Compiler %s not supported.' % compiler)
+    raise Exception('Compiler %s not supported (on this platform).' % compiler)
+
+
+def _check_arch(arch, supported_archs):
+  if arch not in supported_archs:
+    raise Exception('Architecture %s not supported.' % arch)
 
 
 def _is_use_docker_child():
@@ -183,15 +188,15 @@
                                               shortname='%s:%s' % (binary, test),
                                               cpu_cost=target['cpu_cost'],
                                               environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
-                                                       _ROOT + '/src/core/tsi/test_creds/ca.pem'}))
+                                                       _ROOT + '/src/core/lib/tsi/test_creds/ca.pem'}))
         else:
           cmdline = [binary] + target['args']
           out.append(self.config.job_spec(cmdline, [binary],
-                                          shortname=' '.join(cmdline),
+                                          shortname=target.get('shortname', ' '.join(cmdline)),
                                           cpu_cost=target['cpu_cost'],
                                           flaky=target.get('flaky', False),
                                           environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
-                                                   _ROOT + '/src/core/tsi/test_creds/ca.pem'}))
+                                                   _ROOT + '/src/core/lib/tsi/test_creds/ca.pem'}))
       elif self.args.regex == '.*' or self.platform == 'windows':
         print '\nWARNING: binary not found, skipping', binary
     return sorted(out)
@@ -464,45 +469,65 @@
   def configure(self, config, args):
     self.config = config
     self.args = args
-    _check_compiler(self.args.compiler, ['default'])
+    if self.platform == 'windows':
+      # Explicitly choosing between x86 and x64 arch doesn't work yet
+      _check_arch(self.args.arch, ['default'])
+      self._make_options = [_windows_toolset_option(self.args.compiler),
+                            _windows_arch_option(self.args.arch)]
+    else:
+      _check_compiler(self.args.compiler, ['default'])
+      if self.platform == 'mac':
+        # On Mac, official distribution of mono is 32bit.
+        # TODO(jtattermusch): EMBED_ZLIB=true currently breaks the mac build
+        self._make_options = ['EMBED_OPENSSL=true',
+                              'CFLAGS=-m32', 'LDFLAGS=-m32']
+      else:
+        self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
 
   def test_specs(self):
     with open('src/csharp/tests.json') as f:
-      tests_json = json.load(f)
-    assemblies = tests_json['assemblies']
-    tests = tests_json['tests']
+      tests_by_assembly = json.load(f)
 
     msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
-    assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
-                      for a in assemblies]
-
-    extra_args = ['-labels'] + assembly_files
-
+    nunit_args = ['--labels=All',
+                  '--noresult',
+                  '--workers=1']
     if self.platform == 'windows':
-      script_name = 'tools\\run_tests\\run_csharp.bat'
-      extra_args += ['-domain=None']
+      runtime_cmd = []
     else:
-      script_name = 'tools/run_tests/run_csharp.sh'
+      runtime_cmd = ['mono']
 
-    if self.config.build_config == 'gcov':
-      # On Windows, we only collect C# code coverage.
-      # On Linux, we only collect coverage for native extension.
-      # For code coverage all tests need to run as one suite.
-      return [self.config.job_spec([script_name] + extra_args, None,
-                                    shortname='csharp.coverage',
-                                    environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
-    else:
-      specs = []
-      for test in tests:
-        cmdline = [script_name, '-run=%s' % test] + extra_args
-        if self.platform == 'windows':
-          # use different output directory for each test to prevent
-          # TestResult.xml clash between parallel test runs.
-          cmdline += ['-work=test-result/%s' % uuid.uuid4()]
-        specs.append(self.config.job_spec(cmdline, None,
-                                          shortname='csharp.%s' % test,
+    specs = []
+    for assembly in tests_by_assembly.iterkeys():
+      assembly_file = 'src/csharp/%s/bin/%s/%s.exe' % (assembly, msbuild_config, assembly)
+      if self.config.build_config != 'gcov' or self.platform != 'windows':
+        # normally, run each test as a separate process
+        for test in tests_by_assembly[assembly]:
+          cmdline = runtime_cmd + [assembly_file, '--test=%s' % test] + nunit_args
+          specs.append(self.config.job_spec(cmdline,
+                                            None,
+                                            shortname='csharp.%s' % test,
+                                            environ=_FORCE_ENVIRON_FOR_WRAPPERS))
+      else:
+        # For C# test coverage, run all tests from the same assembly at once
+        # using OpenCover.Console (only works on Windows).
+        cmdline = ['src\\csharp\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe',
+                   '-target:%s' % assembly_file,
+                   '-targetdir:src\\csharp',
+                   '-targetargs:%s' % ' '.join(nunit_args),
+                   '-filter:+[Grpc.Core]*',
+                   '-register:user',
+                   '-output:src\\csharp\\coverage_csharp_%s.xml' % assembly]
+
+        # set really high cpu_cost to make sure instances of OpenCover.Console run exclusively
+        # to prevent problems with registering the profiler.
+        run_exclusive = 1000000
+        specs.append(self.config.job_spec(cmdline,
+                                          None,
+                                          shortname='csharp.coverage.%s' % assembly,
+                                          cpu_cost=run_exclusive,
                                           environ=_FORCE_ENVIRON_FOR_WRAPPERS))
-      return specs
+    return specs
 
   def pre_build_steps(self):
     if self.platform == 'windows':
@@ -511,28 +536,24 @@
       return [['tools/run_tests/pre_build_csharp.sh']]
 
   def make_targets(self):
-    # For Windows, this target doesn't really build anything,
-    # everything is build by buildall script later.
-    if self.platform == 'windows':
-      return []
-    else:
-      return ['grpc_csharp_ext']
+    return ['grpc_csharp_ext']
 
   def make_options(self):
-    if self.platform == 'mac':
-      # On Mac, official distribution of mono is 32bit.
-      return ['CFLAGS=-arch i386', 'LDFLAGS=-arch i386']
-    else:
-      return []
+    return self._make_options;
 
   def build_steps(self):
     if self.platform == 'windows':
-      return [['src\\csharp\\buildall.bat']]
+      return [[_windows_build_bat(self.args.compiler),
+               'src/csharp/Grpc.sln',
+               '/p:Configuration=%s' % _MSBUILD_CONFIG[self.config.build_config]]]
     else:
       return [['tools/run_tests/build_csharp.sh']]
 
   def post_tests_steps(self):
-    return []
+    if self.platform == 'windows':
+      return [['tools\\run_tests\\post_tests_csharp.bat']]
+    else:
+      return [['tools/run_tests/post_tests_csharp.sh']]
 
   def makefile_name(self):
     return 'Makefile'
diff --git a/tools/run_tests/sanity/check_cache_mk.sh b/tools/run_tests/sanity/check_cache_mk.sh
index b738d6a..d7ae3d0 100755
--- a/tools/run_tests/sanity/check_cache_mk.sh
+++ b/tools/run_tests/sanity/check_cache_mk.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/run_tests/sanity/check_sources_and_headers.py b/tools/run_tests/sanity/check_sources_and_headers.py
index 44dc49b..c028499 100755
--- a/tools/run_tests/sanity/check_sources_and_headers.py
+++ b/tools/run_tests/sanity/check_sources_and_headers.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,7 @@
   for dep in target['deps']:
     if target_has_header(get_target(dep), name):
       return True
-  if name == 'src/core/profiling/stap_probes.h':
+  if name == 'src/core/lib/profiling/stap_probes.h':
     return True
   return False
 
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 630e7fb..3349d28 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# Copyright 2015-2016, Google Inc.
+# Copyright 2015, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
 
 git submodule | awk '{ print $1 }' | sort > $submodules
 cat << EOF | awk '{ print $1 }' | sort > $want_submodules
- 907ae62b9d81121cb86b604f83e6b811a43f7a87 third_party/boringssl (version_for_cocoapods_1.0-72-g907ae62)
+ c880e42ba1c8032d4cdde2aba0541d8a9d9fa2e9 third_party/boringssl (heads/2661)
  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)
diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml
index f155c8d..efc21e6 100644
--- a/tools/run_tests/sanity/sanity_tests.yaml
+++ b/tools/run_tests/sanity/sanity_tests.yaml
@@ -5,6 +5,7 @@
 - script: tools/buildgen/generate_projects.sh -j 3
   cpu_cost: 3
 - script: tools/distrib/check_copyright.py
+- script: tools/distrib/check_vsprojects.py
 - script: tools/distrib/clang_format_code.sh
 - script: tools/distrib/check_trailing_newlines.sh
 - script: tools/distrib/check_nanopb_output.sh
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 28647e4..e94387c 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -65,6 +65,22 @@
   }, 
   {
     "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "api_fuzzer", 
+    "src": [
+      "test/core/end2end/fuzzers/api_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "grpc", 
       "grpc_test_util"
     ], 
@@ -182,6 +198,22 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "client_fuzzer", 
+    "src": [
+      "test/core/end2end/fuzzers/client_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "compression_test", 
     "src": [
       "test/core/compression/compression_test.c"
@@ -393,6 +425,22 @@
   {
     "deps": [
       "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "goaway_server_test", 
+    "src": [
+      "test/core/end2end/goaway_server_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
       "gpr_test_util"
     ], 
     "headers": [], 
@@ -891,6 +939,22 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "hpack_parser_fuzzer_test", 
+    "src": [
+      "test/core/transport/chttp2/hpack_parser_fuzzer_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "hpack_parser_test", 
     "src": [
       "test/core/transport/chttp2/hpack_parser_test.c"
@@ -923,9 +987,9 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "httpcli_format_request_test", 
+    "name": "http_fuzzer_test", 
     "src": [
-      "test/core/httpcli/format_request_test.c"
+      "test/core/http/fuzzer.c"
     ], 
     "third_party": false, 
     "type": "target"
@@ -939,9 +1003,25 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "httpcli_parser_test", 
+    "name": "http_parser_test", 
     "src": [
-      "test/core/httpcli/parser_test.c"
+      "test/core/http/parser_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "httpcli_format_request_test", 
+    "src": [
+      "test/core/http/format_request_test.c"
     ], 
     "third_party": false, 
     "type": "target"
@@ -957,7 +1037,7 @@
     "language": "c", 
     "name": "httpcli_test", 
     "src": [
-      "test/core/httpcli/httpcli_test.c"
+      "test/core/http/httpcli_test.c"
     ], 
     "third_party": false, 
     "type": "target"
@@ -973,7 +1053,7 @@
     "language": "c", 
     "name": "httpscli_test", 
     "src": [
-      "test/core/httpcli/httpscli_test.c"
+      "test/core/http/httpscli_test.c"
     ], 
     "third_party": false, 
     "type": "target"
@@ -1003,6 +1083,54 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "internal_api_canary_iomgr_test", 
+    "src": [
+      "test/core/internal_api_canaries/iomgr.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "internal_api_canary_support_test", 
+    "src": [
+      "test/core/internal_api_canaries/iomgr.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "internal_api_canary_transport_test", 
+    "src": [
+      "test/core/internal_api_canaries/iomgr.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "invalid_call_argument_test", 
     "src": [
       "test/core/end2end/invalid_call_argument_test.c"
@@ -1013,6 +1141,22 @@
   {
     "deps": [
       "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "json_fuzzer_test", 
+    "src": [
+      "test/core/json/fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
       "grpc"
     ], 
     "headers": [], 
@@ -1191,6 +1335,38 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "nanopb_fuzzer_response_test", 
+    "src": [
+      "test/core/nanopb/fuzzer_response.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test", 
+    "src": [
+      "test/core/nanopb/fuzzer_serverlist.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "no_server_test", 
     "src": [
       "test/core/end2end/no_server_test.c"
@@ -1271,6 +1447,22 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "server_fuzzer", 
+    "src": [
+      "test/core/end2end/fuzzers/server_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "server_test", 
     "src": [
       "test/core/surface/server_test.c"
@@ -1544,6 +1736,22 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "uri_fuzzer_test", 
+    "src": [
+      "test/core/client_config/uri_fuzzer_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "uri_parser_test", 
     "src": [
       "test/core/client_config/uri_parser_test.c"
@@ -1730,7 +1938,10 @@
   }, 
   {
     "deps": [
-      "grpc++_codegen_lib"
+      "gpr", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_codegen"
     ], 
     "headers": [
       "src/proto/grpc/testing/control.grpc.pb.h", 
@@ -1747,9 +1958,35 @@
       "src/proto/grpc/testing/stats.pb.h"
     ], 
     "language": "c++", 
-    "name": "codegen_test", 
+    "name": "codegen_test_full", 
     "src": [
-      "test/cpp/codegen/codegen_test.cc"
+      "test/cpp/codegen/codegen_test_full.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "grpc++_codegen"
+    ], 
+    "headers": [
+      "src/proto/grpc/testing/control.grpc.pb.h", 
+      "src/proto/grpc/testing/control.pb.h", 
+      "src/proto/grpc/testing/messages.grpc.pb.h", 
+      "src/proto/grpc/testing/messages.pb.h", 
+      "src/proto/grpc/testing/payloads.grpc.pb.h", 
+      "src/proto/grpc/testing/payloads.pb.h", 
+      "src/proto/grpc/testing/perf_db.grpc.pb.h", 
+      "src/proto/grpc/testing/perf_db.pb.h", 
+      "src/proto/grpc/testing/services.grpc.pb.h", 
+      "src/proto/grpc/testing/services.pb.h", 
+      "src/proto/grpc/testing/stats.grpc.pb.h", 
+      "src/proto/grpc/testing/stats.pb.h"
+    ], 
+    "language": "c++", 
+    "name": "codegen_test_minimal", 
+    "src": [
+      "test/cpp/codegen/codegen_test_minimal.cc"
     ], 
     "third_party": false, 
     "type": "target"
@@ -1939,6 +2176,19 @@
     ], 
     "headers": [], 
     "language": "c++", 
+    "name": "grpc_node_plugin", 
+    "src": [
+      "src/compiler/node_plugin.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "grpc_plugin_support"
+    ], 
+    "headers": [], 
+    "language": "c++", 
     "name": "grpc_objective_c_plugin", 
     "src": [
       "src/compiler/objective_c_plugin.cc"
@@ -2066,6 +2316,25 @@
   {
     "deps": [
       "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_config", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "src": [
+      "test/cpp/qps/json_run_localhost.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
       "grpc", 
       "grpc++", 
       "grpc++_test_config"
@@ -2108,16 +2377,15 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
-      "grpc++_test_config", 
       "grpc++_test_util", 
       "grpc_test_util", 
       "qps"
     ], 
     "headers": [], 
     "language": "c++", 
-    "name": "qps_driver", 
+    "name": "qps_interarrival_test", 
     "src": [
-      "test/cpp/qps/qps_driver.cc"
+      "test/cpp/qps/qps_interarrival_test.cc"
     ], 
     "third_party": false, 
     "type": "target"
@@ -2128,15 +2396,20 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_test_config", 
       "grpc++_test_util", 
       "grpc_test_util", 
       "qps"
     ], 
-    "headers": [], 
+    "headers": [
+      "test/cpp/qps/parse_json.h"
+    ], 
     "language": "c++", 
-    "name": "qps_interarrival_test", 
+    "name": "qps_json_driver", 
     "src": [
-      "test/cpp/qps/qps_interarrival_test.cc"
+      "test/cpp/qps/parse_json.cc", 
+      "test/cpp/qps/parse_json.h", 
+      "test/cpp/qps/qps_json_driver.cc"
     ], 
     "third_party": false, 
     "type": "target"
@@ -2949,6 +3222,19 @@
   {
     "deps": [
       "boringssl", 
+      "boringssl_test_util", 
+      "boringssl_x509_test_lib"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_x509_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
       "boringssl_tab_test_lib", 
       "boringssl_test_util"
     ], 
@@ -3042,6 +3328,23 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "head_of_line_blocking_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/head_of_line_blocking.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "headers_bad_client_test", 
     "src": [
       "test/core/bad_client/tests/headers.c"
@@ -3295,40 +3598,6 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "h2_full+poll_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_full+poll.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "end2end_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_full+poll+pipe.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "end2end_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "language": "c", 
     "name": "h2_full+trace_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+trace.c"
@@ -3448,9 +3717,9 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "src": [
-      "test/core/end2end/fixtures/h2_ssl+poll.c"
+      "test/core/end2end/fixtures/h2_ssl_cert.c"
     ], 
     "third_party": false, 
     "type": "target"
@@ -3482,23 +3751,6 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "h2_uchannel_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_uchannel.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "end2end_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "language": "c", 
     "name": "h2_uds_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uds.c"
@@ -3508,23 +3760,6 @@
   }, 
   {
     "deps": [
-      "end2end_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_uds+poll.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
       "end2end_nosec_tests", 
       "gpr", 
       "gpr_test_util", 
@@ -3601,40 +3836,6 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_full+poll.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "end2end_nosec_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
-    ], 
-    "headers": [], 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_full+poll+pipe.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "end2end_nosec_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
-    ], 
-    "headers": [], 
-    "language": "c", 
     "name": "h2_full+trace_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+trace.c"
@@ -3720,23 +3921,6 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_uchannel.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "end2end_nosec_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
-    ], 
-    "headers": [], 
-    "language": "c", 
     "name": "h2_uds_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uds.c"
@@ -3746,181 +3930,165 @@
   }, 
   {
     "deps": [
-      "end2end_nosec_tests", 
       "gpr", 
       "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "grpc", 
+      "grpc_test_util"
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "src": [
-      "test/core/end2end/fixtures/h2_uds+poll.c"
+      "test/core/end2end/fuzzers/api_fuzzer.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
     ], 
     "third_party": false, 
     "type": "target"
   }, 
   {
-    "deps": [], 
-    "headers": [
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h", 
-      "include/grpc/support/alloc.h", 
-      "include/grpc/support/atm.h", 
-      "include/grpc/support/atm_gcc_atomic.h", 
-      "include/grpc/support/atm_gcc_sync.h", 
-      "include/grpc/support/atm_win32.h", 
-      "include/grpc/support/avl.h", 
-      "include/grpc/support/cmdline.h", 
-      "include/grpc/support/cpu.h", 
-      "include/grpc/support/histogram.h", 
-      "include/grpc/support/host_port.h", 
-      "include/grpc/support/log.h", 
-      "include/grpc/support/log_win32.h", 
-      "include/grpc/support/port_platform.h", 
-      "include/grpc/support/slice.h", 
-      "include/grpc/support/slice_buffer.h", 
-      "include/grpc/support/string_util.h", 
-      "include/grpc/support/subprocess.h", 
-      "include/grpc/support/sync.h", 
-      "include/grpc/support/sync_generic.h", 
-      "include/grpc/support/sync_posix.h", 
-      "include/grpc/support/sync_win32.h", 
-      "include/grpc/support/thd.h", 
-      "include/grpc/support/time.h", 
-      "include/grpc/support/tls.h", 
-      "include/grpc/support/tls_gcc.h", 
-      "include/grpc/support/tls_msvc.h", 
-      "include/grpc/support/tls_pthread.h", 
-      "include/grpc/support/useful.h", 
-      "src/core/profiling/timers.h", 
-      "src/core/support/backoff.h", 
-      "src/core/support/block_annotate.h", 
-      "src/core/support/env.h", 
-      "src/core/support/load_file.h", 
-      "src/core/support/murmur_hash.h", 
-      "src/core/support/stack_lockfree.h", 
-      "src/core/support/string.h", 
-      "src/core/support/string_win32.h", 
-      "src/core/support/thd_internal.h", 
-      "src/core/support/time_precise.h", 
-      "src/core/support/tmpfile.h"
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
     ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "src": [
+      "test/core/end2end/fuzzers/client_fuzzer.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "src": [
+      "test/core/transport/chttp2/hpack_parser_fuzzer_test.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "src": [
+      "test/core/http/fuzzer.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "src": [
+      "test/core/json/fuzzer.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "src": [
+      "test/core/nanopb/fuzzer_response.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "src": [
+      "test/core/nanopb/fuzzer_serverlist.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "src": [
+      "test/core/end2end/fuzzers/server_fuzzer.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "src": [
+      "test/core/client_config/uri_fuzzer_test.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr_base"
+    ], 
+    "headers": [], 
     "language": "c", 
     "name": "gpr", 
-    "src": [
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h", 
-      "include/grpc/support/alloc.h", 
-      "include/grpc/support/atm.h", 
-      "include/grpc/support/atm_gcc_atomic.h", 
-      "include/grpc/support/atm_gcc_sync.h", 
-      "include/grpc/support/atm_win32.h", 
-      "include/grpc/support/avl.h", 
-      "include/grpc/support/cmdline.h", 
-      "include/grpc/support/cpu.h", 
-      "include/grpc/support/histogram.h", 
-      "include/grpc/support/host_port.h", 
-      "include/grpc/support/log.h", 
-      "include/grpc/support/log_win32.h", 
-      "include/grpc/support/port_platform.h", 
-      "include/grpc/support/slice.h", 
-      "include/grpc/support/slice_buffer.h", 
-      "include/grpc/support/string_util.h", 
-      "include/grpc/support/subprocess.h", 
-      "include/grpc/support/sync.h", 
-      "include/grpc/support/sync_generic.h", 
-      "include/grpc/support/sync_posix.h", 
-      "include/grpc/support/sync_win32.h", 
-      "include/grpc/support/thd.h", 
-      "include/grpc/support/time.h", 
-      "include/grpc/support/tls.h", 
-      "include/grpc/support/tls_gcc.h", 
-      "include/grpc/support/tls_msvc.h", 
-      "include/grpc/support/tls_pthread.h", 
-      "include/grpc/support/useful.h", 
-      "src/core/profiling/basic_timers.c", 
-      "src/core/profiling/stap_timers.c", 
-      "src/core/profiling/timers.h", 
-      "src/core/support/alloc.c", 
-      "src/core/support/avl.c", 
-      "src/core/support/backoff.c", 
-      "src/core/support/backoff.h", 
-      "src/core/support/block_annotate.h", 
-      "src/core/support/cmdline.c", 
-      "src/core/support/cpu_iphone.c", 
-      "src/core/support/cpu_linux.c", 
-      "src/core/support/cpu_posix.c", 
-      "src/core/support/cpu_windows.c", 
-      "src/core/support/env.h", 
-      "src/core/support/env_linux.c", 
-      "src/core/support/env_posix.c", 
-      "src/core/support/env_win32.c", 
-      "src/core/support/histogram.c", 
-      "src/core/support/host_port.c", 
-      "src/core/support/load_file.c", 
-      "src/core/support/load_file.h", 
-      "src/core/support/log.c", 
-      "src/core/support/log_android.c", 
-      "src/core/support/log_linux.c", 
-      "src/core/support/log_posix.c", 
-      "src/core/support/log_win32.c", 
-      "src/core/support/murmur_hash.c", 
-      "src/core/support/murmur_hash.h", 
-      "src/core/support/slice.c", 
-      "src/core/support/slice_buffer.c", 
-      "src/core/support/stack_lockfree.c", 
-      "src/core/support/stack_lockfree.h", 
-      "src/core/support/string.c", 
-      "src/core/support/string.h", 
-      "src/core/support/string_posix.c", 
-      "src/core/support/string_win32.c", 
-      "src/core/support/string_win32.h", 
-      "src/core/support/subprocess_posix.c", 
-      "src/core/support/subprocess_windows.c", 
-      "src/core/support/sync.c", 
-      "src/core/support/sync_posix.c", 
-      "src/core/support/sync_win32.c", 
-      "src/core/support/thd.c", 
-      "src/core/support/thd_internal.h", 
-      "src/core/support/thd_posix.c", 
-      "src/core/support/thd_win32.c", 
-      "src/core/support/time.c", 
-      "src/core/support/time_posix.c", 
-      "src/core/support/time_precise.c", 
-      "src/core/support/time_precise.h", 
-      "src/core/support/time_win32.c", 
-      "src/core/support/tls_pthread.c", 
-      "src/core/support/tmpfile.h", 
-      "src/core/support/tmpfile_posix.c", 
-      "src/core/support/tmpfile_win32.c", 
-      "src/core/support/wrap_memcpy.c"
-    ], 
+    "src": [], 
     "third_party": false, 
     "type": "lib"
   }, 
@@ -3942,528 +4110,25 @@
   }, 
   {
     "deps": [
-      "gpr"
+      "census", 
+      "gpr", 
+      "grpc_base", 
+      "grpc_lb_policy_grpclb", 
+      "grpc_lb_policy_pick_first", 
+      "grpc_lb_policy_round_robin", 
+      "grpc_resolver_dns_native", 
+      "grpc_resolver_sockaddr", 
+      "grpc_secure", 
+      "grpc_transport_chttp2_client_insecure", 
+      "grpc_transport_chttp2_client_secure", 
+      "grpc_transport_chttp2_server_insecure", 
+      "grpc_transport_chttp2_server_secure"
     ], 
-    "headers": [
-      "include/grpc/byte_buffer.h", 
-      "include/grpc/byte_buffer_reader.h", 
-      "include/grpc/census.h", 
-      "include/grpc/compression.h", 
-      "include/grpc/grpc.h", 
-      "include/grpc/grpc_security.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/status.h", 
-      "src/core/census/aggregation.h", 
-      "src/core/census/grpc_filter.h", 
-      "src/core/census/grpc_plugin.h", 
-      "src/core/census/mlog.h", 
-      "src/core/census/rpc_metric_id.h", 
-      "src/core/channel/channel_args.h", 
-      "src/core/channel/channel_stack.h", 
-      "src/core/channel/channel_stack_builder.h", 
-      "src/core/channel/client_channel.h", 
-      "src/core/channel/client_uchannel.h", 
-      "src/core/channel/compress_filter.h", 
-      "src/core/channel/connected_channel.h", 
-      "src/core/channel/context.h", 
-      "src/core/channel/http_client_filter.h", 
-      "src/core/channel/http_server_filter.h", 
-      "src/core/channel/subchannel_call_holder.h", 
-      "src/core/client_config/client_config.h", 
-      "src/core/client_config/connector.h", 
-      "src/core/client_config/initial_connect_string.h", 
-      "src/core/client_config/lb_policies/load_balancer_api.h", 
-      "src/core/client_config/lb_policies/pick_first.h", 
-      "src/core/client_config/lb_policies/round_robin.h", 
-      "src/core/client_config/lb_policy.h", 
-      "src/core/client_config/lb_policy_factory.h", 
-      "src/core/client_config/lb_policy_registry.h", 
-      "src/core/client_config/resolver.h", 
-      "src/core/client_config/resolver_factory.h", 
-      "src/core/client_config/resolver_registry.h", 
-      "src/core/client_config/resolvers/dns_resolver.h", 
-      "src/core/client_config/resolvers/sockaddr_resolver.h", 
-      "src/core/client_config/subchannel.h", 
-      "src/core/client_config/subchannel_factory.h", 
-      "src/core/client_config/subchannel_index.h", 
-      "src/core/client_config/uri_parser.h", 
-      "src/core/compression/algorithm_metadata.h", 
-      "src/core/compression/message_compress.h", 
-      "src/core/debug/trace.h", 
-      "src/core/httpcli/format_request.h", 
-      "src/core/httpcli/httpcli.h", 
-      "src/core/httpcli/parser.h", 
-      "src/core/iomgr/closure.h", 
-      "src/core/iomgr/endpoint.h", 
-      "src/core/iomgr/endpoint_pair.h", 
-      "src/core/iomgr/exec_ctx.h", 
-      "src/core/iomgr/executor.h", 
-      "src/core/iomgr/fd_posix.h", 
-      "src/core/iomgr/iocp_windows.h", 
-      "src/core/iomgr/iomgr.h", 
-      "src/core/iomgr/iomgr_internal.h", 
-      "src/core/iomgr/iomgr_posix.h", 
-      "src/core/iomgr/pollset.h", 
-      "src/core/iomgr/pollset_posix.h", 
-      "src/core/iomgr/pollset_set.h", 
-      "src/core/iomgr/pollset_set_posix.h", 
-      "src/core/iomgr/pollset_set_windows.h", 
-      "src/core/iomgr/pollset_windows.h", 
-      "src/core/iomgr/resolve_address.h", 
-      "src/core/iomgr/sockaddr.h", 
-      "src/core/iomgr/sockaddr_posix.h", 
-      "src/core/iomgr/sockaddr_utils.h", 
-      "src/core/iomgr/sockaddr_win32.h", 
-      "src/core/iomgr/socket_utils_posix.h", 
-      "src/core/iomgr/socket_windows.h", 
-      "src/core/iomgr/tcp_client.h", 
-      "src/core/iomgr/tcp_posix.h", 
-      "src/core/iomgr/tcp_server.h", 
-      "src/core/iomgr/tcp_windows.h", 
-      "src/core/iomgr/time_averaged_stats.h", 
-      "src/core/iomgr/timer.h", 
-      "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/udp_server.h", 
-      "src/core/iomgr/wakeup_fd_pipe.h", 
-      "src/core/iomgr/wakeup_fd_posix.h", 
-      "src/core/iomgr/workqueue.h", 
-      "src/core/iomgr/workqueue_posix.h", 
-      "src/core/iomgr/workqueue_windows.h", 
-      "src/core/json/json.h", 
-      "src/core/json/json_common.h", 
-      "src/core/json/json_reader.h", 
-      "src/core/json/json_writer.h", 
-      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
-      "src/core/security/auth_filters.h", 
-      "src/core/security/b64.h", 
-      "src/core/security/credentials.h", 
-      "src/core/security/handshake.h", 
-      "src/core/security/json_token.h", 
-      "src/core/security/jwt_verifier.h", 
-      "src/core/security/secure_endpoint.h", 
-      "src/core/security/security_connector.h", 
-      "src/core/security/security_context.h", 
-      "src/core/statistics/census_interface.h", 
-      "src/core/statistics/census_rpc_stats.h", 
-      "src/core/surface/api_trace.h", 
-      "src/core/surface/call.h", 
-      "src/core/surface/call_test_only.h", 
-      "src/core/surface/channel.h", 
-      "src/core/surface/channel_init.h", 
-      "src/core/surface/channel_stack_type.h", 
-      "src/core/surface/completion_queue.h", 
-      "src/core/surface/event_string.h", 
-      "src/core/surface/init.h", 
-      "src/core/surface/lame_client.h", 
-      "src/core/surface/server.h", 
-      "src/core/surface/surface_trace.h", 
-      "src/core/transport/byte_stream.h", 
-      "src/core/transport/chttp2/alpn.h", 
-      "src/core/transport/chttp2/bin_encoder.h", 
-      "src/core/transport/chttp2/frame.h", 
-      "src/core/transport/chttp2/frame_data.h", 
-      "src/core/transport/chttp2/frame_goaway.h", 
-      "src/core/transport/chttp2/frame_ping.h", 
-      "src/core/transport/chttp2/frame_rst_stream.h", 
-      "src/core/transport/chttp2/frame_settings.h", 
-      "src/core/transport/chttp2/frame_window_update.h", 
-      "src/core/transport/chttp2/hpack_encoder.h", 
-      "src/core/transport/chttp2/hpack_parser.h", 
-      "src/core/transport/chttp2/hpack_table.h", 
-      "src/core/transport/chttp2/http2_errors.h", 
-      "src/core/transport/chttp2/huffsyms.h", 
-      "src/core/transport/chttp2/incoming_metadata.h", 
-      "src/core/transport/chttp2/internal.h", 
-      "src/core/transport/chttp2/status_conversion.h", 
-      "src/core/transport/chttp2/stream_map.h", 
-      "src/core/transport/chttp2/timeout_encoding.h", 
-      "src/core/transport/chttp2/varint.h", 
-      "src/core/transport/chttp2_transport.h", 
-      "src/core/transport/connectivity_state.h", 
-      "src/core/transport/metadata.h", 
-      "src/core/transport/metadata_batch.h", 
-      "src/core/transport/static_metadata.h", 
-      "src/core/transport/transport.h", 
-      "src/core/transport/transport_impl.h", 
-      "src/core/tsi/fake_transport_security.h", 
-      "src/core/tsi/ssl_transport_security.h", 
-      "src/core/tsi/ssl_types.h", 
-      "src/core/tsi/transport_security.h", 
-      "src/core/tsi/transport_security_interface.h", 
-      "third_party/nanopb/pb.h", 
-      "third_party/nanopb/pb_common.h", 
-      "third_party/nanopb/pb_decode.h", 
-      "third_party/nanopb/pb_encode.h"
-    ], 
+    "headers": [], 
     "language": "c", 
     "name": "grpc", 
     "src": [
-      "include/grpc/byte_buffer.h", 
-      "include/grpc/byte_buffer_reader.h", 
-      "include/grpc/census.h", 
-      "include/grpc/compression.h", 
-      "include/grpc/grpc.h", 
-      "include/grpc/grpc_security.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/status.h", 
-      "src/core/census/aggregation.h", 
-      "src/core/census/context.c", 
-      "src/core/census/grpc_context.c", 
-      "src/core/census/grpc_filter.c", 
-      "src/core/census/grpc_filter.h", 
-      "src/core/census/grpc_plugin.c", 
-      "src/core/census/grpc_plugin.h", 
-      "src/core/census/initialize.c", 
-      "src/core/census/mlog.c", 
-      "src/core/census/mlog.h", 
-      "src/core/census/operation.c", 
-      "src/core/census/placeholders.c", 
-      "src/core/census/rpc_metric_id.h", 
-      "src/core/census/tracing.c", 
-      "src/core/channel/channel_args.c", 
-      "src/core/channel/channel_args.h", 
-      "src/core/channel/channel_stack.c", 
-      "src/core/channel/channel_stack.h", 
-      "src/core/channel/channel_stack_builder.c", 
-      "src/core/channel/channel_stack_builder.h", 
-      "src/core/channel/client_channel.c", 
-      "src/core/channel/client_channel.h", 
-      "src/core/channel/client_uchannel.c", 
-      "src/core/channel/client_uchannel.h", 
-      "src/core/channel/compress_filter.c", 
-      "src/core/channel/compress_filter.h", 
-      "src/core/channel/connected_channel.c", 
-      "src/core/channel/connected_channel.h", 
-      "src/core/channel/context.h", 
-      "src/core/channel/http_client_filter.c", 
-      "src/core/channel/http_client_filter.h", 
-      "src/core/channel/http_server_filter.c", 
-      "src/core/channel/http_server_filter.h", 
-      "src/core/channel/subchannel_call_holder.c", 
-      "src/core/channel/subchannel_call_holder.h", 
-      "src/core/client_config/client_config.c", 
-      "src/core/client_config/client_config.h", 
-      "src/core/client_config/connector.c", 
-      "src/core/client_config/connector.h", 
-      "src/core/client_config/default_initial_connect_string.c", 
-      "src/core/client_config/initial_connect_string.c", 
-      "src/core/client_config/initial_connect_string.h", 
-      "src/core/client_config/lb_policies/load_balancer_api.c", 
-      "src/core/client_config/lb_policies/load_balancer_api.h", 
-      "src/core/client_config/lb_policies/pick_first.c", 
-      "src/core/client_config/lb_policies/pick_first.h", 
-      "src/core/client_config/lb_policies/round_robin.c", 
-      "src/core/client_config/lb_policies/round_robin.h", 
-      "src/core/client_config/lb_policy.c", 
-      "src/core/client_config/lb_policy.h", 
-      "src/core/client_config/lb_policy_factory.c", 
-      "src/core/client_config/lb_policy_factory.h", 
-      "src/core/client_config/lb_policy_registry.c", 
-      "src/core/client_config/lb_policy_registry.h", 
-      "src/core/client_config/resolver.c", 
-      "src/core/client_config/resolver.h", 
-      "src/core/client_config/resolver_factory.c", 
-      "src/core/client_config/resolver_factory.h", 
-      "src/core/client_config/resolver_registry.c", 
-      "src/core/client_config/resolver_registry.h", 
-      "src/core/client_config/resolvers/dns_resolver.c", 
-      "src/core/client_config/resolvers/dns_resolver.h", 
-      "src/core/client_config/resolvers/sockaddr_resolver.c", 
-      "src/core/client_config/resolvers/sockaddr_resolver.h", 
-      "src/core/client_config/subchannel.c", 
-      "src/core/client_config/subchannel.h", 
-      "src/core/client_config/subchannel_factory.c", 
-      "src/core/client_config/subchannel_factory.h", 
-      "src/core/client_config/subchannel_index.c", 
-      "src/core/client_config/subchannel_index.h", 
-      "src/core/client_config/uri_parser.c", 
-      "src/core/client_config/uri_parser.h", 
-      "src/core/compression/algorithm_metadata.h", 
-      "src/core/compression/compression_algorithm.c", 
-      "src/core/compression/message_compress.c", 
-      "src/core/compression/message_compress.h", 
-      "src/core/debug/trace.c", 
-      "src/core/debug/trace.h", 
-      "src/core/httpcli/format_request.c", 
-      "src/core/httpcli/format_request.h", 
-      "src/core/httpcli/httpcli.c", 
-      "src/core/httpcli/httpcli.h", 
-      "src/core/httpcli/httpcli_security_connector.c", 
-      "src/core/httpcli/parser.c", 
-      "src/core/httpcli/parser.h", 
-      "src/core/iomgr/closure.c", 
-      "src/core/iomgr/closure.h", 
-      "src/core/iomgr/endpoint.c", 
-      "src/core/iomgr/endpoint.h", 
-      "src/core/iomgr/endpoint_pair.h", 
-      "src/core/iomgr/endpoint_pair_posix.c", 
-      "src/core/iomgr/endpoint_pair_windows.c", 
-      "src/core/iomgr/exec_ctx.c", 
-      "src/core/iomgr/exec_ctx.h", 
-      "src/core/iomgr/executor.c", 
-      "src/core/iomgr/executor.h", 
-      "src/core/iomgr/fd_posix.c", 
-      "src/core/iomgr/fd_posix.h", 
-      "src/core/iomgr/iocp_windows.c", 
-      "src/core/iomgr/iocp_windows.h", 
-      "src/core/iomgr/iomgr.c", 
-      "src/core/iomgr/iomgr.h", 
-      "src/core/iomgr/iomgr_internal.h", 
-      "src/core/iomgr/iomgr_posix.c", 
-      "src/core/iomgr/iomgr_posix.h", 
-      "src/core/iomgr/iomgr_windows.c", 
-      "src/core/iomgr/pollset.h", 
-      "src/core/iomgr/pollset_multipoller_with_epoll.c", 
-      "src/core/iomgr/pollset_multipoller_with_poll_posix.c", 
-      "src/core/iomgr/pollset_posix.c", 
-      "src/core/iomgr/pollset_posix.h", 
-      "src/core/iomgr/pollset_set.h", 
-      "src/core/iomgr/pollset_set_posix.c", 
-      "src/core/iomgr/pollset_set_posix.h", 
-      "src/core/iomgr/pollset_set_windows.c", 
-      "src/core/iomgr/pollset_set_windows.h", 
-      "src/core/iomgr/pollset_windows.c", 
-      "src/core/iomgr/pollset_windows.h", 
-      "src/core/iomgr/resolve_address.h", 
-      "src/core/iomgr/resolve_address_posix.c", 
-      "src/core/iomgr/resolve_address_windows.c", 
-      "src/core/iomgr/sockaddr.h", 
-      "src/core/iomgr/sockaddr_posix.h", 
-      "src/core/iomgr/sockaddr_utils.c", 
-      "src/core/iomgr/sockaddr_utils.h", 
-      "src/core/iomgr/sockaddr_win32.h", 
-      "src/core/iomgr/socket_utils_common_posix.c", 
-      "src/core/iomgr/socket_utils_linux.c", 
-      "src/core/iomgr/socket_utils_posix.c", 
-      "src/core/iomgr/socket_utils_posix.h", 
-      "src/core/iomgr/socket_windows.c", 
-      "src/core/iomgr/socket_windows.h", 
-      "src/core/iomgr/tcp_client.h", 
-      "src/core/iomgr/tcp_client_posix.c", 
-      "src/core/iomgr/tcp_client_windows.c", 
-      "src/core/iomgr/tcp_posix.c", 
-      "src/core/iomgr/tcp_posix.h", 
-      "src/core/iomgr/tcp_server.h", 
-      "src/core/iomgr/tcp_server_posix.c", 
-      "src/core/iomgr/tcp_server_windows.c", 
-      "src/core/iomgr/tcp_windows.c", 
-      "src/core/iomgr/tcp_windows.h", 
-      "src/core/iomgr/time_averaged_stats.c", 
-      "src/core/iomgr/time_averaged_stats.h", 
-      "src/core/iomgr/timer.c", 
-      "src/core/iomgr/timer.h", 
-      "src/core/iomgr/timer_heap.c", 
-      "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/udp_server.c", 
-      "src/core/iomgr/udp_server.h", 
-      "src/core/iomgr/wakeup_fd_eventfd.c", 
-      "src/core/iomgr/wakeup_fd_nospecial.c", 
-      "src/core/iomgr/wakeup_fd_pipe.c", 
-      "src/core/iomgr/wakeup_fd_pipe.h", 
-      "src/core/iomgr/wakeup_fd_posix.c", 
-      "src/core/iomgr/wakeup_fd_posix.h", 
-      "src/core/iomgr/workqueue.h", 
-      "src/core/iomgr/workqueue_posix.c", 
-      "src/core/iomgr/workqueue_posix.h", 
-      "src/core/iomgr/workqueue_windows.c", 
-      "src/core/iomgr/workqueue_windows.h", 
-      "src/core/json/json.c", 
-      "src/core/json/json.h", 
-      "src/core/json/json_common.h", 
-      "src/core/json/json_reader.c", 
-      "src/core/json/json_reader.h", 
-      "src/core/json/json_string.c", 
-      "src/core/json/json_writer.c", 
-      "src/core/json/json_writer.h", 
-      "src/core/proto/grpc/lb/v0/load_balancer.pb.c", 
-      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
-      "src/core/security/auth_filters.h", 
-      "src/core/security/b64.c", 
-      "src/core/security/b64.h", 
-      "src/core/security/client_auth_filter.c", 
-      "src/core/security/credentials.c", 
-      "src/core/security/credentials.h", 
-      "src/core/security/credentials_metadata.c", 
-      "src/core/security/credentials_posix.c", 
-      "src/core/security/credentials_win32.c", 
-      "src/core/security/google_default_credentials.c", 
-      "src/core/security/handshake.c", 
-      "src/core/security/handshake.h", 
-      "src/core/security/json_token.c", 
-      "src/core/security/json_token.h", 
-      "src/core/security/jwt_verifier.c", 
-      "src/core/security/jwt_verifier.h", 
-      "src/core/security/secure_endpoint.c", 
-      "src/core/security/secure_endpoint.h", 
-      "src/core/security/security_connector.c", 
-      "src/core/security/security_connector.h", 
-      "src/core/security/security_context.c", 
-      "src/core/security/security_context.h", 
-      "src/core/security/server_auth_filter.c", 
-      "src/core/security/server_secure_chttp2.c", 
-      "src/core/statistics/census_interface.h", 
-      "src/core/statistics/census_rpc_stats.h", 
-      "src/core/surface/alarm.c", 
-      "src/core/surface/api_trace.c", 
-      "src/core/surface/api_trace.h", 
-      "src/core/surface/byte_buffer.c", 
-      "src/core/surface/byte_buffer_reader.c", 
-      "src/core/surface/call.c", 
-      "src/core/surface/call.h", 
-      "src/core/surface/call_details.c", 
-      "src/core/surface/call_log_batch.c", 
-      "src/core/surface/call_test_only.h", 
-      "src/core/surface/channel.c", 
-      "src/core/surface/channel.h", 
-      "src/core/surface/channel_connectivity.c", 
-      "src/core/surface/channel_create.c", 
-      "src/core/surface/channel_init.c", 
-      "src/core/surface/channel_init.h", 
-      "src/core/surface/channel_ping.c", 
-      "src/core/surface/channel_stack_type.c", 
-      "src/core/surface/channel_stack_type.h", 
-      "src/core/surface/completion_queue.c", 
-      "src/core/surface/completion_queue.h", 
-      "src/core/surface/event_string.c", 
-      "src/core/surface/event_string.h", 
-      "src/core/surface/init.c", 
-      "src/core/surface/init.h", 
-      "src/core/surface/init_secure.c", 
-      "src/core/surface/lame_client.c", 
-      "src/core/surface/lame_client.h", 
-      "src/core/surface/metadata_array.c", 
-      "src/core/surface/secure_channel_create.c", 
-      "src/core/surface/server.c", 
-      "src/core/surface/server.h", 
-      "src/core/surface/server_chttp2.c", 
-      "src/core/surface/surface_trace.h", 
-      "src/core/surface/validate_metadata.c", 
-      "src/core/surface/version.c", 
-      "src/core/transport/byte_stream.c", 
-      "src/core/transport/byte_stream.h", 
-      "src/core/transport/chttp2/alpn.c", 
-      "src/core/transport/chttp2/alpn.h", 
-      "src/core/transport/chttp2/bin_encoder.c", 
-      "src/core/transport/chttp2/bin_encoder.h", 
-      "src/core/transport/chttp2/frame.h", 
-      "src/core/transport/chttp2/frame_data.c", 
-      "src/core/transport/chttp2/frame_data.h", 
-      "src/core/transport/chttp2/frame_goaway.c", 
-      "src/core/transport/chttp2/frame_goaway.h", 
-      "src/core/transport/chttp2/frame_ping.c", 
-      "src/core/transport/chttp2/frame_ping.h", 
-      "src/core/transport/chttp2/frame_rst_stream.c", 
-      "src/core/transport/chttp2/frame_rst_stream.h", 
-      "src/core/transport/chttp2/frame_settings.c", 
-      "src/core/transport/chttp2/frame_settings.h", 
-      "src/core/transport/chttp2/frame_window_update.c", 
-      "src/core/transport/chttp2/frame_window_update.h", 
-      "src/core/transport/chttp2/hpack_encoder.c", 
-      "src/core/transport/chttp2/hpack_encoder.h", 
-      "src/core/transport/chttp2/hpack_parser.c", 
-      "src/core/transport/chttp2/hpack_parser.h", 
-      "src/core/transport/chttp2/hpack_table.c", 
-      "src/core/transport/chttp2/hpack_table.h", 
-      "src/core/transport/chttp2/http2_errors.h", 
-      "src/core/transport/chttp2/huffsyms.c", 
-      "src/core/transport/chttp2/huffsyms.h", 
-      "src/core/transport/chttp2/incoming_metadata.c", 
-      "src/core/transport/chttp2/incoming_metadata.h", 
-      "src/core/transport/chttp2/internal.h", 
-      "src/core/transport/chttp2/parsing.c", 
-      "src/core/transport/chttp2/status_conversion.c", 
-      "src/core/transport/chttp2/status_conversion.h", 
-      "src/core/transport/chttp2/stream_lists.c", 
-      "src/core/transport/chttp2/stream_map.c", 
-      "src/core/transport/chttp2/stream_map.h", 
-      "src/core/transport/chttp2/timeout_encoding.c", 
-      "src/core/transport/chttp2/timeout_encoding.h", 
-      "src/core/transport/chttp2/varint.c", 
-      "src/core/transport/chttp2/varint.h", 
-      "src/core/transport/chttp2/writing.c", 
-      "src/core/transport/chttp2_transport.c", 
-      "src/core/transport/chttp2_transport.h", 
-      "src/core/transport/connectivity_state.c", 
-      "src/core/transport/connectivity_state.h", 
-      "src/core/transport/metadata.c", 
-      "src/core/transport/metadata.h", 
-      "src/core/transport/metadata_batch.c", 
-      "src/core/transport/metadata_batch.h", 
-      "src/core/transport/static_metadata.c", 
-      "src/core/transport/static_metadata.h", 
-      "src/core/transport/transport.c", 
-      "src/core/transport/transport.h", 
-      "src/core/transport/transport_impl.h", 
-      "src/core/transport/transport_op_string.c", 
-      "src/core/tsi/fake_transport_security.c", 
-      "src/core/tsi/fake_transport_security.h", 
-      "src/core/tsi/ssl_transport_security.c", 
-      "src/core/tsi/ssl_transport_security.h", 
-      "src/core/tsi/ssl_types.h", 
-      "src/core/tsi/transport_security.c", 
-      "src/core/tsi/transport_security.h", 
-      "src/core/tsi/transport_security_interface.h"
-    ], 
-    "third_party": false, 
-    "type": "lib"
-  }, 
-  {
-    "deps": [], 
-    "headers": [
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h"
-    ], 
-    "language": "c", 
-    "name": "grpc_codegen_lib", 
-    "src": [
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h"
+      "src/core/lib/surface/init.c"
     ], 
     "third_party": false, 
     "type": "lib"
@@ -4484,46 +4149,23 @@
     "deps": [
       "gpr", 
       "gpr_test_util", 
-      "grpc"
+      "grpc", 
+      "grpc_test_util_base"
     ], 
     "headers": [
-      "test/core/end2end/cq_verifier.h", 
       "test/core/end2end/data/ssl_test_data.h", 
-      "test/core/end2end/fixtures/proxy.h", 
-      "test/core/iomgr/endpoint_tests.h", 
-      "test/core/security/oauth2_utils.h", 
-      "test/core/util/grpc_profiler.h", 
-      "test/core/util/parse_hexstring.h", 
-      "test/core/util/port.h", 
-      "test/core/util/port_server_client.h", 
-      "test/core/util/slice_splitter.h"
+      "test/core/security/oauth2_utils.h"
     ], 
     "language": "c", 
     "name": "grpc_test_util", 
     "src": [
-      "test/core/end2end/cq_verifier.c", 
-      "test/core/end2end/cq_verifier.h", 
+      "test/core/end2end/data/client_certs.c", 
       "test/core/end2end/data/server1_cert.c", 
       "test/core/end2end/data/server1_key.c", 
       "test/core/end2end/data/ssl_test_data.h", 
       "test/core/end2end/data/test_root_cert.c", 
-      "test/core/end2end/fixtures/proxy.c", 
-      "test/core/end2end/fixtures/proxy.h", 
-      "test/core/iomgr/endpoint_tests.c", 
-      "test/core/iomgr/endpoint_tests.h", 
       "test/core/security/oauth2_utils.c", 
-      "test/core/security/oauth2_utils.h", 
-      "test/core/util/grpc_profiler.c", 
-      "test/core/util/grpc_profiler.h", 
-      "test/core/util/parse_hexstring.c", 
-      "test/core/util/parse_hexstring.h", 
-      "test/core/util/port.h", 
-      "test/core/util/port_posix.c", 
-      "test/core/util/port_server_client.c", 
-      "test/core/util/port_server_client.h", 
-      "test/core/util/port_windows.c", 
-      "test/core/util/slice_splitter.c", 
-      "test/core/util/slice_splitter.h"
+      "test/core/security/oauth2_utils.h"
     ], 
     "third_party": false, 
     "type": "lib"
@@ -4532,465 +4174,36 @@
     "deps": [
       "gpr", 
       "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util_base", 
       "grpc_unsecure"
     ], 
-    "headers": [
-      "test/core/end2end/cq_verifier.h", 
-      "test/core/end2end/fixtures/proxy.h", 
-      "test/core/iomgr/endpoint_tests.h", 
-      "test/core/util/grpc_profiler.h", 
-      "test/core/util/parse_hexstring.h", 
-      "test/core/util/port.h", 
-      "test/core/util/port_server_client.h", 
-      "test/core/util/slice_splitter.h"
-    ], 
+    "headers": [], 
     "language": "c", 
     "name": "grpc_test_util_unsecure", 
-    "src": [
-      "test/core/end2end/cq_verifier.c", 
-      "test/core/end2end/cq_verifier.h", 
-      "test/core/end2end/fixtures/proxy.c", 
-      "test/core/end2end/fixtures/proxy.h", 
-      "test/core/iomgr/endpoint_tests.c", 
-      "test/core/iomgr/endpoint_tests.h", 
-      "test/core/util/grpc_profiler.c", 
-      "test/core/util/grpc_profiler.h", 
-      "test/core/util/parse_hexstring.c", 
-      "test/core/util/parse_hexstring.h", 
-      "test/core/util/port.h", 
-      "test/core/util/port_posix.c", 
-      "test/core/util/port_server_client.c", 
-      "test/core/util/port_server_client.h", 
-      "test/core/util/port_windows.c", 
-      "test/core/util/slice_splitter.c", 
-      "test/core/util/slice_splitter.h"
-    ], 
+    "src": [], 
     "third_party": false, 
     "type": "lib"
   }, 
   {
     "deps": [
-      "gpr"
+      "census", 
+      "gpr", 
+      "grpc_base", 
+      "grpc_lb_policy_grpclb", 
+      "grpc_lb_policy_pick_first", 
+      "grpc_lb_policy_round_robin", 
+      "grpc_resolver_dns_native", 
+      "grpc_resolver_sockaddr", 
+      "grpc_transport_chttp2_client_insecure", 
+      "grpc_transport_chttp2_server_insecure"
     ], 
-    "headers": [
-      "include/grpc/byte_buffer.h", 
-      "include/grpc/byte_buffer_reader.h", 
-      "include/grpc/census.h", 
-      "include/grpc/compression.h", 
-      "include/grpc/grpc.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/status.h", 
-      "src/core/census/aggregation.h", 
-      "src/core/census/grpc_filter.h", 
-      "src/core/census/grpc_plugin.h", 
-      "src/core/census/mlog.h", 
-      "src/core/census/rpc_metric_id.h", 
-      "src/core/channel/channel_args.h", 
-      "src/core/channel/channel_stack.h", 
-      "src/core/channel/channel_stack_builder.h", 
-      "src/core/channel/client_channel.h", 
-      "src/core/channel/client_uchannel.h", 
-      "src/core/channel/compress_filter.h", 
-      "src/core/channel/connected_channel.h", 
-      "src/core/channel/context.h", 
-      "src/core/channel/http_client_filter.h", 
-      "src/core/channel/http_server_filter.h", 
-      "src/core/channel/subchannel_call_holder.h", 
-      "src/core/client_config/client_config.h", 
-      "src/core/client_config/connector.h", 
-      "src/core/client_config/initial_connect_string.h", 
-      "src/core/client_config/lb_policies/load_balancer_api.h", 
-      "src/core/client_config/lb_policies/pick_first.h", 
-      "src/core/client_config/lb_policies/round_robin.h", 
-      "src/core/client_config/lb_policy.h", 
-      "src/core/client_config/lb_policy_factory.h", 
-      "src/core/client_config/lb_policy_registry.h", 
-      "src/core/client_config/resolver.h", 
-      "src/core/client_config/resolver_factory.h", 
-      "src/core/client_config/resolver_registry.h", 
-      "src/core/client_config/resolvers/dns_resolver.h", 
-      "src/core/client_config/resolvers/sockaddr_resolver.h", 
-      "src/core/client_config/subchannel.h", 
-      "src/core/client_config/subchannel_factory.h", 
-      "src/core/client_config/subchannel_index.h", 
-      "src/core/client_config/uri_parser.h", 
-      "src/core/compression/algorithm_metadata.h", 
-      "src/core/compression/message_compress.h", 
-      "src/core/debug/trace.h", 
-      "src/core/httpcli/format_request.h", 
-      "src/core/httpcli/httpcli.h", 
-      "src/core/httpcli/parser.h", 
-      "src/core/iomgr/closure.h", 
-      "src/core/iomgr/endpoint.h", 
-      "src/core/iomgr/endpoint_pair.h", 
-      "src/core/iomgr/exec_ctx.h", 
-      "src/core/iomgr/executor.h", 
-      "src/core/iomgr/fd_posix.h", 
-      "src/core/iomgr/iocp_windows.h", 
-      "src/core/iomgr/iomgr.h", 
-      "src/core/iomgr/iomgr_internal.h", 
-      "src/core/iomgr/iomgr_posix.h", 
-      "src/core/iomgr/pollset.h", 
-      "src/core/iomgr/pollset_posix.h", 
-      "src/core/iomgr/pollset_set.h", 
-      "src/core/iomgr/pollset_set_posix.h", 
-      "src/core/iomgr/pollset_set_windows.h", 
-      "src/core/iomgr/pollset_windows.h", 
-      "src/core/iomgr/resolve_address.h", 
-      "src/core/iomgr/sockaddr.h", 
-      "src/core/iomgr/sockaddr_posix.h", 
-      "src/core/iomgr/sockaddr_utils.h", 
-      "src/core/iomgr/sockaddr_win32.h", 
-      "src/core/iomgr/socket_utils_posix.h", 
-      "src/core/iomgr/socket_windows.h", 
-      "src/core/iomgr/tcp_client.h", 
-      "src/core/iomgr/tcp_posix.h", 
-      "src/core/iomgr/tcp_server.h", 
-      "src/core/iomgr/tcp_windows.h", 
-      "src/core/iomgr/time_averaged_stats.h", 
-      "src/core/iomgr/timer.h", 
-      "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/udp_server.h", 
-      "src/core/iomgr/wakeup_fd_pipe.h", 
-      "src/core/iomgr/wakeup_fd_posix.h", 
-      "src/core/iomgr/workqueue.h", 
-      "src/core/iomgr/workqueue_posix.h", 
-      "src/core/iomgr/workqueue_windows.h", 
-      "src/core/json/json.h", 
-      "src/core/json/json_common.h", 
-      "src/core/json/json_reader.h", 
-      "src/core/json/json_writer.h", 
-      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
-      "src/core/statistics/census_interface.h", 
-      "src/core/statistics/census_rpc_stats.h", 
-      "src/core/surface/api_trace.h", 
-      "src/core/surface/call.h", 
-      "src/core/surface/call_test_only.h", 
-      "src/core/surface/channel.h", 
-      "src/core/surface/channel_init.h", 
-      "src/core/surface/channel_stack_type.h", 
-      "src/core/surface/completion_queue.h", 
-      "src/core/surface/event_string.h", 
-      "src/core/surface/init.h", 
-      "src/core/surface/lame_client.h", 
-      "src/core/surface/server.h", 
-      "src/core/surface/surface_trace.h", 
-      "src/core/transport/byte_stream.h", 
-      "src/core/transport/chttp2/alpn.h", 
-      "src/core/transport/chttp2/bin_encoder.h", 
-      "src/core/transport/chttp2/frame.h", 
-      "src/core/transport/chttp2/frame_data.h", 
-      "src/core/transport/chttp2/frame_goaway.h", 
-      "src/core/transport/chttp2/frame_ping.h", 
-      "src/core/transport/chttp2/frame_rst_stream.h", 
-      "src/core/transport/chttp2/frame_settings.h", 
-      "src/core/transport/chttp2/frame_window_update.h", 
-      "src/core/transport/chttp2/hpack_encoder.h", 
-      "src/core/transport/chttp2/hpack_parser.h", 
-      "src/core/transport/chttp2/hpack_table.h", 
-      "src/core/transport/chttp2/http2_errors.h", 
-      "src/core/transport/chttp2/huffsyms.h", 
-      "src/core/transport/chttp2/incoming_metadata.h", 
-      "src/core/transport/chttp2/internal.h", 
-      "src/core/transport/chttp2/status_conversion.h", 
-      "src/core/transport/chttp2/stream_map.h", 
-      "src/core/transport/chttp2/timeout_encoding.h", 
-      "src/core/transport/chttp2/varint.h", 
-      "src/core/transport/chttp2_transport.h", 
-      "src/core/transport/connectivity_state.h", 
-      "src/core/transport/metadata.h", 
-      "src/core/transport/metadata_batch.h", 
-      "src/core/transport/static_metadata.h", 
-      "src/core/transport/transport.h", 
-      "src/core/transport/transport_impl.h", 
-      "third_party/nanopb/pb.h", 
-      "third_party/nanopb/pb_common.h", 
-      "third_party/nanopb/pb_decode.h", 
-      "third_party/nanopb/pb_encode.h"
-    ], 
+    "headers": [], 
     "language": "c", 
     "name": "grpc_unsecure", 
     "src": [
-      "include/grpc/byte_buffer.h", 
-      "include/grpc/byte_buffer_reader.h", 
-      "include/grpc/census.h", 
-      "include/grpc/compression.h", 
-      "include/grpc/grpc.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/status.h", 
-      "src/core/census/aggregation.h", 
-      "src/core/census/context.c", 
-      "src/core/census/grpc_context.c", 
-      "src/core/census/grpc_filter.c", 
-      "src/core/census/grpc_filter.h", 
-      "src/core/census/grpc_plugin.c", 
-      "src/core/census/grpc_plugin.h", 
-      "src/core/census/initialize.c", 
-      "src/core/census/mlog.c", 
-      "src/core/census/mlog.h", 
-      "src/core/census/operation.c", 
-      "src/core/census/placeholders.c", 
-      "src/core/census/rpc_metric_id.h", 
-      "src/core/census/tracing.c", 
-      "src/core/channel/channel_args.c", 
-      "src/core/channel/channel_args.h", 
-      "src/core/channel/channel_stack.c", 
-      "src/core/channel/channel_stack.h", 
-      "src/core/channel/channel_stack_builder.c", 
-      "src/core/channel/channel_stack_builder.h", 
-      "src/core/channel/client_channel.c", 
-      "src/core/channel/client_channel.h", 
-      "src/core/channel/client_uchannel.c", 
-      "src/core/channel/client_uchannel.h", 
-      "src/core/channel/compress_filter.c", 
-      "src/core/channel/compress_filter.h", 
-      "src/core/channel/connected_channel.c", 
-      "src/core/channel/connected_channel.h", 
-      "src/core/channel/context.h", 
-      "src/core/channel/http_client_filter.c", 
-      "src/core/channel/http_client_filter.h", 
-      "src/core/channel/http_server_filter.c", 
-      "src/core/channel/http_server_filter.h", 
-      "src/core/channel/subchannel_call_holder.c", 
-      "src/core/channel/subchannel_call_holder.h", 
-      "src/core/client_config/client_config.c", 
-      "src/core/client_config/client_config.h", 
-      "src/core/client_config/connector.c", 
-      "src/core/client_config/connector.h", 
-      "src/core/client_config/default_initial_connect_string.c", 
-      "src/core/client_config/initial_connect_string.c", 
-      "src/core/client_config/initial_connect_string.h", 
-      "src/core/client_config/lb_policies/load_balancer_api.c", 
-      "src/core/client_config/lb_policies/load_balancer_api.h", 
-      "src/core/client_config/lb_policies/pick_first.c", 
-      "src/core/client_config/lb_policies/pick_first.h", 
-      "src/core/client_config/lb_policies/round_robin.c", 
-      "src/core/client_config/lb_policies/round_robin.h", 
-      "src/core/client_config/lb_policy.c", 
-      "src/core/client_config/lb_policy.h", 
-      "src/core/client_config/lb_policy_factory.c", 
-      "src/core/client_config/lb_policy_factory.h", 
-      "src/core/client_config/lb_policy_registry.c", 
-      "src/core/client_config/lb_policy_registry.h", 
-      "src/core/client_config/resolver.c", 
-      "src/core/client_config/resolver.h", 
-      "src/core/client_config/resolver_factory.c", 
-      "src/core/client_config/resolver_factory.h", 
-      "src/core/client_config/resolver_registry.c", 
-      "src/core/client_config/resolver_registry.h", 
-      "src/core/client_config/resolvers/dns_resolver.c", 
-      "src/core/client_config/resolvers/dns_resolver.h", 
-      "src/core/client_config/resolvers/sockaddr_resolver.c", 
-      "src/core/client_config/resolvers/sockaddr_resolver.h", 
-      "src/core/client_config/subchannel.c", 
-      "src/core/client_config/subchannel.h", 
-      "src/core/client_config/subchannel_factory.c", 
-      "src/core/client_config/subchannel_factory.h", 
-      "src/core/client_config/subchannel_index.c", 
-      "src/core/client_config/subchannel_index.h", 
-      "src/core/client_config/uri_parser.c", 
-      "src/core/client_config/uri_parser.h", 
-      "src/core/compression/algorithm_metadata.h", 
-      "src/core/compression/compression_algorithm.c", 
-      "src/core/compression/message_compress.c", 
-      "src/core/compression/message_compress.h", 
-      "src/core/debug/trace.c", 
-      "src/core/debug/trace.h", 
-      "src/core/httpcli/format_request.c", 
-      "src/core/httpcli/format_request.h", 
-      "src/core/httpcli/httpcli.c", 
-      "src/core/httpcli/httpcli.h", 
-      "src/core/httpcli/parser.c", 
-      "src/core/httpcli/parser.h", 
-      "src/core/iomgr/closure.c", 
-      "src/core/iomgr/closure.h", 
-      "src/core/iomgr/endpoint.c", 
-      "src/core/iomgr/endpoint.h", 
-      "src/core/iomgr/endpoint_pair.h", 
-      "src/core/iomgr/endpoint_pair_posix.c", 
-      "src/core/iomgr/endpoint_pair_windows.c", 
-      "src/core/iomgr/exec_ctx.c", 
-      "src/core/iomgr/exec_ctx.h", 
-      "src/core/iomgr/executor.c", 
-      "src/core/iomgr/executor.h", 
-      "src/core/iomgr/fd_posix.c", 
-      "src/core/iomgr/fd_posix.h", 
-      "src/core/iomgr/iocp_windows.c", 
-      "src/core/iomgr/iocp_windows.h", 
-      "src/core/iomgr/iomgr.c", 
-      "src/core/iomgr/iomgr.h", 
-      "src/core/iomgr/iomgr_internal.h", 
-      "src/core/iomgr/iomgr_posix.c", 
-      "src/core/iomgr/iomgr_posix.h", 
-      "src/core/iomgr/iomgr_windows.c", 
-      "src/core/iomgr/pollset.h", 
-      "src/core/iomgr/pollset_multipoller_with_epoll.c", 
-      "src/core/iomgr/pollset_multipoller_with_poll_posix.c", 
-      "src/core/iomgr/pollset_posix.c", 
-      "src/core/iomgr/pollset_posix.h", 
-      "src/core/iomgr/pollset_set.h", 
-      "src/core/iomgr/pollset_set_posix.c", 
-      "src/core/iomgr/pollset_set_posix.h", 
-      "src/core/iomgr/pollset_set_windows.c", 
-      "src/core/iomgr/pollset_set_windows.h", 
-      "src/core/iomgr/pollset_windows.c", 
-      "src/core/iomgr/pollset_windows.h", 
-      "src/core/iomgr/resolve_address.h", 
-      "src/core/iomgr/resolve_address_posix.c", 
-      "src/core/iomgr/resolve_address_windows.c", 
-      "src/core/iomgr/sockaddr.h", 
-      "src/core/iomgr/sockaddr_posix.h", 
-      "src/core/iomgr/sockaddr_utils.c", 
-      "src/core/iomgr/sockaddr_utils.h", 
-      "src/core/iomgr/sockaddr_win32.h", 
-      "src/core/iomgr/socket_utils_common_posix.c", 
-      "src/core/iomgr/socket_utils_linux.c", 
-      "src/core/iomgr/socket_utils_posix.c", 
-      "src/core/iomgr/socket_utils_posix.h", 
-      "src/core/iomgr/socket_windows.c", 
-      "src/core/iomgr/socket_windows.h", 
-      "src/core/iomgr/tcp_client.h", 
-      "src/core/iomgr/tcp_client_posix.c", 
-      "src/core/iomgr/tcp_client_windows.c", 
-      "src/core/iomgr/tcp_posix.c", 
-      "src/core/iomgr/tcp_posix.h", 
-      "src/core/iomgr/tcp_server.h", 
-      "src/core/iomgr/tcp_server_posix.c", 
-      "src/core/iomgr/tcp_server_windows.c", 
-      "src/core/iomgr/tcp_windows.c", 
-      "src/core/iomgr/tcp_windows.h", 
-      "src/core/iomgr/time_averaged_stats.c", 
-      "src/core/iomgr/time_averaged_stats.h", 
-      "src/core/iomgr/timer.c", 
-      "src/core/iomgr/timer.h", 
-      "src/core/iomgr/timer_heap.c", 
-      "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/udp_server.c", 
-      "src/core/iomgr/udp_server.h", 
-      "src/core/iomgr/wakeup_fd_eventfd.c", 
-      "src/core/iomgr/wakeup_fd_nospecial.c", 
-      "src/core/iomgr/wakeup_fd_pipe.c", 
-      "src/core/iomgr/wakeup_fd_pipe.h", 
-      "src/core/iomgr/wakeup_fd_posix.c", 
-      "src/core/iomgr/wakeup_fd_posix.h", 
-      "src/core/iomgr/workqueue.h", 
-      "src/core/iomgr/workqueue_posix.c", 
-      "src/core/iomgr/workqueue_posix.h", 
-      "src/core/iomgr/workqueue_windows.c", 
-      "src/core/iomgr/workqueue_windows.h", 
-      "src/core/json/json.c", 
-      "src/core/json/json.h", 
-      "src/core/json/json_common.h", 
-      "src/core/json/json_reader.c", 
-      "src/core/json/json_reader.h", 
-      "src/core/json/json_string.c", 
-      "src/core/json/json_writer.c", 
-      "src/core/json/json_writer.h", 
-      "src/core/proto/grpc/lb/v0/load_balancer.pb.c", 
-      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
-      "src/core/statistics/census_interface.h", 
-      "src/core/statistics/census_rpc_stats.h", 
-      "src/core/surface/alarm.c", 
-      "src/core/surface/api_trace.c", 
-      "src/core/surface/api_trace.h", 
-      "src/core/surface/byte_buffer.c", 
-      "src/core/surface/byte_buffer_reader.c", 
-      "src/core/surface/call.c", 
-      "src/core/surface/call.h", 
-      "src/core/surface/call_details.c", 
-      "src/core/surface/call_log_batch.c", 
-      "src/core/surface/call_test_only.h", 
-      "src/core/surface/channel.c", 
-      "src/core/surface/channel.h", 
-      "src/core/surface/channel_connectivity.c", 
-      "src/core/surface/channel_create.c", 
-      "src/core/surface/channel_init.c", 
-      "src/core/surface/channel_init.h", 
-      "src/core/surface/channel_ping.c", 
-      "src/core/surface/channel_stack_type.c", 
-      "src/core/surface/channel_stack_type.h", 
-      "src/core/surface/completion_queue.c", 
-      "src/core/surface/completion_queue.h", 
-      "src/core/surface/event_string.c", 
-      "src/core/surface/event_string.h", 
-      "src/core/surface/init.c", 
-      "src/core/surface/init.h", 
-      "src/core/surface/init_unsecure.c", 
-      "src/core/surface/lame_client.c", 
-      "src/core/surface/lame_client.h", 
-      "src/core/surface/metadata_array.c", 
-      "src/core/surface/server.c", 
-      "src/core/surface/server.h", 
-      "src/core/surface/server_chttp2.c", 
-      "src/core/surface/surface_trace.h", 
-      "src/core/surface/validate_metadata.c", 
-      "src/core/surface/version.c", 
-      "src/core/transport/byte_stream.c", 
-      "src/core/transport/byte_stream.h", 
-      "src/core/transport/chttp2/alpn.c", 
-      "src/core/transport/chttp2/alpn.h", 
-      "src/core/transport/chttp2/bin_encoder.c", 
-      "src/core/transport/chttp2/bin_encoder.h", 
-      "src/core/transport/chttp2/frame.h", 
-      "src/core/transport/chttp2/frame_data.c", 
-      "src/core/transport/chttp2/frame_data.h", 
-      "src/core/transport/chttp2/frame_goaway.c", 
-      "src/core/transport/chttp2/frame_goaway.h", 
-      "src/core/transport/chttp2/frame_ping.c", 
-      "src/core/transport/chttp2/frame_ping.h", 
-      "src/core/transport/chttp2/frame_rst_stream.c", 
-      "src/core/transport/chttp2/frame_rst_stream.h", 
-      "src/core/transport/chttp2/frame_settings.c", 
-      "src/core/transport/chttp2/frame_settings.h", 
-      "src/core/transport/chttp2/frame_window_update.c", 
-      "src/core/transport/chttp2/frame_window_update.h", 
-      "src/core/transport/chttp2/hpack_encoder.c", 
-      "src/core/transport/chttp2/hpack_encoder.h", 
-      "src/core/transport/chttp2/hpack_parser.c", 
-      "src/core/transport/chttp2/hpack_parser.h", 
-      "src/core/transport/chttp2/hpack_table.c", 
-      "src/core/transport/chttp2/hpack_table.h", 
-      "src/core/transport/chttp2/http2_errors.h", 
-      "src/core/transport/chttp2/huffsyms.c", 
-      "src/core/transport/chttp2/huffsyms.h", 
-      "src/core/transport/chttp2/incoming_metadata.c", 
-      "src/core/transport/chttp2/incoming_metadata.h", 
-      "src/core/transport/chttp2/internal.h", 
-      "src/core/transport/chttp2/parsing.c", 
-      "src/core/transport/chttp2/status_conversion.c", 
-      "src/core/transport/chttp2/status_conversion.h", 
-      "src/core/transport/chttp2/stream_lists.c", 
-      "src/core/transport/chttp2/stream_map.c", 
-      "src/core/transport/chttp2/stream_map.h", 
-      "src/core/transport/chttp2/timeout_encoding.c", 
-      "src/core/transport/chttp2/timeout_encoding.h", 
-      "src/core/transport/chttp2/varint.c", 
-      "src/core/transport/chttp2/varint.h", 
-      "src/core/transport/chttp2/writing.c", 
-      "src/core/transport/chttp2_transport.c", 
-      "src/core/transport/chttp2_transport.h", 
-      "src/core/transport/connectivity_state.c", 
-      "src/core/transport/connectivity_state.h", 
-      "src/core/transport/metadata.c", 
-      "src/core/transport/metadata.h", 
-      "src/core/transport/metadata_batch.c", 
-      "src/core/transport/metadata_batch.h", 
-      "src/core/transport/static_metadata.c", 
-      "src/core/transport/static_metadata.h", 
-      "src/core/transport/transport.c", 
-      "src/core/transport/transport.h", 
-      "src/core/transport/transport_impl.h", 
-      "src/core/transport/transport_op_string.c"
+      "src/core/lib/surface/init.c", 
+      "src/core/lib/surface/init_unsecure.c"
     ], 
     "third_party": false, 
     "type": "lib"
@@ -5001,15 +4214,13 @@
       "grpc"
     ], 
     "headers": [
-      "include/grpc/grpc_zookeeper.h", 
-      "src/core/client_config/resolvers/zookeeper_resolver.h"
+      "include/grpc/grpc_zookeeper.h"
     ], 
     "language": "c", 
     "name": "grpc_zookeeper", 
     "src": [
       "include/grpc/grpc_zookeeper.h", 
-      "src/core/client_config/resolvers/zookeeper_resolver.c", 
-      "src/core/client_config/resolvers/zookeeper_resolver.h"
+      "src/core/ext/resolver/zookeeper/zookeeper_resolver.c"
     ], 
     "third_party": false, 
     "type": "lib"
@@ -5055,326 +4266,29 @@
   }, 
   {
     "deps": [
-      "grpc"
+      "grpc", 
+      "grpc++_base", 
+      "grpc++_codegen"
     ], 
     "headers": [
-      "include/grpc++/alarm.h", 
-      "include/grpc++/channel.h", 
-      "include/grpc++/client_context.h", 
-      "include/grpc++/completion_queue.h", 
-      "include/grpc++/create_channel.h", 
-      "include/grpc++/generic/async_generic_service.h", 
-      "include/grpc++/generic/generic_stub.h", 
-      "include/grpc++/grpc++.h", 
-      "include/grpc++/impl/call.h", 
-      "include/grpc++/impl/client_unary_call.h", 
-      "include/grpc++/impl/codegen/async_stream.h", 
-      "include/grpc++/impl/codegen/async_unary_call.h", 
-      "include/grpc++/impl/codegen/call.h", 
-      "include/grpc++/impl/codegen/call_hook.h", 
-      "include/grpc++/impl/codegen/channel_interface.h", 
-      "include/grpc++/impl/codegen/client_context.h", 
-      "include/grpc++/impl/codegen/client_unary_call.h", 
-      "include/grpc++/impl/codegen/completion_queue.h", 
-      "include/grpc++/impl/codegen/completion_queue_tag.h", 
-      "include/grpc++/impl/codegen/config.h", 
-      "include/grpc++/impl/codegen/config_protobuf.h", 
-      "include/grpc++/impl/codegen/core_codegen_interface.h", 
-      "include/grpc++/impl/codegen/grpc_library.h", 
-      "include/grpc++/impl/codegen/method_handler_impl.h", 
-      "include/grpc++/impl/codegen/proto_utils.h", 
-      "include/grpc++/impl/codegen/rpc_method.h", 
-      "include/grpc++/impl/codegen/rpc_service_method.h", 
-      "include/grpc++/impl/codegen/security/auth_context.h", 
-      "include/grpc++/impl/codegen/serialization_traits.h", 
-      "include/grpc++/impl/codegen/server_context.h", 
-      "include/grpc++/impl/codegen/server_interface.h", 
-      "include/grpc++/impl/codegen/service_type.h", 
-      "include/grpc++/impl/codegen/status.h", 
-      "include/grpc++/impl/codegen/status_code_enum.h", 
-      "include/grpc++/impl/codegen/string_ref.h", 
-      "include/grpc++/impl/codegen/stub_options.h", 
-      "include/grpc++/impl/codegen/sync.h", 
-      "include/grpc++/impl/codegen/sync_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_stream.h", 
-      "include/grpc++/impl/codegen/time.h", 
-      "include/grpc++/impl/grpc_library.h", 
-      "include/grpc++/impl/method_handler_impl.h", 
-      "include/grpc++/impl/proto_utils.h", 
-      "include/grpc++/impl/rpc_method.h", 
-      "include/grpc++/impl/rpc_service_method.h", 
-      "include/grpc++/impl/serialization_traits.h", 
-      "include/grpc++/impl/server_builder_option.h", 
-      "include/grpc++/impl/service_type.h", 
-      "include/grpc++/impl/sync.h", 
-      "include/grpc++/impl/sync_cxx11.h", 
-      "include/grpc++/impl/sync_no_cxx11.h", 
-      "include/grpc++/impl/thd.h", 
-      "include/grpc++/impl/thd_cxx11.h", 
-      "include/grpc++/impl/thd_no_cxx11.h", 
-      "include/grpc++/security/auth_context.h", 
-      "include/grpc++/security/auth_metadata_processor.h", 
-      "include/grpc++/security/credentials.h", 
-      "include/grpc++/security/server_credentials.h", 
-      "include/grpc++/server.h", 
-      "include/grpc++/server_builder.h", 
-      "include/grpc++/server_context.h", 
-      "include/grpc++/support/async_stream.h", 
-      "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/byte_buffer.h", 
-      "include/grpc++/support/channel_arguments.h", 
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/config_protobuf.h", 
-      "include/grpc++/support/slice.h", 
-      "include/grpc++/support/status.h", 
-      "include/grpc++/support/status_code_enum.h", 
-      "include/grpc++/support/string_ref.h", 
-      "include/grpc++/support/stub_options.h", 
-      "include/grpc++/support/sync_stream.h", 
-      "include/grpc++/support/time.h", 
-      "src/cpp/client/create_channel_internal.h", 
       "src/cpp/client/secure_credentials.h", 
       "src/cpp/common/core_codegen.h", 
-      "src/cpp/common/core_codegen.h", 
-      "src/cpp/common/create_auth_context.h", 
       "src/cpp/common/secure_auth_context.h", 
-      "src/cpp/server/dynamic_thread_pool.h", 
-      "src/cpp/server/secure_server_credentials.h", 
-      "src/cpp/server/thread_pool_interface.h"
+      "src/cpp/server/secure_server_credentials.h"
     ], 
     "language": "c++", 
     "name": "grpc++", 
     "src": [
-      "include/grpc++/alarm.h", 
-      "include/grpc++/channel.h", 
-      "include/grpc++/client_context.h", 
-      "include/grpc++/completion_queue.h", 
-      "include/grpc++/create_channel.h", 
-      "include/grpc++/generic/async_generic_service.h", 
-      "include/grpc++/generic/generic_stub.h", 
-      "include/grpc++/grpc++.h", 
-      "include/grpc++/impl/call.h", 
-      "include/grpc++/impl/client_unary_call.h", 
-      "include/grpc++/impl/codegen/async_stream.h", 
-      "include/grpc++/impl/codegen/async_unary_call.h", 
-      "include/grpc++/impl/codegen/call.h", 
-      "include/grpc++/impl/codegen/call_hook.h", 
-      "include/grpc++/impl/codegen/channel_interface.h", 
-      "include/grpc++/impl/codegen/client_context.h", 
-      "include/grpc++/impl/codegen/client_unary_call.h", 
-      "include/grpc++/impl/codegen/completion_queue.h", 
-      "include/grpc++/impl/codegen/completion_queue_tag.h", 
-      "include/grpc++/impl/codegen/config.h", 
-      "include/grpc++/impl/codegen/config_protobuf.h", 
-      "include/grpc++/impl/codegen/core_codegen_interface.h", 
-      "include/grpc++/impl/codegen/grpc_library.h", 
-      "include/grpc++/impl/codegen/method_handler_impl.h", 
-      "include/grpc++/impl/codegen/proto_utils.h", 
-      "include/grpc++/impl/codegen/rpc_method.h", 
-      "include/grpc++/impl/codegen/rpc_service_method.h", 
-      "include/grpc++/impl/codegen/security/auth_context.h", 
-      "include/grpc++/impl/codegen/serialization_traits.h", 
-      "include/grpc++/impl/codegen/server_context.h", 
-      "include/grpc++/impl/codegen/server_interface.h", 
-      "include/grpc++/impl/codegen/service_type.h", 
-      "include/grpc++/impl/codegen/status.h", 
-      "include/grpc++/impl/codegen/status_code_enum.h", 
-      "include/grpc++/impl/codegen/string_ref.h", 
-      "include/grpc++/impl/codegen/stub_options.h", 
-      "include/grpc++/impl/codegen/sync.h", 
-      "include/grpc++/impl/codegen/sync_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_stream.h", 
-      "include/grpc++/impl/codegen/time.h", 
-      "include/grpc++/impl/grpc_library.h", 
-      "include/grpc++/impl/method_handler_impl.h", 
-      "include/grpc++/impl/proto_utils.h", 
-      "include/grpc++/impl/rpc_method.h", 
-      "include/grpc++/impl/rpc_service_method.h", 
-      "include/grpc++/impl/serialization_traits.h", 
-      "include/grpc++/impl/server_builder_option.h", 
-      "include/grpc++/impl/service_type.h", 
-      "include/grpc++/impl/sync.h", 
-      "include/grpc++/impl/sync_cxx11.h", 
-      "include/grpc++/impl/sync_no_cxx11.h", 
-      "include/grpc++/impl/thd.h", 
-      "include/grpc++/impl/thd_cxx11.h", 
-      "include/grpc++/impl/thd_no_cxx11.h", 
-      "include/grpc++/security/auth_context.h", 
-      "include/grpc++/security/auth_metadata_processor.h", 
-      "include/grpc++/security/credentials.h", 
-      "include/grpc++/security/server_credentials.h", 
-      "include/grpc++/server.h", 
-      "include/grpc++/server_builder.h", 
-      "include/grpc++/server_context.h", 
-      "include/grpc++/support/async_stream.h", 
-      "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/byte_buffer.h", 
-      "include/grpc++/support/channel_arguments.h", 
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/config_protobuf.h", 
-      "include/grpc++/support/slice.h", 
-      "include/grpc++/support/status.h", 
-      "include/grpc++/support/status_code_enum.h", 
-      "include/grpc++/support/string_ref.h", 
-      "include/grpc++/support/stub_options.h", 
-      "include/grpc++/support/sync_stream.h", 
-      "include/grpc++/support/time.h", 
-      "src/cpp/client/channel.cc", 
-      "src/cpp/client/client_context.cc", 
-      "src/cpp/client/create_channel.cc", 
-      "src/cpp/client/create_channel_internal.cc", 
-      "src/cpp/client/create_channel_internal.h", 
-      "src/cpp/client/credentials.cc", 
-      "src/cpp/client/generic_stub.cc", 
-      "src/cpp/client/insecure_credentials.cc", 
       "src/cpp/client/secure_credentials.cc", 
       "src/cpp/client/secure_credentials.h", 
-      "src/cpp/codegen/codegen_init.cc", 
       "src/cpp/common/auth_property_iterator.cc", 
-      "src/cpp/common/channel_arguments.cc", 
-      "src/cpp/common/completion_queue.cc", 
-      "src/cpp/common/core_codegen.cc", 
       "src/cpp/common/core_codegen.h", 
-      "src/cpp/common/core_codegen.h", 
-      "src/cpp/common/create_auth_context.h", 
-      "src/cpp/common/rpc_method.cc", 
       "src/cpp/common/secure_auth_context.cc", 
       "src/cpp/common/secure_auth_context.h", 
       "src/cpp/common/secure_channel_arguments.cc", 
       "src/cpp/common/secure_create_auth_context.cc", 
-      "src/cpp/server/async_generic_service.cc", 
-      "src/cpp/server/create_default_thread_pool.cc", 
-      "src/cpp/server/dynamic_thread_pool.cc", 
-      "src/cpp/server/dynamic_thread_pool.h", 
-      "src/cpp/server/insecure_server_credentials.cc", 
       "src/cpp/server/secure_server_credentials.cc", 
-      "src/cpp/server/secure_server_credentials.h", 
-      "src/cpp/server/server.cc", 
-      "src/cpp/server/server_builder.cc", 
-      "src/cpp/server/server_context.cc", 
-      "src/cpp/server/server_credentials.cc", 
-      "src/cpp/server/thread_pool_interface.h", 
-      "src/cpp/util/byte_buffer.cc", 
-      "src/cpp/util/slice.cc", 
-      "src/cpp/util/status.cc", 
-      "src/cpp/util/string_ref.cc", 
-      "src/cpp/util/time.cc"
-    ], 
-    "third_party": false, 
-    "type": "lib"
-  }, 
-  {
-    "deps": [], 
-    "headers": [
-      "include/grpc++/impl/codegen/async_stream.h", 
-      "include/grpc++/impl/codegen/async_unary_call.h", 
-      "include/grpc++/impl/codegen/call.h", 
-      "include/grpc++/impl/codegen/call_hook.h", 
-      "include/grpc++/impl/codegen/channel_interface.h", 
-      "include/grpc++/impl/codegen/client_context.h", 
-      "include/grpc++/impl/codegen/client_unary_call.h", 
-      "include/grpc++/impl/codegen/completion_queue.h", 
-      "include/grpc++/impl/codegen/completion_queue_tag.h", 
-      "include/grpc++/impl/codegen/config.h", 
-      "include/grpc++/impl/codegen/config_protobuf.h", 
-      "include/grpc++/impl/codegen/core_codegen_interface.h", 
-      "include/grpc++/impl/codegen/grpc_library.h", 
-      "include/grpc++/impl/codegen/method_handler_impl.h", 
-      "include/grpc++/impl/codegen/proto_utils.h", 
-      "include/grpc++/impl/codegen/rpc_method.h", 
-      "include/grpc++/impl/codegen/rpc_service_method.h", 
-      "include/grpc++/impl/codegen/security/auth_context.h", 
-      "include/grpc++/impl/codegen/serialization_traits.h", 
-      "include/grpc++/impl/codegen/server_context.h", 
-      "include/grpc++/impl/codegen/server_interface.h", 
-      "include/grpc++/impl/codegen/service_type.h", 
-      "include/grpc++/impl/codegen/status.h", 
-      "include/grpc++/impl/codegen/status_code_enum.h", 
-      "include/grpc++/impl/codegen/string_ref.h", 
-      "include/grpc++/impl/codegen/stub_options.h", 
-      "include/grpc++/impl/codegen/sync.h", 
-      "include/grpc++/impl/codegen/sync_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_stream.h", 
-      "include/grpc++/impl/codegen/time.h", 
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h"
-    ], 
-    "language": "c++", 
-    "name": "grpc++_codegen_lib", 
-    "src": [
-      "include/grpc++/impl/codegen/async_stream.h", 
-      "include/grpc++/impl/codegen/async_unary_call.h", 
-      "include/grpc++/impl/codegen/call.h", 
-      "include/grpc++/impl/codegen/call_hook.h", 
-      "include/grpc++/impl/codegen/channel_interface.h", 
-      "include/grpc++/impl/codegen/client_context.h", 
-      "include/grpc++/impl/codegen/client_unary_call.h", 
-      "include/grpc++/impl/codegen/completion_queue.h", 
-      "include/grpc++/impl/codegen/completion_queue_tag.h", 
-      "include/grpc++/impl/codegen/config.h", 
-      "include/grpc++/impl/codegen/config_protobuf.h", 
-      "include/grpc++/impl/codegen/core_codegen_interface.h", 
-      "include/grpc++/impl/codegen/grpc_library.h", 
-      "include/grpc++/impl/codegen/method_handler_impl.h", 
-      "include/grpc++/impl/codegen/proto_utils.h", 
-      "include/grpc++/impl/codegen/rpc_method.h", 
-      "include/grpc++/impl/codegen/rpc_service_method.h", 
-      "include/grpc++/impl/codegen/security/auth_context.h", 
-      "include/grpc++/impl/codegen/serialization_traits.h", 
-      "include/grpc++/impl/codegen/server_context.h", 
-      "include/grpc++/impl/codegen/server_interface.h", 
-      "include/grpc++/impl/codegen/service_type.h", 
-      "include/grpc++/impl/codegen/status.h", 
-      "include/grpc++/impl/codegen/status_code_enum.h", 
-      "include/grpc++/impl/codegen/string_ref.h", 
-      "include/grpc++/impl/codegen/stub_options.h", 
-      "include/grpc++/impl/codegen/sync.h", 
-      "include/grpc++/impl/codegen/sync_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_stream.h", 
-      "include/grpc++/impl/codegen/time.h", 
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/byte_buffer.h", 
-      "include/grpc/impl/codegen/compression_types.h", 
-      "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/grpc_types.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/propagation_bits.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/status.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h", 
-      "src/cpp/codegen/codegen_init.cc"
+      "src/cpp/server/secure_server_credentials.h"
     ], 
     "third_party": false, 
     "type": "lib"
@@ -5437,230 +4351,33 @@
   {
     "deps": [
       "gpr", 
+      "grpc", 
+      "grpc++_base", 
+      "grpc++_codegen", 
       "grpc_unsecure"
     ], 
-    "headers": [
-      "include/grpc++/alarm.h", 
-      "include/grpc++/channel.h", 
-      "include/grpc++/client_context.h", 
-      "include/grpc++/completion_queue.h", 
-      "include/grpc++/create_channel.h", 
-      "include/grpc++/generic/async_generic_service.h", 
-      "include/grpc++/generic/generic_stub.h", 
-      "include/grpc++/grpc++.h", 
-      "include/grpc++/impl/call.h", 
-      "include/grpc++/impl/client_unary_call.h", 
-      "include/grpc++/impl/codegen/async_stream.h", 
-      "include/grpc++/impl/codegen/async_unary_call.h", 
-      "include/grpc++/impl/codegen/call.h", 
-      "include/grpc++/impl/codegen/call_hook.h", 
-      "include/grpc++/impl/codegen/channel_interface.h", 
-      "include/grpc++/impl/codegen/client_context.h", 
-      "include/grpc++/impl/codegen/client_unary_call.h", 
-      "include/grpc++/impl/codegen/completion_queue.h", 
-      "include/grpc++/impl/codegen/completion_queue_tag.h", 
-      "include/grpc++/impl/codegen/config.h", 
-      "include/grpc++/impl/codegen/config_protobuf.h", 
-      "include/grpc++/impl/codegen/core_codegen_interface.h", 
-      "include/grpc++/impl/codegen/grpc_library.h", 
-      "include/grpc++/impl/codegen/method_handler_impl.h", 
-      "include/grpc++/impl/codegen/proto_utils.h", 
-      "include/grpc++/impl/codegen/rpc_method.h", 
-      "include/grpc++/impl/codegen/rpc_service_method.h", 
-      "include/grpc++/impl/codegen/security/auth_context.h", 
-      "include/grpc++/impl/codegen/serialization_traits.h", 
-      "include/grpc++/impl/codegen/server_context.h", 
-      "include/grpc++/impl/codegen/server_interface.h", 
-      "include/grpc++/impl/codegen/service_type.h", 
-      "include/grpc++/impl/codegen/status.h", 
-      "include/grpc++/impl/codegen/status_code_enum.h", 
-      "include/grpc++/impl/codegen/string_ref.h", 
-      "include/grpc++/impl/codegen/stub_options.h", 
-      "include/grpc++/impl/codegen/sync.h", 
-      "include/grpc++/impl/codegen/sync_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_stream.h", 
-      "include/grpc++/impl/codegen/time.h", 
-      "include/grpc++/impl/grpc_library.h", 
-      "include/grpc++/impl/method_handler_impl.h", 
-      "include/grpc++/impl/proto_utils.h", 
-      "include/grpc++/impl/rpc_method.h", 
-      "include/grpc++/impl/rpc_service_method.h", 
-      "include/grpc++/impl/serialization_traits.h", 
-      "include/grpc++/impl/server_builder_option.h", 
-      "include/grpc++/impl/service_type.h", 
-      "include/grpc++/impl/sync.h", 
-      "include/grpc++/impl/sync_cxx11.h", 
-      "include/grpc++/impl/sync_no_cxx11.h", 
-      "include/grpc++/impl/thd.h", 
-      "include/grpc++/impl/thd_cxx11.h", 
-      "include/grpc++/impl/thd_no_cxx11.h", 
-      "include/grpc++/security/auth_context.h", 
-      "include/grpc++/security/auth_metadata_processor.h", 
-      "include/grpc++/security/credentials.h", 
-      "include/grpc++/security/server_credentials.h", 
-      "include/grpc++/server.h", 
-      "include/grpc++/server_builder.h", 
-      "include/grpc++/server_context.h", 
-      "include/grpc++/support/async_stream.h", 
-      "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/byte_buffer.h", 
-      "include/grpc++/support/channel_arguments.h", 
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/config_protobuf.h", 
-      "include/grpc++/support/slice.h", 
-      "include/grpc++/support/status.h", 
-      "include/grpc++/support/status_code_enum.h", 
-      "include/grpc++/support/string_ref.h", 
-      "include/grpc++/support/stub_options.h", 
-      "include/grpc++/support/sync_stream.h", 
-      "include/grpc++/support/time.h", 
-      "src/cpp/client/create_channel_internal.h", 
-      "src/cpp/common/core_codegen.h", 
-      "src/cpp/common/create_auth_context.h", 
-      "src/cpp/server/dynamic_thread_pool.h", 
-      "src/cpp/server/thread_pool_interface.h"
-    ], 
+    "headers": [], 
     "language": "c++", 
     "name": "grpc++_unsecure", 
     "src": [
-      "include/grpc++/alarm.h", 
-      "include/grpc++/channel.h", 
-      "include/grpc++/client_context.h", 
-      "include/grpc++/completion_queue.h", 
-      "include/grpc++/create_channel.h", 
-      "include/grpc++/generic/async_generic_service.h", 
-      "include/grpc++/generic/generic_stub.h", 
-      "include/grpc++/grpc++.h", 
-      "include/grpc++/impl/call.h", 
-      "include/grpc++/impl/client_unary_call.h", 
-      "include/grpc++/impl/codegen/async_stream.h", 
-      "include/grpc++/impl/codegen/async_unary_call.h", 
-      "include/grpc++/impl/codegen/call.h", 
-      "include/grpc++/impl/codegen/call_hook.h", 
-      "include/grpc++/impl/codegen/channel_interface.h", 
-      "include/grpc++/impl/codegen/client_context.h", 
-      "include/grpc++/impl/codegen/client_unary_call.h", 
-      "include/grpc++/impl/codegen/completion_queue.h", 
-      "include/grpc++/impl/codegen/completion_queue_tag.h", 
-      "include/grpc++/impl/codegen/config.h", 
-      "include/grpc++/impl/codegen/config_protobuf.h", 
-      "include/grpc++/impl/codegen/core_codegen_interface.h", 
-      "include/grpc++/impl/codegen/grpc_library.h", 
-      "include/grpc++/impl/codegen/method_handler_impl.h", 
-      "include/grpc++/impl/codegen/proto_utils.h", 
-      "include/grpc++/impl/codegen/rpc_method.h", 
-      "include/grpc++/impl/codegen/rpc_service_method.h", 
-      "include/grpc++/impl/codegen/security/auth_context.h", 
-      "include/grpc++/impl/codegen/serialization_traits.h", 
-      "include/grpc++/impl/codegen/server_context.h", 
-      "include/grpc++/impl/codegen/server_interface.h", 
-      "include/grpc++/impl/codegen/service_type.h", 
-      "include/grpc++/impl/codegen/status.h", 
-      "include/grpc++/impl/codegen/status_code_enum.h", 
-      "include/grpc++/impl/codegen/string_ref.h", 
-      "include/grpc++/impl/codegen/stub_options.h", 
-      "include/grpc++/impl/codegen/sync.h", 
-      "include/grpc++/impl/codegen/sync_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
-      "include/grpc++/impl/codegen/sync_stream.h", 
-      "include/grpc++/impl/codegen/time.h", 
-      "include/grpc++/impl/grpc_library.h", 
-      "include/grpc++/impl/method_handler_impl.h", 
-      "include/grpc++/impl/proto_utils.h", 
-      "include/grpc++/impl/rpc_method.h", 
-      "include/grpc++/impl/rpc_service_method.h", 
-      "include/grpc++/impl/serialization_traits.h", 
-      "include/grpc++/impl/server_builder_option.h", 
-      "include/grpc++/impl/service_type.h", 
-      "include/grpc++/impl/sync.h", 
-      "include/grpc++/impl/sync_cxx11.h", 
-      "include/grpc++/impl/sync_no_cxx11.h", 
-      "include/grpc++/impl/thd.h", 
-      "include/grpc++/impl/thd_cxx11.h", 
-      "include/grpc++/impl/thd_no_cxx11.h", 
-      "include/grpc++/security/auth_context.h", 
-      "include/grpc++/security/auth_metadata_processor.h", 
-      "include/grpc++/security/credentials.h", 
-      "include/grpc++/security/server_credentials.h", 
-      "include/grpc++/server.h", 
-      "include/grpc++/server_builder.h", 
-      "include/grpc++/server_context.h", 
-      "include/grpc++/support/async_stream.h", 
-      "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/byte_buffer.h", 
-      "include/grpc++/support/channel_arguments.h", 
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/config_protobuf.h", 
-      "include/grpc++/support/slice.h", 
-      "include/grpc++/support/status.h", 
-      "include/grpc++/support/status_code_enum.h", 
-      "include/grpc++/support/string_ref.h", 
-      "include/grpc++/support/stub_options.h", 
-      "include/grpc++/support/sync_stream.h", 
-      "include/grpc++/support/time.h", 
-      "src/cpp/client/channel.cc", 
-      "src/cpp/client/client_context.cc", 
-      "src/cpp/client/create_channel.cc", 
-      "src/cpp/client/create_channel_internal.cc", 
-      "src/cpp/client/create_channel_internal.h", 
-      "src/cpp/client/credentials.cc", 
-      "src/cpp/client/generic_stub.cc", 
-      "src/cpp/client/insecure_credentials.cc", 
-      "src/cpp/codegen/codegen_init.cc", 
-      "src/cpp/common/channel_arguments.cc", 
-      "src/cpp/common/completion_queue.cc", 
-      "src/cpp/common/core_codegen.cc", 
-      "src/cpp/common/core_codegen.h", 
-      "src/cpp/common/create_auth_context.h", 
-      "src/cpp/common/insecure_create_auth_context.cc", 
-      "src/cpp/common/rpc_method.cc", 
-      "src/cpp/server/async_generic_service.cc", 
-      "src/cpp/server/create_default_thread_pool.cc", 
-      "src/cpp/server/dynamic_thread_pool.cc", 
-      "src/cpp/server/dynamic_thread_pool.h", 
-      "src/cpp/server/insecure_server_credentials.cc", 
-      "src/cpp/server/server.cc", 
-      "src/cpp/server/server_builder.cc", 
-      "src/cpp/server/server_context.cc", 
-      "src/cpp/server/server_credentials.cc", 
-      "src/cpp/server/thread_pool_interface.h", 
-      "src/cpp/util/byte_buffer.cc", 
-      "src/cpp/util/slice.cc", 
-      "src/cpp/util/status.cc", 
-      "src/cpp/util/string_ref.cc", 
-      "src/cpp/util/time.cc"
+      "src/cpp/common/insecure_create_auth_context.cc"
     ], 
     "third_party": false, 
     "type": "lib"
   }, 
   {
     "deps": [
-      "grpc++_codegen_lib"
+      "grpc++_config"
     ], 
     "headers": [
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/config_protobuf.h", 
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h", 
       "src/compiler/config.h", 
       "src/compiler/cpp_generator.h", 
       "src/compiler/cpp_generator_helpers.h", 
       "src/compiler/csharp_generator.h", 
       "src/compiler/csharp_generator_helpers.h", 
       "src/compiler/generator_helpers.h", 
+      "src/compiler/node_generator.h", 
+      "src/compiler/node_generator_helpers.h", 
       "src/compiler/objective_c_generator.h", 
       "src/compiler/objective_c_generator_helpers.h", 
       "src/compiler/python_generator.h", 
@@ -5672,22 +4389,6 @@
     "language": "c++", 
     "name": "grpc_plugin_support", 
     "src": [
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/config_protobuf.h", 
-      "include/grpc/impl/codegen/alloc.h", 
-      "include/grpc/impl/codegen/atm.h", 
-      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
-      "include/grpc/impl/codegen/atm_gcc_sync.h", 
-      "include/grpc/impl/codegen/atm_win32.h", 
-      "include/grpc/impl/codegen/log.h", 
-      "include/grpc/impl/codegen/port_platform.h", 
-      "include/grpc/impl/codegen/slice.h", 
-      "include/grpc/impl/codegen/slice_buffer.h", 
-      "include/grpc/impl/codegen/sync.h", 
-      "include/grpc/impl/codegen/sync_generic.h", 
-      "include/grpc/impl/codegen/sync_posix.h", 
-      "include/grpc/impl/codegen/sync_win32.h", 
-      "include/grpc/impl/codegen/time.h", 
       "src/compiler/config.h", 
       "src/compiler/cpp_generator.cc", 
       "src/compiler/cpp_generator.h", 
@@ -5696,6 +4397,9 @@
       "src/compiler/csharp_generator.h", 
       "src/compiler/csharp_generator_helpers.h", 
       "src/compiler/generator_helpers.h", 
+      "src/compiler/node_generator.cc", 
+      "src/compiler/node_generator.h", 
+      "src/compiler/node_generator_helpers.h", 
       "src/compiler/objective_c_generator.cc", 
       "src/compiler/objective_c_generator.h", 
       "src/compiler/objective_c_generator_helpers.h", 
@@ -5896,12 +4600,12 @@
       "third_party/boringssl/crypto/cipher/internal.h", 
       "third_party/boringssl/crypto/conf/conf_def.h", 
       "third_party/boringssl/crypto/conf/internal.h", 
+      "third_party/boringssl/crypto/curve25519/internal.h", 
       "third_party/boringssl/crypto/des/internal.h", 
       "third_party/boringssl/crypto/dh/internal.h", 
       "third_party/boringssl/crypto/digest/internal.h", 
       "third_party/boringssl/crypto/digest/md32_common.h", 
       "third_party/boringssl/crypto/directory.h", 
-      "third_party/boringssl/crypto/dsa/internal.h", 
       "third_party/boringssl/crypto/ec/internal.h", 
       "third_party/boringssl/crypto/ec/p256-x86_64-table.h", 
       "third_party/boringssl/crypto/evp/internal.h", 
@@ -6414,6 +5118,18 @@
       "boringssl_test_util"
     ], 
     "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_x509_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
     "language": "c", 
     "name": "boringssl_tab_test_lib", 
     "src": [], 
@@ -6546,9 +5262,11 @@
       "test/core/end2end/tests/default_host.c", 
       "test/core/end2end/tests/disappearing_server.c", 
       "test/core/end2end/tests/empty_batch.c", 
+      "test/core/end2end/tests/filter_causes_close.c", 
       "test/core/end2end/tests/graceful_server_shutdown.c", 
       "test/core/end2end/tests/high_initial_seqno.c", 
       "test/core/end2end/tests/hpack_size.c", 
+      "test/core/end2end/tests/idempotent_request.c", 
       "test/core/end2end/tests/invoke_large_request.c", 
       "test/core/end2end/tests/large_metadata.c", 
       "test/core/end2end/tests/max_concurrent_streams.c", 
@@ -6602,9 +5320,11 @@
       "test/core/end2end/tests/default_host.c", 
       "test/core/end2end/tests/disappearing_server.c", 
       "test/core/end2end/tests/empty_batch.c", 
+      "test/core/end2end/tests/filter_causes_close.c", 
       "test/core/end2end/tests/graceful_server_shutdown.c", 
       "test/core/end2end/tests/high_initial_seqno.c", 
       "test/core/end2end/tests/hpack_size.c", 
+      "test/core/end2end/tests/idempotent_request.c", 
       "test/core/end2end/tests/invoke_large_request.c", 
       "test/core/end2end/tests/large_metadata.c", 
       "test/core/end2end/tests/max_concurrent_streams.c", 
@@ -6627,5 +5347,1177 @@
     ], 
     "third_party": false, 
     "type": "lib"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base"
+    ], 
+    "headers": [
+      "include/grpc/census.h", 
+      "src/core/ext/census/aggregation.h", 
+      "src/core/ext/census/census_interface.h", 
+      "src/core/ext/census/census_rpc_stats.h", 
+      "src/core/ext/census/grpc_filter.h", 
+      "src/core/ext/census/mlog.h", 
+      "src/core/ext/census/rpc_metric_id.h"
+    ], 
+    "language": "c", 
+    "name": "census", 
+    "src": [
+      "include/grpc/census.h", 
+      "src/core/ext/census/aggregation.h", 
+      "src/core/ext/census/census_interface.h", 
+      "src/core/ext/census/census_rpc_stats.h", 
+      "src/core/ext/census/context.c", 
+      "src/core/ext/census/grpc_context.c", 
+      "src/core/ext/census/grpc_filter.c", 
+      "src/core/ext/census/grpc_filter.h", 
+      "src/core/ext/census/grpc_plugin.c", 
+      "src/core/ext/census/initialize.c", 
+      "src/core/ext/census/mlog.c", 
+      "src/core/ext/census/mlog.h", 
+      "src/core/ext/census/operation.c", 
+      "src/core/ext/census/placeholders.c", 
+      "src/core/ext/census/rpc_metric_id.h", 
+      "src/core/ext/census/tracing.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr_codegen"
+    ], 
+    "headers": [
+      "include/grpc/support/alloc.h", 
+      "include/grpc/support/atm.h", 
+      "include/grpc/support/atm_gcc_atomic.h", 
+      "include/grpc/support/atm_gcc_sync.h", 
+      "include/grpc/support/atm_win32.h", 
+      "include/grpc/support/avl.h", 
+      "include/grpc/support/cmdline.h", 
+      "include/grpc/support/cpu.h", 
+      "include/grpc/support/histogram.h", 
+      "include/grpc/support/host_port.h", 
+      "include/grpc/support/log.h", 
+      "include/grpc/support/log_win32.h", 
+      "include/grpc/support/port_platform.h", 
+      "include/grpc/support/slice.h", 
+      "include/grpc/support/slice_buffer.h", 
+      "include/grpc/support/string_util.h", 
+      "include/grpc/support/subprocess.h", 
+      "include/grpc/support/sync.h", 
+      "include/grpc/support/sync_generic.h", 
+      "include/grpc/support/sync_posix.h", 
+      "include/grpc/support/sync_win32.h", 
+      "include/grpc/support/thd.h", 
+      "include/grpc/support/time.h", 
+      "include/grpc/support/tls.h", 
+      "include/grpc/support/tls_gcc.h", 
+      "include/grpc/support/tls_msvc.h", 
+      "include/grpc/support/tls_pthread.h", 
+      "include/grpc/support/useful.h", 
+      "src/core/lib/profiling/timers.h", 
+      "src/core/lib/support/backoff.h", 
+      "src/core/lib/support/block_annotate.h", 
+      "src/core/lib/support/env.h", 
+      "src/core/lib/support/load_file.h", 
+      "src/core/lib/support/murmur_hash.h", 
+      "src/core/lib/support/stack_lockfree.h", 
+      "src/core/lib/support/string.h", 
+      "src/core/lib/support/string_win32.h", 
+      "src/core/lib/support/thd_internal.h", 
+      "src/core/lib/support/time_precise.h", 
+      "src/core/lib/support/tmpfile.h"
+    ], 
+    "language": "c", 
+    "name": "gpr_base", 
+    "src": [
+      "include/grpc/support/alloc.h", 
+      "include/grpc/support/atm.h", 
+      "include/grpc/support/atm_gcc_atomic.h", 
+      "include/grpc/support/atm_gcc_sync.h", 
+      "include/grpc/support/atm_win32.h", 
+      "include/grpc/support/avl.h", 
+      "include/grpc/support/cmdline.h", 
+      "include/grpc/support/cpu.h", 
+      "include/grpc/support/histogram.h", 
+      "include/grpc/support/host_port.h", 
+      "include/grpc/support/log.h", 
+      "include/grpc/support/log_win32.h", 
+      "include/grpc/support/port_platform.h", 
+      "include/grpc/support/slice.h", 
+      "include/grpc/support/slice_buffer.h", 
+      "include/grpc/support/string_util.h", 
+      "include/grpc/support/subprocess.h", 
+      "include/grpc/support/sync.h", 
+      "include/grpc/support/sync_generic.h", 
+      "include/grpc/support/sync_posix.h", 
+      "include/grpc/support/sync_win32.h", 
+      "include/grpc/support/thd.h", 
+      "include/grpc/support/time.h", 
+      "include/grpc/support/tls.h", 
+      "include/grpc/support/tls_gcc.h", 
+      "include/grpc/support/tls_msvc.h", 
+      "include/grpc/support/tls_pthread.h", 
+      "include/grpc/support/useful.h", 
+      "src/core/lib/profiling/basic_timers.c", 
+      "src/core/lib/profiling/stap_timers.c", 
+      "src/core/lib/profiling/timers.h", 
+      "src/core/lib/support/alloc.c", 
+      "src/core/lib/support/avl.c", 
+      "src/core/lib/support/backoff.c", 
+      "src/core/lib/support/backoff.h", 
+      "src/core/lib/support/block_annotate.h", 
+      "src/core/lib/support/cmdline.c", 
+      "src/core/lib/support/cpu_iphone.c", 
+      "src/core/lib/support/cpu_linux.c", 
+      "src/core/lib/support/cpu_posix.c", 
+      "src/core/lib/support/cpu_windows.c", 
+      "src/core/lib/support/env.h", 
+      "src/core/lib/support/env_linux.c", 
+      "src/core/lib/support/env_posix.c", 
+      "src/core/lib/support/env_win32.c", 
+      "src/core/lib/support/histogram.c", 
+      "src/core/lib/support/host_port.c", 
+      "src/core/lib/support/load_file.c", 
+      "src/core/lib/support/load_file.h", 
+      "src/core/lib/support/log.c", 
+      "src/core/lib/support/log_android.c", 
+      "src/core/lib/support/log_linux.c", 
+      "src/core/lib/support/log_posix.c", 
+      "src/core/lib/support/log_win32.c", 
+      "src/core/lib/support/murmur_hash.c", 
+      "src/core/lib/support/murmur_hash.h", 
+      "src/core/lib/support/slice.c", 
+      "src/core/lib/support/slice_buffer.c", 
+      "src/core/lib/support/stack_lockfree.c", 
+      "src/core/lib/support/stack_lockfree.h", 
+      "src/core/lib/support/string.c", 
+      "src/core/lib/support/string.h", 
+      "src/core/lib/support/string_posix.c", 
+      "src/core/lib/support/string_win32.c", 
+      "src/core/lib/support/string_win32.h", 
+      "src/core/lib/support/subprocess_posix.c", 
+      "src/core/lib/support/subprocess_windows.c", 
+      "src/core/lib/support/sync.c", 
+      "src/core/lib/support/sync_posix.c", 
+      "src/core/lib/support/sync_win32.c", 
+      "src/core/lib/support/thd.c", 
+      "src/core/lib/support/thd_internal.h", 
+      "src/core/lib/support/thd_posix.c", 
+      "src/core/lib/support/thd_win32.c", 
+      "src/core/lib/support/time.c", 
+      "src/core/lib/support/time_posix.c", 
+      "src/core/lib/support/time_precise.c", 
+      "src/core/lib/support/time_precise.h", 
+      "src/core/lib/support/time_win32.c", 
+      "src/core/lib/support/tls_pthread.c", 
+      "src/core/lib/support/tmpfile.h", 
+      "src/core/lib/support/tmpfile_posix.c", 
+      "src/core/lib/support/tmpfile_win32.c", 
+      "src/core/lib/support/wrap_memcpy.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [], 
+    "headers": [
+      "include/grpc/impl/codegen/alloc.h", 
+      "include/grpc/impl/codegen/atm.h", 
+      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
+      "include/grpc/impl/codegen/atm_gcc_sync.h", 
+      "include/grpc/impl/codegen/atm_win32.h", 
+      "include/grpc/impl/codegen/log.h", 
+      "include/grpc/impl/codegen/port_platform.h", 
+      "include/grpc/impl/codegen/slice.h", 
+      "include/grpc/impl/codegen/slice_buffer.h", 
+      "include/grpc/impl/codegen/sync.h", 
+      "include/grpc/impl/codegen/sync_generic.h", 
+      "include/grpc/impl/codegen/sync_posix.h", 
+      "include/grpc/impl/codegen/sync_win32.h", 
+      "include/grpc/impl/codegen/time.h"
+    ], 
+    "language": "c", 
+    "name": "gpr_codegen", 
+    "src": [
+      "include/grpc/impl/codegen/alloc.h", 
+      "include/grpc/impl/codegen/atm.h", 
+      "include/grpc/impl/codegen/atm_gcc_atomic.h", 
+      "include/grpc/impl/codegen/atm_gcc_sync.h", 
+      "include/grpc/impl/codegen/atm_win32.h", 
+      "include/grpc/impl/codegen/log.h", 
+      "include/grpc/impl/codegen/port_platform.h", 
+      "include/grpc/impl/codegen/slice.h", 
+      "include/grpc/impl/codegen/slice_buffer.h", 
+      "include/grpc/impl/codegen/sync.h", 
+      "include/grpc/impl/codegen/sync_generic.h", 
+      "include/grpc/impl/codegen/sync_posix.h", 
+      "include/grpc/impl/codegen/sync_win32.h", 
+      "include/grpc/impl/codegen/time.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_codegen"
+    ], 
+    "headers": [
+      "include/grpc/byte_buffer.h", 
+      "include/grpc/byte_buffer_reader.h", 
+      "include/grpc/compression.h", 
+      "include/grpc/grpc.h", 
+      "include/grpc/status.h", 
+      "src/core/lib/channel/channel_args.h", 
+      "src/core/lib/channel/channel_stack.h", 
+      "src/core/lib/channel/channel_stack_builder.h", 
+      "src/core/lib/channel/compress_filter.h", 
+      "src/core/lib/channel/connected_channel.h", 
+      "src/core/lib/channel/context.h", 
+      "src/core/lib/channel/http_client_filter.h", 
+      "src/core/lib/channel/http_server_filter.h", 
+      "src/core/lib/compression/algorithm_metadata.h", 
+      "src/core/lib/compression/message_compress.h", 
+      "src/core/lib/debug/trace.h", 
+      "src/core/lib/http/format_request.h", 
+      "src/core/lib/http/httpcli.h", 
+      "src/core/lib/http/parser.h", 
+      "src/core/lib/iomgr/closure.h", 
+      "src/core/lib/iomgr/endpoint.h", 
+      "src/core/lib/iomgr/endpoint_pair.h", 
+      "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", 
+      "src/core/lib/iomgr/ev_posix.h", 
+      "src/core/lib/iomgr/exec_ctx.h", 
+      "src/core/lib/iomgr/executor.h", 
+      "src/core/lib/iomgr/iocp_windows.h", 
+      "src/core/lib/iomgr/iomgr.h", 
+      "src/core/lib/iomgr/iomgr_internal.h", 
+      "src/core/lib/iomgr/iomgr_posix.h", 
+      "src/core/lib/iomgr/pollset.h", 
+      "src/core/lib/iomgr/pollset_set.h", 
+      "src/core/lib/iomgr/pollset_set_windows.h", 
+      "src/core/lib/iomgr/pollset_windows.h", 
+      "src/core/lib/iomgr/resolve_address.h", 
+      "src/core/lib/iomgr/sockaddr.h", 
+      "src/core/lib/iomgr/sockaddr_posix.h", 
+      "src/core/lib/iomgr/sockaddr_utils.h", 
+      "src/core/lib/iomgr/sockaddr_win32.h", 
+      "src/core/lib/iomgr/socket_utils_posix.h", 
+      "src/core/lib/iomgr/socket_windows.h", 
+      "src/core/lib/iomgr/tcp_client.h", 
+      "src/core/lib/iomgr/tcp_posix.h", 
+      "src/core/lib/iomgr/tcp_server.h", 
+      "src/core/lib/iomgr/tcp_windows.h", 
+      "src/core/lib/iomgr/time_averaged_stats.h", 
+      "src/core/lib/iomgr/timer.h", 
+      "src/core/lib/iomgr/timer_heap.h", 
+      "src/core/lib/iomgr/udp_server.h", 
+      "src/core/lib/iomgr/unix_sockets_posix.h", 
+      "src/core/lib/iomgr/wakeup_fd_pipe.h", 
+      "src/core/lib/iomgr/wakeup_fd_posix.h", 
+      "src/core/lib/iomgr/workqueue.h", 
+      "src/core/lib/iomgr/workqueue_posix.h", 
+      "src/core/lib/iomgr/workqueue_windows.h", 
+      "src/core/lib/json/json.h", 
+      "src/core/lib/json/json_common.h", 
+      "src/core/lib/json/json_reader.h", 
+      "src/core/lib/json/json_writer.h", 
+      "src/core/lib/surface/api_trace.h", 
+      "src/core/lib/surface/call.h", 
+      "src/core/lib/surface/call_test_only.h", 
+      "src/core/lib/surface/channel.h", 
+      "src/core/lib/surface/channel_init.h", 
+      "src/core/lib/surface/channel_stack_type.h", 
+      "src/core/lib/surface/completion_queue.h", 
+      "src/core/lib/surface/event_string.h", 
+      "src/core/lib/surface/init.h", 
+      "src/core/lib/surface/lame_client.h", 
+      "src/core/lib/surface/server.h", 
+      "src/core/lib/surface/surface_trace.h", 
+      "src/core/lib/transport/byte_stream.h", 
+      "src/core/lib/transport/connectivity_state.h", 
+      "src/core/lib/transport/metadata.h", 
+      "src/core/lib/transport/metadata_batch.h", 
+      "src/core/lib/transport/static_metadata.h", 
+      "src/core/lib/transport/transport.h", 
+      "src/core/lib/transport/transport_impl.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_base", 
+    "src": [
+      "include/grpc/byte_buffer.h", 
+      "include/grpc/byte_buffer_reader.h", 
+      "include/grpc/compression.h", 
+      "include/grpc/grpc.h", 
+      "include/grpc/status.h", 
+      "src/core/lib/channel/channel_args.c", 
+      "src/core/lib/channel/channel_args.h", 
+      "src/core/lib/channel/channel_stack.c", 
+      "src/core/lib/channel/channel_stack.h", 
+      "src/core/lib/channel/channel_stack_builder.c", 
+      "src/core/lib/channel/channel_stack_builder.h", 
+      "src/core/lib/channel/compress_filter.c", 
+      "src/core/lib/channel/compress_filter.h", 
+      "src/core/lib/channel/connected_channel.c", 
+      "src/core/lib/channel/connected_channel.h", 
+      "src/core/lib/channel/context.h", 
+      "src/core/lib/channel/http_client_filter.c", 
+      "src/core/lib/channel/http_client_filter.h", 
+      "src/core/lib/channel/http_server_filter.c", 
+      "src/core/lib/channel/http_server_filter.h", 
+      "src/core/lib/compression/algorithm_metadata.h", 
+      "src/core/lib/compression/compression_algorithm.c", 
+      "src/core/lib/compression/message_compress.c", 
+      "src/core/lib/compression/message_compress.h", 
+      "src/core/lib/debug/trace.c", 
+      "src/core/lib/debug/trace.h", 
+      "src/core/lib/http/format_request.c", 
+      "src/core/lib/http/format_request.h", 
+      "src/core/lib/http/httpcli.c", 
+      "src/core/lib/http/httpcli.h", 
+      "src/core/lib/http/parser.c", 
+      "src/core/lib/http/parser.h", 
+      "src/core/lib/iomgr/closure.c", 
+      "src/core/lib/iomgr/closure.h", 
+      "src/core/lib/iomgr/endpoint.c", 
+      "src/core/lib/iomgr/endpoint.h", 
+      "src/core/lib/iomgr/endpoint_pair.h", 
+      "src/core/lib/iomgr/endpoint_pair_posix.c", 
+      "src/core/lib/iomgr/endpoint_pair_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_posix.c", 
+      "src/core/lib/iomgr/ev_posix.h", 
+      "src/core/lib/iomgr/exec_ctx.c", 
+      "src/core/lib/iomgr/exec_ctx.h", 
+      "src/core/lib/iomgr/executor.c", 
+      "src/core/lib/iomgr/executor.h", 
+      "src/core/lib/iomgr/iocp_windows.c", 
+      "src/core/lib/iomgr/iocp_windows.h", 
+      "src/core/lib/iomgr/iomgr.c", 
+      "src/core/lib/iomgr/iomgr.h", 
+      "src/core/lib/iomgr/iomgr_internal.h", 
+      "src/core/lib/iomgr/iomgr_posix.c", 
+      "src/core/lib/iomgr/iomgr_posix.h", 
+      "src/core/lib/iomgr/iomgr_windows.c", 
+      "src/core/lib/iomgr/pollset.h", 
+      "src/core/lib/iomgr/pollset_set.h", 
+      "src/core/lib/iomgr/pollset_set_windows.c", 
+      "src/core/lib/iomgr/pollset_set_windows.h", 
+      "src/core/lib/iomgr/pollset_windows.c", 
+      "src/core/lib/iomgr/pollset_windows.h", 
+      "src/core/lib/iomgr/resolve_address.h", 
+      "src/core/lib/iomgr/resolve_address_posix.c", 
+      "src/core/lib/iomgr/resolve_address_windows.c", 
+      "src/core/lib/iomgr/sockaddr.h", 
+      "src/core/lib/iomgr/sockaddr_posix.h", 
+      "src/core/lib/iomgr/sockaddr_utils.c", 
+      "src/core/lib/iomgr/sockaddr_utils.h", 
+      "src/core/lib/iomgr/sockaddr_win32.h", 
+      "src/core/lib/iomgr/socket_utils_common_posix.c", 
+      "src/core/lib/iomgr/socket_utils_linux.c", 
+      "src/core/lib/iomgr/socket_utils_posix.c", 
+      "src/core/lib/iomgr/socket_utils_posix.h", 
+      "src/core/lib/iomgr/socket_windows.c", 
+      "src/core/lib/iomgr/socket_windows.h", 
+      "src/core/lib/iomgr/tcp_client.h", 
+      "src/core/lib/iomgr/tcp_client_posix.c", 
+      "src/core/lib/iomgr/tcp_client_windows.c", 
+      "src/core/lib/iomgr/tcp_posix.c", 
+      "src/core/lib/iomgr/tcp_posix.h", 
+      "src/core/lib/iomgr/tcp_server.h", 
+      "src/core/lib/iomgr/tcp_server_posix.c", 
+      "src/core/lib/iomgr/tcp_server_windows.c", 
+      "src/core/lib/iomgr/tcp_windows.c", 
+      "src/core/lib/iomgr/tcp_windows.h", 
+      "src/core/lib/iomgr/time_averaged_stats.c", 
+      "src/core/lib/iomgr/time_averaged_stats.h", 
+      "src/core/lib/iomgr/timer.c", 
+      "src/core/lib/iomgr/timer.h", 
+      "src/core/lib/iomgr/timer_heap.c", 
+      "src/core/lib/iomgr/timer_heap.h", 
+      "src/core/lib/iomgr/udp_server.c", 
+      "src/core/lib/iomgr/udp_server.h", 
+      "src/core/lib/iomgr/unix_sockets_posix.c", 
+      "src/core/lib/iomgr/unix_sockets_posix.h", 
+      "src/core/lib/iomgr/unix_sockets_posix_noop.c", 
+      "src/core/lib/iomgr/wakeup_fd_eventfd.c", 
+      "src/core/lib/iomgr/wakeup_fd_nospecial.c", 
+      "src/core/lib/iomgr/wakeup_fd_pipe.c", 
+      "src/core/lib/iomgr/wakeup_fd_pipe.h", 
+      "src/core/lib/iomgr/wakeup_fd_posix.c", 
+      "src/core/lib/iomgr/wakeup_fd_posix.h", 
+      "src/core/lib/iomgr/workqueue.h", 
+      "src/core/lib/iomgr/workqueue_posix.c", 
+      "src/core/lib/iomgr/workqueue_posix.h", 
+      "src/core/lib/iomgr/workqueue_windows.c", 
+      "src/core/lib/iomgr/workqueue_windows.h", 
+      "src/core/lib/json/json.c", 
+      "src/core/lib/json/json.h", 
+      "src/core/lib/json/json_common.h", 
+      "src/core/lib/json/json_reader.c", 
+      "src/core/lib/json/json_reader.h", 
+      "src/core/lib/json/json_string.c", 
+      "src/core/lib/json/json_writer.c", 
+      "src/core/lib/json/json_writer.h", 
+      "src/core/lib/surface/alarm.c", 
+      "src/core/lib/surface/api_trace.c", 
+      "src/core/lib/surface/api_trace.h", 
+      "src/core/lib/surface/byte_buffer.c", 
+      "src/core/lib/surface/byte_buffer_reader.c", 
+      "src/core/lib/surface/call.c", 
+      "src/core/lib/surface/call.h", 
+      "src/core/lib/surface/call_details.c", 
+      "src/core/lib/surface/call_log_batch.c", 
+      "src/core/lib/surface/call_test_only.h", 
+      "src/core/lib/surface/channel.c", 
+      "src/core/lib/surface/channel.h", 
+      "src/core/lib/surface/channel_init.c", 
+      "src/core/lib/surface/channel_init.h", 
+      "src/core/lib/surface/channel_ping.c", 
+      "src/core/lib/surface/channel_stack_type.c", 
+      "src/core/lib/surface/channel_stack_type.h", 
+      "src/core/lib/surface/completion_queue.c", 
+      "src/core/lib/surface/completion_queue.h", 
+      "src/core/lib/surface/event_string.c", 
+      "src/core/lib/surface/event_string.h", 
+      "src/core/lib/surface/init.h", 
+      "src/core/lib/surface/lame_client.c", 
+      "src/core/lib/surface/lame_client.h", 
+      "src/core/lib/surface/metadata_array.c", 
+      "src/core/lib/surface/server.c", 
+      "src/core/lib/surface/server.h", 
+      "src/core/lib/surface/surface_trace.h", 
+      "src/core/lib/surface/validate_metadata.c", 
+      "src/core/lib/surface/version.c", 
+      "src/core/lib/transport/byte_stream.c", 
+      "src/core/lib/transport/byte_stream.h", 
+      "src/core/lib/transport/connectivity_state.c", 
+      "src/core/lib/transport/connectivity_state.h", 
+      "src/core/lib/transport/metadata.c", 
+      "src/core/lib/transport/metadata.h", 
+      "src/core/lib/transport/metadata_batch.c", 
+      "src/core/lib/transport/metadata_batch.h", 
+      "src/core/lib/transport/static_metadata.c", 
+      "src/core/lib/transport/static_metadata.h", 
+      "src/core/lib/transport/transport.c", 
+      "src/core/lib/transport/transport.h", 
+      "src/core/lib/transport/transport_impl.h", 
+      "src/core/lib/transport/transport_op_string.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base"
+    ], 
+    "headers": [
+      "src/core/ext/client_config/client_channel.h", 
+      "src/core/ext/client_config/client_channel_factory.h", 
+      "src/core/ext/client_config/client_config.h", 
+      "src/core/ext/client_config/connector.h", 
+      "src/core/ext/client_config/initial_connect_string.h", 
+      "src/core/ext/client_config/lb_policy.h", 
+      "src/core/ext/client_config/lb_policy_factory.h", 
+      "src/core/ext/client_config/lb_policy_registry.h", 
+      "src/core/ext/client_config/parse_address.h", 
+      "src/core/ext/client_config/resolver.h", 
+      "src/core/ext/client_config/resolver_factory.h", 
+      "src/core/ext/client_config/resolver_registry.h", 
+      "src/core/ext/client_config/subchannel.h", 
+      "src/core/ext/client_config/subchannel_call_holder.h", 
+      "src/core/ext/client_config/subchannel_index.h", 
+      "src/core/ext/client_config/uri_parser.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_client_config", 
+    "src": [
+      "src/core/ext/client_config/channel_connectivity.c", 
+      "src/core/ext/client_config/client_channel.c", 
+      "src/core/ext/client_config/client_channel.h", 
+      "src/core/ext/client_config/client_channel_factory.c", 
+      "src/core/ext/client_config/client_channel_factory.h", 
+      "src/core/ext/client_config/client_config.c", 
+      "src/core/ext/client_config/client_config.h", 
+      "src/core/ext/client_config/client_config_plugin.c", 
+      "src/core/ext/client_config/connector.c", 
+      "src/core/ext/client_config/connector.h", 
+      "src/core/ext/client_config/default_initial_connect_string.c", 
+      "src/core/ext/client_config/initial_connect_string.c", 
+      "src/core/ext/client_config/initial_connect_string.h", 
+      "src/core/ext/client_config/lb_policy.c", 
+      "src/core/ext/client_config/lb_policy.h", 
+      "src/core/ext/client_config/lb_policy_factory.c", 
+      "src/core/ext/client_config/lb_policy_factory.h", 
+      "src/core/ext/client_config/lb_policy_registry.c", 
+      "src/core/ext/client_config/lb_policy_registry.h", 
+      "src/core/ext/client_config/parse_address.c", 
+      "src/core/ext/client_config/parse_address.h", 
+      "src/core/ext/client_config/resolver.c", 
+      "src/core/ext/client_config/resolver.h", 
+      "src/core/ext/client_config/resolver_factory.c", 
+      "src/core/ext/client_config/resolver_factory.h", 
+      "src/core/ext/client_config/resolver_registry.c", 
+      "src/core/ext/client_config/resolver_registry.h", 
+      "src/core/ext/client_config/subchannel.c", 
+      "src/core/ext/client_config/subchannel.h", 
+      "src/core/ext/client_config/subchannel_call_holder.c", 
+      "src/core/ext/client_config/subchannel_call_holder.h", 
+      "src/core/ext/client_config/subchannel_index.c", 
+      "src/core/ext/client_config/subchannel_index.h", 
+      "src/core/ext/client_config/uri_parser.c", 
+      "src/core/ext/client_config/uri_parser.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr_codegen"
+    ], 
+    "headers": [
+      "include/grpc/impl/codegen/byte_buffer.h", 
+      "include/grpc/impl/codegen/compression_types.h", 
+      "include/grpc/impl/codegen/connectivity_state.h", 
+      "include/grpc/impl/codegen/grpc_types.h", 
+      "include/grpc/impl/codegen/propagation_bits.h", 
+      "include/grpc/impl/codegen/status.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_codegen", 
+    "src": [
+      "include/grpc/impl/codegen/byte_buffer.h", 
+      "include/grpc/impl/codegen/compression_types.h", 
+      "include/grpc/impl/codegen/connectivity_state.h", 
+      "include/grpc/impl/codegen/grpc_types.h", 
+      "include/grpc/impl/codegen/propagation_bits.h", 
+      "include/grpc/impl/codegen/status.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_config", 
+      "nanopb"
+    ], 
+    "headers": [
+      "src/core/ext/lb_policy/grpclb/load_balancer_api.h", 
+      "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_lb_policy_grpclb", 
+    "src": [
+      "src/core/ext/lb_policy/grpclb/load_balancer_api.c", 
+      "src/core/ext/lb_policy/grpclb/load_balancer_api.h", 
+      "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", 
+      "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_config"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_lb_policy_pick_first", 
+    "src": [
+      "src/core/ext/lb_policy/pick_first/pick_first.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_config"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_lb_policy_round_robin", 
+    "src": [
+      "src/core/ext/lb_policy/round_robin/round_robin.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_config"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_resolver_dns_native", 
+    "src": [
+      "src/core/ext/resolver/dns/native/dns_resolver.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_config"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_resolver_sockaddr", 
+    "src": [
+      "src/core/ext/resolver/sockaddr/sockaddr_resolver.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_transport_chttp2_alpn", 
+      "tsi"
+    ], 
+    "headers": [
+      "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"
+    ], 
+    "language": "c", 
+    "name": "grpc_secure", 
+    "src": [
+      "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/surface/init_secure.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr_test_util", 
+      "grpc"
+    ], 
+    "headers": [
+      "test/core/end2end/cq_verifier.h", 
+      "test/core/end2end/fixtures/proxy.h", 
+      "test/core/iomgr/endpoint_tests.h", 
+      "test/core/util/grpc_profiler.h", 
+      "test/core/util/memory_counters.h", 
+      "test/core/util/mock_endpoint.h", 
+      "test/core/util/parse_hexstring.h", 
+      "test/core/util/passthru_endpoint.h", 
+      "test/core/util/port.h", 
+      "test/core/util/port_server_client.h", 
+      "test/core/util/slice_splitter.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_test_util_base", 
+    "src": [
+      "test/core/end2end/cq_verifier.c", 
+      "test/core/end2end/cq_verifier.h", 
+      "test/core/end2end/fixtures/proxy.c", 
+      "test/core/end2end/fixtures/proxy.h", 
+      "test/core/iomgr/endpoint_tests.c", 
+      "test/core/iomgr/endpoint_tests.h", 
+      "test/core/util/grpc_profiler.c", 
+      "test/core/util/grpc_profiler.h", 
+      "test/core/util/memory_counters.c", 
+      "test/core/util/memory_counters.h", 
+      "test/core/util/mock_endpoint.c", 
+      "test/core/util/mock_endpoint.h", 
+      "test/core/util/parse_hexstring.c", 
+      "test/core/util/parse_hexstring.h", 
+      "test/core/util/passthru_endpoint.c", 
+      "test/core/util/passthru_endpoint.h", 
+      "test/core/util/port.h", 
+      "test/core/util/port_posix.c", 
+      "test/core/util/port_server_client.c", 
+      "test/core/util/port_server_client.h", 
+      "test/core/util/port_windows.c", 
+      "test/core/util/slice_splitter.c", 
+      "test/core/util/slice_splitter.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_transport_chttp2_alpn"
+    ], 
+    "headers": [
+      "src/core/ext/transport/chttp2/transport/bin_encoder.h", 
+      "src/core/ext/transport/chttp2/transport/chttp2_transport.h", 
+      "src/core/ext/transport/chttp2/transport/frame.h", 
+      "src/core/ext/transport/chttp2/transport/frame_data.h", 
+      "src/core/ext/transport/chttp2/transport/frame_goaway.h", 
+      "src/core/ext/transport/chttp2/transport/frame_ping.h", 
+      "src/core/ext/transport/chttp2/transport/frame_rst_stream.h", 
+      "src/core/ext/transport/chttp2/transport/frame_settings.h", 
+      "src/core/ext/transport/chttp2/transport/frame_window_update.h", 
+      "src/core/ext/transport/chttp2/transport/hpack_encoder.h", 
+      "src/core/ext/transport/chttp2/transport/hpack_parser.h", 
+      "src/core/ext/transport/chttp2/transport/hpack_table.h", 
+      "src/core/ext/transport/chttp2/transport/http2_errors.h", 
+      "src/core/ext/transport/chttp2/transport/huffsyms.h", 
+      "src/core/ext/transport/chttp2/transport/incoming_metadata.h", 
+      "src/core/ext/transport/chttp2/transport/internal.h", 
+      "src/core/ext/transport/chttp2/transport/status_conversion.h", 
+      "src/core/ext/transport/chttp2/transport/stream_map.h", 
+      "src/core/ext/transport/chttp2/transport/timeout_encoding.h", 
+      "src/core/ext/transport/chttp2/transport/varint.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_transport_chttp2", 
+    "src": [
+      "src/core/ext/transport/chttp2/transport/bin_encoder.c", 
+      "src/core/ext/transport/chttp2/transport/bin_encoder.h", 
+      "src/core/ext/transport/chttp2/transport/chttp2_plugin.c", 
+      "src/core/ext/transport/chttp2/transport/chttp2_transport.c", 
+      "src/core/ext/transport/chttp2/transport/chttp2_transport.h", 
+      "src/core/ext/transport/chttp2/transport/frame.h", 
+      "src/core/ext/transport/chttp2/transport/frame_data.c", 
+      "src/core/ext/transport/chttp2/transport/frame_data.h", 
+      "src/core/ext/transport/chttp2/transport/frame_goaway.c", 
+      "src/core/ext/transport/chttp2/transport/frame_goaway.h", 
+      "src/core/ext/transport/chttp2/transport/frame_ping.c", 
+      "src/core/ext/transport/chttp2/transport/frame_ping.h", 
+      "src/core/ext/transport/chttp2/transport/frame_rst_stream.c", 
+      "src/core/ext/transport/chttp2/transport/frame_rst_stream.h", 
+      "src/core/ext/transport/chttp2/transport/frame_settings.c", 
+      "src/core/ext/transport/chttp2/transport/frame_settings.h", 
+      "src/core/ext/transport/chttp2/transport/frame_window_update.c", 
+      "src/core/ext/transport/chttp2/transport/frame_window_update.h", 
+      "src/core/ext/transport/chttp2/transport/hpack_encoder.c", 
+      "src/core/ext/transport/chttp2/transport/hpack_encoder.h", 
+      "src/core/ext/transport/chttp2/transport/hpack_parser.c", 
+      "src/core/ext/transport/chttp2/transport/hpack_parser.h", 
+      "src/core/ext/transport/chttp2/transport/hpack_table.c", 
+      "src/core/ext/transport/chttp2/transport/hpack_table.h", 
+      "src/core/ext/transport/chttp2/transport/http2_errors.h", 
+      "src/core/ext/transport/chttp2/transport/huffsyms.c", 
+      "src/core/ext/transport/chttp2/transport/huffsyms.h", 
+      "src/core/ext/transport/chttp2/transport/incoming_metadata.c", 
+      "src/core/ext/transport/chttp2/transport/incoming_metadata.h", 
+      "src/core/ext/transport/chttp2/transport/internal.h", 
+      "src/core/ext/transport/chttp2/transport/parsing.c", 
+      "src/core/ext/transport/chttp2/transport/status_conversion.c", 
+      "src/core/ext/transport/chttp2/transport/status_conversion.h", 
+      "src/core/ext/transport/chttp2/transport/stream_lists.c", 
+      "src/core/ext/transport/chttp2/transport/stream_map.c", 
+      "src/core/ext/transport/chttp2/transport/stream_map.h", 
+      "src/core/ext/transport/chttp2/transport/timeout_encoding.c", 
+      "src/core/ext/transport/chttp2/transport/timeout_encoding.h", 
+      "src/core/ext/transport/chttp2/transport/varint.c", 
+      "src/core/ext/transport/chttp2/transport/varint.h", 
+      "src/core/ext/transport/chttp2/transport/writing.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr"
+    ], 
+    "headers": [
+      "src/core/ext/transport/chttp2/alpn/alpn.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_transport_chttp2_alpn", 
+    "src": [
+      "src/core/ext/transport/chttp2/alpn/alpn.c", 
+      "src/core/ext/transport/chttp2/alpn/alpn.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_config", 
+      "grpc_transport_chttp2"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_transport_chttp2_client_insecure", 
+    "src": [
+      "src/core/ext/transport/chttp2/client/insecure/channel_create.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_config", 
+      "grpc_secure", 
+      "grpc_transport_chttp2"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_transport_chttp2_client_secure", 
+    "src": [
+      "src/core/ext/transport/chttp2/client/secure/secure_channel_create.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_transport_chttp2"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_transport_chttp2_server_insecure", 
+    "src": [
+      "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_secure", 
+      "grpc_transport_chttp2"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "grpc_transport_chttp2_server_secure", 
+    "src": [
+      "src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [], 
+    "headers": [
+      "third_party/nanopb/pb.h", 
+      "third_party/nanopb/pb_common.h", 
+      "third_party/nanopb/pb_decode.h", 
+      "third_party/nanopb/pb_encode.h"
+    ], 
+    "language": "c", 
+    "name": "nanopb", 
+    "src": [], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr"
+    ], 
+    "headers": [
+      "src/core/lib/tsi/fake_transport_security.h", 
+      "src/core/lib/tsi/ssl_transport_security.h", 
+      "src/core/lib/tsi/ssl_types.h", 
+      "src/core/lib/tsi/transport_security.h", 
+      "src/core/lib/tsi/transport_security_interface.h"
+    ], 
+    "language": "c", 
+    "name": "tsi", 
+    "src": [
+      "src/core/lib/tsi/fake_transport_security.c", 
+      "src/core/lib/tsi/fake_transport_security.h", 
+      "src/core/lib/tsi/ssl_transport_security.c", 
+      "src/core/lib/tsi/ssl_transport_security.h", 
+      "src/core/lib/tsi/ssl_types.h", 
+      "src/core/lib/tsi/transport_security.c", 
+      "src/core/lib/tsi/transport_security.h", 
+      "src/core/lib/tsi/transport_security_interface.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "grpc", 
+      "grpc++_codegen", 
+      "grpc++_config"
+    ], 
+    "headers": [
+      "include/grpc++/alarm.h", 
+      "include/grpc++/channel.h", 
+      "include/grpc++/client_context.h", 
+      "include/grpc++/completion_queue.h", 
+      "include/grpc++/create_channel.h", 
+      "include/grpc++/generic/async_generic_service.h", 
+      "include/grpc++/generic/generic_stub.h", 
+      "include/grpc++/grpc++.h", 
+      "include/grpc++/impl/call.h", 
+      "include/grpc++/impl/client_unary_call.h", 
+      "include/grpc++/impl/grpc_library.h", 
+      "include/grpc++/impl/method_handler_impl.h", 
+      "include/grpc++/impl/proto_utils.h", 
+      "include/grpc++/impl/rpc_method.h", 
+      "include/grpc++/impl/rpc_service_method.h", 
+      "include/grpc++/impl/serialization_traits.h", 
+      "include/grpc++/impl/server_builder_option.h", 
+      "include/grpc++/impl/service_type.h", 
+      "include/grpc++/impl/sync.h", 
+      "include/grpc++/impl/sync_cxx11.h", 
+      "include/grpc++/impl/sync_no_cxx11.h", 
+      "include/grpc++/impl/thd.h", 
+      "include/grpc++/impl/thd_cxx11.h", 
+      "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
+      "include/grpc++/server.h", 
+      "include/grpc++/server_builder.h", 
+      "include/grpc++/server_context.h", 
+      "include/grpc++/support/async_stream.h", 
+      "include/grpc++/support/async_unary_call.h", 
+      "include/grpc++/support/byte_buffer.h", 
+      "include/grpc++/support/channel_arguments.h", 
+      "include/grpc++/support/slice.h", 
+      "include/grpc++/support/status.h", 
+      "include/grpc++/support/status_code_enum.h", 
+      "include/grpc++/support/string_ref.h", 
+      "include/grpc++/support/stub_options.h", 
+      "include/grpc++/support/sync_stream.h", 
+      "include/grpc++/support/time.h", 
+      "src/cpp/client/create_channel_internal.h", 
+      "src/cpp/common/core_codegen.h", 
+      "src/cpp/server/dynamic_thread_pool.h", 
+      "src/cpp/server/thread_pool_interface.h"
+    ], 
+    "language": "c++", 
+    "name": "grpc++_base", 
+    "src": [
+      "include/grpc++/alarm.h", 
+      "include/grpc++/channel.h", 
+      "include/grpc++/client_context.h", 
+      "include/grpc++/completion_queue.h", 
+      "include/grpc++/create_channel.h", 
+      "include/grpc++/generic/async_generic_service.h", 
+      "include/grpc++/generic/generic_stub.h", 
+      "include/grpc++/grpc++.h", 
+      "include/grpc++/impl/call.h", 
+      "include/grpc++/impl/client_unary_call.h", 
+      "include/grpc++/impl/grpc_library.h", 
+      "include/grpc++/impl/method_handler_impl.h", 
+      "include/grpc++/impl/proto_utils.h", 
+      "include/grpc++/impl/rpc_method.h", 
+      "include/grpc++/impl/rpc_service_method.h", 
+      "include/grpc++/impl/serialization_traits.h", 
+      "include/grpc++/impl/server_builder_option.h", 
+      "include/grpc++/impl/service_type.h", 
+      "include/grpc++/impl/sync.h", 
+      "include/grpc++/impl/sync_cxx11.h", 
+      "include/grpc++/impl/sync_no_cxx11.h", 
+      "include/grpc++/impl/thd.h", 
+      "include/grpc++/impl/thd_cxx11.h", 
+      "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
+      "include/grpc++/server.h", 
+      "include/grpc++/server_builder.h", 
+      "include/grpc++/server_context.h", 
+      "include/grpc++/support/async_stream.h", 
+      "include/grpc++/support/async_unary_call.h", 
+      "include/grpc++/support/byte_buffer.h", 
+      "include/grpc++/support/channel_arguments.h", 
+      "include/grpc++/support/slice.h", 
+      "include/grpc++/support/status.h", 
+      "include/grpc++/support/status_code_enum.h", 
+      "include/grpc++/support/string_ref.h", 
+      "include/grpc++/support/stub_options.h", 
+      "include/grpc++/support/sync_stream.h", 
+      "include/grpc++/support/time.h", 
+      "src/cpp/client/channel.cc", 
+      "src/cpp/client/client_context.cc", 
+      "src/cpp/client/create_channel.cc", 
+      "src/cpp/client/create_channel_internal.cc", 
+      "src/cpp/client/create_channel_internal.h", 
+      "src/cpp/client/credentials.cc", 
+      "src/cpp/client/generic_stub.cc", 
+      "src/cpp/client/insecure_credentials.cc", 
+      "src/cpp/common/channel_arguments.cc", 
+      "src/cpp/common/completion_queue.cc", 
+      "src/cpp/common/core_codegen.cc", 
+      "src/cpp/common/core_codegen.h", 
+      "src/cpp/common/rpc_method.cc", 
+      "src/cpp/server/async_generic_service.cc", 
+      "src/cpp/server/create_default_thread_pool.cc", 
+      "src/cpp/server/dynamic_thread_pool.cc", 
+      "src/cpp/server/dynamic_thread_pool.h", 
+      "src/cpp/server/insecure_server_credentials.cc", 
+      "src/cpp/server/server.cc", 
+      "src/cpp/server/server_builder.cc", 
+      "src/cpp/server/server_context.cc", 
+      "src/cpp/server/server_credentials.cc", 
+      "src/cpp/server/thread_pool_interface.h", 
+      "src/cpp/util/byte_buffer.cc", 
+      "src/cpp/util/slice.cc", 
+      "src/cpp/util/status.cc", 
+      "src/cpp/util/string_ref.cc", 
+      "src/cpp/util/time.cc"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "grpc++_config_codegen", 
+      "grpc_codegen"
+    ], 
+    "headers": [
+      "include/grpc++/impl/codegen/async_stream.h", 
+      "include/grpc++/impl/codegen/async_unary_call.h", 
+      "include/grpc++/impl/codegen/call.h", 
+      "include/grpc++/impl/codegen/call_hook.h", 
+      "include/grpc++/impl/codegen/channel_interface.h", 
+      "include/grpc++/impl/codegen/client_context.h", 
+      "include/grpc++/impl/codegen/client_unary_call.h", 
+      "include/grpc++/impl/codegen/completion_queue.h", 
+      "include/grpc++/impl/codegen/completion_queue_tag.h", 
+      "include/grpc++/impl/codegen/core_codegen_interface.h", 
+      "include/grpc++/impl/codegen/create_auth_context.h", 
+      "include/grpc++/impl/codegen/grpc_library.h", 
+      "include/grpc++/impl/codegen/method_handler_impl.h", 
+      "include/grpc++/impl/codegen/proto_utils.h", 
+      "include/grpc++/impl/codegen/rpc_method.h", 
+      "include/grpc++/impl/codegen/rpc_service_method.h", 
+      "include/grpc++/impl/codegen/security/auth_context.h", 
+      "include/grpc++/impl/codegen/serialization_traits.h", 
+      "include/grpc++/impl/codegen/server_context.h", 
+      "include/grpc++/impl/codegen/server_interface.h", 
+      "include/grpc++/impl/codegen/service_type.h", 
+      "include/grpc++/impl/codegen/status.h", 
+      "include/grpc++/impl/codegen/status_code_enum.h", 
+      "include/grpc++/impl/codegen/string_ref.h", 
+      "include/grpc++/impl/codegen/stub_options.h", 
+      "include/grpc++/impl/codegen/sync.h", 
+      "include/grpc++/impl/codegen/sync_cxx11.h", 
+      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
+      "include/grpc++/impl/codegen/sync_stream.h", 
+      "include/grpc++/impl/codegen/time.h"
+    ], 
+    "language": "c++", 
+    "name": "grpc++_codegen", 
+    "src": [
+      "include/grpc++/impl/codegen/async_stream.h", 
+      "include/grpc++/impl/codegen/async_unary_call.h", 
+      "include/grpc++/impl/codegen/call.h", 
+      "include/grpc++/impl/codegen/call_hook.h", 
+      "include/grpc++/impl/codegen/channel_interface.h", 
+      "include/grpc++/impl/codegen/client_context.h", 
+      "include/grpc++/impl/codegen/client_unary_call.h", 
+      "include/grpc++/impl/codegen/completion_queue.h", 
+      "include/grpc++/impl/codegen/completion_queue_tag.h", 
+      "include/grpc++/impl/codegen/core_codegen_interface.h", 
+      "include/grpc++/impl/codegen/create_auth_context.h", 
+      "include/grpc++/impl/codegen/grpc_library.h", 
+      "include/grpc++/impl/codegen/method_handler_impl.h", 
+      "include/grpc++/impl/codegen/proto_utils.h", 
+      "include/grpc++/impl/codegen/rpc_method.h", 
+      "include/grpc++/impl/codegen/rpc_service_method.h", 
+      "include/grpc++/impl/codegen/security/auth_context.h", 
+      "include/grpc++/impl/codegen/serialization_traits.h", 
+      "include/grpc++/impl/codegen/server_context.h", 
+      "include/grpc++/impl/codegen/server_interface.h", 
+      "include/grpc++/impl/codegen/service_type.h", 
+      "include/grpc++/impl/codegen/status.h", 
+      "include/grpc++/impl/codegen/status_code_enum.h", 
+      "include/grpc++/impl/codegen/string_ref.h", 
+      "include/grpc++/impl/codegen/stub_options.h", 
+      "include/grpc++/impl/codegen/sync.h", 
+      "include/grpc++/impl/codegen/sync_cxx11.h", 
+      "include/grpc++/impl/codegen/sync_no_cxx11.h", 
+      "include/grpc++/impl/codegen/sync_stream.h", 
+      "include/grpc++/impl/codegen/time.h", 
+      "src/cpp/codegen/codegen_init.cc"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "grpc++_config_codegen"
+    ], 
+    "headers": [
+      "include/grpc++/support/config.h", 
+      "include/grpc++/support/config_protobuf.h"
+    ], 
+    "language": "c++", 
+    "name": "grpc++_config", 
+    "src": [
+      "include/grpc++/support/config.h", 
+      "include/grpc++/support/config_protobuf.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [], 
+    "headers": [
+      "include/grpc++/impl/codegen/config.h", 
+      "include/grpc++/impl/codegen/config_protobuf.h"
+    ], 
+    "language": "c++", 
+    "name": "grpc++_config_codegen", 
+    "src": [
+      "include/grpc++/impl/codegen/config.h", 
+      "include/grpc++/impl/codegen/config_protobuf.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
   }
 ]
diff --git a/tools/run_tests/stress_test/README.md b/tools/run_tests/stress_test/README.md
index 1a48e90..cc82b87 100644
--- a/tools/run_tests/stress_test/README.md
+++ b/tools/run_tests/stress_test/README.md
@@ -63,12 +63,14 @@
 The stress tests are launched by the following script (path is relative to GRPC root directory) :

 `tools/run_tests/stress_test/run_stress_tests_on_gke.py`

 

-The script has several parameters and you can find out more details by using the `--help` flag.

-  - `<grpc_root_dir>$ tools/run_tests/stress_test/run_stress_tests_on_gke.py --help`

+You can find out more details by using the `--help` flag.

+  - `<grpc_root_dir>$ tools/run_tests/stress_test/run_on_gke.py --help`

 

 > **Example**

-> `$ tools/run_tests/stress_test/run_stress_tests_on_gke.py --project_id=sree-gce --test_duration_secs=180 --num_clients=5`

+> ```bash

+> $ # Change to the grpc root directory

+> $ cd $GRPC_ROOT

+> $ tools/run_tests/stress_test/run_on_gke.py --project_id=sree-gce --config_file=tools/run_tests/stress_test/configs/opt.json

+> ```

 

-> Launches the 5 instances of stress test clients, 1 instance of stress test server and runs the test for 180 seconds. The test would be run on the default container cluster (that you have set in `gcloud`) in the project `sree-gce`.

-

-> Note: we currently do not have the ability to launch multiple instances of the server. This can be added very easily in future

+> The above runs the stress test on GKE under the project `sree-gce` in the default cluster (that you set by `gcloud` command earlier). The test settings (like number of client instances, servers, the parmeters to pass, test cases etc) are all loaded from the config file `$GRPC_ROOT/tools/run_tests/stress_test/opt.json`

diff --git a/tools/run_tests/stress_test/STRESS_CLIENT_SPEC.md b/tools/run_tests/stress_test/STRESS_CLIENT_SPEC.md
new file mode 100644
index 0000000..62ca8af
--- /dev/null
+++ b/tools/run_tests/stress_test/STRESS_CLIENT_SPEC.md
@@ -0,0 +1,25 @@
+Stress Test client Specification

+=========================

+This document specifies the features a stress test client should implement in order to work with the stress testing framework. The stress test clients are executed against the existing interop test servers.

+

+**Requirements**

+--------------

+**1.** A stress test client should be able to repeatedly execute one or more of the existing 'interop test cases'. It may just be a wrapper around the existing interop test client. The exact command line arguments the client should support are listed in _Table 1_ below.

+

+**2.** The stress test client must implement a metrics server defined by _[metrics.proto](https://github.com/grpc/grpc/blob/master/src/proto/grpc/testing/metrics.proto)_ and must expose _qps_ as a long-valued Gauge. The client can track the overall _qps_ in one Gauge or in multiple Gauges (for example: One per Channel or Stub).

+ The framework periodically queries the _qps_ by calling the `GetAllGauges()` method (the framework assumes that all the returned Gauges are _qps_ Gauges) and uses this to determine if the stress test client is running or crashed or stalled.

+> *Note:* In this context, the term  _**qps**_  means _interop test cases per second_  (not _messages per second_ or _rpc calls per second_)

+

+

+**Table 1:** Command line arguments that should be supported by the stress test client.

+

+>_**Note** The current C++ [stress client](https://github.com/grpc/grpc/blob/master/test/cpp/interop/stress_test.cc) supports more flags than those listed here but those flags will soon be deprecated._

+

+Parameter             |                    Description

+----------------------|---------------------------------

+`--server_addresses`    | The stress client should accept a list of server addresses in the following format:<br> ```<name_1>:<port_1>,<name_2>:<port_2>..<name_N>:<port_N>``` <br> _Note:_ `<name>` can be either server name or IP address.<br><br>_Type:_ string <br>_default:_ ```localhost:8080``` <br>_Example:_ ``foo.foobar.com:8080,bar.foobar.com:8080`` <br><br> Currently, the stress test framework only passes one server address to the client.

+`--test_cases`        |   List of test cases along with the relative weights in the following format:<br> `<testcase_1:w_1>,<testcase_2:w_2>...<testcase_n:w_n>`. <br> The test cases names are the same as those currently used by the interop clients<br><br>_Type:_ string <br>_Example:_ `empty_unary:20,large_unary:10,empty_stream:70` <br>(The stress client would then make `empty_unary` calls 20% of the time, `large_unary` calls 10% of the time and `empty_stream` calls 70% of the time.) <br>_Note:_ The weights need not add up to 100.

+`--test_duration_secs`      | The test duration in seconds. A value of -1 means that the test should run forever until forcefully terminated. <br>_Type:_ int <br>_default:_ -1

+`--num_channels_per_server` | Number of channels (i.e connections) to each server. <br> _Type:_ int <br> _default:_ 1 <br><br> _Note:_ Unfortunately, the term `channel` is used differently in `grpc-java` and `C based grpc`. In this context, this really means "number of connections to the server"

+`--num_stubs_per_channel `  | Number of client stubs per each connection to server.<br>_Type:_ int <br>_default:_ 1

+`--metrics_port`            | The port at which the stress client exposes [QPS metrics](https://github.com/grpc/grpc/blob/master/src/proto/grpc/testing/metrics.proto). <br>_Type:_ int <br>_default:_ 8081

diff --git a/tools/run_tests/stress_test/configs/asan.json b/tools/run_tests/stress_test/configs/asan.json
new file mode 100644
index 0000000..c558855
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/asan.json
@@ -0,0 +1,86 @@
+{
+  "dockerImages": {
+    "grpc_stress_cxx_asan" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_cxx",
+      "buildType": "asan"
+    }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 120,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081,
+          "metrics_collection_interval_secs":120
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "cxx_client_asan": {
+        "baseTemplate": "default",
+        "stressClientCmd": ["/var/local/git/grpc/bins/asan/stress_test"],
+        "metricsClientCmd": ["/var/local/git/grpc/bins/asan/metrics_client"]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080
+        }
+      }
+    },
+    "templates": {
+      "cxx_server_asan": {
+        "baseTemplate": "default",
+        "stressServerCmd": ["/var/local/git/grpc/bins/asan/interop_server"]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "stress-server-asan": {
+        "serverTemplate": "cxx_server_asan",
+        "dockerImage": "grpc_stress_cxx_asan",
+        "numInstances": 1
+      }
+    },
+
+    "clientPodSpecs": {
+      "stress-client-asan": {
+        "clientTemplate": "cxx_client_asan",
+        "dockerImage": "grpc_stress_cxx_asan",
+        "numInstances": 5,
+        "serverPodSpec": "stress-server-asan"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8003,
+    "datasetIdNamePrefix": "stress_test_asan",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
+
diff --git a/tools/run_tests/stress_test/configs/go.json b/tools/run_tests/stress_test/configs/go.json
new file mode 100644
index 0000000..36b465e
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/go.json
@@ -0,0 +1,96 @@
+{
+  "dockerImages": {
+    "grpc_stress_go" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_go"
+    }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 60,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "go_client": {
+        "baseTemplate": "default",
+        "stressClientCmd": [
+          "go",
+          "run",
+          "/go/src/google.golang.org/grpc/stress/client/main.go"
+        ],
+        "metricsClientCmd": [
+          "go",
+          "run",
+          "/go/src/google.golang.org/grpc/stress/metrics_client/main.go"
+        ]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080
+        }
+      }
+    },
+    "templates": {
+      "go_server": {
+        "baseTemplate": "default",
+        "stressServerCmd": [
+          "go",
+          "run",
+          "/go/src/google.golang.org/grpc/interop/server/server.go"
+        ]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "go-stress-server": {
+        "serverTemplate": "go_server",
+        "dockerImage": "grpc_stress_go",
+        "numInstances": 1
+      }
+    },
+
+    "clientPodSpecs": {
+      "go-stress-client": {
+        "clientTemplate": "go_client",
+        "dockerImage": "grpc_stress_go",
+        "numInstances": 15,
+        "serverPodSpec": "go-stress-server"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8007,
+    "datasetIdNamePrefix": "stress_test_go",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
+
diff --git a/tools/run_tests/stress_test/configs/java.json b/tools/run_tests/stress_test/configs/java.json
new file mode 100644
index 0000000..275384c
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/java.json
@@ -0,0 +1,91 @@
+{
+  "dockerImages": {
+    "grpc_stress_java" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_java"
+    }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 60,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "java_client": {
+        "baseTemplate": "default",
+        "stressClientCmd": [
+          "/var/local/git/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/stresstest-client"
+        ],
+        "metricsClientCmd": [
+          "/var/local/git/grpc/bins/opt/metrics_client"
+        ]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080,
+		  "use_tls": "false"
+        }
+      }
+    },
+    "templates": {
+      "java_server": {
+        "baseTemplate": "default",
+        "stressServerCmd": [
+          "/var/local/git/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/test-server"
+        ]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "java-stress-server": {
+        "serverTemplate": "java_server",
+        "dockerImage": "grpc_stress_java",
+        "numInstances": 1
+      }
+    },
+
+    "clientPodSpecs": {
+      "java-stress-client": {
+        "clientTemplate": "java_client",
+        "dockerImage": "grpc_stress_java",
+        "numInstances": 10,
+        "serverPodSpec": "java-stress-server"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8008,
+    "datasetIdNamePrefix": "stress_test_java",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
+
diff --git a/tools/run_tests/stress_test/configs/node-cxx.json b/tools/run_tests/stress_test/configs/node-cxx.json
new file mode 100644
index 0000000..c4245bf
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/node-cxx.json
@@ -0,0 +1,97 @@
+{
+  "dockerImages": {
+    "grpc_stress_cxx_opt" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_cxx",
+      "buildType": "opt"
+    },
+   "grpc_stress_node": {
+     "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+     "dockerFileDir": "grpc_interop_stress_node"
+   }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 60,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "node_client": {
+        "baseTemplate": "default",
+        "stressClientCmd": [
+          "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh",
+          "node",
+          "/var/local/git/grpc/src/node/stress/stress_client.js"
+        ],
+        "metricsClientCmd": [
+          "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh",
+          "node",
+          "/var/local/git/grpc/src/node/stress/metrics_client.js"
+        ]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080
+        }
+      }
+    },
+    "templates": {
+      "cxx_server_opt": {
+        "baseTemplate": "default",
+        "stressServerCmd": ["/var/local/git/grpc/bins/opt/interop_server"]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "stress-server-cxx-opt": {
+        "serverTemplate": "cxx_server_opt",
+        "dockerImage": "grpc_stress_cxx_opt",
+        "numInstances": 1
+      }
+    },
+
+    "clientPodSpecs": {
+      "stress-client-node": {
+        "clientTemplate": "node_client",
+        "dockerImage": "grpc_stress_node",
+        "numInstances": 20,
+        "serverPodSpec": "stress-server-cxx-opt"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8006,
+    "datasetIdNamePrefix": "stress_test_node_cxx_opt",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
+
diff --git a/tools/run_tests/stress_test/configs/node.json b/tools/run_tests/stress_test/configs/node.json
new file mode 100644
index 0000000..7a48c56
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/node.json
@@ -0,0 +1,96 @@
+{
+  "dockerImages": {
+    "grpc_stress_node" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_node"
+    }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 60,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "node_client": {
+        "baseTemplate": "default",
+        "stressClientCmd": [
+          "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh",
+          "node",
+          "/var/local/git/grpc/src/node/stress/stress_client.js"
+        ],
+        "metricsClientCmd": [
+          "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh",
+          "node",
+          "/var/local/git/grpc/src/node/stress/metrics_client.js"
+        ]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080
+        }
+      }
+    },
+    "templates": {
+      "node_server": {
+        "baseTemplate": "default",
+        "stressServerCmd": [
+          "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh",
+          "node",
+          "/var/local/git/grpc/src/node/interop/interop_server.js"
+        ]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "node-stress-server": {
+        "serverTemplate": "node_server",
+        "dockerImage": "grpc_stress_node",
+        "numInstances": 1
+      }
+    },
+
+    "clientPodSpecs": {
+      "node-stress-client": {
+        "clientTemplate": "node_client",
+        "dockerImage": "grpc_stress_node",
+        "numInstances": 15,
+        "serverPodSpec": "node-stress-server"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8005,
+    "datasetIdNamePrefix": "stress_test_node",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
+
diff --git a/tools/run_tests/stress_test/configs/opt-tsan-asan.json b/tools/run_tests/stress_test/configs/opt-tsan-asan.json
new file mode 100644
index 0000000..4f172ef
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/opt-tsan-asan.json
@@ -0,0 +1,135 @@
+{
+  "dockerImages": {
+    "grpc_stress_cxx_opt" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_cxx",
+      "buildType": "opt"
+    },
+    "grpc_stress_cxx_tsan": {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_cxx",
+      "buildType": "tsan"
+    },
+    "grpc_stress_cxx_asan": {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_cxx",
+      "buildType": "asan"
+    }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 60,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081,
+          "metrics_collection_interval_secs": 60
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "cxx_client_opt": {
+        "baseTemplate": "default",
+        "stressClientCmd": ["/var/local/git/grpc/bins/opt/stress_test"],
+        "metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"]
+      },
+      "cxx_client_tsan": {
+        "baseTemplate": "default",
+        "stressClientCmd": ["/var/local/git/grpc/bins/tsan/stress_test"],
+        "metricsClientCmd": ["/var/local/git/grpc/bins/tsan/metrics_client"]
+      },
+    "cxx_client_asan": {
+        "baseTemplate": "default",
+        "stressClientCmd": ["/var/local/git/grpc/bins/asan/stress_test"],
+        "metricsClientCmd": ["/var/local/git/grpc/bins/asan/metrics_client"]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080
+        }
+      }
+    },
+    "templates": {
+      "cxx_server_opt": {
+        "baseTemplate": "default",
+        "stressServerCmd": ["/var/local/git/grpc/bins/opt/interop_server"]
+      },
+      "cxx_server_tsan": {
+        "baseTemplate": "default",
+        "stressServerCmd": ["/var/local/git/grpc/bins/tsan/interop_server"]
+      },
+    "cxx_server_asan": {
+        "baseTemplate": "default",
+        "stressServerCmd": ["/var/local/git/grpc/bins/asan/interop_server"]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "stress-server-opt": {
+        "serverTemplate": "cxx_server_opt",
+        "dockerImage": "grpc_stress_cxx_opt",
+        "numInstances": 1
+      },
+      "stress-server-tsan": {
+        "serverTemplate": "cxx_server_tsan",
+        "dockerImage": "grpc_stress_cxx_tsan",
+        "numInstances": 1
+      },
+      "stress-server-asan": {
+        "serverTemplate": "cxx_server_asan",
+        "dockerImage": "grpc_stress_cxx_asan",
+        "numInstances": 1
+      }
+   },
+
+    "clientPodSpecs": {
+      "stress-client-opt": {
+        "clientTemplate": "cxx_client_opt",
+        "dockerImage": "grpc_stress_cxx_opt",
+        "numInstances": 5,
+        "serverPodSpec": "stress-server-opt"
+      },
+      "stress-client-tsan": {
+        "clientTemplate": "cxx_client_tsan",
+        "dockerImage": "grpc_stress_cxx_tsan",
+        "numInstances": 10,
+        "serverPodSpec": "stress-server-tsan"
+      },
+      "stress-client-asan": {
+        "clientTemplate": "cxx_client_asan",
+        "dockerImage": "grpc_stress_cxx_asan",
+        "numInstances": 10,
+        "serverPodSpec": "stress-server-asan"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8004,
+    "datasetIdNamePrefix": "stress_test_opt_tsan",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
diff --git a/tools/run_tests/stress_test/configs/opt.json b/tools/run_tests/stress_test/configs/opt.json
new file mode 100644
index 0000000..7550518
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/opt.json
@@ -0,0 +1,86 @@
+{
+  "dockerImages": {
+    "grpc_stress_cxx_opt" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_cxx",
+      "buildType": "opt"
+    }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 60,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081,
+          "metrics_collection_interval_secs": 60
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "cxx_client_opt": {
+        "baseTemplate": "default",
+        "stressClientCmd": ["/var/local/git/grpc/bins/opt/stress_test"],
+        "metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080
+        }
+      }
+    },
+    "templates": {
+      "cxx_server_opt": {
+        "baseTemplate": "default",
+        "stressServerCmd": ["/var/local/git/grpc/bins/opt/interop_server"]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "stress-server-opt": {
+        "serverTemplate": "cxx_server_opt",
+        "dockerImage": "grpc_stress_cxx_opt",
+        "numInstances": 1
+      }
+    },
+
+    "clientPodSpecs": {
+      "stress-client-opt": {
+        "clientTemplate": "cxx_client_opt",
+        "dockerImage": "grpc_stress_cxx_opt",
+        "numInstances": 15,
+        "serverPodSpec": "stress-server-opt"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8001,
+    "datasetIdNamePrefix": "stress_test_opt",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
+
diff --git a/tools/run_tests/stress_test/configs/tsan.json b/tools/run_tests/stress_test/configs/tsan.json
new file mode 100644
index 0000000..a7ec083
--- /dev/null
+++ b/tools/run_tests/stress_test/configs/tsan.json
@@ -0,0 +1,86 @@
+{
+  "dockerImages": {
+    "grpc_stress_cxx_tsan" : {
+      "buildScript": "tools/jenkins/build_interop_stress_image.sh",
+      "dockerFileDir": "grpc_interop_stress_cxx",
+      "buildType": "tsan"
+    }
+  },
+
+  "clientTemplates": {
+    "baseTemplates": {
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
+        "pollIntervalSecs": 120,
+        "clientArgs": {
+          "num_channels_per_server":5,
+          "num_stubs_per_channel":10,
+          "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
+          "metrics_port": 8081,
+          "metrics_collection_interval_secs":120
+        },
+        "metricsPort": 8081,
+        "metricsArgs": {
+          "metrics_server_address": "localhost:8081",
+          "total_only": "true"
+        }
+      }
+    },
+    "templates": {
+      "cxx_client_tsan": {
+        "baseTemplate": "default",
+        "stressClientCmd": ["/var/local/git/grpc/bins/tsan/stress_test"],
+        "metricsClientCmd": ["/var/local/git/grpc/bins/tsan/metrics_client"]
+      }
+    }
+  },
+
+  "serverTemplates": {
+    "baseTemplates":{
+      "default": {
+        "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
+        "serverPort": 8080,
+        "serverArgs": {
+          "port": 8080
+        }
+      }
+    },
+    "templates": {
+      "cxx_server_tsan": {
+        "baseTemplate": "default",
+        "stressServerCmd": ["/var/local/git/grpc/bins/tsan/interop_server"]
+      }
+    }
+  },
+
+  "testMatrix": {
+    "serverPodSpecs": {
+      "stress-server-tsan": {
+        "serverTemplate": "cxx_server_tsan",
+        "dockerImage": "grpc_stress_cxx_tsan",
+        "numInstances": 1
+      }
+    },
+
+    "clientPodSpecs": {
+      "stress-client-tsan": {
+        "clientTemplate": "cxx_client_tsan",
+        "dockerImage": "grpc_stress_cxx_tsan",
+        "numInstances": 5,
+        "serverPodSpec": "stress-server-tsan"
+      }
+    }
+  },
+
+  "globalSettings": {
+    "buildDockerImages": true,
+    "pollIntervalSecs": 60,
+    "testDurationSecs": 7200,
+    "kubernetesProxyPort": 8002,
+    "datasetIdNamePrefix": "stress_test_tsan",
+    "summaryTableId": "summary",
+    "qpsTableId": "qps",
+    "podWarmupSecs": 60
+  }
+}
+
diff --git a/tools/run_tests/stress_test/run_on_gke.py b/tools/run_tests/stress_test/run_on_gke.py
new file mode 100755
index 0000000..d4f1c4a
--- /dev/null
+++ b/tools/run_tests/stress_test/run_on_gke.py
@@ -0,0 +1,663 @@
+#!/usr/bin/env python2.7
+# 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.
+import argparse
+import datetime
+import json
+import os
+import subprocess
+import sys
+import time
+
+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
+
+kubernetes_api_dir = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '../../gcp/utils'))
+sys.path.append(kubernetes_api_dir)
+
+import kubernetes_api
+
+
+class GlobalSettings:
+
+  def __init__(self, gcp_project_id, build_docker_images,
+               test_poll_interval_secs, test_duration_secs,
+               kubernetes_proxy_port, dataset_id_prefix, summary_table_id,
+               qps_table_id, pod_warmup_secs):
+    self.gcp_project_id = gcp_project_id
+    self.build_docker_images = build_docker_images
+    self.test_poll_interval_secs = test_poll_interval_secs
+    self.test_duration_secs = test_duration_secs
+    self.kubernetes_proxy_port = kubernetes_proxy_port
+    self.dataset_id_prefix = dataset_id_prefix
+    self.summary_table_id = summary_table_id
+    self.qps_table_id = qps_table_id
+    self.pod_warmup_secs = pod_warmup_secs
+
+
+class ClientTemplate:
+  """ Contains all the common settings that are used by a stress client """
+
+  def __init__(self, name, stress_client_cmd, metrics_client_cmd, metrics_port,
+               wrapper_script_path, poll_interval_secs, client_args_dict,
+               metrics_args_dict, will_run_forever):
+    self.name = name
+    self.stress_client_cmd = stress_client_cmd
+    self.metrics_client_cmd = metrics_client_cmd
+    self.metrics_port = metrics_port
+    self.wrapper_script_path = wrapper_script_path
+    self.poll_interval_secs = poll_interval_secs
+    self.client_args_dict = client_args_dict
+    self.metrics_args_dict = metrics_args_dict
+    self.will_run_forever = will_run_forever
+
+
+class ServerTemplate:
+  """ Contains all the common settings used by a stress server """
+
+  def __init__(self, name, server_cmd, wrapper_script_path, server_port,
+               server_args_dict, will_run_forever):
+    self.name = name
+    self.server_cmd = server_cmd
+    self.wrapper_script_path = wrapper_script_path
+    self.server_port = server_port
+    self.server_args_dict = server_args_dict
+    self.will_run_forever = will_run_forever
+
+
+class DockerImage:
+  """ Represents properties of a Docker image. Provides methods to build the
+  image and push it to GKE registry
+  """
+
+  def __init__(self, gcp_project_id, image_name, build_script_path,
+               dockerfile_dir, build_type):
+    """Args:
+
+      image_name: The docker image name
+      tag_name: The additional tag name. This is the name used when pushing the
+        docker image to GKE registry
+      build_script_path: The path to the build script that builds this docker
+      image
+      dockerfile_dir: The name of the directory under
+      '<grpc_root>/tools/dockerfile' that contains the dockerfile
+    """
+    self.image_name = image_name
+    self.gcp_project_id = gcp_project_id
+    self.build_script_path = build_script_path
+    self.dockerfile_dir = dockerfile_dir
+    self.build_type = build_type
+    self.tag_name = self._make_tag_name(gcp_project_id, image_name)
+
+  def _make_tag_name(self, project_id, image_name):
+    return 'gcr.io/%s/%s' % (project_id, image_name)
+
+  def build_image(self):
+    print 'Building docker image: %s (tag: %s)' % (self.image_name,
+                                                   self.tag_name)
+    os.environ['INTEROP_IMAGE'] = self.image_name
+    os.environ['INTEROP_IMAGE_REPOSITORY_TAG'] = self.tag_name
+    os.environ['BASE_NAME'] = self.dockerfile_dir
+    os.environ['BUILD_TYPE'] = self.build_type
+    print 'DEBUG: path: ', self.build_script_path
+    if subprocess.call(args=[self.build_script_path]) != 0:
+      print 'Error in building the Docker image'
+      return False
+    return True
+
+  def push_to_gke_registry(self):
+    cmd = ['gcloud', 'docker', 'push', self.tag_name]
+    print 'Pushing %s to the GKE registry..' % self.tag_name
+    if subprocess.call(args=cmd) != 0:
+      print 'Error in pushing the image %s to the GKE registry' % self.tag_name
+      return False
+    return True
+
+
+class ServerPodSpec:
+  """ Contains the information required to launch server pods. """
+
+  def __init__(self, name, server_template, docker_image, num_instances):
+    self.name = name
+    self.template = server_template
+    self.docker_image = docker_image
+    self.num_instances = num_instances
+
+  def pod_names(self):
+    """ Return a list of names of server pods to create. """
+    return ['%s-%d' % (self.name, i) for i in range(1, self.num_instances + 1)]
+
+  def server_addresses(self):
+    """ Return string of server addresses in the following format:
+      '<server_pod_name_1>:<server_port>,<server_pod_name_2>:<server_port>...'
+    """
+    return ','.join(['%s:%d' % (pod_name, self.template.server_port)
+                     for pod_name in self.pod_names()])
+
+
+class ClientPodSpec:
+  """ Contains the information required to launch client pods """
+
+  def __init__(self, name, client_template, docker_image, num_instances,
+               server_addresses):
+    self.name = name
+    self.template = client_template
+    self.docker_image = docker_image
+    self.num_instances = num_instances
+    self.server_addresses = server_addresses
+
+  def pod_names(self):
+    """ Return a list of names of client pods to create """
+    return ['%s-%d' % (self.name, i) for i in range(1, self.num_instances + 1)]
+
+  # The client args in the template do not have server addresses. This function
+  # adds the server addresses and returns the updated client args
+  def get_client_args_dict(self):
+    args_dict = self.template.client_args_dict.copy()
+    args_dict['server_addresses'] = self.server_addresses
+    return args_dict
+
+
+class Gke:
+  """ Class that has helper methods to interact with GKE """
+
+  class KubernetesProxy:
+    """Class to start a proxy on localhost to talk to the Kubernetes API server"""
+
+    def __init__(self, port):
+      cmd = ['kubectl', 'proxy', '--port=%d' % port]
+      self.p = subprocess.Popen(args=cmd)
+      time.sleep(2)
+      print '\nStarted kubernetes proxy on port: %d' % port
+
+    def __del__(self):
+      if self.p is not None:
+        print 'Shutting down Kubernetes proxy..'
+        self.p.kill()
+
+  def __init__(self, project_id, run_id, dataset_id, summary_table_id,
+               qps_table_id, kubernetes_port):
+    self.project_id = project_id
+    self.run_id = run_id
+    self.dataset_id = dataset_id
+    self.summary_table_id = summary_table_id
+    self.qps_table_id = qps_table_id
+
+    # The environment variables we would like to pass to every pod (both client
+    # and server) launched in GKE
+    self.gke_env = {
+        'RUN_ID': self.run_id,
+        'GCP_PROJECT_ID': self.project_id,
+        'DATASET_ID': self.dataset_id,
+        'SUMMARY_TABLE_ID': self.summary_table_id,
+        'QPS_TABLE_ID': self.qps_table_id
+    }
+
+    self.kubernetes_port = kubernetes_port
+    # Start kubernetes proxy
+    self.kubernetes_proxy = Gke.KubernetesProxy(kubernetes_port)
+
+  def _args_dict_to_str(self, args_dict):
+    return ' '.join('--%s=%s' % (k, args_dict[k]) for k in args_dict.keys())
+
+  def launch_servers(self, server_pod_spec):
+    is_success = True
+
+    # The command to run inside the container is the wrapper script (which then
+    # launches the actual server)
+    container_cmd = server_pod_spec.template.wrapper_script_path
+
+    # The parameters to the wrapper script (defined in
+    # server_pod_spec.template.wrapper_script_path) are are injected into the
+    # container via environment variables
+    server_env = self.gke_env.copy()
+    server_env.update({
+        'STRESS_TEST_IMAGE_TYPE': 'SERVER',
+        'STRESS_TEST_CMD': server_pod_spec.template.server_cmd,
+        'STRESS_TEST_ARGS_STR': self._args_dict_to_str(
+            server_pod_spec.template.server_args_dict),
+        'WILL_RUN_FOREVER': str(server_pod_spec.template.will_run_forever)
+    })
+
+    for pod_name in server_pod_spec.pod_names():
+      server_env['POD_NAME'] = pod_name
+      print 'Creating server: %s' % pod_name
+      is_success = kubernetes_api.create_pod_and_service(
+          'localhost',
+          self.kubernetes_port,
+          'default',  # Use 'default' namespace
+          pod_name,
+          server_pod_spec.docker_image.tag_name,
+          [server_pod_spec.template.server_port],  # Ports to expose on the pod
+          [container_cmd],
+          [],  # Args list is empty since we are passing all args via env variables
+          server_env,
+          True  # Headless = True for server to that GKE creates a DNS record for pod_name
+      )
+      if not is_success:
+        print 'Error in launching server: %s' % pod_name
+        break
+
+    if is_success:
+      print 'Successfully created server(s)'
+
+    return is_success
+
+  def launch_clients(self, client_pod_spec):
+    is_success = True
+
+    # The command to run inside the container is the wrapper script (which then
+    # launches the actual stress client)
+    container_cmd = client_pod_spec.template.wrapper_script_path
+
+    # The parameters to the wrapper script (defined in
+    # client_pod_spec.template.wrapper_script_path) are are injected into the
+    # container via environment variables
+    client_env = self.gke_env.copy()
+    client_env.update({
+        'STRESS_TEST_IMAGE_TYPE': 'CLIENT',
+        'STRESS_TEST_CMD': client_pod_spec.template.stress_client_cmd,
+        'STRESS_TEST_ARGS_STR': self._args_dict_to_str(
+            client_pod_spec.get_client_args_dict()),
+        'METRICS_CLIENT_CMD': client_pod_spec.template.metrics_client_cmd,
+        'METRICS_CLIENT_ARGS_STR': self._args_dict_to_str(
+            client_pod_spec.template.metrics_args_dict),
+        'POLL_INTERVAL_SECS': str(client_pod_spec.template.poll_interval_secs),
+        'WILL_RUN_FOREVER': str(client_pod_spec.template.will_run_forever)
+    })
+
+    for pod_name in client_pod_spec.pod_names():
+      client_env['POD_NAME'] = pod_name
+      print 'Creating client: %s' % pod_name
+      is_success = kubernetes_api.create_pod_and_service(
+          'localhost',
+          self.kubernetes_port,
+          'default',  # default namespace,
+          pod_name,
+          client_pod_spec.docker_image.tag_name,
+          [client_pod_spec.template.metrics_port],  # Ports to expose on the pod
+          [container_cmd],
+          [],  # Empty args list since all args are passed via env variables
+          client_env,
+          False  # Client is not a headless service.
+      )
+
+      if not is_success:
+        print 'Error in launching client %s' % pod_name
+        break
+
+    if is_success:
+      print 'Successfully created all client(s)'
+
+    return is_success
+
+  def _delete_pods(self, pod_name_list):
+    is_success = True
+    for pod_name in pod_name_list:
+      print 'Deleting %s' % pod_name
+      is_success = kubernetes_api.delete_pod_and_service(
+          'localhost',
+          self.kubernetes_port,
+          'default',  # default namespace
+          pod_name)
+
+      if not is_success:
+        print 'Error in deleting pod %s' % pod_name
+        break
+
+    if is_success:
+      print 'Successfully deleted all pods'
+
+    return is_success
+
+  def delete_servers(self, server_pod_spec):
+    return self._delete_pods(server_pod_spec.pod_names())
+
+  def delete_clients(self, client_pod_spec):
+    return self._delete_pods(client_pod_spec.pod_names())
+
+
+class Config:
+
+  def __init__(self, config_filename, gcp_project_id):
+    print 'Loading configuration...'
+    config_dict = self._load_config(config_filename)
+
+    self.global_settings = self._parse_global_settings(config_dict,
+                                                       gcp_project_id)
+    self.docker_images_dict = self._parse_docker_images(
+        config_dict, self.global_settings.gcp_project_id)
+    self.client_templates_dict = self._parse_client_templates(config_dict)
+    self.server_templates_dict = self._parse_server_templates(config_dict)
+    self.server_pod_specs_dict = self._parse_server_pod_specs(
+        config_dict, self.docker_images_dict, self.server_templates_dict)
+    self.client_pod_specs_dict = self._parse_client_pod_specs(
+        config_dict, self.docker_images_dict, self.client_templates_dict,
+        self.server_pod_specs_dict)
+    print 'Loaded Configuaration.'
+
+  def _parse_global_settings(self, config_dict, gcp_project_id):
+    global_settings_dict = config_dict['globalSettings']
+    return GlobalSettings(gcp_project_id,
+                          global_settings_dict['buildDockerImages'],
+                          global_settings_dict['pollIntervalSecs'],
+                          global_settings_dict['testDurationSecs'],
+                          global_settings_dict['kubernetesProxyPort'],
+                          global_settings_dict['datasetIdNamePrefix'],
+                          global_settings_dict['summaryTableId'],
+                          global_settings_dict['qpsTableId'],
+                          global_settings_dict['podWarmupSecs'])
+
+  def _parse_docker_images(self, config_dict, gcp_project_id):
+    """Parses the 'dockerImages' section of the config file and returns a
+    Dictionary of 'DockerImage' objects keyed by docker image names"""
+    docker_images_dict = {}
+
+    docker_config_dict = config_dict['dockerImages']
+    for image_name in docker_config_dict.keys():
+      build_script_path = docker_config_dict[image_name]['buildScript']
+      dockerfile_dir = docker_config_dict[image_name]['dockerFileDir']
+      build_type = docker_config_dict[image_name].get('buildType', 'opt')
+      docker_images_dict[image_name] = DockerImage(gcp_project_id, image_name,
+                                                   build_script_path,
+                                                   dockerfile_dir, build_type)
+    return docker_images_dict
+
+  def _parse_client_templates(self, config_dict):
+    """Parses the 'clientTemplates' section of the config file and returns a
+    Dictionary of 'ClientTemplate' objects keyed by client template names.
+
+    Note: The 'baseTemplates' sub section of the config file contains templates
+    with default values  and the 'templates' sub section contains the actual
+    client templates (which refer to the base template name to use for default
+    values).
+    """
+    client_templates_dict = {}
+
+    templates_dict = config_dict['clientTemplates']['templates']
+    base_templates_dict = config_dict['clientTemplates'].get('baseTemplates',
+                                                             {})
+    for template_name in templates_dict.keys():
+      # temp_dict is a temporary dictionary that merges base template dictionary
+      # and client template dictionary (with client template dictionary values
+      # overriding base template values)
+      temp_dict = {}
+
+      base_template_name = templates_dict[template_name].get('baseTemplate')
+      if not base_template_name is None:
+        temp_dict = base_templates_dict[base_template_name].copy()
+
+      temp_dict.update(templates_dict[template_name])
+
+      # Create and add ClientTemplate object to the final client_templates_dict
+      stress_client_cmd = ' '.join(temp_dict['stressClientCmd'])
+      metrics_client_cmd = ' '.join(temp_dict['metricsClientCmd'])
+      client_templates_dict[template_name] = ClientTemplate(
+          template_name, stress_client_cmd, metrics_client_cmd,
+          temp_dict['metricsPort'], temp_dict['wrapperScriptPath'],
+          temp_dict['pollIntervalSecs'], temp_dict['clientArgs'].copy(),
+          temp_dict['metricsArgs'].copy(), temp_dict.get('willRunForever', 1))
+
+    return client_templates_dict
+
+  def _parse_server_templates(self, config_dict):
+    """Parses the 'serverTemplates' section of the config file and returns a
+    Dictionary of 'serverTemplate' objects keyed by server template names.
+
+    Note: The 'baseTemplates' sub section of the config file contains templates
+    with default values  and the 'templates' sub section contains the actual
+    server templates (which refer to the base template name to use for default
+    values).
+    """
+    server_templates_dict = {}
+
+    templates_dict = config_dict['serverTemplates']['templates']
+    base_templates_dict = config_dict['serverTemplates'].get('baseTemplates',
+                                                             {})
+
+    for template_name in templates_dict.keys():
+      # temp_dict is a temporary dictionary that merges base template dictionary
+      # and server template dictionary (with server template dictionary values
+      # overriding base template values)
+      temp_dict = {}
+
+      base_template_name = templates_dict[template_name].get('baseTemplate')
+      if not base_template_name is None:
+        temp_dict = base_templates_dict[base_template_name].copy()
+
+      temp_dict.update(templates_dict[template_name])
+
+      # Create and add ServerTemplate object to the final server_templates_dict
+      stress_server_cmd = ' '.join(temp_dict['stressServerCmd'])
+      server_templates_dict[template_name] = ServerTemplate(
+          template_name, stress_server_cmd, temp_dict['wrapperScriptPath'],
+          temp_dict['serverPort'], temp_dict['serverArgs'].copy(),
+          temp_dict.get('willRunForever', 1))
+
+    return server_templates_dict
+
+  def _parse_server_pod_specs(self, config_dict, docker_images_dict,
+                              server_templates_dict):
+    """Parses the 'serverPodSpecs' sub-section (under 'testMatrix' section) of
+    the config file and returns a Dictionary of 'ServerPodSpec' objects keyed
+    by server pod spec names"""
+    server_pod_specs_dict = {}
+
+    pod_specs_dict = config_dict['testMatrix'].get('serverPodSpecs', {})
+
+    for pod_name in pod_specs_dict.keys():
+      server_template_name = pod_specs_dict[pod_name]['serverTemplate']
+      docker_image_name = pod_specs_dict[pod_name]['dockerImage']
+      num_instances = pod_specs_dict[pod_name].get('numInstances', 1)
+
+      # Create and add the ServerPodSpec object to the final
+      # server_pod_specs_dict
+      server_pod_specs_dict[pod_name] = ServerPodSpec(
+          pod_name, server_templates_dict[server_template_name],
+          docker_images_dict[docker_image_name], num_instances)
+
+    return server_pod_specs_dict
+
+  def _parse_client_pod_specs(self, config_dict, docker_images_dict,
+                              client_templates_dict, server_pod_specs_dict):
+    """Parses the 'clientPodSpecs' sub-section (under 'testMatrix' section) of
+    the config file and returns a Dictionary of 'ClientPodSpec' objects keyed
+    by client pod spec names"""
+    client_pod_specs_dict = {}
+
+    pod_specs_dict = config_dict['testMatrix'].get('clientPodSpecs', {})
+    for pod_name in pod_specs_dict.keys():
+      client_template_name = pod_specs_dict[pod_name]['clientTemplate']
+      docker_image_name = pod_specs_dict[pod_name]['dockerImage']
+      num_instances = pod_specs_dict[pod_name]['numInstances']
+
+      # Get the server addresses from the server pod spec object
+      server_pod_spec_name = pod_specs_dict[pod_name]['serverPodSpec']
+      server_addresses = server_pod_specs_dict[
+          server_pod_spec_name].server_addresses()
+
+      client_pod_specs_dict[pod_name] = ClientPodSpec(
+          pod_name, client_templates_dict[client_template_name],
+          docker_images_dict[docker_image_name], num_instances,
+          server_addresses)
+
+    return client_pod_specs_dict
+
+  def _load_config(self, config_filename):
+    """Opens the config file and converts the Json text to Dictionary"""
+    if not os.path.isabs(config_filename):
+      raise Exception('Config objects expects an absolute file path. '
+                      'config file name passed: %s' % config_filename)
+    with open(config_filename) as config_file:
+      return json.load(config_file)
+
+
+def run_tests(config):
+  """ The main function that launches the stress tests """
+  # Build docker images and push to GKE registry
+  if config.global_settings.build_docker_images:
+    for name, docker_image in config.docker_images_dict.iteritems():
+      if not (docker_image.build_image() and
+              docker_image.push_to_gke_registry()):
+        return False
+
+  # Create a unique id for this run (Note: Using timestamp instead of UUID to
+  # make it easier to deduce the date/time of the run just by looking at the run
+  # run id. This is useful in debugging when looking at records in Biq query)
+  run_id = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S')
+  dataset_id = '%s_%s' % (config.global_settings.dataset_id_prefix, run_id)
+  print 'Run id:', run_id
+  print 'Dataset id:', dataset_id
+
+  bq_helper = BigQueryHelper(run_id, '', '',
+                             config.global_settings.gcp_project_id, dataset_id,
+                             config.global_settings.summary_table_id,
+                             config.global_settings.qps_table_id)
+  bq_helper.initialize()
+
+  gke = Gke(config.global_settings.gcp_project_id, run_id, dataset_id,
+            config.global_settings.summary_table_id,
+            config.global_settings.qps_table_id,
+            config.global_settings.kubernetes_proxy_port)
+
+  is_success = True
+
+  try:
+    print 'Launching servers..'
+    for name, server_pod_spec in config.server_pod_specs_dict.iteritems():
+      if not gke.launch_servers(server_pod_spec):
+        is_success = False  # is_success is checked in the 'finally' block
+        return False
+
+    print('Launched servers. Waiting for %d seconds for the server pods to be '
+          'fully online') % config.global_settings.pod_warmup_secs
+    time.sleep(config.global_settings.pod_warmup_secs)
+
+    for name, client_pod_spec in config.client_pod_specs_dict.iteritems():
+      if not gke.launch_clients(client_pod_spec):
+        is_success = False  # is_success is checked in the 'finally' block
+        return False
+
+    print('Launched all clients. Waiting for %d seconds for the client pods to '
+          'be fully online') % config.global_settings.pod_warmup_secs
+    time.sleep(config.global_settings.pod_warmup_secs)
+
+    start_time = datetime.datetime.now()
+    end_time = start_time + datetime.timedelta(
+        seconds=config.global_settings.test_duration_secs)
+    print 'Running the test until %s' % end_time.isoformat()
+
+    while True:
+      if datetime.datetime.now() > end_time:
+        print 'Test was run for %d seconds' % config.global_settings.test_duration_secs
+        break
+
+      # Check if either stress server or clients have failed (btw, the bq_helper
+      # monitors all the rows in the summary table and checks if any of them
+      # have a failure status)
+      if bq_helper.check_if_any_tests_failed():
+        is_success = False
+        print 'Some tests failed.'
+        break  # Don't 'return' here. We still want to call bq_helper to print qps/summary tables
+
+      # Tests running fine. Wait until next poll time to check the status
+      print 'Sleeping for %d seconds..' % config.global_settings.test_poll_interval_secs
+      time.sleep(config.global_settings.test_poll_interval_secs)
+
+    # Print BiqQuery tables
+    bq_helper.print_qps_records()
+    bq_helper.print_summary_records()
+
+  finally:
+    # If there was a test failure, we should not delete the pods since they
+    # would contain useful debug information (logs, core dumps etc)
+    if is_success:
+      for name, server_pod_spec in config.server_pod_specs_dict.iteritems():
+        gke.delete_servers(server_pod_spec)
+      for name, client_pod_spec in config.client_pod_specs_dict.iteritems():
+        gke.delete_clients(client_pod_spec)
+
+  return is_success
+
+
+def tear_down(config):
+  gke = Gke(config.global_settings.gcp_project_id, '', '',
+            config.global_settings.summary_table_id,
+            config.global_settings.qps_table_id,
+            config.global_settings.kubernetes_proxy_port)
+  for name, server_pod_spec in config.server_pod_specs_dict.iteritems():
+    gke.delete_servers(server_pod_spec)
+  for name, client_pod_spec in config.client_pod_specs_dict.iteritems():
+    gke.delete_clients(client_pod_spec)
+
+
+argp = argparse.ArgumentParser(
+    description='Launch stress tests in GKE',
+    formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+argp.add_argument('--gcp_project_id',
+                  required=True,
+                  help='The Google Cloud Platform Project Id')
+argp.add_argument('--config_file',
+                  required=True,
+                  type=str,
+                  help='The test config file')
+argp.add_argument('--tear_down', action='store_true', default=False)
+
+if __name__ == '__main__':
+  args = argp.parse_args()
+
+  config_filename = args.config_file
+
+  # Since we will be changing the current working directory to grpc root in the
+  # next step, we should check if the config filename path is a relative path
+  # (i.e a path relative to the current working directory) and if so, convert it
+  # to abosulte path
+  if not os.path.isabs(config_filename):
+    config_filename = os.path.abspath(config_filename)
+
+  config = Config(config_filename, args.gcp_project_id)
+
+  # Change current working directory to grpc root
+  # (This is important because all relative file paths in the config file are
+  # supposed to interpreted as relative to the GRPC root)
+  grpc_root = os.path.abspath(os.path.join(
+      os.path.dirname(sys.argv[0]), '../../..'))
+  os.chdir(grpc_root)
+
+  # Note that tear_down is only in cases where we want to manually tear down a
+  # test that for some reason run_tests() could not cleanup
+  if args.tear_down:
+    tear_down(config)
+    sys.exit(1)
+
+  if not run_tests(config):
+    sys.exit(1)
diff --git a/tools/run_tests/stress_test/run_stress_tests_on_gke.py b/tools/run_tests/stress_test/run_stress_tests_on_gke.py
deleted file mode 100755
index 634eb1a..0000000
--- a/tools/run_tests/stress_test/run_stress_tests_on_gke.py
+++ /dev/null
@@ -1,556 +0,0 @@
-#!/usr/bin/env python2.7
-# 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.
-import argparse
-import datetime
-import os
-import subprocess
-import sys
-import time
-
-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
-
-kubernetes_api_dir = os.path.abspath(os.path.join(
-    os.path.dirname(__file__), '../../gcp/utils'))
-sys.path.append(kubernetes_api_dir)
-
-import kubernetes_api
-
-_GRPC_ROOT = os.path.abspath(os.path.join(
-    os.path.dirname(sys.argv[0]), '../../..'))
-os.chdir(_GRPC_ROOT)
-
-# num of seconds to wait for the GKE image to start and warmup
-_GKE_IMAGE_WARMUP_WAIT_SECS = 60
-
-_SERVER_POD_NAME = 'stress-server'
-_CLIENT_POD_NAME_PREFIX = 'stress-client'
-_DATASET_ID_PREFIX = 'stress_test'
-_SUMMARY_TABLE_ID = 'summary'
-_QPS_TABLE_ID = 'qps'
-
-_DEFAULT_DOCKER_IMAGE_NAME = 'grpc_stress_test'
-
-# The default port on which the kubernetes proxy server is started on localhost
-# (i.e kubectl proxy --port=<port>)
-_DEFAULT_KUBERNETES_PROXY_PORT = 8001
-
-# How frequently should the stress client wrapper script (running inside a GKE
-# container) poll the health of the stress client (also running inside the GKE
-# container) and upload metrics to BigQuery
-_DEFAULT_STRESS_CLIENT_POLL_INTERVAL_SECS = 60
-
-# The default setting for stress test server and client
-_DEFAULT_STRESS_SERVER_PORT = 8080
-_DEFAULT_METRICS_PORT = 8081
-_DEFAULT_TEST_CASES_STR = 'empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1'
-_DEFAULT_NUM_CHANNELS_PER_SERVER = 5
-_DEFAULT_NUM_STUBS_PER_CHANNEL = 10
-_DEFAULT_METRICS_COLLECTION_INTERVAL_SECS = 30
-
-# Number of stress client instances to launch
-_DEFAULT_NUM_CLIENTS = 3
-
-# How frequently should this test monitor the health of Stress clients and
-# Servers running in GKE
-_DEFAULT_TEST_POLL_INTERVAL_SECS = 60
-
-# Default run time for this test (2 hour)
-_DEFAULT_TEST_DURATION_SECS = 7200
-
-# The number of seconds it would take a GKE pod to warm up (i.e get to 'Running'
-# state from the time of creation). Ideally this is something the test should
-# automatically determine by using Kubernetes API to poll the pods status.
-_DEFAULT_GKE_WARMUP_SECS = 60
-
-
-class KubernetesProxy:
-  """ Class to start a proxy on localhost to the Kubernetes API server """
-
-  def __init__(self, api_port):
-    self.port = api_port
-    self.p = None
-    self.started = False
-
-  def start(self):
-    cmd = ['kubectl', 'proxy', '--port=%d' % self.port]
-    self.p = subprocess.Popen(args=cmd)
-    self.started = True
-    time.sleep(2)
-    print '..Started'
-
-  def get_port(self):
-    return self.port
-
-  def is_started(self):
-    return self.started
-
-  def __del__(self):
-    if self.p is not None:
-      print 'Shutting down Kubernetes proxy..'
-      self.p.kill()
-
-
-class TestSettings:
-
-  def __init__(self, build_docker_image, test_poll_interval_secs,
-               test_duration_secs, kubernetes_proxy_port):
-    self.build_docker_image = build_docker_image
-    self.test_poll_interval_secs = test_poll_interval_secs
-    self.test_duration_secs = test_duration_secs
-    self.kubernetes_proxy_port = kubernetes_proxy_port
-
-
-class GkeSettings:
-
-  def __init__(self, project_id, docker_image_name):
-    self.project_id = project_id
-    self.docker_image_name = docker_image_name
-    self.tag_name = 'gcr.io/%s/%s' % (project_id, docker_image_name)
-
-
-class BigQuerySettings:
-
-  def __init__(self, run_id, dataset_id, summary_table_id, qps_table_id):
-    self.run_id = run_id
-    self.dataset_id = dataset_id
-    self.summary_table_id = summary_table_id
-    self.qps_table_id = qps_table_id
-
-
-class StressServerSettings:
-
-  def __init__(self, server_pod_name, server_port):
-    self.server_pod_name = server_pod_name
-    self.server_port = server_port
-
-
-class StressClientSettings:
-
-  def __init__(self, num_clients, client_pod_name_prefix, server_pod_name,
-               server_port, metrics_port, metrics_collection_interval_secs,
-               stress_client_poll_interval_secs, num_channels_per_server,
-               num_stubs_per_channel, test_cases_str):
-    self.num_clients = num_clients
-    self.client_pod_name_prefix = client_pod_name_prefix
-    self.server_pod_name = server_pod_name
-    self.server_port = server_port
-    self.metrics_port = metrics_port
-    self.metrics_collection_interval_secs = metrics_collection_interval_secs
-    self.stress_client_poll_interval_secs = stress_client_poll_interval_secs
-    self.num_channels_per_server = num_channels_per_server
-    self.num_stubs_per_channel = num_stubs_per_channel
-    self.test_cases_str = test_cases_str
-
-    # == Derived properties ==
-    # Note: Client can accept a list of server addresses (a comma separated list
-    # of 'server_name:server_port'). In this case, we only have one server
-    # address to pass
-    self.server_addresses = '%s.default.svc.cluster.local:%d' % (
-        server_pod_name, server_port)
-    self.client_pod_names_list = ['%s-%d' % (client_pod_name_prefix, i)
-                                  for i in range(1, num_clients + 1)]
-
-
-def _build_docker_image(image_name, tag_name):
-  """ Build the docker image and add tag it to the GKE repository """
-  print 'Building docker image: %s' % image_name
-  os.environ['INTEROP_IMAGE'] = image_name
-  os.environ['INTEROP_IMAGE_REPOSITORY_TAG'] = tag_name
-  # Note that 'BASE_NAME' HAS to be 'grpc_interop_stress_cxx' since the script
-  # build_interop_stress_image.sh invokes the following script:
-  #   tools/dockerfile/$BASE_NAME/build_interop_stress.sh
-  os.environ['BASE_NAME'] = 'grpc_interop_stress_cxx'
-  cmd = ['tools/jenkins/build_interop_stress_image.sh']
-  retcode = subprocess.call(args=cmd)
-  if retcode != 0:
-    print 'Error in building docker image'
-    return False
-  return True
-
-
-def _push_docker_image_to_gke_registry(docker_tag_name):
-  """Executes 'gcloud docker push <docker_tag_name>' to push the image to GKE registry"""
-  cmd = ['gcloud', 'docker', 'push', docker_tag_name]
-  print 'Pushing %s to GKE registry..' % docker_tag_name
-  retcode = subprocess.call(args=cmd)
-  if retcode != 0:
-    print 'Error in pushing docker image %s to the GKE registry' % docker_tag_name
-    return False
-  return True
-
-
-def _launch_server(gke_settings, stress_server_settings, bq_settings,
-                   kubernetes_proxy):
-  """ Launches a stress test server instance in GKE cluster """
-  if not kubernetes_proxy.is_started:
-    print 'Kubernetes proxy must be started before calling this function'
-    return False
-
-  # This is the wrapper script that is run in the container. This script runs
-  # the actual stress test server
-  server_cmd_list = ['/var/local/git/grpc/tools/gcp/stress_test/run_server.py']
-
-  # run_server.py does not take any args from the command line. The args are
-  # instead passed via environment variables (see server_env below)
-  server_arg_list = []
-
-  # The parameters to the script run_server.py are injected into the container
-  # via environment variables
-  server_env = {
-      'STRESS_TEST_IMAGE_TYPE': 'SERVER',
-      'STRESS_TEST_IMAGE': '/var/local/git/grpc/bins/opt/interop_server',
-      'STRESS_TEST_ARGS_STR': '--port=%s' % stress_server_settings.server_port,
-      'RUN_ID': bq_settings.run_id,
-      'POD_NAME': stress_server_settings.server_pod_name,
-      'GCP_PROJECT_ID': gke_settings.project_id,
-      'DATASET_ID': bq_settings.dataset_id,
-      'SUMMARY_TABLE_ID': bq_settings.summary_table_id,
-      'QPS_TABLE_ID': bq_settings.qps_table_id
-  }
-
-  # Launch Server
-  is_success = kubernetes_api.create_pod_and_service(
-      'localhost',
-      kubernetes_proxy.get_port(),
-      'default',  # Use 'default' namespace
-      stress_server_settings.server_pod_name,
-      gke_settings.tag_name,
-      [stress_server_settings.server_port],  # Port that should be exposed
-      server_cmd_list,
-      server_arg_list,
-      server_env,
-      True  # Headless = True for server. Since we want DNS records to be created by GKE
-  )
-
-  return is_success
-
-
-def _launch_client(gke_settings, stress_server_settings, stress_client_settings,
-                   bq_settings, kubernetes_proxy):
-  """ Launches a configurable number of stress test clients on GKE cluster """
-  if not kubernetes_proxy.is_started:
-    print 'Kubernetes proxy must be started before calling this function'
-    return False
-
-  stress_client_arg_list = [
-      '--server_addresses=%s' % stress_client_settings.server_addresses,
-      '--test_cases=%s' % stress_client_settings.test_cases_str,
-      '--num_stubs_per_channel=%d' %
-      stress_client_settings.num_stubs_per_channel
-  ]
-
-  # This is the wrapper script that is run in the container. This script runs
-  # the actual stress client
-  client_cmd_list = ['/var/local/git/grpc/tools/gcp/stress_test/run_client.py']
-
-  # run_client.py takes no args. All args are passed as env variables (see
-  # client_env)
-  client_arg_list = []
-
-  metrics_server_address = 'localhost:%d' % stress_client_settings.metrics_port
-  metrics_client_arg_list = [
-      '--metrics_server_address=%s' % metrics_server_address,
-      '--total_only=true'
-  ]
-
-  # The parameters to the script run_client.py are injected into the container
-  # via environment variables
-  client_env = {
-      'STRESS_TEST_IMAGE_TYPE': 'CLIENT',
-      'STRESS_TEST_IMAGE': '/var/local/git/grpc/bins/opt/stress_test',
-      'STRESS_TEST_ARGS_STR': ' '.join(stress_client_arg_list),
-      'METRICS_CLIENT_IMAGE': '/var/local/git/grpc/bins/opt/metrics_client',
-      'METRICS_CLIENT_ARGS_STR': ' '.join(metrics_client_arg_list),
-      'RUN_ID': bq_settings.run_id,
-      'POLL_INTERVAL_SECS':
-          str(stress_client_settings.stress_client_poll_interval_secs),
-      'GCP_PROJECT_ID': gke_settings.project_id,
-      'DATASET_ID': bq_settings.dataset_id,
-      'SUMMARY_TABLE_ID': bq_settings.summary_table_id,
-      'QPS_TABLE_ID': bq_settings.qps_table_id
-  }
-
-  for pod_name in stress_client_settings.client_pod_names_list:
-    client_env['POD_NAME'] = pod_name
-    is_success = kubernetes_api.create_pod_and_service(
-        'localhost',  # Since proxy is running on localhost
-        kubernetes_proxy.get_port(),
-        'default',  # default namespace
-        pod_name,
-        gke_settings.tag_name,
-        [stress_client_settings.metrics_port
-        ],  # Client pods expose metrics port
-        client_cmd_list,
-        client_arg_list,
-        client_env,
-        False  # Client is not a headless service
-    )
-    if not is_success:
-      print 'Error in launching client %s' % pod_name
-      return False
-
-  return True
-
-
-def _launch_server_and_client(gke_settings, stress_server_settings,
-                              stress_client_settings, bq_settings,
-                              kubernetes_proxy_port):
-  # Start kubernetes proxy
-  print 'Kubernetes proxy'
-  kubernetes_proxy = KubernetesProxy(kubernetes_proxy_port)
-  kubernetes_proxy.start()
-
-  print 'Launching server..'
-  is_success = _launch_server(gke_settings, stress_server_settings, bq_settings,
-                              kubernetes_proxy)
-  if not is_success:
-    print 'Error in launching server'
-    return False
-
-  # Server takes a while to start.
-  # TODO(sree) Use Kubernetes API to query the status of the server instead of
-  # sleeping
-  print 'Waiting for %s seconds for the server to start...' % _GKE_IMAGE_WARMUP_WAIT_SECS
-  time.sleep(_GKE_IMAGE_WARMUP_WAIT_SECS)
-
-  # Launch client
-  client_pod_name_prefix = 'stress-client'
-  is_success = _launch_client(gke_settings, stress_server_settings,
-                              stress_client_settings, bq_settings,
-                              kubernetes_proxy)
-
-  if not is_success:
-    print 'Error in launching client(s)'
-    return False
-
-  print 'Waiting for %s seconds for the client images to start...' % _GKE_IMAGE_WARMUP_WAIT_SECS
-  time.sleep(_GKE_IMAGE_WARMUP_WAIT_SECS)
-  return True
-
-
-def _delete_server_and_client(stress_server_settings, stress_client_settings,
-                              kubernetes_proxy_port):
-  kubernetes_proxy = KubernetesProxy(kubernetes_proxy_port)
-  kubernetes_proxy.start()
-
-  # Delete clients first
-  is_success = True
-  for pod_name in stress_client_settings.client_pod_names_list:
-    is_success = kubernetes_api.delete_pod_and_service(
-        'localhost', kubernetes_proxy_port, 'default', pod_name)
-    if not is_success:
-      return False
-
-  # Delete server
-  is_success = kubernetes_api.delete_pod_and_service(
-      'localhost', kubernetes_proxy_port, 'default',
-      stress_server_settings.server_pod_name)
-  return is_success
-
-
-def run_test_main(test_settings, gke_settings, stress_server_settings,
-                  stress_client_clients):
-  is_success = True
-
-  if test_settings.build_docker_image:
-    is_success = _build_docker_image(gke_settings.docker_image_name,
-                                     gke_settings.tag_name)
-    if not is_success:
-      return False
-
-    is_success = _push_docker_image_to_gke_registry(gke_settings.tag_name)
-    if not is_success:
-      return False
-
-  # Create a unique id for this run (Note: Using timestamp instead of UUID to
-  # make it easier to deduce the date/time of the run just by looking at the run
-  # run id. This is useful in debugging when looking at records in Biq query)
-  run_id = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S')
-  dataset_id = '%s_%s' % (_DATASET_ID_PREFIX, run_id)
-
-  # Big Query settings (common for both Stress Server and Client)
-  bq_settings = BigQuerySettings(run_id, dataset_id, _SUMMARY_TABLE_ID,
-                                 _QPS_TABLE_ID)
-
-  bq_helper = BigQueryHelper(run_id, '', '', args.project_id, dataset_id,
-                             _SUMMARY_TABLE_ID, _QPS_TABLE_ID)
-  bq_helper.initialize()
-
-  try:
-    is_success = _launch_server_and_client(gke_settings, stress_server_settings,
-                                           stress_client_settings, bq_settings,
-                                           test_settings.kubernetes_proxy_port)
-    if not is_success:
-      return False
-
-    start_time = datetime.datetime.now()
-    end_time = start_time + datetime.timedelta(
-        seconds=test_settings.test_duration_secs)
-    print 'Running the test until %s' % end_time.isoformat()
-
-    while True:
-      if datetime.datetime.now() > end_time:
-        print 'Test was run for %d seconds' % test_settings.test_duration_secs
-        break
-
-      # Check if either stress server or clients have failed
-      if bq_helper.check_if_any_tests_failed():
-        is_success = False
-        print 'Some tests failed.'
-        break
-
-      # Things seem to be running fine. Wait until next poll time to check the
-      # status
-      print 'Sleeping for %d seconds..' % test_settings.test_poll_interval_secs
-      time.sleep(test_settings.test_poll_interval_secs)
-
-    # Print BiqQuery tables
-    bq_helper.print_summary_records()
-    bq_helper.print_qps_records()
-
-  finally:
-    # If is_success is False at this point, it means that the stress tests were
-    # started successfully but failed while running the tests. In this case we
-    # do should not delete the pods (since they contain all the failure
-    # information)
-    if is_success:
-      _delete_server_and_client(stress_server_settings, stress_client_settings,
-                                test_settings.kubernetes_proxy_port)
-
-  return is_success
-
-
-argp = argparse.ArgumentParser(
-    description='Launch stress tests in GKE',
-    formatter_class=argparse.ArgumentDefaultsHelpFormatter)
-argp.add_argument('--project_id',
-                  required=True,
-                  help='The Google Cloud Platform Project Id')
-argp.add_argument('--num_clients',
-                  default=1,
-                  type=int,
-                  help='Number of client instances to start')
-argp.add_argument('--docker_image_name',
-                  default=_DEFAULT_DOCKER_IMAGE_NAME,
-                  help='The name of the docker image containing stress client '
-                  'and stress servers')
-argp.add_argument('--build_docker_image',
-                  dest='build_docker_image',
-                  action='store_true',
-                  help='Build a docker image and push to Google Container '
-                  'Registry')
-argp.add_argument('--do_not_build_docker_image',
-                  dest='build_docker_image',
-                  action='store_false',
-                  help='Do not build and push docker image to Google Container '
-                  'Registry')
-argp.set_defaults(build_docker_image=True)
-
-argp.add_argument('--test_poll_interval_secs',
-                  default=_DEFAULT_TEST_POLL_INTERVAL_SECS,
-                  type=int,
-                  help='How frequently should this script should monitor the '
-                  'health of stress clients and servers running in the GKE '
-                  'cluster')
-argp.add_argument('--test_duration_secs',
-                  default=_DEFAULT_TEST_DURATION_SECS,
-                  type=int,
-                  help='How long should this test be run')
-argp.add_argument('--kubernetes_proxy_port',
-                  default=_DEFAULT_KUBERNETES_PROXY_PORT,
-                  type=int,
-                  help='The port on which the kubernetes proxy (on localhost)'
-                  ' is started')
-argp.add_argument('--stress_server_port',
-                  default=_DEFAULT_STRESS_SERVER_PORT,
-                  type=int,
-                  help='The port on which the stress server (in GKE '
-                  'containers) listens')
-argp.add_argument('--stress_client_metrics_port',
-                  default=_DEFAULT_METRICS_PORT,
-                  type=int,
-                  help='The port on which the stress clients (in GKE '
-                  'containers) expose metrics')
-argp.add_argument('--stress_client_poll_interval_secs',
-                  default=_DEFAULT_STRESS_CLIENT_POLL_INTERVAL_SECS,
-                  type=int,
-                  help='How frequently should the stress client wrapper script'
-                  ' running inside GKE should monitor health of the actual '
-                  ' stress client process and upload the metrics to BigQuery')
-argp.add_argument('--stress_client_metrics_collection_interval_secs',
-                  default=_DEFAULT_METRICS_COLLECTION_INTERVAL_SECS,
-                  type=int,
-                  help='How frequently should metrics be collected in-memory on'
-                  ' the stress clients (running inside GKE containers). Note '
-                  'that this is NOT the same as the upload-to-BigQuery '
-                  'frequency. The metrics upload frequency is controlled by the'
-                  ' --stress_client_poll_interval_secs flag')
-argp.add_argument('--stress_client_num_channels_per_server',
-                  default=_DEFAULT_NUM_CHANNELS_PER_SERVER,
-                  type=int,
-                  help='The number of channels created to each server from a '
-                  'stress client')
-argp.add_argument('--stress_client_num_stubs_per_channel',
-                  default=_DEFAULT_NUM_STUBS_PER_CHANNEL,
-                  type=int,
-                  help='The number of stubs created per channel. This number '
-                  'indicates the max number of RPCs that can be made in '
-                  'parallel on each channel at any given time')
-argp.add_argument('--stress_client_test_cases',
-                  default=_DEFAULT_TEST_CASES_STR,
-                  help='List of test cases (with weights) to be executed by the'
-                  ' stress test client. The list is in the following format:\n'
-                  '  <testcase_1:w_1,<test_case2:w_2>..<testcase_n:w_n>\n'
-                  ' (Note: The weights do not have to add up to 100)')
-
-if __name__ == '__main__':
-  args = argp.parse_args()
-
-  test_settings = TestSettings(
-      args.build_docker_image, args.test_poll_interval_secs,
-      args.test_duration_secs, args.kubernetes_proxy_port)
-
-  gke_settings = GkeSettings(args.project_id, args.docker_image_name)
-
-  stress_server_settings = StressServerSettings(_SERVER_POD_NAME,
-                                                args.stress_server_port)
-  stress_client_settings = StressClientSettings(
-      args.num_clients, _CLIENT_POD_NAME_PREFIX, _SERVER_POD_NAME,
-      args.stress_server_port, args.stress_client_metrics_port,
-      args.stress_client_metrics_collection_interval_secs,
-      args.stress_client_poll_interval_secs,
-      args.stress_client_num_channels_per_server,
-      args.stress_client_num_stubs_per_channel, args.stress_client_test_cases)
-
-  run_test_main(test_settings, gke_settings, stress_server_settings,
-                stress_client_settings)
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index c4c3751..5b9a8fa 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -437,6 +437,25 @@
     "ci_platforms": [
       "linux", 
       "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "goaway_server_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
       "posix", 
       "windows"
     ], 
@@ -1094,7 +1113,7 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
-    "name": "httpcli_format_request_test", 
+    "name": "http_parser_test", 
     "platforms": [
       "linux", 
       "mac", 
@@ -1115,7 +1134,7 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
-    "name": "httpcli_parser_test", 
+    "name": "httpcli_format_request_test", 
     "platforms": [
       "linux", 
       "mac", 
@@ -2053,7 +2072,28 @@
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
-    "name": "codegen_test", 
+    "name": "codegen_test_full", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "codegen_test_minimal", 
     "platforms": [
       "linux", 
       "mac", 
@@ -2597,6 +2637,27 @@
       "posix", 
       "windows"
     ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "head_of_line_blocking_bad_client_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
     "cpu_cost": 0.2, 
     "exclude_configs": [], 
     "flaky": false, 
@@ -4195,6 +4256,30 @@
     ], 
     "flaky": false, 
     "language": "c++", 
+    "name": "boringssl_x509_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan"
+    ], 
+    "flaky": false, 
+    "language": "c++", 
     "name": "boringssl_tab_test", 
     "platforms": [
       "linux", 
@@ -4585,6 +4670,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -4651,6 +4758,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -5377,6 +5506,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -5443,6 +5594,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -6155,6 +6328,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -6218,6 +6412,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -6925,6 +7140,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -6991,6 +7228,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -7633,6 +7892,22 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -7681,6 +7956,22 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -7988,1158 +8279,6 @@
       "bad_hostname"
     ], 
     "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "call_creds"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "connectivity"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "default_host"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "disappearing_server"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_delayed_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "bad_hostname"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "call_creds"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "connectivity"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "default_host"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "disappearing_server"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_delayed_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "bad_hostname"
-    ], 
-    "ci_platforms": [
       "windows", 
       "linux", 
       "mac", 
@@ -9445,6 +8584,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -9489,6 +8650,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -10201,6 +9384,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -10264,6 +9468,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -10915,6 +10140,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -10957,6 +10203,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -11524,6 +10791,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -11587,6 +10875,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -12175,6 +11484,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -12217,6 +11547,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -12805,6 +12156,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -12868,6 +12240,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -13533,6 +12926,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -13599,6 +13014,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -14020,15 +13457,21 @@
       "bad_hostname"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14036,15 +13479,21 @@
       "binary_metadata"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14052,15 +13501,21 @@
       "call_creds"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14068,15 +13523,21 @@
       "cancel_after_accept"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14084,15 +13545,21 @@
       "cancel_after_client_done"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14100,15 +13567,21 @@
       "cancel_after_invoke"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14116,15 +13589,21 @@
       "cancel_before_invoke"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14132,15 +13611,21 @@
       "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14148,15 +13633,21 @@
       "cancel_with_status"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14164,15 +13655,21 @@
       "compressed_payload"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14180,15 +13677,21 @@
       "connectivity"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14196,15 +13699,21 @@
       "default_host"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14212,15 +13721,21 @@
       "disappearing_server"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14228,15 +13743,43 @@
       "empty_batch"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_cert_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14244,15 +13787,21 @@
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14260,15 +13809,21 @@
       "high_initial_seqno"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14276,15 +13831,43 @@
       "hpack_size"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_cert_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14292,15 +13875,21 @@
       "invoke_large_request"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14308,15 +13897,21 @@
       "large_metadata"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14324,15 +13919,21 @@
       "max_concurrent_streams"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14340,15 +13941,21 @@
       "max_message_length"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14356,15 +13963,21 @@
       "negative_deadline"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14372,15 +13985,21 @@
       "no_op"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14388,15 +14007,21 @@
       "payload"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14404,15 +14029,21 @@
       "ping"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14420,15 +14051,21 @@
       "ping_pong_streaming"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14436,15 +14073,21 @@
       "registered_call"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14452,15 +14095,21 @@
       "request_with_flags"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14468,15 +14117,21 @@
       "request_with_payload"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14484,15 +14139,21 @@
       "server_finishes_request"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14500,15 +14161,21 @@
       "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14516,15 +14183,21 @@
       "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14532,15 +14205,21 @@
       "simple_delayed_request"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14548,15 +14227,21 @@
       "simple_metadata"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14564,15 +14249,21 @@
       "simple_request"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14580,15 +14271,21 @@
       "trailing_metadata"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_ssl+poll_test", 
+    "name": "h2_ssl_cert_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -14845,6 +14542,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -14887,6 +14605,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -15226,688 +14965,6 @@
       "bad_hostname"
     ], 
     "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "call_creds"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "bad_hostname"
-    ], 
-    "ci_platforms": [
       "linux", 
       "mac", 
       "posix"
@@ -16165,6 +15222,26 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -16225,6 +15302,26 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -16608,566 +15705,6 @@
       "bad_hostname"
     ], 
     "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "call_creds"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "connectivity"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "disappearing_server"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_delayed_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "bad_hostname"
-    ], 
-    "ci_platforms": [
       "windows", 
       "linux", 
       "mac", 
@@ -17451,6 +15988,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -17517,6 +16076,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -18221,6 +16802,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -18287,6 +16890,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -18991,6 +17616,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -19057,6 +17704,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -19683,6 +18352,22 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -19731,6 +18416,22 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -20038,1126 +18739,6 @@
       "bad_hostname"
     ], 
     "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "connectivity"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "default_host"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "disappearing_server"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_delayed_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "bad_hostname"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "connectivity"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "default_host"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "disappearing_server"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_delayed_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "bad_hostname"
-    ], 
-    "ci_platforms": [
       "windows", 
       "linux", 
       "mac", 
@@ -21441,6 +19022,28 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -21485,6 +19088,28 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -22134,6 +19759,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -22176,6 +19822,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -22722,6 +20389,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -22785,6 +20473,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -23352,6 +21061,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -23394,6 +21124,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -23961,6 +21712,27 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -24024,6 +21796,27 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -24384,666 +22177,6 @@
       "bad_hostname"
     ], 
     "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uchannel_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "bad_hostname"
-    ], 
-    "ci_platforms": [
       "linux", 
       "mac", 
       "posix"
@@ -25281,6 +22414,26 @@
   }, 
   {
     "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "graceful_server_shutdown"
     ], 
     "ci_platforms": [
@@ -25341,6 +22494,26 @@
   }, 
   {
     "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "invoke_large_request"
     ], 
     "ci_platforms": [
@@ -25721,39 +22894,371 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "--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}'"
     ], 
+    "boringssl": true, 
     "ci_platforms": [
-      "linux"
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "language": "c++", 
+    "name": "json_run_localhost", 
     "platforms": [
-      "linux"
-    ]
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_secure"
   }, 
   {
     "args": [
-      "binary_metadata"
+      "--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\": 4, \"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": [
-      "linux"
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "language": "c++", 
+    "name": "json_run_localhost", 
     "platforms": [
-      "linux"
-    ]
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_secure"
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "--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}'"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_secure"
+  }, 
+  {
+    "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\": 4, \"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": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_secure"
+  }, 
+  {
+    "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}'"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_secure"
+  }, 
+  {
+    "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\": 0, \"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\": 0, \"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": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_secure"
+  }, 
+  {
+    "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}'"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_secure"
+  }, 
+  {
+    "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}'"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_insecure"
+  }, 
+  {
+    "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\": 4, \"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": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_insecure"
+  }, 
+  {
+    "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}'"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_insecure"
+  }, 
+  {
+    "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\": 4, \"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": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_insecure"
+  }, 
+  {
+    "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}'"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_insecure"
+  }, 
+  {
+    "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\": 0, \"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\": 0, \"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": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_insecure"
+  }, 
+  {
+    "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}'"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1000.0, 
+    "defaults": "boringssl", 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_insecure"
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/00.bin"
     ], 
     "ci_platforms": [
       "linux"
@@ -25762,14 +23267,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/01.bin"
     ], 
     "ci_platforms": [
       "linux"
@@ -25778,14 +23283,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0159f564d91869bc07239f5551a493c2845a4524"
     ], 
     "ci_platforms": [
       "linux"
@@ -25794,14 +23299,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/02.bin"
     ], 
     "ci_platforms": [
       "linux"
@@ -25810,14 +23315,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0211f960c2da343c3cde6406e650d73278e01e47"
     ], 
     "ci_platforms": [
       "linux"
@@ -25826,14 +23331,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0236f28708dcc2e044d67ecf93539ce6c33a727a"
     ], 
     "ci_platforms": [
       "linux"
@@ -25842,14 +23347,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "compressed_payload"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/02434dcdaca96b9eacee76eb351e99f015eaa05e"
     ], 
     "ci_platforms": [
       "linux"
@@ -25858,14 +23363,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "connectivity"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/03.bin"
     ], 
     "ci_platforms": [
       "linux"
@@ -25874,46 +23379,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "disappearing_server"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0302b90625ac9f61f45b45d043fda23b5472d711"
     ], 
     "ci_platforms": [
       "linux"
@@ -25922,94 +23395,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "invoke_large_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/04.bin"
     ], 
     "ci_platforms": [
       "linux"
@@ -26018,46 +23411,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "negative_deadline"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "no_op"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "payload"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0433cabb8c28820bda0a6eac35d17d120f1b6865"
     ], 
     "ci_platforms": [
       "linux"
@@ -26066,142 +23427,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_delayed_request"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0452ea591951af85724608917fda16926dad7451"
     ], 
     "ci_platforms": [
       "linux"
@@ -26210,55 +23443,40855 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "simple_metadata"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0468ab4bf4f7e10b680f43efae4bf9686834d220"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "simple_request"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/04e01f399f194434b2b724877df64828e8f52c14"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/05.bin"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0539bf31b2310091ce30d0123142d63589939105"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0542a0e5aeb1658cc965724bfced56770569263b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/056e56878b249c7fd0b95576b352ab2f4d46582e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/05dee1c3847f2bca29bd14ed701ce64999b298b2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/06.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/064d3beeef29a647deb1b345426ea7212de71cfe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/067298a97640cc5e212647864d21bc1fa6bb7e75"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/070c7005e63abba72c6bc1a0ee6d44e340f2d2be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07674d39538e07c29342cb2ee8856bc71fc06638"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07aa7d6c71878eb78b25ca12d79082f70ae7f64c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07ae5ed3dedbd83e376c892a9546cc0cd733c26f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07cc8b298d1502d0c30f3f160871e66e5a1f3fe1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/08.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/085865a209776911782f592c9f30ffe0ad3814a0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/09.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/092b85d1f5c922287e476e6e75ad8a0a80c779a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/09923e3ef02243b1902406c637f9516cbe99d7cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0a.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0a71ae781345f9ee2b08008a81f9055e6c1d5256"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0a7aad5682c304b0cbda31445b221238e0293a9f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0b.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0b6f0ea99a329e054032e6c292b99c3bcad0c9f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0bbd89b21cfd192174c25803c7f1afeec88e6524"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0c.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0d.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0d16d6c2c128ac4ee7b596b763822b4194968533"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0d8bd296d63a5aca5f80d7a7d00387048babda36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0d9d8241c5568fea586d21f91ae1891dac31ba24"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0e.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0e2a9ad3aacba320563095a874768a9e546a3db2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0f2831e0f73521a0991e11115c16847afca16bb3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0fa216ec645b3973b5e6d28baedd5acc1542e69e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/10302aa7598eb36d0ac22d0478eb0f2a6b010ea6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1109cb814fd134862a3f5ef5c9b2244585882b8f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/119410315423e5f37919886ced7f03235e5792aa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/12083209096187575021a775826b08b70b39ed4c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1254c9256157e6362003c97c8c93d8cd67a28772"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/12a97827d0f817e3ffd8d9cf1bdba0f945b6fda4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/12ef45f6beba92677a2a7508fc5e1bfef30ded66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/130c41e2dd87c36b4079c8e5bd380dbe3e0a2b38"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/13c409dcf7752c25b2b51ac5fad9201b505d7059"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/143789594154049441d565b65ce725fc4f8c12bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/149044286608a7945721c61f12196bebd5adb2ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/157586c7c0ba8fd0dc9bfc2426229a7da934cec2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/15c37fe5be9f23c0f0e59e12ee7666007acdb3c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1661d0799cbf2015fd64e9f648ebb49281d41c6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1671cf01e5baf796c5572b7b0e15d226a5c93f23"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/16a9beb811f836a444172a5da9290b47d77c32ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/16d52016278caebf92ba455f7ac8a8c7482c3563"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/173ebf4139ee6d7a574b6767059d82375674bbf4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17cfb281eaa8a17d77e08c3648bb93f3b5aa5297"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/183c878064b6a0ddf6a22dc4a2aa0d33a2d802d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1887558eb48d6a4341610fd0395cef8e87744044"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/18c856af1e2ebb934401e523043eaf80aecc8363"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/18f2d7626b6ad4859e735e448b00b6916f1d3e2e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/19dcc3082c76b85177ce6a56d195473aaa285268"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1a6b907bfa02ceebeb80aab47b3c3c51161eb868"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1b699132724acab3d42fb5210c07b74343449873"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c0417c96e6408d2902ef8fe4b8cd05f1ce4a50f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c6e5ad8dbff133707cc85b05a0057abf55d08ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c73564518349ebc87c4023b9d9a3cbc4fbc6cdd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c98433d827ea4aae2ba8a68c4d11bc2527cb15d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1ccd81836f26b7ececde2b02a22b19ab2a498631"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1d8b40b4798e652184df3bcffe1b1d7e32648f79"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1e4a2a6998218ea8f475aa2ee27869207b33b612"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1e55e5f47b550bab133099e5a98d7c751a0a2d7b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1e7d2d8f6109f4c02815ce8582c799134f2ff5dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1fda93a85f7b5b7a0c2d68a03123e58a6d20f124"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/20322515ebf6df572cb2f596d8a20d3d8893193d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/207c5a0f80f052ac7b48f6dd45cd33987be27f32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2099db589f606dd8932a950280f5d2b23751af9f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/21f3be485826850e4f4670bb81982e2827815426"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/240afe42d3e2834c46a79d9df0dd6ca018831398"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/24a87af0954c808fbd3f2c55185d4b1fa9459f4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/24df70902c288fcac060365c2e6f61269a3606b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2500fc12d5d1b5ed99fc3fe518c28849d1c8d6e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2501c7c3f78829725e6bf556277785588318106b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2507810915aecd3adf1287edf8c9f54b23a8ebd5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/253b8946a7cf403dd466f1685df2f741d4660a34"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/26865cd90c1461694d94d96232436372df2a91fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2743ee5a764fb0c4e04cdf84c9b3810ac8093998"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2748d28f2e03d740a89f7a50ea52450d0c5523f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2837baed2fbf1612f88224e91ddc46241dd9d972"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/28f8c7af6aab3bbabe028f780e174b27b924a146"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2942908b7973da7113098a0ea25487e3372db173"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/296c3f5b9880fe7ccff4d2a67f489b38b5b6fd6e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2a600cae342e8e9e23406bb1e76133f48d936766"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2ab009994e603404e194ebe0120840d388fb765e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2ad5ed48b598bd9e2d486a21eed5314736e5b56a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2aee21e4d1175963fa719d376406bb10d4818bdd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2af392765963966f2d1ddd5d5af4fcadd93c3b06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2af4e625522d128d03252f35b5fa5094cbcebc9f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2b931953e9bd02c3310a05234e91550bcd8ddf62"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2b933a0ede25a06e32c7d9cc5a3eda78086f3060"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2bbe5b2c12a964b53a5e6f78cdd5f595d95082a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2bc326b3ecf6d069595bc27cc1bca76b374c8e85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2c917a39d34aad10d611a1647a6df6502b4d4d59"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d61ec2cff75eadbc47e0932998b8a797e0cd96c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d9440daa210b9298f34982dcf7adc3564ad965c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d974f9fd1c57bce55cb9f1bbc25eb1e7a10454b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2db3a358c43c179a728f0650a00be295e88f8060"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2e21a2f9bff2514667aaec75629c82daa067ff57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2e82bfb7e8eede401ce75f6afe8c15ffd06130db"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2f0a8f0f96402ba1681ab3a9095a3dea47cdc53f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2f120ceed5250084f62010df9bf8fe8e8f3f643b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2f44fd38efef5818750f9adc9b133e40f9cdec71"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2f57224df35ff1583d14436a477330db23d70b0a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2fa6a874e625ca4d71941408d94698f898be4ea1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/301c057536319f49dcec68ab96677714e3dbf793"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30694ac08ff5a6a10cc781b9042c89f4019cfe0a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/307a91e344b94923837e01a1657ff277f44db07d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30fbe0ac4c74e2be3edd4f21b72bcae02e6c623f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/313001e1cc15ef9887b43e0c6de398eea2f20e00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/31429d04a34cc6643eebed7eeb8a807a83b57b1f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3230d9876d770657d86dfb768b80494cda52abc8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/32594aaa716c1a04b0f927ef964f1593735cb289"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/32b9de8461fd32b1236abb86abc91c82652d6e2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/32c108ead009572fbe9a216b372e5c0b3843238e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3399ac8bb9e0d3a2cbf22a95d1e20c70e2415e41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/342d148e59fb500ad76d583cf828c16cd3d3ed2e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3465fb573ac3c59a0804aadeba2f205870abcc3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/364f77bffd55805e2be9d2b3a071012e8fc3a083"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/368d2b5d4c6776afbed8e5e76cc3a4ccdde1df42"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/383043f6c05edc5a18f5c8e7b9d0314db63eab5e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3850b085a0a33fa2a08630dddb03e0f1adb1bee9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/38c609f72f5a2cf977788afef9c34652f754add0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3a287590e2d38d5dbc0b85d29ae2497d27aa0305"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3a4fa4e81b78cae093b2d53b0a6f272a398a7cda"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3aee5ced2869452b8ed65313d01b9b9c87144cd4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3b002ab57ff8080fbb1e72d985ca6f59f96a171e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3c84d21c46b89e7573750dd4517ea2eb58e37e27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3c8e6352f6c2a07bd5ef2b9a93c103935c8eaf0d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3d8c66be71e0ae0dfb0c2c7b84e4d8336f92b7ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3dedcaf501bc9718e5d372862b081fc9fdfb3959"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3df06a68edfc53fa88634c657a50cc6820354165"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3f36ae935255c4bbd2bd8d4a85bfa92bba02225c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3f47ad9ab401599f42d3c4f37ab9f702e3ff0fc9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42324d3d9e013cd43d4feeed1b48fbe1ea18a732"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42a8e7c267f66a0747f30b4053ec79325074dc97"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42c3c4a4e7d21e79d1e36494d5324f10a5ecbb04"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43676969fb81dcc1699b6a17eb465ef3cd4c2ab8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/439d4e4ed3ab9fe77e2bbda5b2be3d123beefa00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/441c94c010d19206c337d3c850cc449523ab480d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4449ec3eda232c394fad83e34b002e9bb46862e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/449ece0109a8543f26311f3ddc23525a2f288b64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/44bf16b9eb7302a6b02a600ac92dadf916c4e629"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/44e1fdcc46db56bf61a6702fd10766b56d35bc74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/45657516294c5426c490e6aa522a79077c972856"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/465b299ab3509b61016406e0d1d93f7774c03c8c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/46efabc911aab09a5e7a34a19ef97ce710594a77"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/472adcbc2a1970f2392e596c28bd44087b8f3431"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/47e402f3386843e0055431750f30b710e10295dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/47ecf4079ea23d4de5fd9282f733eb5429f7ab05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/484ab9d070fffe7e3d1a1704c9fa2ce01e192450"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4905b3fb0f7d2196a5612e8e432abda666e4317d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/490f5aa97dc05ef1ce089fa9d4fd377bacafcf18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4a3eae69f4c5dc768b166620af348316c9fac3e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4c3dcb9cb14f89b3616fc7cca78f2ebc502907eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4c686a41d4d2226b3cc76b8154d8df090d075f00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4d472e5a8e8ee92be6f23a101babbc601dd2512c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4d4aa6ddd6404300e5278682e560f25292e9804e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4e36813fde9b5de1b62de95f498f2e0a48b5c5f7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4ef22ea5b0aa8b80a180a9654f5aef121c5aad83"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4f53cc7b3ed0c77c3b5e4478f54caa40e0bf64b6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5000fa3e29de15e7533b0e04b37eb1985ae69891"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/50841095cafd9f9de6684fb3d89cd5fe148494ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/50bfe6100bf11339372ba29fe0c9b38c3ec2ebf0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/51d7466ac65468db7094bdedc60d1604231acc05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/51ed796a5f8d8fccebe013ccccdc1ed5d8b8b4c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/528cc09294d2288fc91a4bab7cf6ec621c6621b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5298ce28a7eab28c99964c0d838b017355607c92"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/52dba1b997f903c5fa3d7da71421b36d96d9f55c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/53e68cd362f3c8d64941efbb0b527c52da5e8424"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/546fe2e2b1e2756c3f121d0545866798c85c9b8b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/54a0a2c37ce1830f241f6e2828adc8057cfa385f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/55ed466781b547db5957233bd8db0ce1f189183f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5677b3500e9353856c8d87fbe1476a22df4231f8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/56f3ca8174d263240113de88e7547e7b1c5cb2cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/57798cc4375de344391221fd07d591f5c64d646d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/57da1745490c2f21ecb86370f1f72f77752bc739"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/57dea4528141649208fa2af10c18e98e80c1758b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/588f9166c839baf3102185d38f77f9a750e62c7f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5939ec5fd8f4e02ff0720cfa3ef685876bb3549d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/594d676c8c05d75ba8587d9e900850dff5e21ff8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/595603f4ed37e3716cbe53b3ef180e5cdf8005f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5a3c9d98651a315b5bde737482ff54f6b90361e0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5a6491ab9c23fae58967d4a4b5d5cfb23f620001"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5a85c9bd6a6d7a2f753dd315e4747fc0249c8799"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5a8ca84c7d4d9b055f05c55b1f707f223979d387"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5be956066b72ea1799e333a7bd17fb0b8fc2b91c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5d0137a19ae57cfdf5172a8b51e8ea0a0a893690"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5d2f29b31d78b47077b15779d620747034d18c05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5d765c856a9a8650e1b17813340b9b6ba0989b58"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5e1391f44f904fa54e66ec174e4c8879921e842a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ea01efbec747fc55ae29eb2b779f00889ca6922"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/60e8618c075ec5fd47a1699271c6da1b5befd579"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6184ea16753b0827f728285f18dad4b3bde00024"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6186bfc21ff7df3982e5d9757e5c7160da0f493a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6230cce2862a18c4c92dc6fb4e034a1d15e1ff18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/62fbfe90a1b9ac471bc2644c896f64515f6b3c7e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/638c36cfe098b98008e594eddf90fdacfc078fae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6421db654fff309bc191aba0330fbcd1347655e3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/64c572e594c2d491a902e8fdff7b617ac0c6881b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/64eb970cc80162a4b80d49364f4227db3429e156"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/655b880459e6e00100727af9df52b64f6d77a653"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/660c071578cbdccb503317ecbf2fd331bc4ac82d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/66ac31199d08e7a3b066059cd409457a850847b2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/66ef59d5da68fdb5e55b60fc8a8a764afb021b4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/682cb8ad9fe4641e7a140ae3d3ee27c841ba397f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/696ea30e2e1490f2f31b153641b2c29152ded5c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6a10118289fe7179c4e9bb6a1b466ba34c582bfb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6bfbea131237606756a12f275e736045c0956536"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6c1c2177f3483086607c717d0c6c35a81d79e18e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ded157ecd3fce79fa69c51ee9ecb4639013e6ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6e1cf196e7c8ad4226d89f3ca2c6f7949598bec2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ef96bc0c5b6ab5f8a4453b9cf5784fd55e3b59f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6f88ae246aa4af9c74732d87a758ba5ca0f40caf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6f8ffc96f9ebe390929165e32bdc187afb7a40ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/70bd921a3d4700d49ad6b99e0cfee42c36a13b3a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/710f61e5765c91bcf9cf2e07264771cf2feae48d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/71c01818823d5c5fd8a3d1cb4c5db4aca51efdb2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/71e2b03b503dbbdc0d2e724c562b9f1c77f972fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7240f3408714c2dcdcb448f234efef4f08e6b2fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/727f43500183aec9c0d9be7d2363fa1761cda5d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/72a3729a9bb74378156dcd42171e39ec348c71d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/72c363848fe754c23e1f9f2acc2f025666417d2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/73889340124f1f88859aab4e6ce36c0019a44218"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7462e4d1834938e8a5fb975da6865cc7d6b225f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/74b69a49c2df95009ff18d820bbe7fe6ae797aae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/74cc62178f9c631dc49cf09b0ff5884322d33969"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/74eef5817db3984a020b2868f3c9979d0220c829"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/758ce3af56f75edb8faa20ef78ffda5511dffb3a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/761f683f6486e3efb606bf08fa527a4c1a51f302"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/76487a234f6f7276d8eba4edabef7623a592fdf6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/767c4f399ccca740ea3032eeade86851f12e7f9a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/767d136ac4b3e33d9aa5320d941693e09648e59b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/768b6302130ac824947f956e062184afaafcdbab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/77d4480781e1e1a9d5d5c02ff53fba10127f8b6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/77e8407dfe09892312213f7d6b2ad8a961b6b88e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/792276ed826b9078ecfbd51e0136962f5e10ed6e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7a0b2f8659484409af6a76d1df273b8dc66e3439"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7be89fb64b3d931387e8a5b1ef51bf9cda18006a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7c026422a34cb34de673a1d6702cbde67d112d27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7c58daa09675ba2b11e69636bb78dc0d1343bb51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7c9b4e2ea03542254235893edd042a822145e504"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7cdff0948ef64e551ad02f857acd5956d91530c9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7d33039255c9611d0e9e0cc7e230f87ad55c007f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7d6713afac17551fc2628c0f9f18c41a1aa9c2f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7d88455cc77259c8bf17c1cdc0b24edf5667c79c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7de73ddcb20d0940b937323599a5094bfb26ae6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7e8f7517bb0bb95011b48f1f4f4a631d4d756a5f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/80a249d17248e0dc7dcc9fb64d8ac2dd0320a544"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/80a56bd23287d856a653f22f57f7d1442235b713"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/80b6a3cf5bb7cdeffcb6cbaaa10889168542a25a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/811533455c494627bb5b5802f4ed7a386f57cb1e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8123e9dc4d43115412f07fcf9946c99d9a1a55c3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/820d5ba2e9d91563dae39a1b02833fbef1e6d8f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/83c29132911949c65d508753420708e9a0ffd6ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8492f54a92f9a2a05af1a078489a3a68145d8985"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/84c995b299f8d6fa0733d11f0b1a0b4414a7e232"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/85220ed0c63891f376bee53c785b407fd9548f8b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8554d0f8fc68c84fbd8515165a3d98aad0dfab3e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/856fb7cd57f36cfcc8a2cad0cf61f9fff9696776"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8711e2f477871e3ca68642bbb388e7f473f25394"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8713d28e8cf45d3670ad40829a83b1fc7cd41a75"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8778868ac7a23d552d93772aa8566cf427a0c1f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8791b58ad0dbfdf9c37d48bc60940f86c6c7e3b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/87add83a18a25fe585df8adc124eae6d70733f74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/880070b48f04fd1c8ffafd750e1c4d37ff404c6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/885267691bb42bc807b6e578571430a81513eee0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/88be31c841a66f523045f7bd1708ce64272e4276"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/893ea11ec0c4425940d18a32acf23d5967d98dd9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8949e5c946cf6ec7d1981d553972d4f3a6026987"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8a034b07b9baf1b441c0fb0322652772973f20ff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8a912877743b165b233303efaf502f5092b3c5b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8a9f7329b30a562837353767313df7fa9a1f31f7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8b253ba946d6768c147f5d52552e150b703437e0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8b53f252f8558726dc0daaee84e2b4d2f0835f44"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8b7ebe7fb16e63e2584595ee77afb19359356eda"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8c501e1c87c42c4b7765ab027bd537ef72656605"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8d7bb385d6b13b0e689a1e81e29113746218ba99"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8d951b7ab0231fb1dc573433b354eac58c699c36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8e94dd64fdbf453f06b351d6a8f77a43cc34e4bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8ea86819b4ac803bb12fd6b63e6496238aa329c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8f43b11f10961dcce8eaa8340c96d10bdbc937ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8f8b66436bade06813ec9ed4fce6774914b73db3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8ff5277cdbe1417da64bfdb342747a23f5e4f956"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/901c9a33205897999e7e78063ccdc5d363267568"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/90230730fae07c8eeb6b5bd571a119b486a21473"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/91e2f574e7ceb7f69a93011aac68903cd014a6c7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/92273cf09f18534ae700c1f35dfab49faa091c54"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/929980ce480ca47855bdebb8f6ebef7fa447fd5b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9379dd6ade6947a59a1786435a2d55a705161ae5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/950511efda7aea60b3bfae95e31683210a88792c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9538327ef9f0a8d380a473bd25114b6859acf9b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9629c9a0c98f15eec2b7fd114fa5ff9ff5c61a19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/96a80511d8ef3ffdd370a3cc9467713a538259bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/984b6ee241b92be62923c6dc5bacaadb36183b89"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/98b88c0751f1d9e5dc3d4751d2cb52ed8f0b008d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9a0de0d63d44e00fc88e6cb88f4b8665db3b4b5e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9a24710002a240ad32b7adb5310f4970c09cc8ca"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9a425eda58b05407e671f6b86a6664eb728843cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9b6f00dd2752afbd223aad960168e4e535330d30"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9bc5b4a9a81905cbc7ee4a25482068dcab93898d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9bfd723bfa4162bb5801a6050af0a8b2db10d4ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9c0911c1a4b91f842670082c14af67d1f4b7bb6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9c5538a5492013e6bdbcce2a373be19fc97c4f20"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9c837f4e6cb572b3431b3a5065b889273712810e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9d91fac343dd8a7848746ca5472fb1452052bfb7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9ebd34b96faba2fea70a50533df78a8c1dc35247"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9f1db4144e46f913ca02e0abe2ccd5c7481e2a92"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9f77859f13bbe482011164f7a5e1a2a77d8596f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9fb07d3aba4e2d39eff7d31111515d7df2c981ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a074a30fc5c627e8093a8f860d67661df22f8148"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a10775155c8eb3a834d067c0978753513d5e1d75"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a1b04c2504a75f50d47875bd1db804cef3674cf0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a1b153e4cde45a7302094f6c751e3248d2f0fb8e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a1dffc6b0fabef88188bc4c140bc2d331d73f997"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a25eb9c166a097ea3afa590e3584eb9986bd9445"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a2ac5153026b26fcbea42786e238b15017a684be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a3026496fa01a4cae2682da4b3e7cfae09929698"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a3c9b6e89b534d02bdad07207c4fdcda536f28a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a3cc00f1a2020ff2e2d53bc91a212b5fdbe5c006"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a55fb292d4e1ffcdaf933f2dbdd8410628eb7acc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a6914c7bbe81fd2138bc20e63b27c0cadd0471ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a693801403d7721b5b3d7d4525cc0b830ab35e06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a6f614d434a1fe2162f7872100baef21b2051b53"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a78a65e7bd4c3cf41fce74155e97a758658fe8b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a8d353c157cc3788a86a0d572adcc7744e7e902a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a8f87a7038125bd0e3b753c2a42ebdc3e4c75cba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a9548cec37ad3c54d4bff10c9127db3638065d77"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a967ca556a517366de03b8a9d21e991783f0896c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a96e54f84588c424c5ff2615fb0745684a11de39"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a994ed559126fb75d245d34816a727d8585045ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa926963580066aa503c5433dad9889fabc4ee08"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aabcb4ea803e0b5399cb7a2cca8d28baa3f6c4ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aaf2bf9eaf71df9e0c597335e8d6f8c2d370b093"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ab013aca29d6027d443e9dc0c550a26e7a23f01d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ab1a75a7dec4c780749be5afa45fdb9e7e7907ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ab4a63521f8afd81d6f5bf117597039cb02d453a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ab850ea6858b0b4798d8d8c60cf7d715b9064c85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ab8c19341f57f87c38055a9aaee515f8e65a33f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/abe27eee1a472ac0dafe73619602ff44bf7d0657"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/acb49fc7f5d61f15e2e0b8f391678365381c5ab9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ad8f14d76933f67a10d9e8442eaa1b88b2395cd7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/af042d0ae8cd624acfa12788ffc0154e6f49394b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/af0a181159725d308833841738c5d14d478228e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b05cbc7820c94bb3ee46dd3869ea39923338b4ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b0ff62377b87b846f720a70f0b7f7bdc76aa1315"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b12be9771ea0f5b687f50fa9abe5cb8bb688fa6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b23f1233d0e21c4aaaebe2fe5931903698b2408c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b29d3c87c76355ce07ea4d4c354bf9d40294abb3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b33f833f291ebba4d777c2bae51193553c27d138"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b37f3e85a80b5dcde6b48b46f162418fd2ee83ec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b3b9e307ce3af6fa515a33668374e15fcc909ae5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b4037205abce710935a93d656f69928ecc814b50"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b436d6ea729dd071f87b21819cf1f32979216aee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b46794fb4115e84da13a79153b2ea44d89d952a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b49df296137b4c86eef0fd5fc55bbdd1cb3c4a7e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b4dfbd50da81516e8afcd93def813b4b813c3ae1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b51853fe4f799f7f959922fda1b3500668a45157"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b56db2235df5a81ff15d0c07612de7eee0272304"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b5daec8e0821e8626c9b93ece56ccfef0511346b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b61f6be57dd30d8c76aae7b966ffee26093f49ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b766e4a3e84ee0a2f57fccbc3a7f7f812b2032d3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b77ca0306f700c8c88854e73ccbdf470fba3f820"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b792b464ceb568355e80a4588a3ae1b43f05a34d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b7f282fbd77193d822df9c8156370398e1fd099c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b821e8d3e12441e1120723cf4eda4d939794b17f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8a74cc440fbfaa2a523f20ca964976bde128fd0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8cd185f946c392f8fb5adca4851043df849ac6e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b93e4c7538558dfe92d2925646029b5dafe653d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b94adf31dbe157a38e8b3a873658b8dace55f517"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b96fd7809c6f18c465e834a96dd60b43b32fac73"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bad.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bb349c691efa909b4c5412b9210e1acf4a4b7505"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bbf053837b7e0e2adc868be62fc91248b8dce176"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bbf7ccb14d60a1d4fa79e572464c687530ca6c2a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc5e743f85f6632110277f09847381a402e1624c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc6770a9bad24599ea4970735e9b17702a12b651"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc7f0b79a1781772d7f48e168462f99da27b03e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc96b9415e9bb48d27f37d91c51d10ec08139974"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc9b5b6ba4b6ccbb9e5ff75edd0df8eef9c36d4c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bcae3229d884c5cfc36ae28c672f9b960e30042f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bcc7eb464ff05cd0cd2669611776e55ca4dcb2b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd1ed73f6cf97f980d23ff2e9f4f4e78b80bda57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd459204c5fee8000abc7d895a317028351d0dec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd4786be14d852c68e605eaefa782f79064f32e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd5c6df9c2cfaa96d768b1fe6e8fff57bf1d02c9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd7314ef323557ccf3a97c1b1ba4bed0a9b24de2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd891b3b4256f1c4207c3bbe5bd86f5e90a49ee2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bde8a553b10a613c32f800429a07f0b5a2d37e53"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/be0ccf7b9b4581e01a42e9cad6343c93ccf6f362"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/be40890ee61e101a7429d53cd9ffd59ee600e0f6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bef8cedf1a792786a027114c85a89a1bef3155c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bf0d70e0d09e5c2ddd79b55dbabdd58b385307f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c004d2a6d36524db9e0c18c5df6170366dd2b6f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c17ca23726e7bca7b0d92398f827cfb25c7f0d40"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c1937db2c3dff32ff22a53a8b76614602cf41d73"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c2d14ed959df62d2f6dbe46c71489bed68e3c0f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c343ddb31042500e460861abc70e98ce3088ceed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c45cc40cc387134dec06733a01bde8fc44a2c9d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c4a63251d65cb186242e7aba5ab3d4709d3f0065"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c53efcb830c4ae5cba7b3e0803635445e1469103"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c56726277ddeb233e30b6223158042aafb944191"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c5e5b4c1e4e2bae55c1355950c3c7a593cb3fc04"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c69863dd21c782e609d6ecdb9150f887a0f39989"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c73e85bdaa195d9659ae9b08995a9fb716f9c92a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c73fbc2e78f496b5666da99bccac9445ac9feeac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c76a1cca503160ca659aad6f7a05ca8fe5db439e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c7c13a37189ce2482f5517f6ef0903431194e11b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c837e4dc49146de843c9556c1b3c886abb552db7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c918b9e3e9cdfdb21d94ef0fba85b25f3ed9d098"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c957b37c99c5bb22b2c1f6dd050c57e685505599"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c978dc651b961f2d48aad95b40ac761b3467f212"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c9bda5eb1a93526b4809d147647cc78452988e29"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ca086cf78308275212c52012f06edf3b4152204a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ca6add6699d063e2212335264ad3e004327afc1a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ca6b20544c093b14703410d792c8f73e73205bce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cc34f9a0d85a22556faffadf90182f7c44bf168a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cc7087fd7c7398e7c2afe3fb03e705262b5e843a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cca20202993dda83570ac83c0b1967ce225c78b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ccdff5940d61b708f67fcc55dc26ac1ad4f4c298"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cd0e7c4cd361b786b6f27c481ed601fd373cb221"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cd4f2c59f0cf55d9a73fb0b96d701c784c446048"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cdc064f39a9a67210b1be6b195d38d5d0d73eaa0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ce02561c4cfd1ec7e272cf81678149350f8a066c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cf26c6969c0f649a2ccd780edb8b3dc314ff7701"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0a0ee428270236e707457b9560a91c233ed2326c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0b1b50227d01f99998b01ed218f5d4dc3839d44f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-14359c8f754c2ecdae21deeeec033ae10360033a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1b9aeaf762bb1a972dda8f3a455df2628efd693b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-1bc1a02532d212c8975e0cdcd5127c98fcaf752b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-212c3b09f310867e1e8ffa7faecac75c12f4cda3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2ccee0e61103a767acec12b9146d478202b93b27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-2f1092c48db455fbe1ae5e275f8d221dc8c52f00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4ae4941b4c3f857966a0e3c05f789a0a5ae15bbf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-4e4d7a383785c83b78ed6597bfed360079a49a08"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5c774460d2dc7ae9d471ef4b87609b13e4e95219"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-6db86c556caf542fe8c3345ef396467b1d609d32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-72ab4efc255cfc55ed03c1002187a68e2e18e33b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-7ca23a3e10cdbf579cf81a50e51af358f86631eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-89e1b03278bad9790ae0f8614a8389414d1eab37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8ab0b6e57b90ab4c6b8d5de8278464eb428f4668"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-8e2e3975a865fb107fff8060f4f949aa235727d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-916f6ab61cd358be9a241e2eb09851f700335eda"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-97ec5404605d0d7bed44c2b845e06f6d9479c152"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9862337313ff89e8dd6fbd6f870a568ec4bd6ecc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-9e53b8c6ea7f6ae5c53e5834c50eac8e9f33259a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-a6224f954d8234d45e6f6ea27aca4d65ca77b6c7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ba2c1509ff87865d9e23c056b9c7fe2732825ef0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bac7a77b50e53ff71b0f52ce635e64ac15a787dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-bebee7dd27c149af9e7b573300c686969fde9eb3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ca8aa113c22037a2a552c1763f845609d555ef9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-cce6ffed471344173c135e536b454f469bd07e03"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-dc6abf90d5e8e1b96f7e25f418b1a7f572e6a738"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e45753da8952c41715a65010250efba0a4a4d243"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-e7930097a989131890a316b0b1ed85801699562b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed3086c0ca03a427fca1817b52a4d6530fb4096b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ed7959740df2fdcf62626e370dcd7eb43963731b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ef09afe157880d7f363fb87f6bc194ce1a72554c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-f8bf4b7d89c07d661b695a3e4fdf269b853fe168"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-fb41c97305a2c94d367e40863dc046c8f78a57c9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d00326f1b0a93acb1cb7fe02ba0342cc6e1875e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d0692d73e38ed8c154ebddd627ce99890a1cf798"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d0fcc9d6dc91ead9fd27f0c613ea031f21fb4de4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d17e7451bcef39ce542d84f2539f9586ea35f21e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d18b5e648be40b0ea52fc8b10bcbae9bd4325f0e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d194d6aa501f75ed24fc399ee594fb77341e5d38"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d1ade96319d9de82cf3b0480d226a5ad9f31eaa1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d1b53c2a386259ce958c34e2cb281514e14e0d03"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d290717010121ba2745e551e7a80be6e9f6d59e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d2956eabd7b8b9d6b136731a3a4fa077f184aa13"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d2c828ee88b3e352fad3263f1e1ff901a41fc7a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d3124f8fe39ebe943d0d5a7087a51d7e852505bd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d333dc3999c6dcca82d85f72e65e10c07f12d978"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d3bec93d378e7466bacd95be431500ed30cba449"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d48a5cefe695d0494df4540ea395dcdd90a332ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d4c3ed789ef8a888244504601964f0a0c994a66d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d4caa070bca058455b68c7b96961e3ca0f151b32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d63251b34cf38052b657d62e353aa42d905e52c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d65f32b4af92080a496fb0965075c060c70ee444"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d712d007679af5438c7bda723ddc724c2e57b0c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d80ba5bbc230065821c0c6530f70bdf205e817cc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d8137be32de0a676678672fe6f82992b2ca61fef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d8bbba8dd44b71161c835cb09610e47401de44e3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d913cc4e8f2900d7035d196fd62707cf1194e02b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d91e9bf6b6c78f35a68ba877f3325b3c1ee3db35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d97ade864dccd3eea245411665e5126f97302063"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d9f752e6e02987d7bfe6f0f4c4d70644d357fef5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/da23c62c70f6c1174adc08093c429f1ec657921a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dab32e8bb17a9bd7b04b8b895b7b48c27d38ef51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dacc3689e0a7b90aeebfaee000adf89e95e50cf9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dad2c9af972d2e21c4437f0d94fdeacd7c8c7641"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/db7c4b56e701832634e61cc0b3ab5206fabf518d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dd0e562fcf5edda051585b70d3b3780a9a6a2818"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dddf3303e3e8e558ca6f147ec11d8195b6de30bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dde3b1c08399b61df7de4997194d9392c2e4c3cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/de838de0352fc7ee32452bc83043cf587176e120"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/deeec423355ed885b906c6770c96d3f17583fdf3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/df616ee922cc89908b771e5276e47abcbaff1346"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/df8ef8bf4069afd375066fbb74cbe137f73db829"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/df949398b0b614309219c4128b167746e16a1ead"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dfe6d60fd53eb8f4174366d1515c5a90ce10bf1b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dfefc5d84c18606a3aefd5bb721a06e192b4420e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e022322a04b3ac1452055563bb41976a03a146ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e06db057637f6738a48464cc2d65d7399fe296e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e0e7112238b555fdc12a1c5e9adb50703ae56a43"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e140f7efd72850d181a0145bb9ea7d92e61dec95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e1a0398910c28ad61e065e98e884a7492f6dc594"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e212833dd63750f436254c0c81f1ddd42fb9a17e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e23c0abb4f625880dbae1cc81ce5b146992f5d36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e33f7d7998fe6e12ecc4014c8434e4ca591371b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e401c1abdd1ef0458dd46e35167c4734667ebcc0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e42a9e07845680b8aad95408657c87b01873bcbe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e42fc248764aac6f6e0af5b5705272f82101287f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e4ba9f46387c5687fb9003724893c0b199debf2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e55693473101ac4626e04012beb1b9b6d93a0a94"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e57acbf9e36c755cc50b00bc868c01ca1c1f6842"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e590a42febe0442ddf632b05cda112b3aca43380"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e5afbabdb437dfc44f06ddf8b9f793868e8fdde0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e5d120938961b8ed1e0f46e342683432b9081dd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e62f5243dd375cb4b71c864a18ddd50b5b99762f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e6660a661f0adb7be809c558ca15573add24f686"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e66b054263dd9e7ea90d7dfaee555e2f24bfb60f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e72218971bac83f556e86b0a65ec303e2a05eac8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e73a05b1cf7dfeeada6356bb18ec4381485bb3d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e75fa90650f1d67ff9849024e88a91300690778c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e79ffffd4bd565b2b5bb8d0f191c8e34385de085"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e8c24e95b095fee6053a49f51326479b60949424"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e8fd7c4270b5f2cb56fb06684858c39c7ccfa909"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e921037de2e963b653e881fba095eeb33799d749"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ea2cf809383d8725bec1b44ab774f04b3e6d5ae5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ea351febbe2c4e73fb0e0d34e7d2a23ff46b79f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ea6cc4b0a83ac8d578c4927f3c9d5a57a4464df3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eb342f6fd92411d7beb1f82983a19849d45ff46f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eb9367a74ba61abe8d5f5fdb7c1c840b2d27dab7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eb9faf5efb229c562a6825f930b8316f2aff2864"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ebbc2aa89ec745a7201eb4aa1aded15d35e4206c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ec012a94d14659f311451e89e757bd06a93d30b8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eca1d41de5486c09c6aa7767289daa7185379220"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ed9a1a597bad76e9ed9e52ba2e5c80304583c006"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eda5d435276e002a08358fd67a2bbd75902236a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/edfcf299569efc4788937d2cd4ca0e625fb9e527"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef264406b5a2263cd7a9145f7ca68ed8fd6c50ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef4127bfbb6d1b7490a076c4af795b1e40b2bcd8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef930a505edebc0ff6ca7eef7549bbaa21d95b4a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/efa80ac7daa93de08fc91bdf2a912269a3f2396a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f0a7e39c194ee3f30312ae2f4827bdbd43416a42"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f0e8450c85a3c6dfaa50ee65399270c59a127088"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f0ee077bc982be02a547d81d85e5c69e36fe38fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f1a6421ddd077ba6971eee7ba1084ed66fd1bee3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f1b592b7e1a5af83eea1bccc2d7bcca302173d57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f224ca8baea51bbc26a3814af9253483c66ad8f8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f238d0b5973d8d4081ba7036711d8c3091554e28"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f2bb9fb90c0fb7dfd765e1c528330881e721c7d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f37b108d4dca7cdd24f464ad880a57aa038528ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f3c0468b37c09b998096d18cd13a522dec09888b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f47f636b8e22e8db428ea956d9336bd12b928a9e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f4d74d507a7171e5f116bf750a20435eeaf81f3f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f4dc057d97c34f31ea542d67593b8d3a295bf52a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f59e8ceab587254d408a4af86cd938d896eb0b6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f65e41c8021049c4ca8782902de25d6791bae63a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f693fbf860c6cd1090a6dc220c20eb5c51543208"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f71de0dac54e25fe658e8c78208b855d3f0db23c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f73f63e243ea6484a97ece29bb8d4f33841410fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f788d2b893fe39fe24582acffa6a70f1ca4e3037"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f7b309af25b6ae5029a9548142333a905e3c99be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f7c45ab223810b0b6b77042055a86800e5ec213a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f7c686af20a3cf5b5c569a570656df83db3fe165"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f8373fd74d8a4eafc7d015e2643c2a277656b716"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f861e708b6d0e0ca691d88a31e73f3d2643deacd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f8a02d7d9317428fd142c05f9428840d3d30aff4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f91f27afa6e72fd653eb41b316ad2d2e88fc0bb7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f9540ce65b08ec33d9157d03bf5231b767460d4a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f96f406763e8d6a53de319e67e942696cc10a4b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f97d97545054500e8035ac3c73957d0f75b2715b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fa423921deeaeda55d2ff74e9541e5d89ddc7d36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fa45cfbecd8680693570d90f214abd9febf681a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fa99f1f9be3384be1229657b26374545228c2318"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fae6e98220e0943926fe570bd32ea7f0dcd34feb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bfb049d4a99a529ff339218a5d962983118d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fb9505e4511c982f4f26675979a138a3408d80e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fc0cb8a6287528bfbe1e43d452fc40a180c221f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fc2bb278363a5f7d4dbfe8d123a8092a99d5a9f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fc37856ff6d7a1cce83efad8cc7727f5aac44200"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fc9879794ab7f7cdc4959c204788fce6146c0579"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fda1618a9c7d2d7c22234b3c7f996116bc5e6e4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fe680903482b870b820690f61cc607e5d26a652a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fef5208b90316cac47bdc95ffd384b9c9a8a7c78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ff6138cc4a36bad9a76401072dbd41fd2ad437cc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ffd263ba66c7dd7180f5b8e13a3f7b8bf169dd79"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-0fa0559576ad2a45b06d0bfb84115963d7d48206"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-82b2ae1d2174f5782b32c89ce60f68bf5a30c0e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-e45753da8952c41715a65010250efba0a4a4d243"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f1536451f002afe7a6ff34a3755026e4ace1fee3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-f40dcae7e7cc52e44d49c7fd5452e33a77ef4499"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/001946397b463a3562c5951f6325069d8a3a2ded"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/00c8446b230bebbae2b473552b174a06b446337a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/01b05a9eaa95950f697627264bbd5006060f68e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/01c9569f5835a576fc50ea03141662c7ef1aa088"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/025215e11687c7d2e0055e5b2b902d08e0436f78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/02ba99615d1d69eb328adce99670f659959c1bc1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/03abf728ac1d833c2d4a9ff7e0c912b949edc04c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/03beeae554ed6952e94a0bf32cdbe9f97eb3ba43"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/05b4eaa1e1a759aa6b23521c06d915174e8fec88"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/05cfa5deaead322efce84b710758a24440cef16e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/07048654244e377ddf246e8cc18f71443035cd2b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/078232947d7ff25557e836b4e9e907214e99b320"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/08a8a647b6a8f47ae10852322d14832fc15021f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0949f4ac376808482be6ab2dcb18a2ecb08d9a52"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0b6fa6330bce65dfe7f758bcbfca2a2844dd07a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c30868720d5e1a19ff23c53740749c37a43540d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c5e0660ddf5f14af8f3fbcc754a967506994c9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0d36da88698737ec1ca7b55b30fe2b2036de7e19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0d8c547f1d261ba07c2648bae009636c17709600"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0dd33527db106a3e84172e8f2189734b00ced4ed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0e354d89d02c6c5cbba2f140dab7b609bf00793e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0e3a18f0f08dcb9dd174627bc997f74a5c7a1390"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0f83cbec19c834f534f353f4fce20c0cd88231f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0f98d7d56e9a99b97e5dc7eb122ef22e9684077b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0fd8859246740606c498755ab00d6147abcfec00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/100bb8f2e6a0b41da13f4edb5c15d4a04e564840"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/101305ccd08c7a8bd0c2913c37d3dd0d39d4bb64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/10f5d1937cb068fee7f85e2654be2bfe77498bb9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/110074f658208166d52897c9266fc46cbaa8af36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1160214cdb23e8fc187078a8d6796656c1ade925"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/118ffddb43ccf9dae8bdb4702232d1dc39b021f7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1306c4c6ea714d4db0e4d814c944d8d40335e0fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1402bbcac6fa24eeb0475250e33f704096e2fb45"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/143e0d4f546bbb984a7c3ac1c60a37dcf85ea58d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1576c915ee38f5bd19f285ed0ed47e36026518f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1602788cf33d0354d6d48ead549e5137cd211979"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/17b1758fc7cd69a00d140f113b1ac894023ff20b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/18185cbf9e9cfc1fd28d27ed0d651d7cee6a2c06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1875a4acdcffe505ca92ea8af8d9d6b174736e80"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/18850965807039500c7f5450a907e86825cf823d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/18926cdc608599e8df6b0f4df99d4ad856ef4373"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1965cd58fc41578a837231c69075994da2e871d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/19e984af62c36fe982284c87421d8ee46173e9f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1aee32faadffa3c2ec508e8fd30006423665488f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1ba08b63181066ffab948eb301a6a2363a81872d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1c222dae4e2cde1fca9f9bf6226200f70d625342"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1ca51ab2fefef4f549c4a8e7f4910c6b5a4b4b1d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1cbcaad71950c62d41bab50f9c242d014cc0d904"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1d19042e6db2a90c52fcc3cb0aa76f2fd335014e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1d458954e8174bbb5dd4d0053df47d6b7adf290a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1dc86d0febe4adc5353230cea24b5f7cce829283"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1e84d42fcf18bbf81ef6e8a16a0c57abbf8d292a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1f040e756f76357979f317e0c6541f72fd93df06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1fe7d16ffc2084d5d3c5f23d16902ae8810a5393"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1ffc4952225dda41de59603e487ff7fd3026b958"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/20216d27af2b3dcc83d944e5f7a489ed2eff98fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/204093594b568ada9c7857a971f2a4b42123ee1c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/20539e464ced1a0a63d74bae731ca0a75db05967"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/205cf2b6994f10b783aa0a06938a5e47cb581126"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/207e12d6a84dc8fa020b3a60b3f75932ca4f8fa5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/20ea73876cc9cd5b3d3efa1bda21deb5eac2d61e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2166c7093c424a2136c4cb8b10d0b124047320d4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/21a6a133f3d1e06c077032ba56a7df4161f62efe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/224fa2e83fd8ecaa9059ad37a55238f74b8e0829"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/230527b90b0179139c961aca426187893191fdf2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2467fa0f8a9f4bd121f544892f0782498b2df533"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/246dcf347eba7f4d4e04d97dabc002f0acf2164e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/252de25a5237c830ad8c5e4732c176e03785042b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/25761748660a64111a8daa46f72ea1f336c2046a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2585dc7b6c095e978b56e0249fe9b5c61a4840af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/25949b623930511f9d43fea4aa56a4389a28e11a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/26110f21dcb0fde99942e631366ebbd9d895860d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2663ce44ca5832381cbbdf7b252e39d6df021a93"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/269afce3bfff993c05c2a3b28c6cf3dfb3f461d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/26b8a9d27cef1ce4c3c5aefa2dee50001aab4b13"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/27f37037525aac7a41ffbadd6ce52e5a1851a2b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/289cdf83f89f70a13e9078259f764a339617c827"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/28ee8cae75efa07da9649933a9482d00643b5395"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/299034b9e0cc8d91c049c489dca6d1a2b8b08959"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/29952a15459cce9c647255ab5d7486df0507eff4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/299faa82b90ef12421d160148dfb6cd0077b57c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/29be7d33920998bae7329d77d4c81989eae91647"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2a8260b23460f90f770cedcafa14868d24db201e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2b230a7b55b17f2f8e89c4be73a662d781f7fb3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2b71439e9ebf611a92386b9f21ad44bde7926184"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c342f8715556398d49bcf3343b5a249d968e19e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c6e69067c68c145dc5d3a60b86d8081fdf95d0d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2c79128c697b53256c56b9c57c7259866e0e2347"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2d83097b3cbd2245b085e749fe923fb590790e0c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2dce4a1fc4bb00bfcd43d549a3785913c9280369"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2deb1aeb93c2abca4177b1fe886eb354c83fe8af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2e9860242d55a74cec244bb5c5445eb2797a3157"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2f288409c5f3cf2a10b3e1970a9c3d037dabe080"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2f5f6d281a3d0473a04a17cbcbc6fd06cb73fd8b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/301e10bb6d9f60d91efde4e0c48893203a5b8b88"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/302a11eb9b9687464b88c9a670da371f6a6c57e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3128887b8e02f1873ed6b36766a870543269ea00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/31545e9fe4c6aa43329dc0d4a735842574fcaaed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/31d12a2b1378120d15b4097371d792daa95de0a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/320dc10f64b59b0eb0ae140912eded1ef9276556"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3336748264594689041e4080b51bc56f716d0689"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/333d0554d91872e693d118d6988132d95b7920ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/337d579ab5eb157d7d58e9287d447976062cbd8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/33c32a80db0ec311ee8744991c5b19345bfd8fe9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/35fbd748458e3fd6068957d46a9fbb2b0113d2b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/361c6f4374443671f039fd9659577e4460178020"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/368c75135a7341a96627d0dcfc4b2081003d8979"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/370b2c16cc353621091eda4964d4c4329205ffc3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/370f893353f792c99754ece93baed2105decd71e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/375c2462d6ae891222686f9519294811fa5de010"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/379b177d55b1eb86ddb66dc3a037fd8283ee07c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3a01c85934363bd2067f76d0d40c491f9f846c8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3a3eb65d51f30f4cd16cc6f8436a5b00702a5712"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3ae87e3150628c422ada13002b08f2d9c5a9d78e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3afbc4c35885b79c6e6628afce93ce852d7767de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3b3b4f9a985ec49f6c54bae798208625e5adb777"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3c7b516e302ad3503a933b5dcfb8c58acaea07a0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3d4d961511c1de95a81b129f2fe96390209de2e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3da7577acd806e1d92d48211b22fd9db352fd834"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3e8f531043a07df2280bca73fe4a7987d82ce67e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3fcc2da89f438b247cb5b4b41e15aceccfa75b36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4040224f3df361afe45bce682d56d26f13829413"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/41aad2f11a7ab418213352e84de872d9997db8d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/41b499e86caed7b48c59aaaf51360c3c71029400"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/42554ddbe59429d30d718282ca606ed8b5a90eb3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/42c395ab373346fb283ace021bdc1f6428f92f80"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/43202ad9b1a689d919ab9ae91c2d0223394867bf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/438789ebe8a5d676f6f03ef8329c3d77579aeba4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/44153f8b7af5a3b27625a46af89e1712daa3ae8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/44d64196fb2e8d9506734a81304f6ef17b9bc29d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/44f0973ec77d6fb9eac931e84fa7ec6fdadccca6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/450f9f56c80c8b71e37302a254ba7c3f7298dfd7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/451e69ab65e0fe0a5731622ed21ab2b5380df677"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/46dcb1c399e5a514267fbbd5a50939f34e0ad6be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/47e8aee44c2c7bd870f15b50fc085c5a8030edfc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/489e9830136adcc53f4b191199c33504685b3737"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/49112bf1277d93601eb6526fe9ee9d45864d759e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4a11af9ef42aeb36691185520be281c4760ad27b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4a4553c2e939cd50981bc38e8ddb1f2109ddb3a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4b2ce115b15082ed951f4dc0b432da6a9d37bf85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4b585eb75ebca2187c0aa5a6abe4c8125aa80127"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4b611a3748757e2fa89fcd2fb22d34444fbf5b42"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4e21c4b5c454df51c102f09ea1ba78c42133ee16"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4eaff3c3515a1ca019d46b9be0b7318eaffb63d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4ec113a0126fc5746fa3f955727d009040e8377f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4f5b9d5c707a35084918c272efd1295d301ca0b5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4f8b5b7489cca36225acec0f9aa7f5c556d79d8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/50ece7ea16659b4e1a2284cea963fab662c19e6b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/514c9cd7b6519b596900d924ff2caa173d688f4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/51c6c5297acebf9d21a8a7d6261d0a17c2adfb56"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/52c00bde7f4af95a86deb0a6717d1faf2828a939"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/534c900ade27c8f7fccb1f3b7e7703f77f13a8f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5360327e8bc8969f31b364df3081b51a1e03900c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/542c958c84d1e319b9ba23c52de2c4bca08a8dc7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5482dc4af170def9c183315efaa48f9c186926a1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/54e67ed1036f3f5b315e0e3c02948c30eba900fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/55ca8f6d9928c239a7abb32554463e6e1e1ee084"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/570ca8d2555dde94aa3b3121e8f5256e83eabe5e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/57ee6efc38f4c544a3ea3e5e73987e825bdf2980"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/58a067ec6eda7191a5a910d8120633271d3af074"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/58d6dffb65a1fe1bc4e3fa970a15459587a32f77"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/591ef436ef8cc982b48fd827a4555b57cd9780e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/59d78f6397f0483d139f5bd0a9f264156f34acc4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5a2447fdfdbf123f4592c1284007b7d50a01750b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5ca233a53e3e425cc12e04b466a49789291eaa00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5dc7b2086a39f56d8b9135f524d34a01fcabafd8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5e1659e7cd840ab3f958273ebffdd215f2c81da6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/605e474e9d9436488dfe084d348908e4dfab81a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6066fc9e28b4ce704230f0e8cf21e7c3195aa2a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/607dac8012f188cb035b189fc3637028137023e0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/611343a6b8879b393ba2f38ed41c7f5355355920"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/62c843359941660da3fc9eea62a5732aaa3be283"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/636a19b8f50c4efccccea83ab78a933d999e41fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/64696e93ead18265cdac3fb37dae29ad3be6d764"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/64c0e0b4d9c2d25fdcb1e2bdcb999487fc096dad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/64cad305e1858eae27cd723778fb9f4b7052eaa5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/64d27dc9f984c49d421a5b0cb0391992d5aac1a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/653ec14661c40ea25bdbab4a7cb9371c669d10d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/66145518601b1405361df12570f6e0b2b9a2e5b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/662d81374a2c96f867ccd88a4295190827c45453"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/669256f857011c32f5757ec19b2e5b9a372f6c23"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6749752b02f7d14fff9ac35f6b68dd62f5b49fcd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/67e72cea2b7042f08e8dfba5191d27bb390e4d00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/685fbddd9ea612b25e325a50bd659997b4d77da1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/69542ed81b00a5ec8daaf4e8d509201eecd502c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/69be4179b28e408a0574935e893c6986bbca0de9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/69e52eef5dd0c51012b5c974cf70f4074ba814a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6b1698d096095d4035ce67a8680b52eada00cce2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6bfd3679f4e30aaaa1808e96c980edcfa9cac1c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6e2796549e29e5066f780a5e926fd6e3bb362450"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6e71553967212dfea2c9995f3641e582d8c2105b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/71106770243ccca03f5025aadb298ee3a825824b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/717695057d76b81c344ed8c23cc024195caa9405"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7353a7b2ea9f61325728b2f118416549e89dd79b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/739228a1400cd69c47f110002c34dbe1661e8c41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7465a4955a064e8f1bb777d4b0de5b3df8469831"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/74e6831be67485fb59b8e226fb8a48d88faf57d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/753efc088d6023ca113a12acc54015a22f7daf9f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/759a1e2e34cad14321a5e5790b1e6a783312fea1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/77ea9180617391d8503427a1c060538182f7729f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7885df741c88ca4b539798d9985c445f41cc2929"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7af3156d286a32a6a6fede46d93ec12ded1ac138"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7af41e5391204f4596cb1461792e2e23f9390b7b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7c2e48b0d08aaeb95b5ca26036384aa2cec9de77"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7c73c0671308e37a8075a20863e70e180ef8b6ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7e18989175bba8d9aea34413d6f328549e1c6825"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8021c689f0078c5c59419c9959f5c58472245bc7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/807b8c4ca068cff4bc0fc8e854c1215a2fe65960"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/80bd4827db81a1da28fae8c150f5e2d46651c598"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/813d2c34c0df8d4a918e68e58cf0ae3703d0d46f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/824152f7bd022996b41327002f6971cd9900b265"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/829a1dc2bcb22a230df8aa20540def0e16864983"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/82c0e02a867a5fdfb805e01ebf1a008220311e27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/831248cea079b629bf0ef6d9d02c159d6f8ed41b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/834527ef0bc1572c584938ca7fe5336961754708"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8382c249fc9c7a248833d89de554e63807c475f7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/83baaee9b46770d9eef0e161a6e52cda76e3b043"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/842cea88bccc41d7e2625dae8ff7268ee79e9f57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/850c639595eae3cc9c2cfef473e28fd4e8174dc8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/857ce08213a5106c746767352c6863d7bd134208"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/86eb156ff8ddd7edc535840d412342ada6f3b184"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/871a2e4d73a7fbb50f71558517a2f704b7fdb868"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8795e24f23db36e4f9ab609c9faff601b984eb6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/87e97b460042d045629263ad10ff3de7b000f0a1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/89cf42c02d7135afa6c81d8a0c2bc4c3df557769"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b7b914723bfc23ec650cb91d209141641fba09f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b8b9fcdfff1f891b1694614b7309cb4a2098f4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8b8f6d58dff9ab0c37183ec93c9a600d5ba5d9e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8ba00963037c9ff548b7a702497441799075f14b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8bacacba71bfa5c74fd74cb6577a49a7aec9cf1f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8c527bdf0f304a31866f71cdb298511041ecd320"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8d352ea63259e26e1bb61f5a8f78254be4e3e7b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8dfc4e78007040009f37109f9ca928c31b3ebb49"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8ea624983d766ed45780378a3eec24eb2faeb229"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8eeb8cf054ebd546ca0555ef1cd4ac6a08628917"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/90a9c3390752b94ca19a58cb2fe6267bc818f718"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9125277ed9ec5d59e51f3e1a8d97d25ef88a5d4f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/91916df7c8f04d8c2b6b8f4aeaeee6972ce0de74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/92cce6dc5c31acd62347b15d89d52ab94b507e0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/92ea0d3200665e1836ac12bed0837425cb9f43de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9329b80d0125cc994d7ad36540c7a8265d76983c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/94108ac8420347598c7cee743b2a158b1270fb8f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/954ea72fdbeaf5b46d18c6d5bb77fc1a0f97569d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9552c3f6304af40224b800f3a3a5df3887a530f6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/96e5126447131d3d59cc6547f6b91d3433ce37c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/970fccda0b34b59ade44d52e1212699b4d2419a8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/97c4b73f72b248b4ebf4bf30892d0db828a85297"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/98c0c0a3c8c05aec3082755a4635e65baecf4752"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/98da5edafac67704810f093b38c86e4c77b75349"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/98dddd3f679af150e9933bd864ae20e20b7aa25a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/999d0995c2f09beda8783eac95d7643a11d5c89a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9a43f48d4f6219618f8cc9e876880fe81109ad72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9a4da2a37a26c114e1226bfbe1cf80ec5ca99a66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9abf980e8909aeb31936553ca22ccfd8680c4dab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9b1355c6e2c43ce83001bbead09a79852e04feef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9b4d4ce0457f5300d6b4b309762acfdbc41e3965"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9bd059ff0a90e86ada1ba7e5b90ae04637ae9e90"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9c4eac3dd734a74673c76e6b21fd9c18cdfa831c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9d2dd744ba59c1e8ec091e23938e46d1bb5ee519"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9d362d2aaeee243a5b54621d8187c4b16f87c9f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9d6947df24c9ebcbec72c568d9708d7b1ecae63c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9dfdce1b090a559a14f9a5852f78547413b1d1ed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9e2ab07030bd35a4c31df32c79aca5e76c1d04f8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9f0ab521c728be21e93112b2730c52bc1d6c0021"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9f2316ddcea948c947fbbf35ae87b767b8c1dc55"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9f9ed47f98b4905f1f6ef2b552a66905bdf79b1b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9fee3212240d4bccfdab3696dbbc579b06d39982"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a09ef34c93fe0ffc13045f67b7ecec683fb72e98"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a30fc2605f4e74f7003f902ea4a4c994e3ce9bfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a33e1b28074a41fc5c2611a67161ae5638a47dd5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a3cd54d43d3b3bdfcf224d636dc11ce1b5ee4d30"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a4874327383ca168f9d9d59cffe327f61e9a6610"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a4e4a0473ac1f2b8de86efdf00fcb382a343126d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a502dbaf3c842bd86e9ae513e8782eb23c70ad7a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a60ae4e21a913e84405814f18555f0c179c24167"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a6603e797695274d10bce000f66ca0a715f7d8c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a6d4b6043d86c376e9b166d5ca395f3e099ae229"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a6f0d1ed80393ec0a884718b44fe2dc9f852d38a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a706f2067bfbda7837eaad68972d60547e2957c3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a814c5743d492b96d2b402f9e819bf8406262224"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a8e67676784506d2e6eab3a0dfa25e53a80b40a0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a9d71e1ff2912d8874e38fc61cbd9a8ef28af4a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/aaada46c7f3bff58c2dd6f4a8394135ed5f253ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ab27fb527771c7d86f74afb6864e95402328ec0e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ab8d6e1ecbd80c6223b8623a386c61023502a57c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/abd52da5882855a63632a6917df3639538928cd3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ac38a6572f8420b4df37d9e39088d1905fced71d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ac727124e46a249419f088c8665324a11b357b84"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/adb9bf315315338bcad85929917b9def2aa098cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ade2d2f0e120a9527487e9b92458ee6844800e4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ae8c538d4ad7f2996ac724bad7a075e1aea32556"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/af8b24ffaecdfaf96c0cd7c76f31dc9e1b4d0935"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/afcce9e02e0696a2af073855a386f589cc12c94d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b00a32e8bfb75e75f31410dfe3592da6248275c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b09f98e13e5b67a4dd7f74eff00bb247b9967844"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b24a0dd1bc0bfabb832f0d1c8410c018c4ddaf4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b283eb8884c98dd50523995ce221aa1ecb3ca182"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b2a79b262ee3966c5ce7c7b42dcffd55d7d0956b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b2aa4861b5104e8bb8bb173f4b023a2172a7b9a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b33eb7e1bde4c69671dbbf9489b4d4b87c5d23fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b39bfaf6a3072d8a50984dcc54967e9246f8d3e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b3f33b78433af7f607bc99b569b0cef95a1a6ca0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b46e762671a5e28c7061da3baee6fc41dcc0122b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b6d86bedf3cf19441114e463458a454709e627b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b755933ad6e318ee9e0c430ff69be7a515d44def"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b7b664a39372dd6142b8ef7906857e4ab3f1fc84"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b7c31bb5f6acc65b88e31400dcae71f7be392c86"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ba942f8fb244b60561a067129c242c4bc4fdd5e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/baa28a5baedb645f4430940a4b4b1142f4b03e0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/baf7839388e10ff0c410a58797482cb83693b309"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/bbc03bf6274a79528d43e200e8f1aaa770a155d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/bc9e17fed43c5d0668a87e8d6354c344c5b4d00b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/bcc7340f8876a7dff381ca676efc39d30eed9f48"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/bd0bef14e73aa1073eb5acb6e4cc901c976335f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/be3237e72b3d8d56eec0520145dd7d1a5064eede"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/be8cc5bab95e0ea7af538ca11175d710da6207d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/be988fc0c00a8422020dea3dc72451b09e25e1ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c0deaead93c9b3f2fc211fb7f0711ac192715a40"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c24143cf5f6f77f002e0ab82e3060906e2e7d062"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c3afa705dab02fea4d892134e7c01c3af270cb6e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c3de41124a14ea562360aabc9e12666851bff2fe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c4e60ae7c05b12a90dd7c43fbc85ae4be7540f18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c5d0c169d326d79fc4ee8521b282dbcbf33c1d5c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c5dfb4a82f91d07041d4b0ca6cc34cfa1e9c7199"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c685689a9d5b259afe237d857b7c6551dc95c176"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c77087b4651f4c62a780d77a3b4c233490244e8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c784ad2e205ba49b5bb1302746723dbc57320981"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c84da54dacf04445b50448a70fb0ecdd08e9234a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c8cb20176e427d2e108187924f570ef1df6d440c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c916ea9c6901c1e77af764773bd2843baa2ebdc6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c97ebf43d8a5ce5cdb8e93a5d0362239c284ab4d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ca0db313bf949ba3f87a5254646a7a7dc8a7f89d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cc4197d2381a75b674fe4944b8c690fe69a0b3b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cceb4c620c02337138e489383db0d4f4e2c7a722"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cd4be18b1ae872c40580edc4fe8cbdf1fe2a3881"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cd76ed6aff7e074b0cfdcc6305ec4e453d8304bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ce990633c0f2b2a2ddb66144ed942d4bc9bcd8fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ceb297908903ba0fc24982ad4e6010e79dfbdd5e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cedd54df6d34491dbf7843c2621d6818418aca02"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cf75632ee185df2cbbbe148e2e1ad5410f11d361"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cfa40fccc5ea4304e83ca26f4e567765c2c08627"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-12b69708d452b3cefe2da4a708a1030a661d37fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-3bd02c98286bfa7be8e13c5500ddb587bba74fbb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-53e93a1906d8442d058500e7107929cdd3e84ff8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-570c79624a2e4d36be107745d2b25e74464553af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-8e546795782dffa5d5f5e94c9510aac178fcee39"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d5af12c391b7bf0ce63ee3dc656ee4410fe496eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-d92bb454bbbd415175df541661e3696453ce3e43"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-e470e9fd09a5c9ef303813a40361c897650289fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d194592e6f471dd487ca2625e6c3da7802ea372f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d1b1863b478e1ea71eafac9e03256080c8f0d1c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d24d1b9d754391fd0b11b0456a2e8c6050cadee6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d250e525e8ff2ae4a9bddb2e478a90a1242155f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d257c41db22b60cd937de16b9d90a44b9fa8e426"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d2df8e95436cf98ef2189191a75a3d9c78b1be6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d3386702918881101368cdba2c4967e86ff3a7b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d363f288f48fba8fde401978b7e764295735645e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d36e015b1e14ecb9559d67bb09c2851699f0aa35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d49450b97f489f0dea74a9f83c71abeba1066d3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d4a72650e8218ec551fef6560ddd136d52828a4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d60469c0b5b385f20d55aa5cca55bc2c801f3b95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d70b2046ee62676b525490b70812c2157e5a3585"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d727b7edb460c549d7b12b90f581048c9f4747e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d89026894e6c5f8b5c88dec12950f56c4b6924ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d90c312791129dee8c5f85cb3308323d0c39b70d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d91281daad9b821294db204dfc244b2d0d5496e4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/da322a6b88da87babb52d1527fe54cb4ac214b32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/da4d300d0a8e6f803ec053e3e7689c4b91eaef90"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/da538941f1613c627523cb1be71eb220d1ca2579"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/da8d4c7f02dbeaa543c159b3a4e527059978a429"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/data_frame.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/dc4a248fa4c903ce3a571dd18aea575019445740"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/dc7ebba06558484af10b5aafd01ec4fd59276b12"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/dc815fd6d5e817898238481472f359bc50b510c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/dccd1fd6d3394f5f68c87950ed7356a2e9ef0f6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/dd662353bad317cee7d16191a39e094bfa4898f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/df684493457bc8d87dec2ca0825f7b43978fecfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e0d1ee5e2e169dcae87f790f5c27e84a3453cedb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e18cab69ad5cc17c88f8b56ca9929ca8af3eed30"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e1bd70aa5c802cd4462ff4833c09ed432ce4c9fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e1f2e203d39ab2509d4a67f7a44265b1e6364334"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e262f378a3d27bc519d472ce3650bdffcd48a055"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e309e21c69e4b96ab37f675f4e87a52453512ef8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e30c4ef6423bd4d872792fbd6954ff8e47d31a97"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e3422e8f5d63a9ef180aab552353955c7aba90b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e40b0fa5d814be8f2081ca2c8e0a4090d4893831"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e442f9fd63bc5345de1c14803d4ca4bb6f1152cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e4c0e27cfd3690b8255a8214d6dd055385d1d24e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e4dc0a111e77dc495c5db07df5e2917adb674697"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5a7c086208248a15ee6fa5195fc4ce22469de15"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5ac3394971400b6636d029aec7ec665a94ecf29"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e61f728210ce72ed8b2c066bd1b1ecf9e6824b77"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e6a08259a7d47601eab5c0249cb6547024e002c7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e6b3c920b47e00055226d49b9f715c5d4353e3e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e6f5cc0702a5f38b9e7339849e1dd2e4001e547d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e7c26599fb2e2b031346ff1ba09294fd758f7abe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e8323c817d18f0c920d3cf53be41a9bc0fd64b76"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e969affd8af10a1b87dc63afd3b29cce3e58fbb2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e9f7f7f258c72222397a960652c01d2a37e2afe3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/eb969b9ab1b0d6b5d197795223ba7a091ebd8460"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ebb0786acc21c6185356eae9a62490a03fddd1f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ec180175f0edea0a6c3eea2ae719b006bc029ff8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ed6358fbe6721c9ac01a6f4cab4d2df377eb1f11"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ee436743977b8e31feec22a91b1ce23dee96665e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ef1984d6146670122c7a7246374bca460e7284e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/eff9ad9144a2953fadc019fe72eb1cc3447c33fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/empty"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f03120d1a8376638e071735bf4746454b6ede389"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f09410ab7bc19ee1ff206f94e8eec2931faef15f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f1b9b6803e41beabb1a762d511fc148116e09e78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f24f925945aaf5e8b5ee470935e5aa7f847e7a72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f41f9319bda14ef21b925c46945b30728503dfaf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f4499e3d4bf60ae3ae929c485a13ea4dc2713369"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f5b1eab444efb2664a295d4e6d087eb209c0c480"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f66305230042fa83fcd1b98c469d90ffef3ff6da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f6af3f46aacee395877d7f7909f8e412a6538efb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f74143e8160754e40eb4d21a182c970210707979"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f7812b2aca4d12ffbdac67bcacc41b34524de6cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f8467d9574de94b9bb904f75a6a7e2405c36f105"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f84f5d6188cf099465f0b70337b87ad8aa8efb78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f8fb1348ec3ceeb75c2a03df6a2ead0de6f4127a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f91f76fa45a23adfed48a10ec9512cf16bfb6636"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f96843fdf2d6fdd661c26201d96ae7bec72c6c3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f9940356ee9b212849fbdf0d818b17af1a4f3c6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f9c875c00b7327df5bf21c3e051b55b0d2ed3cc8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fb340fff42a4d7ebf6b82adb9345655ffeeb05d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fc3ef8b3cb43e4d2721b252e7fb578d83ed6605f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fcc557c9844892675be823fac8788eb694a3a118"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fda07f0de15cac77ccc54ec221d81cdade189bfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fdb553b8d82e68270a7345b048772bf8367b1224"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fe1390762579b5c335bbdea73e251b95b979c3c9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fecccfc70b1cf1a524b9f28a9ba2c153c8e14d0e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/fef80aa34c31700ac8e53bede4a97131176ceef0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/hdr_frame.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/settings_frame_1.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0141fcddc9807ee093313b2256f1306fbbdc6cda"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0255050a9ccb25f46d6c1bf6a5a8a4c0c7635599"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0320a995a8c76c64c8a0e0297f632b76d9bc92d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/042091aeac4cc255506b96fa11c7354e699fde76"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/06995c2f3f01c7ec50547415dc324c64030b7a3e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/06f7ce769fe07804fc842462d4be8c1aa2ba82c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0781b055c85ab8fbd0a3d0080a32e394af8761c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/080e1f19e6061c5bcac31add2095f87f6ce46129"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0828169ba82152a8907f1001e3d98804397d4610"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/08ffc4a4160e9fe6f322c28870a89a41fd9c37d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/090a7a758898a6e7c9108b7e8a1cb9cda383e707"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0940663729501b750a18542e1041cc26385c6148"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0a10bd140c6c5fb109a0816ca061739688a6db9a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0a4d3fda02cdcb7adad1daa80d65780c9c8d1464"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0ad812832efa33e086874fbf3496664d3f1b4dbe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0c9996d4fef87bacd7a001e99a515b3ba3d5788f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0d6210208831fe55951af56cdeee3d54a91a5361"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0d784965b2262df7ed7a1eb57b92a718cc76bde8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0dc9e41eedf35ccedf4e2b0d230ead7c4d72fdb2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0dd470c8939ed535de6b36f7b7bfb68aeace493e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0e61e471fa6d3405daef4276ee00cf5fc189f378"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/0e9196f951874edbb5ed098739ea5c8b6c0751c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/11442d93a554b9e7f9ab02782bbf9443bf6e1ddc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/11833b795d04eda5a3af56ef7b3c3a26a8ee3444"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/141272316382b0f3e9ec841c735b84e7aa517c3e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/15ae43369798e48c396dfe7d53a21878b96e66c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/166bf1843c229d34a2880d234dd166c27bdc11fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/179e8ac763b4051a953a38b6b3b1f1e1f6cc6c9e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/17faf0ba8a491a835d35977a9007b90ab7d30d2a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/188f6cf2470e95b228341de305ef839b27f01a5c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/1ab3e52adace335d02e2b5130eb4f7c918add7fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/1b5150514364e2c17f5a4edac1b7af99b936f55a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/1e8befb98cbaba059d6771abd1680e19484e7723"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/1e9b962969c359bc2ff766704c8ca8e25f5eccfc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/1f80af104acf41b912bf4a48fb938267e3718719"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/1fcc4afd6f48e83d61ea74970df3ca9dcd8ec291"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/213a734ccdb813b18ad9f2dd99b7f9967ee1460b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/2151945f43991c27e123c45dc72b93752a47e65f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/21545d998c27a5a1572a89a552937752432b1c14"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/23c7443fa1ab713e7c34ec50222b1b8cceaedc65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/2445bb2c6779712dc9e14c01fecb7103f8732858"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/244b0a20500e31d3c538418800db816b07f4d210"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/2461b9fa6b5bc4b6424dec5b9a18d4ec7c309112"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/24ec2f3e17d3850564788f3fed17a5c586c44658"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/2537b8d6b902b8dfc6e17f194cf7d05ddecf74cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/253ad01acea4b7038edc3f2a8c4a0c0f5c4dcd05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/256d0bbdbed22f5867a6f503bf082011e61ee12b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/26f0e88adbd8f8cdf778131a35b33ecf8711fa49"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/2e5dd8fb9d2a31fad9d681eda697d085b647b57c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/2fdfd2abf30c636ec8c841f1ac26594e25664f0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/311dac5092e36134d3490f98aa4207425e0ee941"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/320fe6224a5b691c0425e34b6b14e8c6fe9f9620"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3255f1c7441a7150dc3c33022bfbe8c956c7b7b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/33bc9db104eb72891fb096f34cbac191b3f9918d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/342ff1db70a7616b4ef76c03a42802c6702c18cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/344c011df992ccfc0ec682c14a1cb2d7959998c7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/35775efb9d0d68fa07987b9a84934389b528e436"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3650168db6fe115fb1e73eed4b76cd224d977d01"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/38228bf98cdb50fd3fa830ba5a9d4c7399063dff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/38717bee901151b22a10beb12c6623ccc844d3c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3a4bb427a85bdc5bf66ac71db073c99e0dc9f881"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3ab48621d9b8f075369099a8ec7517bd23fd6e70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3aec8d9311130dfbb6584fe6e619579c21992b5f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3b14837f22905dcb04f93aed2aa69bf95924fb9d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3be63c163805927e04fd7f84d96122c48240e601"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3bf2e349747c0f539181e0d4084a5fe506811a9e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3c5af4d73e94d0e8ad5666b6acb340f929031e95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3d2b25346a9671d83bd082d170a45eed739bae6b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3de7b860c3fba2bc55707fd6875dce276f2f249b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3e2004ff9f40e398e0f41138a25a8b66e3d843d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/3f8983e457033cc85997c356935ba9c21460e86b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4105669086d83a20f8d991088553ba08202478cd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4180619316eef7912d1cf52ffe85897242e1ae88"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/420291d7139d9246de747739fd98102434a742dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4256437fc5897c0cd5d755816e4e68c7be326849"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/42b25a5413c536478a3e63da5adef4250babf2f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/42bef44ae751a45c671d9da5b1231d2ac747a48d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/438c3c9045c3cf7910aceec34f77b47a70ca4abd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/43af96b4f65ed0ace7236427f2f8833c4835989e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/44c6119bb91a452d6128ce0ea0d62938800779ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/46d595331689ae01d77aff387747a98ff3480096"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/471a307b81dc37459087d41532741c5c9d7ba836"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/48900b4a5557530922ce45c15ad0d3b0a337520d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/48bcce2c6487b18706ef0c609ca39c456215bac8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/49027bbd3f3f3cafa315843c8fe8280f86985273"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/499376c5e291da2f9c25999abf4960fab5a92ec8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4a3b7ce0cdf217963a0b692769e5d6f4befe73b8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4a3fdb96bc8c80f1992f0f72f963f84856cbade8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4aae80e05793d7adb42a7e6e8a5283b677318777"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4c7a034d3a3b4f29d99caf021a0e9bbb89706c2e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/4ce8a43fb17a075627160812ad26c25210d8a82d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5032a75a98cd14d4dab75c1c5e2cd981abb19dcf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/50b3f4b6aed97f442496d27f3b4315a18ba76d5f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/51064b88a98658d48a0da7f1545c2d1293ad9538"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/51752f12d59fadaaa0dc72e6370612b84ee1555b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/51eff6fcbfe1a51ceb3f5f2140c01eea89b4313d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/51f65f681cf3a1218d83ad58642c06deaea86210"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/521809903d36db80b1ccd707f354361f2bf05075"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/53de87ae94acdc8e58a369459c12a3240f1294fe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/54a2b3993c3483745f6314c870a038a8e58f97a7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/55d60c2e5040a38be8ca41de63e137e3fef892a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5653c44a5b520bdf2bdc599b7966f1d7c44950b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5838b5a683229ebb6e6277e2810863e642b8afc2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/588d225784891ac88e30ac6eb5651d63fac34083"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/58d51c21a20b6549567a0ab8fee29d162dd3fc5a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/58f1036d8ff855841ec25b3c33e85a8fec0d94b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5a99df42fb7bbafa2d55714ee235b1c46776b2ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5b42793550699b2c015bed677cfcddc052f73513"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5b8ca72ba00231c38b19f582127e6a146eba4282"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5baa13dc95da05e7ba02bbe9583ea24517a29a1a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5bab61eb53176449e25c2c82f172b82cb13ffb9d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5c6f6b6f7f3e7b435f060abb73c20d2b773a7f56"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5c9fd9cc7100feaeead1e0e45201945a6e76fd85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5ff49c9edc7361797a951585f3e180222c8dd95d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/6129954942e26c2a9ec071b6659675745613cf3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/61fa69b6b51b0ed91914fe48779173f8d26a1d54"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/6362ac61cfb6e964aff78f3cd648475dfd5fd4e9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/644deba51c79b6ebd470bd4367452941045d112a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/64beae98e2276749b133e6368c9e0f19a79eba96"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/64d7add9192301fd878854dc96f9fa9053f03992"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/65566df65e8f55428b6672cc351df414fa8f936c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/65bb703af35d5afb824cd68c41d7a1aeb3848d35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/66c537bf59cb3667c037b3517be3d31245c9da8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/66f576baeb0c9435a56eb7375dadc5b5d630ed87"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/67b4cec5183659aeae0f5bc71b3adf0542a11828"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/68c94721eda2f62481bff9f1d183df70498d0c5b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/68ee8169a65d58edb9fc1c752ea81dfec383203c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/6b203d49bbba6ee74def0d35c2266e06ad3c45d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/6d580f28d785c0bf87ac351a31a89289449feadb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/6f231dec759eb2105e09263d53e171de19a92c74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/70ff6621a09e4f641538cb1b27e8b382b2f56a94"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/71981b55f27a1eb6274eda247048fa2c597f5004"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/71c2b0bebf7f0e916e4ab7eb36d47ccca2b9101c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/74610e278a5b90aa12ce1beaf222c4306b02ed43"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/748ee9817eba56ec9938601a0e380c74bad4563f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7727e3eeb2a48c46bf5a678c300ff8a38b8ffe3a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/78176d80c1d74c4b1b820d386ae483ac4d1d92b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/789abb571563a6795220046f76b7cf0ade90743c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/78f5ff40e5554aa9c31b45f79a7ae9699f93e7fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7a28fc2e9c72d51d29e87eed63ed405c9779b5e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7a42083be21dce7f96edef1f3b3b2fea0bcaeb3f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7a51275b11ecb1efec9251390531681c8d6f2481"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7b9682cd7a3984698f6eac034c59c0f91b4fb83d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7ba7239a29d6183960e3986abc8f19cfb548b905"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7d3b3d5f23d0ede9f7e5dbd1115db58c8a54a213"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/7ff3b6239b04479a9caf67f45b2d0c619f712815"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8035c81c95dedfc27c3649064f98f49e3e72c21f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/804e1052842ce4d44b9c775ade2b18fcb8ce7bcf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/80514b85933ea9bdd3462595f949c5af24409b87"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8057c32b8bd28a5ec2105d62f2abe8cf69c9f5fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/806a3bd4e078d91adeacedfd3e47ef8ae229244a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8090444f98218e65ff9594789ff22bbea3c0497c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/80e516692955d5f224706f268e247858858e16d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/810a1372fa97380265f5529c5043ae96f007f5bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8127597d3c146b2a89579e44daef9d03a0f941ec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/82ed571f8922caa572d13b4cc9b5c5fabafaade9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8328e86178800f87a3bf6f80749984f45b0cd0e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/84441efd7d8bdb0ce2fac28f218d3d5d4d77f1d4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/84cbf70f45a64d5a01d1c96367b6d6160134f1ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/85eb0f4502a51e646dab4ae08eabd90613cdf8e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/86080f33e4eae21b37863c253ce61eaa13021a97"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/862e3ccf601ee0f7fbd8b23e6811fd50485a118f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/86bae059b18af8ae263e5ae0022b67da0cfc0fbe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/870f9cc4bd89c6c04c6a51ceae1efa8634627cd6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8762a523cdb78d2344d553fa52a229bd63c44e51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/894211571f9153c3c2ea4102541dac69be8aaa9c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/894e9b7832c52acb04bfa994ef53c7105d8db206"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8b0e12978b8e2eecf62346e438e47d0993845693"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8b3fa0bd4f289eff6a04a5205e04baaeafbdf637"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8d1deedd1e463f8c95129a6f839c380a7c83ab04"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8d1e029bd72381e382c87e61b4c5a9741d80d644"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8dd1983889b6632228d4897c365a1e6124d101e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8dfc2183691385432f92957cff0b2538e5a0ebfa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8eb9b86b4f0aa79b8ef84b44e1fb03094e7bb426"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8ec540c36da3814e93da765bf2ff0825b59c1bd0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8f1bec32f4b8e64062f5405a096543e61d771076"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8f3e48c49d0794909f6e8e61e5a4312edf484c33"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/8fbbf3c0eaa25b64d0a97a8ee08006539e649199"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/907d0021d42d0fdc867fd02d3609cdce13c8a055"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/919511c217a3427c22cad4a71aae31a6cd47b193"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9267c81c3283da8193c198de05e05fa30631a453"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/92e80997a4237d76f10b70dae2870b7255c97435"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/935322db76f5d4c74c2dc68fc4631915b8e24323"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/939f2627ef6263d0176566de267ff3eb910e6a60"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/94adea6a0d9a44bee6f5e88adcee57be9e9e3597"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/94dcbe0d3352bd9b230096b8dce9c6d8d63f9d51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/95dad738f60e3e5eb0f1cdafd91ad461f4418e8f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/960c0a21c9e5c1a61b93b34da3189b0de1c264df"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/96903512b1f1dec08206123f024b62d0e31cd4dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/96a89c005e8d9992e34cc149b0be096ad0051446"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/97db8a66dd513eea47a5a25115508f4e59984854"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/98f2cb84ad89550cf56ee54e11f1448ae7287247"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/993497422a59b7f9f0f6db8c867339b5c9e4c978"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/999821e3750a7f2c9db663d2d100b4404c225040"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/99b2ed83be40cab431d1940e8de2dc3ebfe9352f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/99e888b7372b29256dbefd476855ff73584cc00f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9b18087deb3cfafa1b964aa65d8ee980bc61404e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9b3c745ea3e313909a228a07b49aae110b02ae4a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9be1ce0ba77758928ff5e9c45139b1624cbe9c2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9c703141efd69eb8f32a58133c8035fb585e0f4c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9c7f77981677499f0426a0ffb5cb79d5fe55dcb2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9ca59e6cadaa5be9af30dfe5620d1bcd70f442e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9d139835d91474e8d8361d65698a31b8b38c4f7b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9e2179564a99e96e179c96f28802a0a2759b581c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9e56bb3b68d2e2617cb2d2f0f3941f7fc832e462"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9f318b2c2ff9cf4615bd06ba13bdd086b4ad08c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/9f8d90b1480989fc46ea2f1c66cf687638994587"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a09db5715f0bc3879a0e18e4db5a6b5640b254a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a0c59a090818bca29d76ccf9843f7e2faf330ddf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a1cf10478e5e01a0d951c743a3dd45aa5fc409f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a22c0f03f8c005a4612a9dcbcd6a643334c35d2f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a3154b8ed26b3461f2b091c732da00b63ce8bed3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a84a1ed1a24e753a27adfd3ba806f06fc44f899f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a871e7ce66afd4f57702cd1299de06cd08995561"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a8dc736ea964586b7dcbf2bc065ec4675d1daba3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/a91a835836c72217824f0b63491d9b623130502a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ab97c1f6033dc7d96f69b9e1461fd594c16f4ebf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ac8a8c23acd8c290a11dc7828f7f397957fa6400"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ac94b2788f5252f9e2e8502c7c75e04bef4c0b76"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ad03b4f58470c43db6593a35be48989486d754f9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/af417c83e831a96fda1bdde99a1af6509ef2df3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/affd292cd2ce3306b4651cc7ec0ec0524cbbae3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/b0587e6e319f4b56d877e7ed46bc7da9b1e7249c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/b166aa66b5b3ad178bc38aee5768226c8adc082f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/b1ade0571262c6e5f1d72f6d25ebb513d2055bc9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/b244c690157ff21d073940ef8c77d1898f37cf8e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/b523091ee4f17d20f51f9b5cf82293465cf61780"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/b7d4d49ac2c530eb8444a449feb689ee50fd210d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/b855c161121bfa29c6fb22d3c0236fae4af6984e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/bcf4684ce097faa7e9d99b6e93cc2de24f57aee3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/bdca6504d2ee7925f62e176355bb481344772075"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/beb208fd8675ba7de2ecb12998d2d628d579ca7c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/bf0c98689ab81fc32787023300caf9a4175583dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/bf479e97b39b697e715663de6a1e78dd58d64122"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/bf826c96be94d1b42eea0666f7239cc5f699a375"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c17650d19ae4a48abb36739c83d8979453f5705f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c1e5307d88feda2c3b15fc221cba92bcf41622bf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c249f408c552a0408eab3fe1d1cbeca95cd537c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c26b460aebc9082c519539069f7e060042989696"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c2eae71daad0d3561ab4d09b8b85372b8d790bc1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c37fda8d02e99132a1de99f959596c784ab8a53c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c4836760377a7091fb20f4afa9c712875792b9a7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c48caad597176404f776d532d4baf9faf7655ee2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c4eff0f59986fc5ab09d5bd95f394292f2882659"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c5fc2086d167c8c3a7d9ec778db69c5fa14a59fe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c600877ce547166eb1b9d83afbe128d98767f8a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c6a98fdaf6de78e59e1a149a43f3e42222d650b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c8d22f7fb4f37f2d8cc7953fa2d599d38d899aec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c90951c19b24bac84296e3ec32cdeafe99e99cfb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/c95ff2a172626efb50e94aa6781feba609820076"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ca6c557afb9c571de62e9b65ca6469a6133760da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/cb2d0fb23f66c968af2e80d59f71d4c1aed96fbd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/cc60a642cc2037ad3c459a57381b8f65d8d7aa35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ccd3b8aa26c52f6d9c607c26ebdf621142aff745"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ccdfd1354997eb117bd76b75440a7e4ff20bf564"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/cd7a7b8f08c189e95ae3e2ea44b9015000e823f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ce05678d812a5f8ae8e115938410116ce9169456"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ce6b642b81373f05baa2a6fe6e9d5d1387046285"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/cf84d06e4dddb997a79a41f9b6122bf620bbdb4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/cfbcc3e8cd65aa8b654688145ade34b8789468a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d131f83ee73450ff45565d0c638be7d8beeb30d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d1c7ae01a81a122c2fd7c5d8debcae7566e9ee2f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d2817b89d7aaa7fa880c077b1a67168ec2f4f0f7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d3ccd7039dd34baef465c4b78baa7a30312a8f07"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d4cfaf3b59b22b654d7af80ee6715ce5015bfdc0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d5670827c8e8d4c95ac0f738c0790c19916c0336"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d59d7e94863f1ed89cacfbaabf7bc59946036c8f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d8b15e9e555ad9900ba4be8cc9f87bef75725b24"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d9748abd540810c2449c3dd39a0ebb62754e520f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/da9fc821f0c1e00728b139b36269bc3d21c0a8cc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/dcd1bd94ad97b4e67fd7e12ff1bf7c039eb17f66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/dd3ba9b139e13324fc76cd62af84b00ca8b87205"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/de0a9dce0ea4e4bfdcb13f788ae728bf979fed25"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/deb6f9a930d9b31586ede19fd8fd3caae0e5b1f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/dee95e0280b70681eddfb68e3b418126c5661e18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/df01203edfa2dfe9e108ddde786ae48235624fef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/df0adbe2523508e9afb42a58d98c2657710d6033"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e05fcba1b22f658c8bd6f3c330b2b3c9faebf977"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e145caa75d73e3d819a9cb4b6217f1f53112f3f8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e1d86c0094657386197d191855b5645ac1dd5936"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e25adf8de44f5978d00b7e8c52aee89c5cd1fe93"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e29f05162e3d96d5549f96aa4a54c868535b2847"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e3a970ac8636d29da3ded328b876ed3550cb3209"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e3cfdc862187b4ec28bd4fb2ced5094bb5b09909"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e4ce52007d001806fc9368b62c124dfc56e8471c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e52173f0bc3325629046e85e2dc41acc6ba7d1c3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e6589006e3bda4c57247ad66fcd73ac00ee2cbe2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e790f5d312957dbfd20abdefe4b1735779ff9689"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e8809017a4cf6c1e80a93f661166ead961f26bb4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e9733e973c33b38c2087b7f1deb36688b3b14259"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ea8134769855d574f6673bf0301eb2e24632c6eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/eb489536e4e5589a93a17cd36669475b8f2a5e1b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/eb48ebd4d01e5623dd16ae61938b3333fab3ce78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/eb6ca7624384239c7f7e0d83edb7cc334b7926d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ec9457ad41ed745ea9377ffdb16ad09f981daa7f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/edff5256a2d60d0e51caef25dc1d6f1643dad6d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ee4d9c5d22512da42726f47213ff56404d1d81d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/eef2f30b5e2ecd98ebefb12d57aba8b4ad52d904"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ef23911de1a27d03d2d4983ca1527e17d6a7092b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ef5b7fc62a2daecf1e8f928b1fa3ebd028413a41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ef718258ca1870198e91a2fbc1eaa90b620673fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/efb46deb37a78f41dd760f6b7203b20956eb114e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/efdd6824bd2456e3e408e0e84369c4fa3aa14f41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/efec040a5de1969df5e37e4bc50a0a8f0de341d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f1e30464c24dc1d7cec7ec1dd2adec8512232b43"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f27a617b936814476770a3b31a5afb80d0f3b423"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f3f0d99ac2962f8fddb25c65fb4c8c6eb63518a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f4628084cf46f139babb886a782b4ab5977d5d2e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f4753e8881e4b3c71f2728149be7d04cc648f6a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f52f4d51aaaed0f9c3a20936cf5efd25d0692f67"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f7cf30724ab740918eee6e4a6b6658ae3d7706e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f823828ffd2a60efee36f1de52cb0f024ac5b4bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f8760761bd5ab7b47376bfbc5a44e16b2d5ca800"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/fb15042c268625089ef6c8aa3d8a6f12d1d02c74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/fc3dd4292d6884a770199596f5e9cbc1e869e5fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/fdf548cde981fab4fb17bd63a124b75eddc5c836"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/fe47fb18b064e26479c3c3140082bd01065e897a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ff2097734bd7bb8451aece13c9336c4624735170"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ff2c949863eb4e14d9e835c51591304403d91b6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/ff7d6ff060e63355701b2e655c802902338497de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/request1.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/request2.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/request3.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/request4.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/request5.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/response1.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/response2.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/response3.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/response4.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/response5.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/response6.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/http/corpus/toolong.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "http_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/006d552e952c42b5340baaeb85c2cb80c81e78dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/007eb985c44b6089a34995a7d9ebf349f1c2bf18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/03b74a08f23734691512cb12d0b38d189a8df905"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0495693af07325fb0d52eafd2d4c4d802c6457c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/05454ab015cf74e9c3e8574d995517e05dd56751"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0716d9708d321ffb6a00818614779e779925365c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0a9b3522a8e711e3bd53e2c2eb9d28b34a003acc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0ade7c2cf97f75d009975f4d720d1fa6c19f4897"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0b1fcf0ac07e1e50cfe27316c7e1c8cc997f1318"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0bc13548356d08009703d35e9c8d74397367bdfb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0ea9a160c57f2c705dce037196e360bf9be739c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0f20d9c46991c0e97419e2cca07c7389f1d6bdf8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/0f2e2e6346f70c419300b661251754d50f7ca8ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/108b310facc1a193833fc2971fd83081f775ea0c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/108e5bcd69b19ad0df743641085163b84f376fe8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/10e3ecd5624465020fdf0662a67e0f0885536cae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/113c8c97cbb0a2b6176d75eaa9ac9baaa7ccddcc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/11479d936dd006410a5946b6081a94d573bf8efd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/11aa091189b78d1cc35c7ff4907ac16a73aba547"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1227907b2ee5a9492a890beed55332e4560834c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/134d65130947ec69cf8df8483424b45e99cf04e3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/13584505caa892d94982a968bbc4391ebcfe0d06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/137f554ee0f6b903acb81ab4e1f98c11fe92b008"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1401ea03ec78b8f20dc7be952555004d7147f0f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/141d45a59b073aeec4443cd7bcf20f7833ddbc95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/15a8f2e7f94aa00b46f1b991416aa015dd633580"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/15c9c1284c27c8893559e15c9b2a50cbd5bbb56f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/15d1a6cda48ef569b368a0c4627435bc2c80a988"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/17a29f2ac6df774585d7713091b299729738030c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/17b815f1f72cb64481bc40263e91ce063040f739"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/182d57403d2c973a394055017d35b7621aa0aa05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/190fbe2da448f6bdec0706c5301ad13363ae3ad9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1b045a24b8f1f1fd6e8234d5019952ee7713a8b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1b6453892473a467d07372d45eb05abc2031647a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1c6463aa2dabcb4fadc8e5441d8b418535e768af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1dea95b5050b766274ef80847505c0e4f47f3ebb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1df0754d3e7970b3afe549b11ca128dcd0d4832b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1dfe267b623b20cd97c6e8969d8b9148af9f4a2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/1e5c2f367f02e47a8c160cda1cd9d91decbac441"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/20efdba13ca7a3657d071b3d56997aa3b083068a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/215a956168f77421253e947c2436371d56aa7ea1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2174b9ab6bf4f7c21fe1ed56957f1776ef611959"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/232f4bced4075545bb1469d5c2360f083ec7ec65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/26aca41ee8f199e7c0c7cf31d979952571c53fc9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/27d84210636e9e83786be9e9b96b69f70b743b86"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/27da426a5883662d19ea78f306d7a992be52f827"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/296dcda6f7e6979e68ddef7cbc1206a355084ad3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/29b08c03ca5a6851fa4604a984cb7ff44433a5a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2a3d964ec4527ad9f02129fcbf087b67a6ea6444"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2b04974149815b143afb17af4388d751217e54ec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2b3b1ad952e3acb566e32a84e2d503acde13eb53"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2cc301a6ed7f01e2cd339f02bd0fda20c227a17e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2d3d5b9275553430b4cfa68114099120ad7809ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2d5dbf403e0c12e2fe21b04ca3daff171c028ab7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2d7c769bed62004270034b976b1d940a5686106b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2db120231eea12d9cdc6a00f30839b3cef2046be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2db610e1a230409a205cf22fbad3348a54cbe703"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2df1dd2e2f5d57e7d9d4e60a756a86e603573225"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2e32faacd3ea4461ec7aace297b4be6904d9a389"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2e756d91759d7e74f5b776c0d2a1935292f576d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/2f09b24f9f5fa0af2c29b604b4b0f97fa6163895"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3027d901361162b38fcaf17f97ba7d9646e32495"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/30d4467ecb771ece9ed6c78a46adc299072d9db9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/311048bbf4c4bbabcde73607d7e76915cee9312e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/323b48969d7bf9a50aacf0912f1b5cb02119e2ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/33400a242baeb5c46ddb1578c28b10d32a9c3cd3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/356a192b7913b04c54574d18c28d46e6395428ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/35e995c107a71caeb833bb3b79f9f54781b33fa1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/373769c15c145472c8ec3bdde8fc84e85ec79211"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3795d911970a1fd8416b93649051b418948e3edf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/37d3333e1e2a384c3ba14a52682ca29f061d1ac7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/38cd33bb390445e35b6514024b1317902cb7ba1b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3a90c688f44447a78efc111872b061a001f04d2b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3b1e7b56ad4465d126ea994d34d20dcecbb3a50a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3c0a8d6c31edaca124714624eb64cb8ec0cbab13"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3cc0c9adcf3882f01409c70391c3cd30588ef34c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3d0d9878b812ce4634962ba3dd755c0953550200"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3d4d5887a2fcdc5dd360b8a6f89dbce6500d8580"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/3efb5b7ff94c5b9d411c93da9a70e1cc547f4c59"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/421b7e8ea86e3c07474af16ab3ccef55d1857205"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/428d051e437dd260f2a2f7ed920d9734ca34dc90"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/42adc281578ffb1b8684b78b47aa40a16d10b6e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/43620ecd2e2fd58fe5650da2e9783f980f29ec07"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/43b1ffcda49477adb1632822202631990ed3a269"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/45279f85bf2f533a629073caf89403006279fab2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/455d9bb597f08bf698454157ecd86647b5dec4e0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4561eb5c7e43cae048c06aaaad3d5f5218b376e9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/46417b001eeb87c32b642499fd5e1690d5d88c7f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/468af040024e96e9878ef33cc52755c5e7f5cbd5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/469e5ed2547e9e55a96e96eb832c615631e3b576"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/472b07b9fcf2c2451e8781e944bf5f77cd8457c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/486da8aff04083c5e0fe112e733f2ae510e312a1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/488a5ed641e340ae51992e04ce6590bdec587218"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4a0a19218e082a343a1b17e5333409af9d98f0f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4a6644a1a3d5218f4bbd60220cab79c0b7bef45e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4b39d4b8a9a04b9469e8fe4016322327fe540882"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4bb0294e14946fb1f64213384097a676d3ef94f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4cd66dfabbd964f8c6c4414b07cdb45dae692e19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4d134bc072212ace2df385dae143139da74ec0ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4efa35221b2088e785048d0ff8fd99b03d5316fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4fa2a4a5a2f7dc4ddbdecae3ee85c787817b4cf8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4fed4bf2dc6259d9de54e9fa7db4fd5a61f2535e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4ff800de0863adb5851fa26935159aa53b11cba7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/4ff99a030518a132748c44bc1d836018e5b82cd0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/531c87b9772e54e3e183ef729f0a7d5a0d584f46"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/534d66e7b0709d1e7692faae9e7f7299c92bba4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/548775f9d7d13339dba3001f8238b84e9a457533"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/54ec3b2d8a9b7a6d8204712eb1b90da703cf8a79"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/552cfe1d8958e6d003ec8e883c4983dd67ef255e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/55f0c61d096a08506076489ded3b868db4086770"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/56cd60743c2cee939f5f357905bd36ec9363f441"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/56e5f35e3d08b4e17e3558cacddf9e5ed13a0159"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/580b03c49fba02bb8e399500eb66f2ff0482b22a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5852643fbbcf92b0181327b69b4874c6ba6fa9f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/58f497e5efaf9f69080f9eef63b0b9dabcfdbc0d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/59129aacfb6cebbe2c52f30ef3424209f7252e82"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/598a287a3e56caae23ed63abc95d5f3457165eef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5a37a26dd2482226f534f79d321d28e7a615ab72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5a710dcd4c78ca1a74ceb9fbfb011f7ac86a5f7b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5ae7b87f5377d5ffc16fd3f69b4a4aa7be8b1184"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5b3fe86d5a309a6ba745881bd220fe1100b271ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5c38b7da113ab4535dbc22777ce8a1480c1c9d1e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5ca6c45a8d2e11c782806df43e7668beb4aba8f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5da7b543313339f84fd52e96bacf3a73368a1d2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5e12ae9117668bcc22832640cc626315940aeba8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5e397439a2680ed827c46704969c6711dabbda84"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5e629dfb8b7533c7c2d173d4c3d587c88112cc29"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5e785c7c26813577f3e30ef8f7e37ab2a9ffe39c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5f3394f5058822cc044b92654837625897176480"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/5fb9bcbbb30a377209eab0541d144e44e71508d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6008213a61d06b4382b223768530c3452968b7b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/60ba4b2daa4ed4d070fec06687e249e0e6f9ee45"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/625ed64c30c8ab2f0b3bc75690f9faa4270f0041"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6314c2b304d04dc0108a95d29a93515e85e2b0b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6462d8079d2ea921617e7d073b85cfab706800d3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6474383282788e556aa86f57fc8650137ad264d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/648c3f58ecc8fb4b8c779e6b11006ab5b1986dad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/66328e03a2ccd5e54dab23b816182786e6f518b6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/683e9045bc95e0cb5fc16ec64b118433475ba559"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/689f13680f4682303c8aa6828b67955959dc9669"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/68c6ba7f0602a5410d1fa3c5de24fe264436b993"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/699cafde80b1e1777306f781186d1253f018ab23"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/69ab053b59e235fd6af246c5180f15bd95295113"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/69afa12510b2e653b0af7c7030832647b2d63c37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6b75857f86be5c51b21a97f4a61e69e8bb6cd698"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6c75e71ecde9f073a7bad89f4831c8cde0bc1830"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6ce5170dc4f2eee3b31a875b6a41f2444959f3dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6d2859436fbbee637f0a5981ca82e8f88a1d0d28"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6d63e39f56d1d537bab9c2830303cabab3cd9035"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6e05a0a240fe2974e14527bbe390d294564156e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6e6c9d301adb0f0ddffd79cdf3426a2de99bad48"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/6e989edf725ec64849377681ce02641c3d1870e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/70142f66475ae2fb33722d8d4750f386ecfefe7b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/719edbe667ce2729ac78a22dac29263c91144029"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/71f99ca2bda6ef2e15b965479a79587f9d794be0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/743e89b768af4bd591ea7228118550b1bfb8e7d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7714a1a32872442a2eaff472685f3ea69451a732"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7719a1c782a1ba91c031a682a0a2f8658209adbf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/775e8ffda1f5d340dba472d06dc7c8bf8159e379"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/77de68daecd823babbb58edb1c8e14d7106e83bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7957dc9aac31e6a6783fb3a6ee073688fed6cf9d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7ae893cbbf9b11ff411640b80985ce618907559c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7b20ac50954063e3ad00813acab4a98b2bfdb858"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7b6273145fb090de1c6163586f884a1da4b5cfbf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7cf84b5a78281e6c6b5a9884110f3dbc6a40e310"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/7ef13b83e6bde582d9000be043e729cd3221c150"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/82059e250904b478f65daa0e647c1647ba6d6a3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8207fdf4bd302d6b6b1894990b353944a8716aa7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/831a49ad81b59025c241ac9e58bd88463fd798eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/84582c1dbe026475319df14c19967d1dd0bf751f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/860d4ad0b7c026d1fcf51932b5e46500be7860a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/865c7cf36a4f4499a6242e51b77b58b868a7447b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/87a2b80f9272583517c0207af176fc40ea55022c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/887309d048beef83ad3eabf2a79a64a389ab1c9f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/88d89860ccaf21e5f0f002303a2cd853ecbb2acb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/88f658400b1870ddf081fb03020c3098b0b1e083"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/88f8b0984bb2f081918ad883c8f0ffacb5a8ff0a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/89304953495f060c7abd3584d83cb1c8e6d6653b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8a5f6dc6873e3fd51fd866854d85258f8aa83a02"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8a87261277c15667e2957dd52c5db6757ebc8e88"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8aa61d8bd260942521bb1ba82cd4cce2324fdbee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8d8874439569824e371a0284460440175cdb8a27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8d952ec2e33b2a6a1c7876898719a610f5546388"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8e6fec8a05b24f221b6e94fdfe205e5bf7709a2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8e7fda77644ff91578d25243fad51a3cd6d60860"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8ea6295ff82bb119acd44a91b463b19fedafb226"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8ee51caaa2c2f4ee2e5b4b7ef5a89db7df1068d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8ef4dd9f2d0f9d770c937d9a43413d24df83f09b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8efd86fb78a56a5145ed7739dcb00c78581c5375"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8f0ba762c2fed0fc993feb91948902ac397b0919"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/8fe81e450694cac1eb4c4a5c966ffbc56ade3513"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/902ba3cda1883801594b6e1b452790cc53948fda"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/910a1528b28ebc6ff2f2a4fedb013c86de4103e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/92049bf3d8a0ec93c2d1633631c0082e66ca69e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/920a3c318f3127b9c30ab02a077555c7dfbb6edb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/925fc05dd661aeb4a776dcbc5df3dcb2cefaf0a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9367ba65affd5bf7aabf79c28e783cc5d93518e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/939f5049b1eefb91ccbd3fcecaed8cb21ea6b285"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9405c2b00eaa5526f71cc78914dbd3ecaf093b6e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/94d3598751569d2a5be258e59665cbbf0692dfbe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/94f96d95d01e98fd2f04ce26c0913e5f9a882fb4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/95b54a84db75abab401d282fdb04440a879a9708"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/96189202e587ec951d5795da3e03062f2fb5d708"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9711703428704ce2827a719eddb9d54be23a0cb7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9734597e96eebe99b2243121a51d178a338ec46f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9747c85a9510011bf87c23a80b029b9f2d04c37d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/97d170e1550eee4afc0af065b78cda302a97674c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/98e02e7fc96479e8d10ff2cc7610be772e2d6fba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/996156b191b619eff79b2fcbb7598518a09b06bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/99667fcfa6d583a742fb5450527fc86dfb78ebbf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9b1ead2dbeeb1a3e9a7bebcf6964c3cfbc7e8867"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9b7669e201574bfb979d56110539a90da5aca2c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9c24b456af3cb51a1ff2780c2d9cbdd7d93f6c76"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9d0441f23ae7d5a3a5b1140497868ee6eeab656b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9d890bd3139a8f9a44d435ff8edfbeb5b072ded0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9e6a55b6b4563e652a23be9d623ca5055c356940"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9ec88420ef0408642f6930996e35f5b9f18ec88c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9edd067c569315d5e93b0d14c7eac9fa6d81d3cd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9fbda4f714043d975389b536b4497c6d713452e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/9fc8cb8ab3b05e306e5e81d9d949e69f931244ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a02b857f2eff73e8e188f35529dd91f8144b23b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a060d5bfd1235cbbe4bcecf332fa3b03bc2282e3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a0931fae1d43e7887c1cabde83fdfc52eaeedba8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a0d4af29c6c223b48fe34d6a09b3a7466242f33c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a1abe8a785030d475a7350438fd23a05c382c110"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a1fb86293eac950c2b4f5182d9e4b5d9e0982ef6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a2d4e3d6f5ba43c9199d5d2011678f82cfd55afc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a39653cb3d97c58c44013197f4d7557577700177"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a4c74ad56ae0e94e96101a8f2ce9b1e588df5e44"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a6b34b06b00e9226f2bd961483f9da81d8de99a8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a72c3b9cc71eb7f0e0e4dabcd2dcd2b997f21c07"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a749d24bac55bc19465acc92b12244c56ca0f20d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a78009ff8b3f4d722ee0eb84795e857e74a58aea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a7ae4b16677806d78d0016c276b6722eba8eef3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a806f43dd48e35e75c27814c13a2a96c12449bd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a90a858013f90d2a94e0d62a7156ffd6848bf238"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a94bfbfe16d026b52d7f73cf78fdf7d6a6c5c58b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/a9718f029d11a9335ef596cbd42794de5b0b18b5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/aa6e08a488d1ed00aa51f20c2477fc89e7b0a852"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/aaa038513c192fec501e4e7302156872ce2fde37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ac2686c095a5a1c92a1d4209a6c287778720c86d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ac9231da4082430afe8f4d40127814c613648d8e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/aff25e569bd8c93157e08cd18ebcd896438e34c9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/affced8168ec801de89deac663f708f0c96cf1a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b015dfc2f62b640d7c25adab7b38c5fcb5cb64c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b021dd7cd98b63092685ea092df0dc01c8f63334"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b17485b8bdec8809b3819a83753ca893871df403"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b32ef51eca9c6c658e6fb75fdf96bbba066404e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b3f0c7f6bb763af1be91d9e74eabfeb199dc1f1f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b45a1635ec526bcc890f9d735976704e516c5f19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b50ce51a7baa28cd298ebd05b4a3b9b70f9d4370"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b5126721812b925426b30d283d2bb8b6969f230a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b57af943a3ee411bffeaa3872eec9c6fb01569a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b5abf6fd22ed0f852781de35d043059d0f86f3cd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b6f19238d2b04c5b86a17369093dafda34f332e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b858cb282617fb0956d960215c8e84d1ccf909c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/b9c38fad09c80db7781fefbe51039752de575ecc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/bb407c8992800444201dccfe744dac49c0295fde"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/bc335734f73502b92d2bd3587259ce915985f0ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/bd113c2c8a2328e3674c680c7cff829a6c8ab924"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/be051d58015d4af1977a5dfd14ef3fd070ecc9d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/be461a0cd1fda052a69c3fd94f8cf5f6f86afa34"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/bef524502f8dbbc45af717ece01ec88edd7f903b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c0b6a90832b78ed5f6d129d3640c612540527c85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c18d315f0d35849b2aae4a47cab4608204b85d76"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c257fd6bc9e5254a733378ab4ddd39629c4a3069"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c2bf7f49d8f2e13a60af4473b3b3451b65b3aa9a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c308517acf6f7088634d491a1608240f83a3ac95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c3badd71ef8a51b97ce93cbfe99f6778048f2128"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c482a632702ae7f532d126e70149dda4fadc3cd7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c541bb86e55b98e083b141114066f9c17d853374"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c5b50b9015b6aaedd7eb1077b1204858f837b53c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c62ef0dbd1350da9ea5a32e56672d385837643e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c7a34d6d49e1da1ccd490350c2df3a168ed09ae8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c88c4bec8d440c56d3ea7abce39276f0927dbe0a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c92f147bfc034003ac42ed9e62a16c84102ab417"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/c96b0fe6034668edf37ef0f5f391d5107953dc06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cac74aa5d7aab7fce0253f00c1a025980c1f9b7a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/caea0a0e6d8708cf682eaa446c344da56a7d5515"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cc8a3dd2678d4b400ad630f402012b894e841b05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cd851bec7adad52f79777fb9347d5fd2f9486aa7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ce3899b62ba3efe00eb31ddad2861ffe16a30d06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ce8b76fdcdbf1c951afc2b115be9acc8a6358b32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cec87b67871fc7a59652bc3546fbbb68e4d31e28"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cf32406111908544e504c84731147f072cdf2fbd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cf35dc76bf9a2052636c1ecc92942161830dcdc3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cf6a5e6bfe4f15b43e411dd2782e10f1670c9767"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cfc45616f5f0e7c25df91f6984ff5f6f1648beab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cff891e5858ae68d08ecc8470ca6a68c9438bfa3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/cfff4e9d08cba81b663dd1999710008342851e19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/crash-f21867fe8b6df0b54c13e2e6e613dce871ecf0f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/d1db03c626fb16c3b9cd44cc38cf40ebd355a194"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/d85ca051da784c0441898c5affbf11a2ae8f56bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/da03f536ceaf609972aa2a699687cc6f73ac0dcd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/da4b9237bacccdf19c0760cab7aec4a8359010b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/dcc45e405208d7a2db33d0b5b9da2a2f1b034957"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/dcc60d3aaa1fc4d00201a3512284fcb79b5b68ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/dd0567ae57bf3cc85891a1ca988c2945d9186678"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/dd890a5a32e9f0489c6c77695f2155041f00fc9a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/df88e2baf7b76ffb2e94b9da57fd8d137f44b1ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e00ee378c3f6e0b3cd89bd6e7517478d093f73dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e0c124e90d068e2a70a3e148052869033453ec58"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e0d87b1f3e54e5adc5c2205f9e14772822a25766"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e1199df649697c570db5d6b2ea09d755eddd32b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e235f6f2a8b6a22117f1baa932fb6c69799e1136"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e3a654055a867ae62d8e68fa2c410228ac55cb6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e3c680aac46b9c46392e3b2c43ecdcc1547f2023"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e3d134b35cc25a4861d90023c95988ec6103ddd5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e3ff65de4b1622315c3b34b7a5e39bffb275489d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e4a4085cc31476f5de9047422851d8ccf86339df"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e4e3c69da200af932c8a79fa055d7aeea28eb1d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e6c3dd630428fd54834172b8fd2735fed9416da4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e71eb37fca2070521e1e07c503c2bcd6445b35ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e760e6e22ae8cd1ea78fe28b5eb1f3d7b5fdc536"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e95ff1142118a2ca5b84935612a8a64d55360e64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/e9c5e2c67930513941753c2d54591c7098c82f6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/eb26070d17ffa908204912e75cb4313835042038"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ebc6aee49e5ae57722df86e7fa33c420f045a449"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ed1dc11d713e7487de18ce8317b62916959206d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ede3f66106acd7796da8b3942d029fe213058286"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/eed7bd220cd511b6d42ce6553019266a22a3d56a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f090932162756b798b1a050b05e3d36a3437c4fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f1905eaa84ba6a3593ec6ac0486a5b42893c01f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f4635fbbf765ead81a261ca152df02622e182d2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f46eeb1020c7c4153e742a50bc24c2c6939dab1e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f473451610783521d51bc08cdd920ddd97f8a71f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f63aa599600f6e7d648c4287905e16e8e6e479fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f667dcf1c06e87db2dc49d86ea1c285e796f8f8c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f8d0f85975e49b959799cc52847110cc940b9db1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f92c47e35da42d79a48beff54b93cd28f55f05fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/f9a33bb8bd78d869fbafa402d9be58940ce2c318"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/fbf6f3156c1bd4bb701839bc0e26533bdccd1c9a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/fe2ef495a1152561572949784c16bf23abb28057"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/ff8fb34603c7f772768d61504954553e6bed173c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test1.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test2.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test3.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test4.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test5.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test6.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test7.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test8.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/json/corpus/test9.json"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "json_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/0052f8fb6a7884ced8a6754aa13441be1f7dcd51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/0c35544f40d428d103e9c5b969ad9cd16767b110"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/0c60ee9ed55c9af6190b132ef6636c1d2abe4540"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/0ecb3e69889c036a86d21eb942077dc9abd649be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/1324c95dafe597fe05f9babe92fe6fbf181c1897"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/14eb42f7423081b455820daa2c02b358315dc0fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/23121c5f633db5d7c1a9f2225240754246fee513"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/235548307ee9f2b0855fded42a871990d9ade956"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/28ed3a797da3c48c309a4ef792147f3c56cfec40"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/2bf123dbfa1d37a04493b5662a4b3b9c147485fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/2d4c0908ecc0310ea234d10b6bdb4f4ca3c41dd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/304e8cdc9122b709ec2c063a5c8c38489a788033"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/324d4a2aed8bc1840fee212fd38dadec80a72ea2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/33353a0b011901a13d010c6b165074ccdaa717ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/37dfead09389fcd9b9d24ef817a0fed13d8ff2b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/47879cc364be304754f6af15563ad6f9a538da41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/49a5cef4c730ecab22712b156ddba5106f165afd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/4bbbbb794a098deeacff73b774c30f12c54ceacb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/4c498ce69c8476f745693deb23272930e05cad60"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/4fb5e3085c32e9bccac9e18343cca07017d037de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/4fe5e46c1299e7f3e8a41dde3ae1bf1b60b4a43c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/670cc6bae958cb4f15e7297fe63959ac5799aa42"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/675f3263af7d1bbb084872f2b23f6d363227e85d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/67fe0d2acc727c8a39a707b92c6cebda9bd20986"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/6995dd153f712ad257ab5a365e5a4b84dc676ed3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/6d15065785eb8f4b5f17357a520cb4815a2cb355"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/73285d7a70d73b517648067520d921e4477dbbfa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/747d1ed8bee4c6f0438beaf88ae76d8ef9f63da2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/763878a34b3adeb99a03b54d09768a4451617016"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/7b4b0c2555178333ba15203a930c88ef7e7500e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/7b8a91aa46e370eb61307b4998889dc89775462f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/7cd11836c64f98742fa7beccec5c981ef4dd62ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/7d8f4f045e70e8a2cb45dc3c001504f5c2614b16"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/7e9848558fb004e14795b3ebd3e1488dcde1db8c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/89734c37ee267e69a6950c6d60ee541c1be5ccff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/9034aaf45143996a2b14465c352ab0c6fa26b221"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/91e3b6a3484ab4b95cdeecc5aefe1291824060e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/95cd94c858e5e97f7df4a5eb7552e5e0d5ce1ec4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/971f42d5a4d9816145ebc9dd28ba33ed3f5860b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/9db3a1854de87fd643b910aeab50553afc73e667"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/a147873135c6c52d4da03c260a0165bc0ab1b979"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/a710eead945dabbbffa213a980c75f9463a27398"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/a72406e3ca06d941fe8e168bbf67da88a81c947b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/a8a62a7ebb7d68b211ae319e082575935c07d188"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/a8abd012eb59b862bf9bc1ea443d2f35a1a2e222"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/aab56035a3533b5d83a32a439f179eb678250113"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/ac174acef2c5da26fadc7270bab9c8c4e938c463"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/acbbd60eeb76e41ce254d0fef353b92abe69c831"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/c1eed32e1e353737987da851ad760312ea8e557c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/c4214ace2c4bab24bb356f71aedca08544baad70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/c4f87a6290aee1acfc1f26083974ce94621fca64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/d285d78d3ba966b4b199453d38ead1aa36a7484f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/df5200f371cff3cae0e1595cd86d641725f5d1ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/dfc66cb172919102f3ba14f6816228aa46f78154"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/e53e789a4c175c6a2c468472f1047d0fe8db1177"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/e67fe6794e755ea801272980f2c272edb027f6dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/ead61e86fedf118df8e44ed70ce002be651cf291"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/eced8b29efbdc82eb8a1d0865c5f382f0ff78446"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/f107c60f00da44a2c412c5b89c733efe5f9be4aa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/f58a9135d07ea9a5e3e710f6b3bf6d48d5942dfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/f8c2c4ddd2f474b4839f13a9be862c00ab0ece77"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/faa1781e1444bba5b8c677bc5e2a38d023a1ec65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_response/fccda587af845f0685275960649d8f4a45272a95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_response_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/000def12957806bb0d40005cb651d35b4cde7b4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0068af2acc3020f344ee84b2c8adfb90492354c3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/009132022c3a1660b701728ac92e26baf82e8eac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/00bf0233aa1155b34a3081e4a2b7a1c9cdf8ea1e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/013197cfb12b59755b807501c6d6615859f9cd3f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/018a4332eb19f2398162317cb6ad2e8cf700dfd6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0273d3496bf5f4594e59083ac319f8f863a15be0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0355002521e74dcdb3a0c633338bd02ab1d85312"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/053d8d6ceeba9453c97d0ee5374db863e6f77ad4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0628c29e3ae264f8fa08652435bb3e61afe60883"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/065e91578e5359b70a668164310af6f0dd40e922"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/06b4b617d5937da8a7b58aed5341dc5ef6d1bcd7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/07216a4f5934890b89d845f6256546c2681350ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/08584e8308b7f52f0fe380358800d7f585cba89c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/085a37568e99ec5855bd96affd259921515479e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0903d1e9297179c18de6a3707b16f27d0d54ed67"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0aa20a75bff4e8af10330c66d288e900146f1a39"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0ae76e2b24ca999bd5e09e517aa4d88f5b5f58a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0c3025fdfb008a6563ea2a2bb6cbc79b8ccbf8f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0d219165cd317142afa36b8b5476cc022c95c4e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0e053123dd6256de5aff55b0731f913de250c18e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0e065f98325849ac05eed515865b33dba0264cd4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0e4ff715d491c9f0b471c400b71804739b6d400a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0ec94942046cd7e00bc058204c1d046075ca9531"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0f0e8da530eb8c924cee6985d9c3dfd93274ef8c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/0ff365225c981d74b89499d1e708684ed4d0b570"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/113b1efff1677c1b9a24f89aec0c3ecc228ddf62"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/11697d621eab6743ba22715722d5b23830b79075"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/12463318b795c756f389bc0fb1cca9645eafef28"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/12784250cf16ec999529f601ae5c5798e853d34a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/13122d08c1cee0dae6434605917d4cc6d8ea8cc5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/148a1118649dd8aa9b4ed778efdf7c1611aa5d27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/15dea2bb5fb36a3dd5172796da66a821a32918e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/16488fe15a7e33cb41f2b7c159c99154464b3fd3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1870a48a3c9c1dd9027cbd85beb503b43cff6e89"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1900b6a9123667a79020319aa7fd54d230bc7073"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1a000f1cbccd2ab6f7e623e015ed2e84284c9dbf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1c1d403f6175d52ac4430d1ef2401b549761707e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1c2ae0e1915e18dffc2215e9121f1afe0e4335c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1c5d2eef52426db9d0842f3d57b27a219434c512"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1d0676867c1ebce84531035fa7eb86ed00762df5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1d92b263fa70450b0d0aeb81bf5d2f69eefbbd99"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1e843ed4864d6a808b671dd6769ae191ac8a13ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/1eb06a34ee568d584c4b33472788889bc68af3f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/2169c2b4d560d74a5487df68b56f3af1d648f544"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/21f8f7583e58c1c81a3ac8237b5fa58071edf8a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/231e348407fdcb14412c691b0b20982940160ccd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/27b8f060e3296eaef77dcdd4c2cd11d5650604ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/28ed3a797da3c48c309a4ef792147f3c56cfec40"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/291fcc6e043942638fa3c865c0a1be5e4dcc0e70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/2a7f6c1f8fdc090b24ceb90ab4f3a7b331c06c86"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/2b85f180fe56f84925b274819ce10a8972a594e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/2dea73d7d10ba0dcfd103f7542bdf7458e772b2b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/2e9c19f98ef88b83ec2dea8b1b7f92b8337f757b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/2fbd59ffb74aba392b86f4fe2ff8067b6d45cce8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/31059c32ea28d37b7442f51b20e966665662783c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/31f78e35feb36037864df5f8f47136f8e6e4768a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/326d322d1aa31696a14518830e544770f12146ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/337df26552e0884ff133cc1be8e72020be38f457"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/33a2a0aa86956097e034b5ee16aeceacee7efc34"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/33d175d1ecb3a85be7dd93d24efc3ddda0a85ad6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/3718a1b790db16bcfc4ec30691fab24ea7bb0b74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/37aa3946054035b712102a62b71c94747dfd1491"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/37b697adc0708ad12e4ed7355f3f8fdf1b7919ca"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/37bf4642c5e5a806e2042cdf5ead9bf3c97b9ac1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/37d94ca6a20303389b35404f3dfd20aaa9ff0851"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/39278604f6a1102366464bbe769ae846e542bc56"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/396b57d9a11a1b135e36ad266e155cc0c3b77d21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/39a49db120a807fe4e80c502254a5009625c7599"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/39f04d1c6d4beefa3e3d6eae3a5317d969787055"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/3b199b80209fa0b8ffedba4381019f8729cc09d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/3ccf7ffb96c3e4789409db33cc12bfd8ddc24c1a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/3d04382d1fe11ff3b717100aece7f9eff2d04b9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/3d4eb9f836bb40cf4c734073bcba8b73e4cc93ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/41dc8c55e41d32c30865f9761931ddd4c5b740f8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/41ef7b74d212f8f7f6681edcffd0db719030d31d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/431187b5926fa7d0823305a9f87635616ea3ef27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/44c6da04b8378986721f7225e70a1514695c176c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/450161236e37a1dfc0da6398c4876df82ff640ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/45257a176ca6a05ec65a6df430bbb6b85d0a676f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/46d1c2f2edcc9cdc0d1698fa0c8853cb19a6e7d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/4764bd4297bf0c405348d2bb87b8fbc02beadcb8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/48199bfd0e2c160f56d03e881bb5dfe276eec462"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/48e865c56e8db13640d6ecbfc0f2486eb77e07d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/499b003b8b98edd9dbe2668c8c6af948769d7e87"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/4a55591c4b390c5a36cecc6f1b6f5105300b546b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/4d33f97ec69c64e14dcf205be36a6319ddb8a20d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/4dbfb08904739928e19c2f459040b35ac410f699"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/501bd6fe1de2719cf8d2c517a071e5d883fbe766"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5208871ea8948223b64b304336cea41ac3240244"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5348c71be34967458403bd4b58bb2a8a744d35ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/54362c2f6965268d0835a992c3ba656171b8f044"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/54411aa13f6d9118028171935322bbbc74c15329"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/54c50af22d147f192918499b4b3819eb389468a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/55441aac903d96b36bf8a11bc804234bcf0c04da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/56e1a7c279482a57fcbca43468df96a791ee22b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/57cbea7c563d5c4b6b290271b0009c3f348d92da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/57e11c7a62f0fc807d7b51bb1ef0f0e22f43795b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/585183c1a240df6926689fe1bd8cb434664db4d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5b2ee8ca40508bf108a729dcb228191670ec34d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5b47eabaf74479348fd0318f174d649dbe96e7d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5ba93c9db0cff93f52b521d7420e43f6eda2784f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5cc827e33932ccf8c72c6a839074e856d93463d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5cc89bbf687f94ff87241a8f935905e1c441de33"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5ec6596f12462fe9f36924c262f97408b54bbba8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5f8f3af69295223fb04c37d28035bb75b4cbd705"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/5fd76d48b9fefecbdabd4511decc161b25db79dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/614cf839ccac2d896d61a0ba0ab1f42b2fabafea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/618305cc2d3d3814d78b77ffbf421b769bd862cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/61dfcd913c4f0a8d005bd089c34e95d8dbbf1897"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/65a89e10aab00039680e1f7d014737b634c74d8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/66a273dbf5e37410efd45518a42b06a65cffe1f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/673ff0de0702e8098892060a5365c175d8ef18fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/68465c782c37bfdd98ac493b0458444bb94336e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/688451dee13d0be420598c6e205a3bc419173e18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/68a1d9150e1380c219e0a1deb3993f321e000ecd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/69f49bf7ae8886f5b4c6296fdb1c570256919604"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/6a425f414cd69ffffdbaa34d03eb43841b432e11"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/6ca9e6e85f9b007a0920b0112decbd1403d506da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/6cd62e3d67b4154639adbe753115bfdd770edddb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/6d4f2de4cc427417d6335ff5396ea2588509bb5b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/6ea84030dd0b5b03e4720c244ea8b4ec65e1f236"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/710c1fc8cf7dc1386312c34de5057933fcf868b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/720e81dcaf83f867288a90293c5de3b088d5c556"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/72cdc8f78ab5237f96ed354264c726ac79ec429c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/73535a4f7af7e4c6aa23556cacd63f6929ac33fe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/73d7b933a5673a4d6f5905006ef6266dda1e4fba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/753aea13c82d1f8841c2bd4309b1b55d0ae2ba8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/754428e00e8a1d0471e00bd9e8f060ab88ab640e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/761c29151b23b4d14ce6261626641df1182f7a96"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7658451dd805f277a5b1c3d4065d752d2d8de5f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/767e91cedcd9bc1bdac882acc34a53cc23cf4d02"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/77d3754bdd4ea358369c936ed36b974b4181f6ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7a95295bebe6237f65deb15ffeccab22716d574d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7ad88b82e87fbfb3d4bddaa2f6e201a151e3a007"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7b1010cc012e34af1d03e8845868ff0e1db3a601"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7d3ddbd11e82807321c9a53835ea897cf43aa7f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7da9c5ab5f049da297b0f4c1322edd696202d02a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7e265a019c02e5d089152849ac00bb005fa644f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/7f33bff4f740eb898b908374b0c1badd47566947"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/81f13b9b65891f2bfce77cb183a06045c461fee6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/846a14a480ffa1ad0f6333f3ecf2be3057ce6aed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/87373a7f89feba2d50591b433f69877044155af2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/8833ba4c780c94fc6c3c466f849c0387acefdb20"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/8c23a5ecd20db4da2c061f3463254e9de104c8b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/8d883f1577ca8c334b7c6d75ccb71209d71ced13"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/8dc80bd5f5d1fea64412203e304432edcf5f52c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/8fc9a9ea6ad7d6d51e770076eaddacad9f970c6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/8fd167de17534776ef57aba2f27675789a11b8db"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/9117d3e51560813b3ce4615dced18fa0e4d0a25a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/921c68eaa8776f7544e195ae52224355d08a2d4d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/9293945411fca2dc81fc34b36b575a384e6d489e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/933287d66c3ff3f0a21f2c583c763f2f65872ef8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/933d1d91283403f0a56571f533f482e9744eb735"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/93855fc41b3e3004ca6ba85f34b985042d4c9869"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/9544f445c39470f05785b52cfc31bb73bda22659"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/97757217fde05ff4fc15c864bf29e9f560fd1c62"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/9877c0f2d40dd43878bb0209bbc4b5fa93bec55a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/98bc5065f79dd9d20cdac14ba28f0cf39908cb5f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/992860817f7fb0e49423607355dab973aa7ab815"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/995ee3d74bc6042fd6a8908c9df5a4cb530378d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/9a38c24a6e87e99a72a3a4f007b117ec191a1705"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/9aa97a0ffcdc37a8ef487355fb7271eb6891deaa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/9b9fddc17ed7bc05a81c18f01e800a4e9efd0c8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a0d4cb9a5a30bb01e8e4f68d636fb173632ed29d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a1e070288ec564d10a8c59779aa07fa771fa1d4f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a23d10723415d20f4ef1ed9b14d9dc24494856a0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a245750cfe4212dca7bfde918de85f64eb053232"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a24bbe3600f4dfd61bb8415c6a291e0521e4f267"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a25104d039a549c8d457ecea3b55369ed312f086"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a33c4fcabe6aebe012cd01c8cb851a9ab0a12098"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a393e1727b0decca9f193179765c3a83d7096437"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a5507f06be4735a3a9e416ea986d52c1a6a20909"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a5adf028c902d17dd6a7ddeadabbed2b36420313"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a6aa1237a282ee3a93f2544bb6bb7704e565209e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a871185cabce7b96c9e2f6ffb40d9901c774b335"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a89d0e67bf53e22533a635f103d1fd400969ad56"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/a8d1b4e5672a501d7a6cd14b2929297f3a82e035"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/aa614cc8d05a3a58c30a890c10b9a0c1d609b228"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/aa65320376f63805cc82b247612b2e05b87bdbee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/abd3f6e2cc8887942de20e1c257427b825aed0ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ad0653a3a63675a7ce797e69b4673866b88ace33"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ae2ce27806f67312e0d0e29a492db9ab9cb9bf4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ae4c0e671bd004165a1e7877d9c67249a165d2df"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/af75c24dff7e22948ed141c763a1309e6f540bcc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b0f228c6d0cbbc9f10117f344d5aae6f001d00fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b2c6eab05580b85cda591093d3f05c44bf453fce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b35281c0aae174d1ddc8999d97b9713f8004f285"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b484ae40795cf9730ba94d5a4ca40aa47b88eacb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b49c2fed1417a981ba29b32be73ee1700bea7ec9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b68542373c05c0ed25231d09955b2c699d37c45b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b6d42cbe913f7275b574a71f0768781bdb6f45b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b80b6c2cae83c2097c7e4c1fb181d47cb8fd0519"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/b90ab62d8591182fd90cd21cdb893178d97f7e0e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ba45c93ee6b8b286798d8791ec049207c448f7cd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ba67e81ef0f9a14bf5a1ca228bff87c681e83a44"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/bbd1f06ddee4fbbd0e5c9c915889862e5df34f9c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/bd982feb5dd4362e6bd9746ed216c25ce2749df4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/be77053335e6496288fcf8b6c4d0b4abf86493ff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/bfb53203499969fac4f4be48e1bcd9235c2fa101"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c143576bdb5b34ad89fa3319507ae382a721f587"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c1ac502a15c53a90a1934f4a31d30f93db36dc8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c1b29883768551fa5aadc38ba6eaad8007b9b85b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c2331fe0660ab5e411f6d38968c706aed390d8f6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c32647119c244cc018bb1863853d5c7bd37090df"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c4098733900c27861bbf74a71afcbbd93d62f8ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c4f5769bf3b4f2a55c006b4cf5a3bba44b347241"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c6ea7b2d47402a458d5d03235bb042b61e05b2e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c7255dc48b42d44f6c0676d6009051b7e1aa885b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c7d77af55176ae0ae5e59f46e48e1e6ea108d799"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c80827341dcdf1c21b303b82ec7e6df7eaf63f3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c9501031a75c067b6602e2831f03421b87be4496"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/c98f88d962dfbc2a83e08bfbd8a87b0cc5a8b330"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ccd33fa22b2983978f9617b3cde76ea05b683c2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/cd0e7701fd79879c56f680817a0d2705751b1f44"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/cd1c2b5c2684d831aab5265e9cd6f1ee045dab9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/cf98e8b01e7a759f28a9c5f59c896317d74ac47c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d1d171589e035be85dc347278f0735151a342d68"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d243143bf9b8adf6be92a157428ec6cbfd785423"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d2cd278979f2842ebd890f1d84712750273ad0fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d2e96eb2699c7dd4a183f13d3a063a1aa9c192fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d3178f8b0d26275667c27bb8533a61643213e4d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d46f536ea4b601c0ff313a5eb5b47e2b55aa9eb0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d4be3038631eac422022ee23f43b47905a15b2b5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d56b30a2d1b5a2a13ae00392bcb4ca72085310d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d67f85948143218d11e2fb7936a119741036045d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d6930ea81dfd91856a06a0c16483e47616642b4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d737c10038a92add90e2ebea5c174ed249de8018"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/d758a67f018b176dfc7d29630cf8cb587f5b2a6b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/dc7139105787f3ba67d7971d80796e9cf5786a91"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/dc8ec35f43e994b9c4ac61275d6b934990d42181"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/dd2694fe12a018bc6af6f288b5c22a030eec8049"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/de7424f44508582a953f137195533b7a0191eda7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/de91a02040d792dfcb71a4cb5aa4c1c006201273"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/deb576067b11f6e2a3a39b0f2ef38ddae5c67b18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/df58248c414f342c81e056b40bee12d17a08bf61"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e076020b2826abd3a4b960fb33a35fd7d0606dd8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e0bcf682342967c002621acd2563a2157826d156"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e1edca08a7654b42a64647abb0e773eddddb580b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e2fa528289b5971f5b40b3687a2a6f0d17348de6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e52af0ba8750572b98f3a8968de77811ddff0893"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e5a0f40647f805b5001645ce2d94505e72fa64f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e69762f0c6a2750c0b03503a6aec90ffc94bcb72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e7064f0b80f61dbc65915311032d27baa569ae2a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e863a4420854c36168d2b8dd39ce474ebe11cd26"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e8993f97bb9c83f87c64cfc429095eeaccf32953"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e9875d9a54b3ebc57df4da886cd30a39252ac666"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/e98a9d92bbbac9b1e64c0641e967adebd681b2aa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/eb7c31f48c77b742fa29126ac78a2c06c41208e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ec174492517f988010ed3ddbd003cb388f477bb6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ec4d6a393be7ec80ccb8c531337a7fc3ef140e66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ecd40909ab5e2c61841d9fb95b8aacc87651100c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ed17c8ddb6cc8a0b653dc87aca999d31e80c781a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ee0b476126bb1c2249b299323718ecef1250645e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ee1fb6a0b4139c07f1cf6bce850eaac9a2db29ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/eeac145c017ed35305f0ae69f820fc41e26e7997"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/efac7390c6e3a653d3ce93c3d6902f2f1c281ce0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f0f0dace93d51cd8e045aeacca89424fc836eebc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f3341b8cc55c0bb6e2d0a1f7f06d68e4f04057f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f59ff56e341b94f2bddfd718b48ae9ab1692d720"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f5a1824b9fd9f124df8097017607bcfa00eccfce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f5b92b69853a5d123bffdc6b0ab093f767ec30ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f6aea4c380e41ddef2489ee581ab35e17fa3e8dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f7b7254a3af7c41cb86e4b23bb93c5a6d55e2583"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f7bdc1b174f53a49c6ef8f8cdb9b8e74e0a5d4ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/f98c78c028baf22f39c77faf6e70edb86ac1d927"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/fb440171bca6ff922727e9ff2a4ac40d8d7905ff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/fc76cc4030b422e4cb5c145c3e8ed122e242acf0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/fcab3b80624b431e464dc12d3b6da1cf538bd15e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/fdb3a9b59798d7e851d9074db69422b1d2df38dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/fe5de5f387e31b029d589d9b1777fd0d6b3e47b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/nanopb/corpus_serverlist/ff52d938aaa10c08b2eb0830fc0066c3b57e040f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "nanopb_fuzzer_serverlist_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/01c008fa.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/021ec59f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/02918e4ad9e8928845f232c0cb043057add3c9a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0336e1ff71939de9e2007fdb4aba891e35a37488"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/033dd2f6.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0384345c.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/03b9be1fa172dff5d1543be079b9c64fa2c9a278"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/05c3a0390d0f52d241728926fa901599a47e4606"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/05efe6d81ce606557691432634e81f61e68b0b81"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/06bd2f82fefb9943787d63ea359f9b77072380c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0766afc7c27c06ea18d896083470d587a380de3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/07ad7e0ea2aaecba37f2429a64e946fc6e2556f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/07c96c06eddbed5a3ce050436bc805f6821cbc9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/081e56ce6f6b1c57adb806fbc5baa9f93f87513a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/08492d3d0994005206d1d3213b8747d1026ae1eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/09938e3256d06a8e168eb038d8a58b8462f7f697"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0aa599e20761777c2cb9b41cd89e5c2e18f82d9e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0aa7b949.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0abd533e.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0b275a7f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0c413d2b361b2221585026d42f3046ff4135d2ff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0d10bb63.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0e349b8762703d080b3a696600e21d64c23a2ed3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0f700e05.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0ff4d220.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/10724098.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/108e270a272e312fc97ec23004b80fdc7bad3906"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/11516d58.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/11cda3f70be4b507ea936bca93af9ce5aaab3be7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/13501419f349b7855d2e94060bd08b28923d1f37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1421a8e9f045ac65a0f6938fae93fece1060c41d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/146b7d66ad932c4b623eec8004e286d3705697d3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/14f9a0cda0d64590430218aaf6dedd9be2a3533f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/15ae78a8543a4794a27e6c79b0d34540322b97fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/15afdcf2cadb93f56dbe36233d8cd7ea9d2bd6fe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1650b19093c56a1e86ee192bd9cd8d2266a9e353"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/16753235697083ecc45c117287f1d8ce6ad1ad1a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/17d7c718ec2597353a5dd2c78d6717a3d6aabfae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/18d8d274aa7c163fd6d0084d5c25c8623e10c541"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/18f00b5f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1939a9021aba59ea2e49d3d0909e6fdf86ac3f9e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1a69d5fc.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1aa6897b6eebb8c68c972cc5025b39c7e60c17fe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1cf17783de9e662f3720847f2d83d86dcdcab500"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1cfdde7a.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1d614f3d6b826f844178a77094bedb534748a362"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1e92aaa5.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1ea5651f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1f992057.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/20fd12d3670571283dc0c5dbb3fc139a8e943790"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/21475569.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/218c1b123428a07622570947e9b7cdb48c310ca5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/21a2dcda.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/22ad891a.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2463aea879c5ab49f8409d0e5c062c7e086b034b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/24ed80095e58199c52997f174046272f61ce4a8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/25ab638f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/26048c58bd5f2a94843f6fd1e4ab0be04b232636"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/26870785fd0564f552af4e0ca418738a85b21086"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2701d1669c2996c097a74c5255d569615357b916"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/27ac2ae2.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2814d70c.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/282b6585.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2a688fd507072e1cfa2e3bc58652a7cd82dface3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2abe64b96e5e72adcf2dcc43444a69d0fb664b66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2ad6cedd32cd646ba8e25226c7c13a107c1d6447"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2b14c6e618ec95754ea7e24fe6bc5a3a97df6897"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2b40aa21723c7e67e92e74a3083df008461d591c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2bf69fe6b40734cc3f0abdd765757809b14b0b88"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2c6660ba.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2cc6d1f3ee8933518e91b8410781fa6e105b3a15"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2e4805c3.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2f20e2decd09b6f211a5469c67efbada355e6c04"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2f3b1cd6780fe475f76f17e9e36541963d993165"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/2fb017cd4c34f4af183d03c4a219d2bb36ee2dd6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/30bba77d0f420c4f454011476f3c94e31c50c161"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3224e6cd.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/326ec4d5.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3292129aa7f6eba86b70fff64408f18fff895c12"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/32b11997.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/32cecacca27b249bd764f852168036c5f962bd16"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/330ad4b6.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/33b4cf1ac251f0ba0c014005ef8207afe1dea623"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/33e2ecd5c9bbc1f1dcab29d00195e0ab6d04642d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/340b032d39e2b212828a2bd1a97e2b6b81dcd41b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/34bba9e4.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/374262a5acf9cde1f480e7b7254c788e1936a4de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/37ec9df8.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/38df7e63181cbd045e5af9dbee463360c8254618"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/39ea47bb.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3aa82376296ab5a33f2921d7705b75b78b683c2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3ca5da2f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3d7ef8c7b05f26e914c479dedb1bef5e378d2d94"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3dc665f93db294b9ccb8fcec94bcc2a91f3a04e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3de41f3f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3e2077a4fd2def7b11e618d46245d0aa85824317"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3e3ae35a.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3e787760.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3f3069cf26f761366f947e025f7049254d555e7f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/407607d2.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/40af8d589c76d7912bec06c2ae1f2466065018e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/418f392319c44d06a018ce4c62569d527829177a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/41b31ef0.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/422708b4.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/422fa704.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4271fbb36e03cee79b21a4a5a65f37ceef58a8cd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/42b0afca.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/43fc6abab9840be5ee614211f17395b5966f6070"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/44516839d35af9ccaf8a2c62f3ce6a723482445e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/44f342a6.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4558ddeb.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/459c0bf6.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/468cf8bf3e31e1013c7c6d2288baac47ff90aa63"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4aa883d0.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4b7bcb4ae6c0222a1a24d1fb1a5d96519750ca5e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4c412cc1a775cea041fa270483d610afb72f463b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4d55d5ae.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4db3d4075ed27f2a2311f85dd1d6df028cc5d083"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4eb269c3.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4ecfe1be695df0d2489dddb52da8bcdeb6ed779d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4f97bd97ab5dc6b4c0f62f8459be8a9593dc83b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/4ff50e49865768323f94116bd98d2314455273cc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/508def44e4d60f237f18a40d7058e58a752a74e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/51a1abd1.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/52b5478161de7b2eba0f7bfbc29aea985c8d9ee7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/52ecfedca3b2b26e6999b6afc846f3dbd5d35130"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/53d18398c0d484de00afd8d583fe802d55d4da44"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/53de507f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/540ada69.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5413b531fe06923ddf2c9e3eb958769374bc2445"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5429f0da.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5435005f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/546367bfdd2b9464fbfe5d74f55d8cd220accbab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/54d0fc6c.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/55af20415ead0ddd417f37fa91a4c767b749ee34"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/55f6fb1a.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5780565e.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/57918260.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5841d898d2cd804f2d6373538e341dfba8a4dfab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/58b88a24.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/597fdab5.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/59ce7091c00075943d79e857c01ad1af5f38c78e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/59d0b24d1acd01c749fb4bd6802a5f4dd003ce75"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/59dcfde4.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5ac92c4a7fb476393f8275fe4b79a2b13e3bcad9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5d43ac923d7607a16e3d7bf8b838f52622871251"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5d817877.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5e2508e15c79fbe9c2e6c1a393b490356a17efbc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5f758756.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/5f820fa8d44229219d0b7c4724e3e40a2ace97f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/61e798bdd49b339983fea4ccfe18efe44afbd69b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/62d05f336176a10a2c339c04d818f23b6e9a2637"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6499e2db.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/64cdbb31d5eda779d07885fa7881812db7800c05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/65077d2946cfb822cf92c9dfc44517a34589f277"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/65099066.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/652bfdce.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/65d5ae42e6acb429459a1e1a5fb35f09c0f95de2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/65fd6cb3058ee0baae854cc7859b7c0c1e1c1166"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6652f7be83a876214affc3f230040757f7db4ea8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/67b04816.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/67ebf074c7f928c4fe32fef44e5c958cf441c93c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/68f564fd8064233897ff704b5955b33a2e29293a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/69891e9f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6c5bb78b51cf5006c92258292de19550985c00ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6dc4455c.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6e050e98.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6f3bd9f33ca05bebe3811f7b3ae6ed112e1e45b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6f9d75e1af7ae7010d32872da888a582a25fddb4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/70ebe7f32c63ca8940017eb83e6db4d8b39ee03c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/712300b98afdb5f0d15c657c13cea76841164b13"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/71ab07577909ca4b766f8ea0c6b8ec2bc395fc66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/72296cf9e1052ced4b60e2053aba9f1a569144e9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/7342b3febb07521e39abdf4ee976d16199d51239"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/746715fe.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/76294f12a5974e9f87d8f092d0df5429cf6c0466"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/769f5d079151d1b5cab388c47a74f3c297c18d58"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/7839f12a8410a73d66e191cb5183d36d09a375e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/7b453adcb9c4bf31dbc448ff32c2bc90ebcbdf0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/7ddfac7d7845b424bf670070781ca6ff8586c63b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/7f15bbce.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/7ffd05db.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8164d3c4af043c47cfd6966873bccd2353d072bf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/81fb19dfcb3c3a18fd9e7c177356479503e75e6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/82dda42ddde662192ebaa96788945b7673bb486b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8338ebee.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/84a3c6cf853ff318ae163231ce295171a59d5871"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/86a19d13cc65790696299c819cac17b14e337647"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/86e6dbf2.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/88017b0894db1e6f4e3a6640ffe2876d31a54723"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8846918f967dd6513040c6d382fcd68ff7099873"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/885fe25a0b441ef46ab176b88771c133e530cb73"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/88e1329b.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8b186384.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8c04817a75fddd71f13779f2ad5b994f45c333a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8c72c3f35e9b9fd168ad9024c953a703f33ae3c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8c760938a2a72fa92b27e00e05005e2e4c429359"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8da521d9.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8de81717.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/8ec00f45afb097066f47d0bad256a8b856b1efe8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/90224b8e.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/90240c7c.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9099ac4e83f6460c80b5557c87f653e4c65aa091"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/914ed07570b6441365a3636d05850f7316c7f2a8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/916b825da0ffc46fdb6120b1044e98ae158fce70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/93c3ffcb7e3bcb5ed7e37a5b3dfb97b43ca42718"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9540d3ad3fa75bfb95c0d57cefd737611c7069a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/954337ef.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/95d25ba2e190fafa2b3ca1e1c467b9ef64868962"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9764015f89a0b7a59f3b5359b0a037b38d6e39d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/97aed4bd.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/986c9ca7db83b2cddbae2a0db2dca87f52277074"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9953eb28aa1ed661612a4710a9d16a15de4ae353"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9a176b6f7e0dc5f681a1788d8954f76fabd08cad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9a6963b0d0fcb0e91a31748c47c6f0e1e842fea9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9bf7553a.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/9d2d18fce18c790035d8f67ed798703bdda0a949"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a112d484b70e778835fcd478fd651828720791e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a24bf2dc.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a32be0653ccc65463445b4aaf24a7a1164d5c642"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a357658d.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a3a2b1af.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a5348197.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a5b529754606b96a8c801615ac12a1f6ee5c3f54"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a5cc3762cb2b2cac316c60ddee794016057fb4ff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a7e64803.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a8d229374635fa6f2a75ca1669892e1bc244e719"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a8f2345b2c949e9e32a434c99accf771f405eb65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a9463428cdc47d37efb6e3c5633d1e5e78911f16"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a9966f7181d08f6a9ff8158736ad77a285d743a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a9e22d93.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/aa3c8974.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/aa825693.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/aa8729d7.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/aaafca90a7f59184f3d768a1d6f9093e8f737b8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ad810f7f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/aedefcd9bd7fc10b7bf60372da54c43e953523bd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/aefcbc29f2caea5038cda4dbc927cdadd9b844c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b06ce623.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b1128694.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b220d23a13d98d4815b1f7a3e4fe7dd8672b1c83"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b28959dd.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b431df13.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b5acaa52.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b7ce4a4f6eea20c0b83d9f7fa8406a0730ee0040"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b829143b.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b887097732b9c30719f6c7ea7a7cbac531512a31"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b924c842.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/bad4f467.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/bc9545cebdcb3af82406a5f0c1b286d28f9d4f5a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/bd63e44a3b004e7ed471c2367c3efae2c58a676d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/be9b6e78.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/bf5e21c32becb5839deeb81e9174cf6478a25473"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/bfb55acd5b66521eb5bd8ce6b57b3b6895883675"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/bfcbffa9.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c004455e9d60bc2fff094e79cd0b38507023e018"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c039ac9a5a570f8fd9064df9320890b885edf9c3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c1188b44.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c12835aa9f3513d3f7179ee4f9976292713f7cb9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c13188118af1634061b6a3947b81618891aeb6a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c35968bf.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c43d97f2.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c4534867.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c4a71cdd29759b51f9cc54175ad69c44b4ab6eb6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c559f565.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c56fada76f5c198232201a608072a1a63e3d3785"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c5ff50ae447ac7a0c8fb3363b2458824d405e64c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c66e84d1.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c6a1d2cc8935808b6e317a69baec1c3cb87cac94"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c7c44b98faa21c8f0645a818a65b60d956d15952"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c8073f5f41970fab4738215e42ec97a4383855e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c81dec02.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c8812dc8a1ab1592a2d7b71300e1a0a5da6a6382"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ca843c66c4c4807ccb1615b472c79bc459e5c6cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/cbb04be69714f81f5cd09e36e8ea4e69ea73d618"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/cc97ece92b72cc2a4d045e16c0e2f2021bc014f8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/cca29902.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/cdba6c45.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-0f4b135c0242669ce425d2662168e9440f8a628d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-239cc27a23827ea53b60ccbaee0ecc64dad2bff0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-41ab0e868e84612275f77118f9e832bc94ff45c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7af5da2a8da23d197d9336e32da72c9ff64c15b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7e121dd3be057176369bea160d873040b32a03dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-e34b0a9a428001cb4094a9ebca76329f578811a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d0f7eebc.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d2031009d3783fcf083963fa30bb493f7f935541"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d28155c6c92642c61dfb097f7b2eb1d6ced272c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d6979f0f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d8a1d141a9e3876b71c7decbe6e3affccf6de397"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d9074e68.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d95556cac07e720909aaf2ac09d876106420463f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d96da249094db51ea92b1413907abfd27a4f2426"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/da7e44a9.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/dab172ff.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/dad922e2daf84cf039f50cf8636eaa9dbd01ff83"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/db33559d4afb4c32e68525c000fde16a4c3300f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/dcabac1ef8b197ef39b188bcf5dc470f9749e903"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/df5d3cf5f05eab65ef9d385e263780ae73c42b19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e0d9a9a7.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e2652fbb.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e2c954e1.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e3bab014.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e7ad0c4b7d0f289c90a3988309e9e03b78f7eea3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e9bbe2fe47b7b9c2683e7f17f4a33625c6ffbd8c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e9d96662.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/eb66106b.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/eba8472a.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ed8da77f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ee64e1ba4897bfd7c6baa1fb72d4c5f83b5654e4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f0387dfdd6b8c925d958113e669ec4a1897034b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f1121b952e75463cc71137683dc2528f9cbc19b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f3220426.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f3d084cf20b92a5f026fe7cc6e5af49bde28693d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f4024b01.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f541d27e.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f5424a9d7bd14317b6de7b15587df28bfde8362d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f5c877c4.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f5f0615030439dda162e8862b6bbd09f81f14d81"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f74b9428.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f7bf0d7bb0dd6e1866ccef9fafc3cb295db2f07f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f826100f.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f88ffb7f3066f2706cfcd9be077595e07834cc15"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/f8b46e92c7ceb4c2f2cdcb3452a6d8c58768eaa2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fa36b4280d9e28edd81c5e4d192d1a5c2765e5e4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fb3b0d80.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fb84edfa9e8cbddba26a7184e7fdc219bde556c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fd14bea45ecaf13af0053900edb2f17b71a0bf09"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fd26e0a6.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fd943e69304dffebf47e1e40b0849e12abeee287"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fdf67df81857577361d319e76559c5e85a257b07"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe1957b9bc7c6bf9d8b6089c422d72a0f444da6e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe66893c.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe69ddfa5827dd560bb0b5d4da7d982273f17ef9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ff227015.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ff898c08.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-082763e16153cb6b8f3f5308cd060e822f475e5a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-13501419f349b7855d2e94060bd08b28923d1f37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-14862768a1fe076896fd37e2543ddd23192a9e3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1a3ebf8f8bb0b5a0109a5ef44734cc64170377f9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1ae0ed17a042aab8a3c3199c83a809b0243d1424"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-1b6c4b5c1949adae3efd5e3264bb32a40eea524e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-3991c873ba814d0cd03a67d25fff0c8fe8713aca"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-4c6da955e4c101b81a62b2f8e934d94a62ae534b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-58f116dfba8d428a01ca596174fca63f4ac523f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-59f6edc7cf4aeed49b4dc024052db4846d5d7fc8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-63ebf780ee6c2003eba622686a4bf94c503ad96e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-68ed2d33c9d32f73343c097303c3d5a6a3467c83"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6d37c5e6d7efee56319b1316725fdc5aee5a52c3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-6e980a9d12c392175b5f66683e608626ae983276"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7233d53f94386b0339b2c2b01ef2d348f5862f1f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-7281d9eaed0d20b0b6b5e7709c57e78fefe9c315"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-73e0a41066bc09c8e3fbd0dd7628445bcdaabb4a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-93cd6b3f9786ee107a0e2d135b40d13f96e652ed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9a176b6f7e0dc5f681a1788d8954f76fabd08cad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-9de2e92150e54982d4e502b18f374f8cd8fd453b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a61a28cf78149518466b87e5463ec5c771dc504e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-aa23c18f6badd88a7bec65e8b04f7801ba624ec6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ba2b1fde90cc70d9abae22c4c4cb051aae8aa148"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bda43d420a3e5d5228a5f5130207a1f11fc1c81f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c05c239719a7beeca2c126b7e5ef7251fa615b54"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-c151762e5f37e233142059c1b269ce55434cf6a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-cacd0e0c5f7d4169085735400100da4d36397185"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3c3cba3897fafec97665411ea1f94a89bb4de7b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-d3fcd80cd6f1bb05f5e5084ebb2ee801067863fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-ddfe613d8791b2d377e14fbdffb18b84a89d49b6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f67be653815f6c2c10eea55c8009e1167ac9c20b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/02d156dc5e6f2c11c90c2e06fcee04adf036a342"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/042dc4512fa3d391c5170cf3aa61e6a638f84342"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/0e9bbe975f2027e8c39c89f85f667530368e7d11"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/1155aa6ea7ef262a81a63692513ea395f84dad6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/13856a5569ffd085a4d5c07af5f8e9310835a118"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/14b57bcbf1e17b1db1de491ef2ba3768f704b7dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/1794310671a060eead6e5ee66ac978a18ec7e84f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/1d30b2a79afbaf2828ff42b9a9647e942ba1ab80"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/1fcf5d9c333b70596cf5ba04d1f7affdf445b971"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/23162c8a8936e20b195404c21337ee734d02a6bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/23f3198b815ca60bdadcaae682b9f965dda387f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/2ef3893b43f1f60b77b59ce06a6bce9815d78eaf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/356c3c129e203b5c74550b4209764d74b9caefce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/396568fc41c8ccb31ec925b4a862e4d29ead1327"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/3b1e7526a99918006b87e499d2beb6c4ac9c3c0c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/3b58860f3451d3e7aad99690a8d39782ca5116fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/41963cc10752f70c3af7e3d85868efb097a0ea9c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/47b5228404451fc9d4071fa69192514bb4ce33c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/56a2da4b2e6fb795243901023ed8d0aa083d1aab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/574c2f13858a9a6d724654bd913ede9ae3abf822"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/582f789c19033a152094cbf8565f14154a778ddb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/636c5606fc23713a1bae88c8899c0541cfad4fd8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/63fe493b270b17426d77a27cbf3abac5b2c2794a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/655300a902b62662296a8e46bfb04fbcb07182cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/6ae3acd9d8507b61bf235748026080a4138dba58"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/6b70979a70a038ff6607d6cf85485ee95baf58e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/7314ab3545a7535a26e0e8aad67caea5534d68b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/7ff4d8b8d1ffd0d42c48bbb91e5856a9ec31aecb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/87daa131e0973b77a232a870ed749ef29cf58e6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/884dcaee2908ffe5f12b65b8eba81016099c4266"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/8d7e944fd5d0ede94097fcc98b47b09a3f9c76cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/9671149af0b444f59bbdf71340d3441dadd8a7b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/96c8d266b7dc037288ef305c996608270f72e7fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/975536c71ade4800415a7e9c2f1b45c35a6d5ea8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/99750aa67d30beaea8af565c829d4999aa8cb91b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/a1140f3f8b5cffc1010221b9a4084a25fb75c1f6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/a1f0f9b75bb354eb063d7cba4fcfa2d0b88d63de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/a296eb3d1d436ed7df7195b10aa3c4de3896f98d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/a8b8e66050b424f1b8c07d46f868199fb7f60e38"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/aba1472880406a318ce207ee79815b7acf087757"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/af55baf8c8855e563befdf1eefbcbd46c5ddb8d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/b3c0bf66c2bf5d24ef1daf4cc5a9d6d5bd0e8bfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/c28a47409cf5d95bb372238d01e73d8b831408e4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/c3ef1d41888063a08700c3add1e4465aabcf8807"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/c550a76af21f9b9cc92a386d5c8998b26f8f2e4d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/c79721406d0ab80495f186fd88e37fba98637ae9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/ceb4e2264ba7a8d5be47d276b37ec09489e00245"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/cf4395958f5bfb46fd6f535a39657d016c75114c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/d46668372b7e20154a89409a7430a28e642afdca"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/d6fe7412a0a1d1c733160246f3fa425f4f97682a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/dns.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/e241f29957b0e30ec11aaaf91b2339f7015fa5fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/ea02d9fea9bad5b89cf353a0169238f584177e71"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/ec4731dddf94ed3ea92ae4d5a71f145ab6e3f6ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/ed2f78646f19fc47dd85ff0877c232b71913ece2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/f6889f4a6350fea1596a3adea5cdac02bd5d1ff3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/f6f3bd030f0d321efe7c51ca3f057de23509af67"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/f97598cff03306af3c70400608fec47268b5075d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/f9e1ec1fc642b575bc9955618b7065747f56b101"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/fe0630a3aeed2ec6f474f362e4c839478290d5c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/ipv4.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/ipv6.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
+      "test/core/client_config/uri_corpus/unix.txt"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "uri_fuzzer_test_one_entry", 
     "platforms": [
       "linux"
     ]
diff --git a/vsprojects/build_vs2010.bat b/vsprojects/build_vs2010.bat
index 64b0ed5..1bc3c86 100644
--- a/vsprojects/build_vs2010.bat
+++ b/vsprojects/build_vs2010.bat
@@ -1,5 +1,5 @@
 @rem Convenience wrapper that runs specified gRPC target using msbuild
-@rem Usage: build.bat TARGET_NAME
+@rem Usage: build_vs2010.bat TARGET_NAME
 
 setlocal
 @rem Set VS variables (uses Visual Studio 2010)
diff --git a/vsprojects/build_vs2013.bat b/vsprojects/build_vs2013.bat
index be3caa9..82c0a3a 100644
--- a/vsprojects/build_vs2013.bat
+++ b/vsprojects/build_vs2013.bat
@@ -1,5 +1,5 @@
 @rem Convenience wrapper that runs specified gRPC target using msbuild
-@rem Usage: build.bat TARGET_NAME
+@rem Usage: build_vs2013.bat TARGET_NAME
 
 setlocal
 @rem Set VS variables (uses Visual Studio 2013)
diff --git a/vsprojects/build_vs2015.bat b/vsprojects/build_vs2015.bat
index 50485a3..c6e1b43 100644
--- a/vsprojects/build_vs2015.bat
+++ b/vsprojects/build_vs2015.bat
@@ -1,5 +1,5 @@
 @rem Convenience wrapper that runs specified gRPC target using msbuild
-@rem Usage: build.bat TARGET_NAME
+@rem Usage: build_vs2015.bat TARGET_NAME
 
 setlocal
 @rem Set VS variables (uses Visual Studio 2015)
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 8c64423..bdae447 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -51,6 +51,7 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
 		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj", "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
@@ -663,6 +664,17 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "http_parser_test", "vcxproj\test\http_parser_test\http_parser_test.vcxproj", "{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpcli_format_request_test", "vcxproj\test\httpcli_format_request_test\httpcli_format_request_test.vcxproj", "{A43C3292-CAE7-1B8C-A5FD-52D9E3DCFD82}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -674,7 +686,7 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpcli_parser_test", "vcxproj\test\httpcli_parser_test\httpcli_parser_test.vcxproj", "{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "init_test", "vcxproj\test\init_test\init_test.vcxproj", "{117CA7AD-C42B-9217-6C95-42A801777BC5}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -685,7 +697,29 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "init_test", "vcxproj\test\init_test\init_test.vcxproj", "{117CA7AD-C42B-9217-6C95-42A801777BC5}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "internal_api_canary_iomgr_test", "vcxproj\test\internal_api_canary_iomgr_test\internal_api_canary_iomgr_test.vcxproj", "{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "internal_api_canary_support_test", "vcxproj\test\internal_api_canary_support_test\internal_api_canary_support_test.vcxproj", "{D53575C6-713C-E6E3-FD74-E65F20916498}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "internal_api_canary_transport_test", "vcxproj\test\internal_api_canary_transport_test\internal_api_canary_transport_test.vcxproj", "{ED24E700-964E-B426-6A6A-1944E2EF7BCB}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -1025,6 +1059,18 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "head_of_line_blocking_bad_client_test", "vcxproj\test\head_of_line_blocking_bad_client_test\head_of_line_blocking_bad_client_test.vcxproj", "{23DF0572-DBF1-08DA-8EAD-8508354C90A4}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{BA67B418-B699-E41A-9CC4-0279C49481A5} = {BA67B418-B699-E41A-9CC4-0279C49481A5}
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "headers_bad_client_test", "vcxproj\test\headers_bad_client_test\headers_bad_client_test.vcxproj", "{7819A11E-607E-F0C0-FC47-C704CF7D818C}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1229,7 +1275,7 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_ssl_proxy_test", "vcxproj\test/end2end/fixtures\h2_ssl_proxy_test\h2_ssl_proxy_test.vcxproj", "{A9092608-E45E-AC96-6533-A6E7DD98211D}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_ssl_cert_test", "vcxproj\test/end2end/fixtures\h2_ssl_cert_test\h2_ssl_cert_test.vcxproj", "{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -1241,7 +1287,7 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_test", "vcxproj\test/end2end/fixtures\h2_uchannel_test\h2_uchannel_test.vcxproj", "{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_ssl_proxy_test", "vcxproj\test/end2end/fixtures\h2_ssl_proxy_test\h2_ssl_proxy_test.vcxproj", "{A9092608-E45E-AC96-6533-A6E7DD98211D}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -1349,18 +1395,6 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_nosec_test", "vcxproj\test/end2end/fixtures\h2_uchannel_nosec_test\h2_uchannel_nosec_test.vcxproj", "{BD79A629-4181-DB5E-C28F-44EB280A6F91}"
-	ProjectSection(myProperties) = preProject
-        	lib = "False"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{47C2CB41-4E9F-58B6-F606-F6FAED5D00ED} = {47C2CB41-4E9F-58B6-F606-F6FAED5D00ED}
-		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
-		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
-		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
-		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
-	EndProjectSection
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -2429,6 +2463,22 @@
 		{FF2CEE6D-850F-E22C-53A0-8C5912B14B20}.Release-DLL|Win32.Build.0 = Release|Win32
 		{FF2CEE6D-850F-E22C-53A0-8C5912B14B20}.Release-DLL|x64.ActiveCfg = Release|x64
 		{FF2CEE6D-850F-E22C-53A0-8C5912B14B20}.Release-DLL|x64.Build.0 = Release|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug|Win32.ActiveCfg = Debug|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug|x64.ActiveCfg = Debug|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release|Win32.ActiveCfg = Release|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release|x64.ActiveCfg = Release|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug|Win32.Build.0 = Debug|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug|x64.Build.0 = Debug|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release|Win32.Build.0 = Release|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release|x64.Build.0 = Release|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Debug-DLL|x64.Build.0 = Debug|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release-DLL|Win32.Build.0 = Release|Win32
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release-DLL|x64.ActiveCfg = Release|x64
+		{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}.Release-DLL|x64.Build.0 = Release|x64
 		{A43C3292-CAE7-1B8C-A5FD-52D9E3DCFD82}.Debug|Win32.ActiveCfg = Debug|Win32
 		{A43C3292-CAE7-1B8C-A5FD-52D9E3DCFD82}.Debug|x64.ActiveCfg = Debug|x64
 		{A43C3292-CAE7-1B8C-A5FD-52D9E3DCFD82}.Release|Win32.ActiveCfg = Release|Win32
@@ -2445,22 +2495,6 @@
 		{A43C3292-CAE7-1B8C-A5FD-52D9E3DCFD82}.Release-DLL|Win32.Build.0 = Release|Win32
 		{A43C3292-CAE7-1B8C-A5FD-52D9E3DCFD82}.Release-DLL|x64.ActiveCfg = Release|x64
 		{A43C3292-CAE7-1B8C-A5FD-52D9E3DCFD82}.Release-DLL|x64.Build.0 = Release|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug|Win32.ActiveCfg = Debug|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug|x64.ActiveCfg = Debug|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release|Win32.ActiveCfg = Release|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release|x64.ActiveCfg = Release|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug|Win32.Build.0 = Debug|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug|x64.Build.0 = Debug|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release|Win32.Build.0 = Release|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release|x64.Build.0 = Release|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Debug-DLL|x64.Build.0 = Debug|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release-DLL|Win32.Build.0 = Release|Win32
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release-DLL|x64.ActiveCfg = Release|x64
-		{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}.Release-DLL|x64.Build.0 = Release|x64
 		{117CA7AD-C42B-9217-6C95-42A801777BC5}.Debug|Win32.ActiveCfg = Debug|Win32
 		{117CA7AD-C42B-9217-6C95-42A801777BC5}.Debug|x64.ActiveCfg = Debug|x64
 		{117CA7AD-C42B-9217-6C95-42A801777BC5}.Release|Win32.ActiveCfg = Release|Win32
@@ -2477,6 +2511,54 @@
 		{117CA7AD-C42B-9217-6C95-42A801777BC5}.Release-DLL|Win32.Build.0 = Release|Win32
 		{117CA7AD-C42B-9217-6C95-42A801777BC5}.Release-DLL|x64.ActiveCfg = Release|x64
 		{117CA7AD-C42B-9217-6C95-42A801777BC5}.Release-DLL|x64.Build.0 = Release|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|Win32.ActiveCfg = Debug|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|x64.ActiveCfg = Debug|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|Win32.ActiveCfg = Release|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|x64.ActiveCfg = Release|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|Win32.Build.0 = Debug|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|x64.Build.0 = Debug|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|Win32.Build.0 = Release|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|x64.Build.0 = Release|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|x64.Build.0 = Debug|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|Win32.Build.0 = Release|Win32
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|x64.ActiveCfg = Release|x64
+		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|x64.Build.0 = Release|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|x64.ActiveCfg = Debug|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|Win32.ActiveCfg = Release|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|x64.ActiveCfg = Release|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|Win32.Build.0 = Debug|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|x64.Build.0 = Debug|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|Win32.Build.0 = Release|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|x64.Build.0 = Release|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|x64.Build.0 = Debug|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|Win32.Build.0 = Release|Win32
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|x64.ActiveCfg = Release|x64
+		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|x64.Build.0 = Release|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|Win32.ActiveCfg = Debug|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|x64.ActiveCfg = Debug|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|Win32.ActiveCfg = Release|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|x64.ActiveCfg = Release|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|Win32.Build.0 = Debug|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|x64.Build.0 = Debug|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|Win32.Build.0 = Release|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|x64.Build.0 = Release|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|x64.Build.0 = Debug|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|Win32.Build.0 = Release|Win32
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|x64.ActiveCfg = Release|x64
+		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|x64.Build.0 = Release|x64
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Debug|Win32.ActiveCfg = Debug|Win32
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Debug|x64.ActiveCfg = Debug|x64
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Release|Win32.ActiveCfg = Release|Win32
@@ -2957,6 +3039,22 @@
 		{AF9D0EB2-2A53-B815-3A63-E82C7F91DB29}.Release-DLL|Win32.Build.0 = Release|Win32
 		{AF9D0EB2-2A53-B815-3A63-E82C7F91DB29}.Release-DLL|x64.ActiveCfg = Release|x64
 		{AF9D0EB2-2A53-B815-3A63-E82C7F91DB29}.Release-DLL|x64.Build.0 = Release|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|Win32.ActiveCfg = Debug|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|x64.ActiveCfg = Debug|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|Win32.ActiveCfg = Release|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|x64.ActiveCfg = Release|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|Win32.Build.0 = Debug|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|x64.Build.0 = Debug|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|Win32.Build.0 = Release|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|x64.Build.0 = Release|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|x64.Build.0 = Debug|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|Win32.Build.0 = Release|Win32
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|x64.ActiveCfg = Release|x64
+		{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|x64.Build.0 = Release|x64
 		{7819A11E-607E-F0C0-FC47-C704CF7D818C}.Debug|Win32.ActiveCfg = Debug|Win32
 		{7819A11E-607E-F0C0-FC47-C704CF7D818C}.Debug|x64.ActiveCfg = Debug|x64
 		{7819A11E-607E-F0C0-FC47-C704CF7D818C}.Release|Win32.ActiveCfg = Release|Win32
@@ -3229,6 +3327,22 @@
 		{EA78D290-4098-FF04-C647-013F6B81E4E7}.Release-DLL|Win32.Build.0 = Release|Win32
 		{EA78D290-4098-FF04-C647-013F6B81E4E7}.Release-DLL|x64.ActiveCfg = Release|x64
 		{EA78D290-4098-FF04-C647-013F6B81E4E7}.Release-DLL|x64.Build.0 = Release|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug|x64.ActiveCfg = Debug|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release|Win32.ActiveCfg = Release|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release|x64.ActiveCfg = Release|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug|Win32.Build.0 = Debug|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug|x64.Build.0 = Debug|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release|Win32.Build.0 = Release|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release|x64.Build.0 = Release|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Debug-DLL|x64.Build.0 = Debug|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release-DLL|Win32.Build.0 = Release|Win32
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release-DLL|x64.ActiveCfg = Release|x64
+		{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}.Release-DLL|x64.Build.0 = Release|x64
 		{A9092608-E45E-AC96-6533-A6E7DD98211D}.Debug|Win32.ActiveCfg = Debug|Win32
 		{A9092608-E45E-AC96-6533-A6E7DD98211D}.Debug|x64.ActiveCfg = Debug|x64
 		{A9092608-E45E-AC96-6533-A6E7DD98211D}.Release|Win32.ActiveCfg = Release|Win32
@@ -3245,22 +3359,6 @@
 		{A9092608-E45E-AC96-6533-A6E7DD98211D}.Release-DLL|Win32.Build.0 = Release|Win32
 		{A9092608-E45E-AC96-6533-A6E7DD98211D}.Release-DLL|x64.ActiveCfg = Release|x64
 		{A9092608-E45E-AC96-6533-A6E7DD98211D}.Release-DLL|x64.Build.0 = Release|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug|Win32.ActiveCfg = Debug|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug|x64.ActiveCfg = Debug|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release|Win32.ActiveCfg = Release|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release|x64.ActiveCfg = Release|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug|Win32.Build.0 = Debug|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug|x64.Build.0 = Debug|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release|Win32.Build.0 = Release|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release|x64.Build.0 = Release|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Debug-DLL|x64.Build.0 = Debug|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release-DLL|Win32.Build.0 = Release|Win32
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release-DLL|x64.ActiveCfg = Release|x64
-		{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}.Release-DLL|x64.Build.0 = Release|x64
 		{A8039D43-910E-4248-2A22-74366E8C4DCD}.Debug|Win32.ActiveCfg = Debug|Win32
 		{A8039D43-910E-4248-2A22-74366E8C4DCD}.Debug|x64.ActiveCfg = Debug|x64
 		{A8039D43-910E-4248-2A22-74366E8C4DCD}.Release|Win32.ActiveCfg = Release|Win32
@@ -3389,22 +3487,6 @@
 		{485E6713-487D-F274-BDE7-5D29300C93FE}.Release-DLL|Win32.Build.0 = Release|Win32
 		{485E6713-487D-F274-BDE7-5D29300C93FE}.Release-DLL|x64.ActiveCfg = Release|x64
 		{485E6713-487D-F274-BDE7-5D29300C93FE}.Release-DLL|x64.Build.0 = Release|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug|Win32.ActiveCfg = Debug|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug|x64.ActiveCfg = Debug|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release|Win32.ActiveCfg = Release|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release|x64.ActiveCfg = Release|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug|Win32.Build.0 = Debug|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug|x64.Build.0 = Debug|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release|Win32.Build.0 = Release|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release|x64.Build.0 = Release|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Debug-DLL|x64.Build.0 = Debug|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release-DLL|Win32.Build.0 = Release|Win32
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release-DLL|x64.ActiveCfg = Release|x64
-		{BD79A629-4181-DB5E-C28F-44EB280A6F91}.Release-DLL|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/vsprojects/grpc.sln b/vsprojects/grpc.sln
index 3f6b337..029c9ed 100644
--- a/vsprojects/grpc.sln
+++ b/vsprojects/grpc.sln
@@ -51,6 +51,7 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
 		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj", "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
@@ -99,6 +100,7 @@
 	ProjectSection(ProjectDependencies) = postProject
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boringssl", "vcxproj\.\boringssl\boringssl.vcxproj", "{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}"
diff --git a/vsprojects/grpc_protoc_plugins.sln b/vsprojects/grpc_protoc_plugins.sln
index 9471aae..ace295d 100644
--- a/vsprojects/grpc_protoc_plugins.sln
+++ b/vsprojects/grpc_protoc_plugins.sln
@@ -3,23 +3,10 @@
 # Visual Studio 2013
 VisualStudioVersion = 12.0.21005.1
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_codegen_lib", "vcxproj\.\grpc_codegen_lib\grpc_codegen_lib.vcxproj", "{A828FD72-44CE-4EA5-8966-6E4624458D58}"
-	ProjectSection(myProperties) = preProject
-        	lib = "True"
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++_codegen_lib", "vcxproj\.\grpc++_codegen_lib\grpc++_codegen_lib.vcxproj", "{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}"
-	ProjectSection(myProperties) = preProject
-        	lib = "True"
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_plugin_support", "vcxproj\.\grpc_plugin_support\grpc_plugin_support.vcxproj", "{B6E81D84-2ACB-41B8-8781-493A944C7817}"
 	ProjectSection(myProperties) = preProject
         	lib = "True"
 	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500} = {AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}
-	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_cpp_plugin", "vcxproj\.\grpc_cpp_plugin\grpc_cpp_plugin.vcxproj", "{7E51A25F-AC59-488F-906C-C60FAAE706AA}"
 	ProjectSection(myProperties) = preProject
@@ -37,6 +24,14 @@
 		{B6E81D84-2ACB-41B8-8781-493A944C7817} = {B6E81D84-2ACB-41B8-8781-493A944C7817}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_node_plugin", "vcxproj\.\grpc_node_plugin\grpc_node_plugin.vcxproj", "{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{B6E81D84-2ACB-41B8-8781-493A944C7817} = {B6E81D84-2ACB-41B8-8781-493A944C7817}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_objective_c_plugin", "vcxproj\.\grpc_objective_c_plugin\grpc_objective_c_plugin.vcxproj", "{19564640-CEE6-4921-ABA5-676ED79A36F6}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -69,22 +64,6 @@
 		Release|x64 = Release|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Debug|Win32.ActiveCfg = Debug|Win32
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Debug|x64.ActiveCfg = Debug|x64
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Release|Win32.ActiveCfg = Release|Win32
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Release|x64.ActiveCfg = Release|x64
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Debug|Win32.Build.0 = Debug|Win32
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Debug|x64.Build.0 = Debug|x64
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Release|Win32.Build.0 = Release|Win32
-		{A828FD72-44CE-4EA5-8966-6E4624458D58}.Release|x64.Build.0 = Release|x64
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Debug|Win32.ActiveCfg = Debug|Win32
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Debug|x64.ActiveCfg = Debug|x64
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Release|Win32.ActiveCfg = Release|Win32
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Release|x64.ActiveCfg = Release|x64
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Debug|Win32.Build.0 = Debug|Win32
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Debug|x64.Build.0 = Debug|x64
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Release|Win32.Build.0 = Release|Win32
-		{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}.Release|x64.Build.0 = Release|x64
 		{B6E81D84-2ACB-41B8-8781-493A944C7817}.Debug|Win32.ActiveCfg = Debug|Win32
 		{B6E81D84-2ACB-41B8-8781-493A944C7817}.Debug|x64.ActiveCfg = Debug|x64
 		{B6E81D84-2ACB-41B8-8781-493A944C7817}.Release|Win32.ActiveCfg = Release|Win32
@@ -109,6 +88,14 @@
 		{3C813052-A49A-4662-B90A-1ADBEC7EE453}.Debug|x64.Build.0 = Debug|x64
 		{3C813052-A49A-4662-B90A-1ADBEC7EE453}.Release|Win32.Build.0 = Release|Win32
 		{3C813052-A49A-4662-B90A-1ADBEC7EE453}.Release|x64.Build.0 = Release|x64
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|Win32.ActiveCfg = Debug|Win32
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|x64.ActiveCfg = Debug|x64
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|Win32.ActiveCfg = Release|Win32
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|x64.ActiveCfg = Release|x64
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|Win32.Build.0 = Debug|Win32
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|x64.Build.0 = Debug|x64
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|Win32.Build.0 = Release|Win32
+		{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|x64.Build.0 = Release|x64
 		{19564640-CEE6-4921-ABA5-676ED79A36F6}.Debug|Win32.ActiveCfg = Debug|Win32
 		{19564640-CEE6-4921-ABA5-676ED79A36F6}.Debug|x64.ActiveCfg = Debug|x64
 		{19564640-CEE6-4921-ABA5-676ED79A36F6}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/boringssl/boringssl.vcxproj b/vsprojects/vcxproj/boringssl/boringssl.vcxproj
index 27125c4..59db775 100644
--- a/vsprojects/vcxproj/boringssl/boringssl.vcxproj
+++ b/vsprojects/vcxproj/boringssl/boringssl.vcxproj
@@ -156,12 +156,12 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\cipher\internal.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\conf\conf_def.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\conf\internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\curve25519\internal.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\des\internal.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\dh\internal.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\digest\internal.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\digest\md32_common.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\directory.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\dsa\internal.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\ec\internal.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\ec\p256-x86_64-table.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\evp\internal.h" />
@@ -400,6 +400,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\buf\buf.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\bytestring\asn1_compat.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\bytestring\ber.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\bytestring\cbb.c">
@@ -446,6 +448,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\curve25519\curve25519.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\curve25519\x25519-x86_64.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\des\des.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\dh\check.c">
@@ -828,6 +832,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\ssl\ssl_cipher.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\ssl\ssl_ecdh.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\ssl\ssl_file.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\ssl\ssl_lib.c">
diff --git a/vsprojects/vcxproj/boringssl/boringssl.vcxproj.filters b/vsprojects/vcxproj/boringssl/boringssl.vcxproj.filters
index 8cee094..bd996bd 100644
--- a/vsprojects/vcxproj/boringssl/boringssl.vcxproj.filters
+++ b/vsprojects/vcxproj/boringssl/boringssl.vcxproj.filters
@@ -217,6 +217,9 @@
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\buf\buf.c">
       <Filter>third_party\boringssl\crypto\buf</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\bytestring\asn1_compat.c">
+      <Filter>third_party\boringssl\crypto\bytestring</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\bytestring\ber.c">
       <Filter>third_party\boringssl\crypto\bytestring</Filter>
     </ClCompile>
@@ -286,6 +289,9 @@
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\curve25519\curve25519.c">
       <Filter>third_party\boringssl\crypto\curve25519</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\curve25519\x25519-x86_64.c">
+      <Filter>third_party\boringssl\crypto\curve25519</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\des\des.c">
       <Filter>third_party\boringssl\crypto\des</Filter>
     </ClCompile>
@@ -859,6 +865,9 @@
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\ssl\ssl_cipher.c">
       <Filter>third_party\boringssl\ssl</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\ssl\ssl_ecdh.c">
+      <Filter>third_party\boringssl\ssl</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\ssl\ssl_file.c">
       <Filter>third_party\boringssl\ssl</Filter>
     </ClCompile>
@@ -912,6 +921,9 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\conf\internal.h">
       <Filter>third_party\boringssl\crypto\conf</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\curve25519\internal.h">
+      <Filter>third_party\boringssl\crypto\curve25519</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\des\internal.h">
       <Filter>third_party\boringssl\crypto\des</Filter>
     </ClInclude>
@@ -927,9 +939,6 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\directory.h">
       <Filter>third_party\boringssl\crypto</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\dsa\internal.h">
-      <Filter>third_party\boringssl\crypto\dsa</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\third_party\boringssl\crypto\ec\internal.h">
       <Filter>third_party\boringssl\crypto\ec</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj
index 9281fa3..cdb128e 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj
@@ -191,107 +191,107 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\src\core\profiling\timers.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\backoff.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\block_annotate.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\env.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\load_file.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\murmur_hash.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\stack_lockfree.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\string.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\string_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\thd_internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\time_precise.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\tmpfile.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\load_file.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\thd_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\time_precise.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\tmpfile.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\core\profiling\basic_timers.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\profiling\basic_timers.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\profiling\stap_timers.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\profiling\stap_timers.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\alloc.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\alloc.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\avl.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\avl.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\backoff.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\backoff.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cmdline.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cmdline.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_iphone.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_iphone.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_linux.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_linux.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\env_linux.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\env_linux.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\env_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\env_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\env_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\env_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\histogram.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\histogram.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\host_port.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\host_port.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\load_file.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\load_file.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_android.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_android.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_linux.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_linux.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\murmur_hash.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\slice.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\slice.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\slice_buffer.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\slice_buffer.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\stack_lockfree.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\string_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\string_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\string_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\string_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\subprocess_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\subprocess_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\subprocess_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\subprocess_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\sync.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\sync.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\sync_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\sync_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\sync_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\sync_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\thd.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\thd.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\thd_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\thd_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\thd_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\thd_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time_precise.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time_precise.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\tls_pthread.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\tls_pthread.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\tmpfile_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\tmpfile_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\wrap_memcpy.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\wrap_memcpy.c">
     </ClCompile>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
index b85060f..8af6fdd 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
@@ -1,137 +1,137 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\core\profiling\basic_timers.c">
-      <Filter>src\core\profiling</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\profiling\basic_timers.c">
+      <Filter>src\core\lib\profiling</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\profiling\stap_timers.c">
-      <Filter>src\core\profiling</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\profiling\stap_timers.c">
+      <Filter>src\core\lib\profiling</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\alloc.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\alloc.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\avl.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\avl.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\backoff.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\backoff.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cmdline.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cmdline.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_iphone.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_iphone.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_linux.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_linux.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_windows.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\cpu_windows.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\env_linux.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\env_linux.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\env_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\env_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\env_win32.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\env_win32.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\histogram.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\histogram.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\host_port.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\host_port.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\load_file.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\load_file.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_android.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_android.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_linux.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_linux.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\log_win32.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_win32.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\murmur_hash.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\slice.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\slice.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\slice_buffer.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\slice_buffer.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\stack_lockfree.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\string.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\string.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\string_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\string_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\string_win32.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\string_win32.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\subprocess_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\subprocess_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\subprocess_windows.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\subprocess_windows.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\sync.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\sync.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\sync_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\sync_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\sync_win32.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\sync_win32.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\thd.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\thd.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\thd_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\thd_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\thd_win32.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\thd_win32.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time_precise.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time_precise.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\time_win32.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\time_win32.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\tls_pthread.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\tls_pthread.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_posix.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\tmpfile_posix.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_win32.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\tmpfile_win32.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\wrap_memcpy.c">
-      <Filter>src\core\support</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\wrap_memcpy.c">
+      <Filter>src\core\lib\support</Filter>
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
@@ -263,41 +263,41 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\src\core\profiling\timers.h">
-      <Filter>src\core\profiling</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h">
+      <Filter>src\core\lib\profiling</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\backoff.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\block_annotate.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\env.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\load_file.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\load_file.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\murmur_hash.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\stack_lockfree.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\string.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\string_win32.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string_win32.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\thd_internal.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\thd_internal.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\time_precise.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\time_precise.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\tmpfile.h">
-      <Filter>src\core\support</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\tmpfile.h">
+      <Filter>src\core\lib\support</Filter>
     </ClInclude>
   </ItemGroup>
 
@@ -323,11 +323,14 @@
     <Filter Include="src\core">
       <UniqueIdentifier>{c5e1baa7-de77-beb1-9675-942261648f79}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\profiling">
-      <UniqueIdentifier>{93b7086c-8c8a-6bbf-fb14-1f166bf0146a}</UniqueIdentifier>
+    <Filter Include="src\core\lib">
+      <UniqueIdentifier>{52037bcb-5719-a548-224d-834fbe569045}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\support">
-      <UniqueIdentifier>{bb116f2a-ea2a-c233-82da-0c54e3cbfec1}</UniqueIdentifier>
+    <Filter Include="src\core\lib\profiling">
+      <UniqueIdentifier>{ba38d79d-d5de-a89e-9ca2-c5235a03ca7f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\support">
+      <UniqueIdentifier>{a4812158-7fba-959e-4e09-50167fe38df8}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
 </Project>
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
index d29e689..29cab37 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
@@ -293,8 +293,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\async_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\byte_buffer.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\channel_arguments.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\status_code_enum.h" />
@@ -311,9 +309,8 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
@@ -333,6 +330,30 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\secure_credentials.h" />
@@ -340,8 +361,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\common\secure_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\secure_server_credentials.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\cpp\common\core_codegen.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\cpp\common\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
   </ItemGroup>
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
index c9b3bb9..15e2807 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
@@ -201,12 +201,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\channel_arguments.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\slice.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
@@ -255,15 +249,12 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -321,6 +312,78 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h">
+      <Filter>include\grpc++\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h">
+      <Filter>include\grpc++\support</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\secure_credentials.h">
@@ -338,12 +401,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h">
       <Filter>src\cpp\client</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\cpp\common\core_codegen.h">
-      <Filter>src\cpp\common</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\cpp\common\create_auth_context.h">
-      <Filter>src\cpp\common</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h">
       <Filter>src\cpp\server</Filter>
     </ClInclude>
@@ -356,6 +413,9 @@
     <Filter Include="include">
       <UniqueIdentifier>{82445414-24cd-8198-1fe1-4267c3f3df00}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc">
+      <UniqueIdentifier>{16946104-53ac-ac76-68b9-f9ec77ea6fae}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++">
       <UniqueIdentifier>{784a0281-f547-aeb0-9f55-b26b7de9c769}</UniqueIdentifier>
     </Filter>
@@ -377,6 +437,12 @@
     <Filter Include="include\grpc++\support">
       <UniqueIdentifier>{a5c10dae-f715-2a30-1066-d22f8bc94cb2}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc\impl">
+      <UniqueIdentifier>{48c3b0ae-c00f-fa20-6965-b73da65d71cb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl\codegen">
+      <UniqueIdentifier>{dc8bfccd-341f-26f0-8ee4-47dde62a6dd1}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src">
       <UniqueIdentifier>{328ff211-2886-406e-56f9-18ba1686f363}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc++_codegen_lib/grpc++_codegen_lib.vcxproj b/vsprojects/vcxproj/grpc++_codegen_lib/grpc++_codegen_lib.vcxproj
deleted file mode 100644
index de2526b..0000000
--- a/vsprojects/vcxproj/grpc++_codegen_lib/grpc++_codegen_lib.vcxproj
+++ /dev/null
@@ -1,215 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>grpc++_codegen_lib</TargetName>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>grpc++_codegen_lib</TargetName>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
-    </ClCompile>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/grpc++_codegen_lib/grpc++_codegen_lib.vcxproj.filters b/vsprojects/vcxproj/grpc++_codegen_lib/grpc++_codegen_lib.vcxproj.filters
deleted file mode 100644
index 3cc0082..0000000
--- a/vsprojects/vcxproj/grpc++_codegen_lib/grpc++_codegen_lib.vcxproj.filters
+++ /dev/null
@@ -1,200 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
-      <Filter>src\cpp\codegen</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h">
-      <Filter>include\grpc++\impl\codegen\security</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="include">
-      <UniqueIdentifier>{cf409044-341b-37b5-03f3-0b09c3c474c4}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc">
-      <UniqueIdentifier>{cddccffd-da89-18ad-da57-0c9d704a4633}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc++">
-      <UniqueIdentifier>{cb8cb5ad-cf23-a491-046c-1c0688be53ac}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc++\impl">
-      <UniqueIdentifier>{a734ff7f-2489-0c04-3fc6-35e361240cf1}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc++\impl\codegen">
-      <UniqueIdentifier>{ffc473f2-ece4-fedf-238f-f161e5c3d5e7}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc++\impl\codegen\security">
-      <UniqueIdentifier>{89065a9e-e4a0-e5e4-32e9-51cd4cadab46}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc\impl">
-      <UniqueIdentifier>{45ab28cb-74e7-1a53-77c1-bbf2ec383fa2}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc\impl\codegen">
-      <UniqueIdentifier>{311586c5-1a08-e1ba-8dd8-d1cbe10156b3}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src">
-      <UniqueIdentifier>{e9bdb195-1cf9-a0f4-231c-fcee59eb54ca}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src\cpp">
-      <UniqueIdentifier>{d2e57ea3-c758-0f7c-3bc9-e71dd87bd654}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src\cpp\codegen">
-      <UniqueIdentifier>{f93ade18-7c50-7ed9-b8e7-383b11f077c2}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
index 3d1aee0..fcda361 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -293,8 +293,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\async_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\byte_buffer.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\channel_arguments.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\status_code_enum.h" />
@@ -311,9 +309,8 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
@@ -333,11 +330,34 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\common\core_codegen.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\cpp\common\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
   </ItemGroup>
@@ -402,6 +422,9 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
       <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index 70a23bf..1dc95f9 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -186,12 +186,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\channel_arguments.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\slice.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
@@ -240,15 +234,12 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
-      <Filter>include\grpc++\impl\codegen</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -306,6 +297,78 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h">
+      <Filter>include\grpc++\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h">
+      <Filter>include\grpc++\support</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h">
@@ -314,9 +377,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\common\core_codegen.h">
       <Filter>src\cpp\common</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\cpp\common\create_auth_context.h">
-      <Filter>src\cpp\common</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h">
       <Filter>src\cpp\server</Filter>
     </ClInclude>
@@ -329,6 +389,9 @@
     <Filter Include="include">
       <UniqueIdentifier>{5c4eb19f-d511-e8fd-e1d6-c377cdc7d3b1}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc">
+      <UniqueIdentifier>{f3dd91a8-058b-becf-9e41-eb42c7bc6e55}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++">
       <UniqueIdentifier>{eceb50c0-bb49-3812-b6bd-b0af6df81da7}</UniqueIdentifier>
     </Filter>
@@ -350,6 +413,12 @@
     <Filter Include="include\grpc++\support">
       <UniqueIdentifier>{0ebf8008-80b9-d6da-e1dc-854bf1ec2195}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc\impl">
+      <UniqueIdentifier>{c1049250-64f6-f900-d2e5-1718e148f1f0}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl\codegen">
+      <UniqueIdentifier>{adf6b8e3-4a4b-cb35-bb3d-568af97b58d1}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src">
       <UniqueIdentifier>{cce6a85d-1111-3834-6825-31e170d93cff}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 869acb4..4eec05a 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -267,7 +267,6 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
@@ -279,471 +278,458 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_plugin.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_args.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_uchannel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\compress_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\connected_channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\context.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_client_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_server_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\client_config.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\uri_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\algorithm_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\message_compress.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\debug\trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\format_request.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\httpcli.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\closure.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\executor.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\resolve_address.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_client.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_common.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_rpc_stats.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\api_trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call_test_only.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_init.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\completion_queue.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\event_string.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\init.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\lame_client.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\surface_trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\byte_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\http2_errors.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata_batch.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\static_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport_impl.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\auth_filters.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\b64.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\handshake.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\json_token.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\jwt_verifier.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\secure_endpoint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\security_connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\security_context.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_interface.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\mlog.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\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_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\surface_trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
+    <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\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" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_context.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_plugin.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_args.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_channel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_uchannel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\compress_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression_algorithm.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\connected_channel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_client_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_server_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\client_config.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\connector.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\default_initial_connect_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\debug\trace.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\format_request.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\parser.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\closure.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\executor.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_epoll.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_poll_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_common_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_linux.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\udp_server.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_eventfd.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_nospecial.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_reader.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_string.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\api_trace.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer_reader.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_details.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_log_batch.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_connectivity.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_create.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_init.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_ping.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\secure\server_secure_chttp2.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\completion_queue.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\event_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\lame_client.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\metadata_array.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server_chttp2.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\validate_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\version.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\byte_stream.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\timeout_encoding.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli_security_connector.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\b64.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\parsing.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\client_auth_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_lists.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\google_default_credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\writing.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\handshake.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\json_token.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\connectivity_state.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\jwt_verifier.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\secure_endpoint.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata_batch.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_connector.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\static_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_context.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\server_auth_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport_op_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init_secure.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli_security_connector.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\fake_transport_security.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\b64.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\ssl_transport_security.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\client_auth_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\secure\secure_channel_create.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\channel_connectivity.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\google_default_credentials.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\handshake.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config_plugin.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\json_token.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\connector.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\jwt_verifier.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\default_initial_connect_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\secure_endpoint.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\security_connector.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\security_context.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\server_auth_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\server_secure_chttp2.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init_secure.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\secure_channel_create.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\transport_security.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\context.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\mlog.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\placeholders.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
     </ClCompile>
@@ -751,6 +737,34 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\dns\native\dns_resolver.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\sockaddr\sockaddr_resolver.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_context.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_plugin_registry.c">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 44cf627..17c88c4 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -1,485 +1,449 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_context.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_filter.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_plugin.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_args.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_channel.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_uchannel.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\compress_filter.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression_algorithm.c">
+      <Filter>src\core\lib\compression</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\connected_channel.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
+      <Filter>src\core\lib\compression</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_client_filter.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
+      <Filter>src\core\lib\debug</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_server_filter.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
+      <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
+      <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\client_config.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
+      <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\connector.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\default_initial_connect_string.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <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\client_config\lb_policies\round_robin.c">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.c">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.c">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
-      <Filter>src\core\compression</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
-      <Filter>src\core\compression</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\debug\trace.c">
-      <Filter>src\core\debug</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\format_request.c">
-      <Filter>src\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli.c">
-      <Filter>src\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\parser.c">
-      <Filter>src\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\closure.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\executor.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_epoll.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_poll_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_common_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_linux.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\udp_server.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_eventfd.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_nospecial.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json.c">
-      <Filter>src\core\json</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_reader.c">
-      <Filter>src\core\json</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_string.c">
-      <Filter>src\core\json</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
-      <Filter>src\core\json</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
-      <Filter>src\core\proto\grpc\lb\v0</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
-      <Filter>src\core\surface</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\api_trace.c">
-      <Filter>src\core\surface</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer.c">
-      <Filter>src\core\surface</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer_reader.c">
-      <Filter>src\core\surface</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call.c">
-      <Filter>src\core\surface</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_details.c">
-      <Filter>src\core\surface</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_log_batch.c">
-      <Filter>src\core\surface</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_connectivity.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_create.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_init.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_ping.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\secure\server_secure_chttp2.c">
+      <Filter>src\core\ext\transport\chttp2\server\secure</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\completion_queue.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\event_string.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\lame_client.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\metadata_array.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server_chttp2.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\validate_metadata.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\version.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\byte_stream.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\timeout_encoding.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli_security_connector.c">
+      <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\b64.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\parsing.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\client_auth_filter.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_lists.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_metadata.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_posix.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_win32.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\google_default_credentials.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\writing.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\handshake.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\json_token.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\connectivity_state.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\jwt_verifier.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\secure_endpoint.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata_batch.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_connector.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\static_metadata.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_context.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\server_auth_filter.c">
+      <Filter>src\core\lib\security</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport_op_string.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init_secure.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli_security_connector.c">
-      <Filter>src\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\fake_transport_security.c">
+      <Filter>src\core\lib\tsi</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\b64.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\ssl_transport_security.c">
+      <Filter>src\core\lib\tsi</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\client_auth_filter.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security.c">
+      <Filter>src\core\lib\tsi</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\secure\secure_channel_create.c">
+      <Filter>src\core\ext\transport\chttp2\client\secure</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials_metadata.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\channel_connectivity.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials_posix.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\credentials_win32.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\google_default_credentials.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\handshake.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config_plugin.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\json_token.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\connector.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\jwt_verifier.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\default_initial_connect_string.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\secure_endpoint.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\security_connector.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\security_context.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\server_auth_filter.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\server_secure_chttp2.c">
-      <Filter>src\core\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init_secure.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\secure_channel_create.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.c">
-      <Filter>src\core\tsi</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.c">
-      <Filter>src\core\tsi</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\transport_security.c">
-      <Filter>src\core\tsi</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\context.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\mlog.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c">
+      <Filter>src\core\ext\transport\chttp2\server\insecure</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create.c">
+      <Filter>src\core\ext\transport\chttp2\client\insecure</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\placeholders.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.c">
+      <Filter>src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
       <Filter>third_party\nanopb</Filter>
@@ -490,11 +454,50 @@
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
       <Filter>third_party\nanopb</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
+      <Filter>src\core\ext\lb_policy\pick_first</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
+      <Filter>src\core\ext\lb_policy\round_robin</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\dns\native\dns_resolver.c">
+      <Filter>src\core\ext\resolver\dns\native</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\sockaddr\sockaddr_resolver.c">
+      <Filter>src\core\ext\resolver\sockaddr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_context.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_plugin.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_plugin_registry.c">
+      <Filter>src\core\plugin_registry</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
@@ -528,421 +531,436 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
       <Filter>include\grpc\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_filter.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_plugin.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_args.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_channel.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_uchannel.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\compress_filter.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\connected_channel.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
+      <Filter>src\core\lib\compression</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\context.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
+      <Filter>src\core\lib\compression</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_client_filter.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
+      <Filter>src\core\lib\debug</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_server_filter.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
+      <Filter>src\core\lib\http</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h">
+      <Filter>src\core\lib\http</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\client_config.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h">
+      <Filter>src\core\lib\http</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\connector.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <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\client_config\lb_policies\round_robin.h">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.h">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.h">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\uri_parser.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\algorithm_metadata.h">
-      <Filter>src\core\compression</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\message_compress.h">
-      <Filter>src\core\compression</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\debug\trace.h">
-      <Filter>src\core\debug</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_win32.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\format_request.h">
-      <Filter>src\core\httpcli</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\httpcli.h">
-      <Filter>src\core\httpcli</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\parser.h">
-      <Filter>src\core\httpcli</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\closure.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\executor.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_internal.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\resolve_address.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_win32.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_client.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_server.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\surface_trace.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json.h">
-      <Filter>src\core\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_common.h">
-      <Filter>src\core\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_reader.h">
-      <Filter>src\core\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h">
-      <Filter>src\core\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h">
-      <Filter>src\core\proto\grpc\lb\v0</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h">
-      <Filter>src\core\statistics</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_rpc_stats.h">
-      <Filter>src\core\statistics</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\api_trace.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call_test_only.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_init.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\completion_queue.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\event_string.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\init.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\lame_client.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\server.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\surface_trace.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\byte_stream.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\timeout_encoding.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\http2_errors.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\auth_filters.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\b64.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\internal.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\handshake.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\json_token.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\jwt_verifier.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\secure_endpoint.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\security_connector.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\security_context.h">
+      <Filter>src\core\lib\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\connectivity_state.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\fake_transport_security.h">
+      <Filter>src\core\lib\tsi</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\ssl_transport_security.h">
+      <Filter>src\core\lib\tsi</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata_batch.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\ssl_types.h">
+      <Filter>src\core\lib\tsi</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\static_metadata.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security.h">
+      <Filter>src\core\lib\tsi</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security_interface.h">
+      <Filter>src\core\lib\tsi</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport_impl.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\auth_filters.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\b64.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\credentials.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\connector.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\handshake.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\json_token.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\jwt_verifier.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\secure_endpoint.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\security_connector.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\security_context.h">
-      <Filter>src\core\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.h">
-      <Filter>src\core\tsi</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.h">
-      <Filter>src\core\tsi</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_types.h">
-      <Filter>src\core\tsi</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security.h">
-      <Filter>src\core\tsi</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_interface.h">
-      <Filter>src\core\tsi</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\mlog.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.h">
+      <Filter>src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
       <Filter>third_party\nanopb</Filter>
@@ -956,6 +974,24 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
       <Filter>third_party\nanopb</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
@@ -977,65 +1013,116 @@
     <Filter Include="src\core">
       <UniqueIdentifier>{ea745680-21ea-9c5e-679b-64dc40562d08}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\census">
-      <UniqueIdentifier>{fb3aefc2-8205-b0bf-525f-ab5e339f7f76}</UniqueIdentifier>
+    <Filter Include="src\core\ext">
+      <UniqueIdentifier>{3f32a58f-394f-5f13-06aa-6cc52cc2daaf}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\channel">
-      <UniqueIdentifier>{d897b6c3-c555-234e-a589-b4f008063615}</UniqueIdentifier>
+    <Filter Include="src\core\ext\census">
+      <UniqueIdentifier>{9bf70bd2-f553-11b2-c237-abd148971eea}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\client_config">
-      <UniqueIdentifier>{e71e6928-b1e3-0616-0961-1505370458ab}</UniqueIdentifier>
+    <Filter Include="src\core\ext\client_config">
+      <UniqueIdentifier>{003725f8-37fc-80b5-deba-baae32caf915}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\client_config\lb_policies">
-      <UniqueIdentifier>{a3eca4d5-f760-61a6-7251-556b828c8b44}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy">
+      <UniqueIdentifier>{030f00ff-6c54-76c8-12df-37e3008335d1}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\client_config\resolvers">
-      <UniqueIdentifier>{6d97b8d9-2c15-927a-892a-709d073c02ab}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb">
+      <UniqueIdentifier>{fe41339e-53fb-39b3-7457-7a0fbb238dbe}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\compression">
-      <UniqueIdentifier>{263cb913-dfe6-42a4-096b-cac231f76305}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto">
+      <UniqueIdentifier>{a7c27f6b-6d15-01cf-76d9-c30dddea0990}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\debug">
-      <UniqueIdentifier>{1da7ef8a-a06d-5499-b3de-19fee4a4214d}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto\grpc">
+      <UniqueIdentifier>{bc714e6d-8aba-91df-7db9-7f189f05a6ff}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\httpcli">
-      <UniqueIdentifier>{a9bc00ad-835f-c625-c6d9-6a1324f98b9f}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto\grpc\lb">
+      <UniqueIdentifier>{adf7e553-94ef-14fd-e845-03104f00a06f}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\iomgr">
-      <UniqueIdentifier>{1baf3894-af37-e647-bdbc-95dc17ed0073}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0">
+      <UniqueIdentifier>{0406d191-8817-38c3-a562-e3541201f424}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\json">
-      <UniqueIdentifier>{e665cc0e-b994-d7c5-cc18-2007392019f0}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\pick_first">
+      <UniqueIdentifier>{b63ded00-b24f-708e-333f-ce199e421875}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto">
-      <UniqueIdentifier>{1ff04466-0905-8a5d-d6f4-7ff2df4c13b5}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\round_robin">
+      <UniqueIdentifier>{2472d352-cf94-f317-646e-72b769cea846}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto\grpc">
-      <UniqueIdentifier>{7c7ad0b3-bf85-5bd3-e0c8-4f5468a8e2e6}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver">
+      <UniqueIdentifier>{6bfa6808-9dcb-8990-deed-5cf58a149dda}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto\grpc\lb">
-      <UniqueIdentifier>{3d533dad-8100-e8a3-b7c3-1fc13a4d60da}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver\dns">
+      <UniqueIdentifier>{e8fe6413-ab8c-48d5-2c7b-aa79e3db4ab2}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto\grpc\lb\v0">
-      <UniqueIdentifier>{0ffcf868-7617-5fed-b6ce-2162d9d09148}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver\dns\native">
+      <UniqueIdentifier>{94e34be0-29d2-1731-3c1e-617ec4986acb}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\security">
-      <UniqueIdentifier>{1d850ac6-e639-4eab-5338-4ba40272fcc9}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver\sockaddr">
+      <UniqueIdentifier>{98c1ccc2-2c91-a3d2-6040-a2e15993d51a}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\statistics">
-      <UniqueIdentifier>{0ef49896-2313-4a3f-1ce2-716fa0e5c6ca}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport">
+      <UniqueIdentifier>{e3abfd0a-064e-0f2f-c8e8-7c5a7e98142a}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\surface">
-      <UniqueIdentifier>{aeb18e82-5d25-0aad-8b02-a0a3470073ce}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport\chttp2">
+      <UniqueIdentifier>{ac42667b-bbba-3571-20bc-7a4240ef26ca}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\transport">
-      <UniqueIdentifier>{168fa1b1-1c18-eb55-9a4d-746bc58df2c1}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport\chttp2\alpn">
+      <UniqueIdentifier>{ef2aa344-783f-7fbd-c83a-47e2d38db14d}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\transport\chttp2">
-      <UniqueIdentifier>{b8b623c3-a168-a2b1-0d5f-b70a1f1cd8d2}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport\chttp2\client">
+      <UniqueIdentifier>{dbffebe0-eebb-577d-1860-ef6837f4cf50}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\tsi">
-      <UniqueIdentifier>{0b0f9ab1-efa4-7f03-e446-6fb9b5227e84}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport\chttp2\client\insecure">
+      <UniqueIdentifier>{4e699b02-fae4-dabd-afd2-2e41b05bef0e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\client\secure">
+      <UniqueIdentifier>{e98ed28e-8dc5-3bb4-22a2-8893831a0ab8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\server">
+      <UniqueIdentifier>{1d36fe16-b004-6bee-c661-328234bbb469}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\server\insecure">
+      <UniqueIdentifier>{e8539863-6029-cca4-44a9-5481cacf8144}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\server\secure">
+      <UniqueIdentifier>{0afa539f-8c83-d4b9-cdea-550091f09638}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\transport">
+      <UniqueIdentifier>{6f34254e-e69f-c9b4-156d-5024bade5408}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib">
+      <UniqueIdentifier>{5b2ded3f-84a5-f6b4-2060-286c7d1dc945}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\channel">
+      <UniqueIdentifier>{1931b044-90f3-cd68-b5f8-23be77ca8efc}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\compression">
+      <UniqueIdentifier>{dadf7fe9-3f15-d431-e4f6-f987b090536c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\debug">
+      <UniqueIdentifier>{19122742-9b92-5b67-9fb9-e552ac62ca5d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\http">
+      <UniqueIdentifier>{dab8f03a-73de-8cfa-88fb-6e04402efb54}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\iomgr">
+      <UniqueIdentifier>{5468ba38-b8a3-85b1-216f-48a2364e18df}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\json">
+      <UniqueIdentifier>{cb2b0073-f2a7-5c63-d182-8874b24bdf36}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security">
+      <UniqueIdentifier>{c4661d64-349f-01c1-1ba8-0602f9047595}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\surface">
+      <UniqueIdentifier>{a21971fb-304f-da08-b1b2-7bd8df8ac373}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\transport">
+      <UniqueIdentifier>{e9d0d3fc-c100-f3e6-89b8-649f241155bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\tsi">
+      <UniqueIdentifier>{95ad2811-c8d0-7a42-2a73-baf03fcbf699}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\plugin_registry">
+      <UniqueIdentifier>{02bec99b-ff39-88d7-9dea-e0ff9f4a2701}</UniqueIdentifier>
     </Filter>
     <Filter Include="third_party">
       <UniqueIdentifier>{aaab30a4-2a15-732e-c141-3fbc0f0f5a7a}</UniqueIdentifier>
diff --git a/vsprojects/vcxproj/grpc_codegen_lib/grpc_codegen_lib.vcxproj b/vsprojects/vcxproj/grpc_codegen_lib/grpc_codegen_lib.vcxproj
deleted file mode 100644
index a6a5a85..0000000
--- a/vsprojects/vcxproj/grpc_codegen_lib/grpc_codegen_lib.vcxproj
+++ /dev/null
@@ -1,184 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{A828FD72-44CE-4EA5-8966-6E4624458D58}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>grpc_codegen_lib</TargetName>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>grpc_codegen_lib</TargetName>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\vsprojects\dummy.c">
-    </ClCompile>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/grpc_codegen_lib/grpc_codegen_lib.vcxproj.filters b/vsprojects/vcxproj/grpc_codegen_lib/grpc_codegen_lib.vcxproj.filters
deleted file mode 100644
index be1e623..0000000
--- a/vsprojects/vcxproj/grpc_codegen_lib/grpc_codegen_lib.vcxproj.filters
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="include">
-      <UniqueIdentifier>{1fe03afe-0c52-a706-2c50-4ea691805d81}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc">
-      <UniqueIdentifier>{386f8a29-15ac-1f26-30ee-d9a605a802be}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc\impl">
-      <UniqueIdentifier>{9828c5d3-4dc2-f116-97bf-015089243c94}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc\impl\codegen">
-      <UniqueIdentifier>{0e88ed03-ed1e-49c0-15d7-69934b433494}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj
new file mode 100644
index 0000000..faf93fd
--- /dev/null
+++ b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protoc.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>grpc_node_plugin</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>grpc_node_plugin</TargetName>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\compiler\node_plugin.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_plugin_support\grpc_plugin_support.vcxproj">
+      <Project>{B6E81D84-2ACB-41B8-8781-493A944C7817}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj.filters b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj.filters
new file mode 100644
index 0000000..28b197f
--- /dev/null
+++ b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj.filters
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\compiler\node_plugin.cc">
+      <Filter>src\compiler</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="src">
+      <UniqueIdentifier>{089d5d6b-d438-dc98-b30f-bd608e3bbb78}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\compiler">
+      <UniqueIdentifier>{1cc34440-c001-7578-c4d3-78f5d98fb602}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj
index 058ae4f..a81d317 100644
--- a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj
+++ b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj
@@ -148,30 +148,20 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
-  </ItemGroup>
-  <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+  </ItemGroup>
+  <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\compiler\config.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\cpp_generator.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\cpp_generator_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\csharp_generator.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\csharp_generator_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\generator_helpers.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\objective_c_generator.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\objective_c_generator_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\compiler\python_generator.h" />
@@ -185,6 +175,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\compiler\csharp_generator.cc">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\compiler\node_generator.cc">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\compiler\objective_c_generator.cc">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\compiler\python_generator.cc">
@@ -192,11 +184,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\compiler\ruby_generator.cc">
     </ClCompile>
   </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_codegen_lib\grpc++_codegen_lib.vcxproj">
-      <Project>{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}</Project>
-    </ProjectReference>
-  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
diff --git a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters
index b1a63eb..b3d2dc2 100644
--- a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters
@@ -7,6 +7,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\compiler\csharp_generator.cc">
       <Filter>src\compiler</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\compiler\node_generator.cc">
+      <Filter>src\compiler</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\compiler\objective_c_generator.cc">
       <Filter>src\compiler</Filter>
     </ClCompile>
@@ -18,56 +21,20 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\config_protobuf.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\compiler\config.h">
       <Filter>src\compiler</Filter>
     </ClInclude>
@@ -86,6 +53,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\compiler\generator_helpers.h">
       <Filter>src\compiler</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator.h">
+      <Filter>src\compiler</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator_helpers.h">
+      <Filter>src\compiler</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\compiler\objective_c_generator.h">
       <Filter>src\compiler</Filter>
     </ClInclude>
@@ -113,21 +86,18 @@
     <Filter Include="include">
       <UniqueIdentifier>{93ed419d-4540-7fa4-814d-3392745b77ff}</UniqueIdentifier>
     </Filter>
-    <Filter Include="include\grpc">
-      <UniqueIdentifier>{ae5560ea-77fe-ab95-c7a3-4538c66591a8}</UniqueIdentifier>
-    </Filter>
     <Filter Include="include\grpc++">
       <UniqueIdentifier>{893c09ee-e315-e763-9d9d-37522ba2f51c}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc++\impl">
+      <UniqueIdentifier>{3e8c71a4-8a06-a577-2799-2224a1ad1f1b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen">
+      <UniqueIdentifier>{ec2a6e26-915b-ba1b-4f59-f361dc01105c}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++\support">
       <UniqueIdentifier>{1c34d005-1ffb-8a31-881a-c6bb431cda69}</UniqueIdentifier>
     </Filter>
-    <Filter Include="include\grpc\impl">
-      <UniqueIdentifier>{3c047248-00c2-4c59-fffd-9e313353e390}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc\impl\codegen">
-      <UniqueIdentifier>{749ae941-63f0-c623-8b4b-a3114ec81bb7}</UniqueIdentifier>
-    </Filter>
     <Filter Include="src">
       <UniqueIdentifier>{94c9769a-a6cd-49fd-2b30-e52d2d02ed91}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index 487ffe0..f0a8f7b 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -153,12 +153,17 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\fixtures\proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\memory_counters.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\mock_endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\parse_hexstring.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port_server_client.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\client_certs.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\server1_cert.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\server1_key.c">
@@ -175,8 +180,14 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\memory_counters.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\mock_endpoint.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\parse_hexstring.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\port_posix.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\port_server_client.c">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index 68c75e8..a1d31eb 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -1,6 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\client_certs.c">
+      <Filter>test\core\end2end\data</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\server1_cert.c">
       <Filter>test\core\end2end\data</Filter>
     </ClCompile>
@@ -25,9 +28,18 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\memory_counters.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\mock_endpoint.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\parse_hexstring.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\port_posix.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
@@ -60,9 +72,18 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\memory_counters.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\mock_endpoint.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\test\core\util\parse_hexstring.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
index 2a3c50e..33860c4 100644
--- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
@@ -151,7 +151,10 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\fixtures\proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\memory_counters.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\mock_endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\parse_hexstring.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port_server_client.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h" />
@@ -165,8 +168,14 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\memory_counters.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\mock_endpoint.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\parse_hexstring.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\port_posix.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\port_server_client.c">
@@ -186,6 +195,9 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
       <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
index cdb19e1..372bb2a 100644
--- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
@@ -13,9 +13,18 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\memory_counters.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\mock_endpoint.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\parse_hexstring.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\port_posix.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
@@ -42,9 +51,18 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\memory_counters.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\mock_endpoint.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\test\core\util\parse_hexstring.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\passthru_endpoint.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 83a48c3..26050dc 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -269,417 +269,406 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_plugin.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_args.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_uchannel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\compress_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\connected_channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\context.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_client_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_server_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\client_config.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\uri_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\algorithm_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\message_compress.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\debug\trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\format_request.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\httpcli.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\closure.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\executor.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\resolve_address.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_win32.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_client.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_common.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_rpc_stats.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\api_trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call_test_only.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_init.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\completion_queue.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\event_string.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\init.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\lame_client.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\surface_trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\byte_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\http2_errors.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata_batch.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\static_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport_impl.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\mlog.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\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_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\surface_trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
+    <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\ext\client_config\client_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init_unsecure.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_context.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init_unsecure.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_plugin.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_args.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_channel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_uchannel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\compress_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression_algorithm.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\connected_channel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_client_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_server_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\client_config.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\connector.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\default_initial_connect_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\debug\trace.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\format_request.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\parser.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\closure.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\executor.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_epoll.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_poll_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_common_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_linux.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\udp_server.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_eventfd.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_nospecial.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_reader.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\api_trace.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer_reader.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_details.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_log_batch.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_connectivity.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_create.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_init.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_ping.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\completion_queue.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\event_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\lame_client.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\metadata_array.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server_chttp2.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\validate_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\version.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\byte_stream.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\timeout_encoding.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\channel_connectivity.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\parsing.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config_plugin.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_lists.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\connector.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\default_initial_connect_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\writing.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\connectivity_state.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata_batch.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\static_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport_op_string.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\context.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\mlog.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\dns\native\dns_resolver.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\sockaddr\sockaddr_resolver.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\placeholders.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
     </ClCompile>
@@ -687,6 +676,30 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_context.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_unsecure_plugin_registry.c">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 7c14e8c..a4acf51 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -1,425 +1,395 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init_unsecure.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_context.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init_unsecure.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_filter.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_plugin.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_args.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_channel.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\client_uchannel.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
+      <Filter>src\core\lib\channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\compress_filter.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression_algorithm.c">
+      <Filter>src\core\lib\compression</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\connected_channel.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
+      <Filter>src\core\lib\compression</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_client_filter.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
+      <Filter>src\core\lib\debug</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\http_server_filter.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
+      <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.c">
-      <Filter>src\core\channel</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
+      <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\client_config.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
+      <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\connector.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\default_initial_connect_string.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <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\client_config\lb_policies\round_robin.c">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.c">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.c">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
-      <Filter>src\core\client_config</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
-      <Filter>src\core\compression</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
-      <Filter>src\core\compression</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\debug\trace.c">
-      <Filter>src\core\debug</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\format_request.c">
-      <Filter>src\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli.c">
-      <Filter>src\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\parser.c">
-      <Filter>src\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\closure.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\executor.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\iomgr_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_epoll.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_multipoller_with_poll_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\resolve_address_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
+      <Filter>src\core\lib\json</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_common_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_linux.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_client_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_posix.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_server_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\udp_server.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_eventfd.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_nospecial.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.c">
-      <Filter>src\core\iomgr</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.c">
-      <Filter>src\core\iomgr</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json.c">
-      <Filter>src\core\json</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_reader.c">
-      <Filter>src\core\json</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_string.c">
-      <Filter>src\core\json</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
-      <Filter>src\core\json</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
-      <Filter>src\core\proto\grpc\lb\v0</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\api_trace.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
+      <Filter>src\core\lib\surface</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\byte_buffer_reader.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_details.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\call_log_batch.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_connectivity.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
+      <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_create.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c">
+      <Filter>src\core\ext\transport\chttp2\server\insecure</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_init.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_ping.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\completion_queue.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\event_string.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\init.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\lame_client.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\metadata_array.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\server_chttp2.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\validate_metadata.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\surface\version.c">
-      <Filter>src\core\surface</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\byte_stream.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\timeout_encoding.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create.c">
+      <Filter>src\core\ext\transport\chttp2\client\insecure</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\channel_connectivity.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\parsing.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\client_config_plugin.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_lists.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\connector.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\default_initial_connect_string.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2\writing.c">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\connectivity_state.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\metadata_batch.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\static_metadata.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\transport\transport_op_string.c">
-      <Filter>src\core\transport</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\context.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.c">
+      <Filter>src\core\ext\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\mlog.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\dns\native\dns_resolver.c">
+      <Filter>src\core\ext\resolver\dns\native</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\sockaddr\sockaddr_resolver.c">
+      <Filter>src\core\ext\resolver\sockaddr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\placeholders.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
-      <Filter>src\core\census</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.c">
+      <Filter>src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
       <Filter>third_party\nanopb</Filter>
@@ -430,6 +400,42 @@
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
       <Filter>third_party\nanopb</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
+      <Filter>src\core\ext\lb_policy\pick_first</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
+      <Filter>src\core\ext\lb_policy\round_robin</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_context.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\grpc_plugin.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_unsecure_plugin_registry.c">
+      <Filter>src\core\plugin_registry</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
@@ -465,379 +471,388 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
       <Filter>include\grpc\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_filter.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\grpc_plugin.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_args.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\channel_stack_builder.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_channel.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\client_uchannel.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\compress_filter.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h">
+      <Filter>src\core\lib\channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\connected_channel.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
+      <Filter>src\core\lib\compression</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\context.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
+      <Filter>src\core\lib\compression</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_client_filter.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
+      <Filter>src\core\lib\debug</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\http_server_filter.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
+      <Filter>src\core\lib\http</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\channel\subchannel_call_holder.h">
-      <Filter>src\core\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h">
+      <Filter>src\core\lib\http</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\client_config.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h">
+      <Filter>src\core\lib\http</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\connector.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <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\client_config\lb_policies\round_robin.h">
-      <Filter>src\core\client_config\lb_policies</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_factory.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy_registry.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_factory.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolver_registry.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\dns_resolver.h">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\resolvers\sockaddr_resolver.h">
-      <Filter>src\core\client_config\resolvers</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_factory.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\subchannel_index.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\uri_parser.h">
-      <Filter>src\core\client_config</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\algorithm_metadata.h">
-      <Filter>src\core\compression</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\compression\message_compress.h">
-      <Filter>src\core\compression</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\debug\trace.h">
-      <Filter>src\core\debug</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_win32.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\format_request.h">
-      <Filter>src\core\httpcli</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\httpcli.h">
-      <Filter>src\core\httpcli</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\httpcli\parser.h">
-      <Filter>src\core\httpcli</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\closure.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\endpoint_pair.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\exec_ctx.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\executor.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\fd_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iocp_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_internal.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\iomgr_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_set_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\pollset_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\resolve_address.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h">
+      <Filter>src\core\lib\json</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_utils.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\sockaddr_win32.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_utils_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\socket_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_client.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_posix.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_server.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\tcp_windows.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_posix.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\workqueue_windows.h">
-      <Filter>src\core\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json.h">
-      <Filter>src\core\json</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_common.h">
-      <Filter>src\core\json</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_reader.h">
-      <Filter>src\core\json</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h">
-      <Filter>src\core\json</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\surface_trace.h">
+      <Filter>src\core\lib\surface</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h">
-      <Filter>src\core\proto\grpc\lb\v0</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h">
-      <Filter>src\core\statistics</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_rpc_stats.h">
-      <Filter>src\core\statistics</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\api_trace.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\call_test_only.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h">
+      <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_init.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\channel_stack_type.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\completion_queue.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\event_string.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\init.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\lame_client.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\server.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\surface\surface_trace.h">
-      <Filter>src\core\surface</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\byte_stream.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\alpn.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\bin_encoder.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_data.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_goaway.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_ping.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_rst_stream.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_settings.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\frame_window_update.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_encoder.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\timeout_encoding.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_parser.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\hpack_table.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\http2_errors.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\huffsyms.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_channel_factory.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\incoming_metadata.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\client_config.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\internal.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\connector.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\status_conversion.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\initial_connect_string.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\stream_map.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\timeout_encoding.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_factory.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2\varint.h">
-      <Filter>src\core\transport\chttp2</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\lb_policy_registry.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\chttp2_transport.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\parse_address.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\connectivity_state.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_factory.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\metadata_batch.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\resolver_registry.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\static_metadata.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport_impl.h">
-      <Filter>src\core\transport</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.h">
+      <Filter>src\core\ext\client_config</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\mlog.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h">
-      <Filter>src\core\census</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0\load_balancer.pb.h">
+      <Filter>src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
       <Filter>third_party\nanopb</Filter>
@@ -851,6 +866,24 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
       <Filter>third_party\nanopb</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
@@ -872,59 +905,104 @@
     <Filter Include="src\core">
       <UniqueIdentifier>{88491077-386b-2039-d14c-0c40136b5f7a}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\census">
-      <UniqueIdentifier>{a7596ee2-afee-3a82-7e6e-bd8b8f904e04}</UniqueIdentifier>
+    <Filter Include="src\core\ext">
+      <UniqueIdentifier>{82f86e8c-00a4-f566-d235-670fc629798d}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\channel">
-      <UniqueIdentifier>{cc102c4b-66ff-cf4c-2288-d76327e1a183}</UniqueIdentifier>
+    <Filter Include="src\core\ext\census">
+      <UniqueIdentifier>{3f21cd12-b8b9-18f8-8780-e21bbe2285d0}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\client_config">
-      <UniqueIdentifier>{02bd7340-02ee-4337-ffa5-0b6ecc7cf60c}</UniqueIdentifier>
+    <Filter Include="src\core\ext\client_config">
+      <UniqueIdentifier>{25fa8af3-0a05-987c-741f-fa8ff9d65d51}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\client_config\lb_policies">
-      <UniqueIdentifier>{308af086-46c7-fa66-9021-19b1c3d4a6bd}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy">
+      <UniqueIdentifier>{a23781d2-27e4-7cb0-12cd-59782ecb21ce}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\client_config\resolvers">
-      <UniqueIdentifier>{dd617c24-6f07-fdff-80d5-c8610d6f815e}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb">
+      <UniqueIdentifier>{25a465c8-d1e8-6248-c005-bb2062206472}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\compression">
-      <UniqueIdentifier>{2e3aca1d-223d-10a1-b282-7f9fc68ee6f5}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto">
+      <UniqueIdentifier>{40fc2615-d244-0d36-4486-ba6f0fa468bb}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\debug">
-      <UniqueIdentifier>{6d8d5774-7291-554d-fafa-583463cd3fd9}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto\grpc">
+      <UniqueIdentifier>{1d129f24-a399-12ef-68de-023aff7dde52}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\httpcli">
-      <UniqueIdentifier>{1ba3a245-47e7-89b5-b0c9-aca758bd0277}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto\grpc\lb">
+      <UniqueIdentifier>{21858d9d-30b5-8847-5882-6b47df0fa293}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\iomgr">
-      <UniqueIdentifier>{a9df8b24-ecea-ff6d-8999-d8fa54cd70bf}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0">
+      <UniqueIdentifier>{1795a20b-3e7c-e27d-eae1-96582fa9a958}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\json">
-      <UniqueIdentifier>{443ffc61-1bea-2477-6e54-1ddf8c139264}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\pick_first">
+      <UniqueIdentifier>{e27f9ecf-97bb-1a2e-3135-a41f732dcf55}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto">
-      <UniqueIdentifier>{7f4bb22a-65ba-0f8f-6387-66b1f6677a80}</UniqueIdentifier>
+    <Filter Include="src\core\ext\lb_policy\round_robin">
+      <UniqueIdentifier>{e5fc1091-5d60-404f-775b-686ef4b3266f}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto\grpc">
-      <UniqueIdentifier>{9c2bd164-c317-8a13-564d-3b28b0fd79cf}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver">
+      <UniqueIdentifier>{88c78e27-267a-95df-07c5-50e5fbc2f40c}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto\grpc\lb">
-      <UniqueIdentifier>{2bad8e10-4fc5-d8b3-e026-4abbd0c25cda}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver\dns">
+      <UniqueIdentifier>{2e0a9b4f-6394-7c0e-6e5a-0f8b3ee29b41}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\proto\grpc\lb\v0">
-      <UniqueIdentifier>{4475c8ed-e01b-8906-47d0-8a504189c0d5}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver\dns\native">
+      <UniqueIdentifier>{3d5398c8-928b-9096-8eb7-f8c40ee68c4d}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\statistics">
-      <UniqueIdentifier>{e084164c-a069-00e3-db35-4e0b1cd6f0b7}</UniqueIdentifier>
+    <Filter Include="src\core\ext\resolver\sockaddr">
+      <UniqueIdentifier>{71686ed0-fbf9-02a4-d65a-a73f7dc4e2be}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\surface">
-      <UniqueIdentifier>{6cd0127e-c24b-d43c-38f5-198db8d4322a}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport">
+      <UniqueIdentifier>{967c89fe-c97c-27e2-aac0-9ba5854cb5fa}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\transport">
-      <UniqueIdentifier>{6687ff98-e36e-c0b1-2756-1bc79edec406}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport\chttp2">
+      <UniqueIdentifier>{702829f0-099e-2ab7-6b44-ed7cff3ec083}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\transport\chttp2">
-      <UniqueIdentifier>{5fcd6206-f774-9ae6-4b85-305d6a723843}</UniqueIdentifier>
+    <Filter Include="src\core\ext\transport\chttp2\alpn">
+      <UniqueIdentifier>{7d4830f7-20db-07d3-c3a9-ecfe63ae1992}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\client">
+      <UniqueIdentifier>{0d589e16-e470-4968-318c-796af5a33637}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\client\insecure">
+      <UniqueIdentifier>{34dfdc9b-ab97-47f0-c1e1-b2e7381c3de6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\server">
+      <UniqueIdentifier>{81fb55f4-9216-441b-8389-a7120bbcd45e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\server\insecure">
+      <UniqueIdentifier>{3f53dcb6-71d7-28ff-1794-26a08e4601fe}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\transport">
+      <UniqueIdentifier>{45b20f28-376c-9dea-1800-8a0193411946}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib">
+      <UniqueIdentifier>{8bd5b461-bff8-6aa8-b5a6-85da2834eb8a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\channel">
+      <UniqueIdentifier>{fb964f3d-a59c-a7ba-fee5-6072dbb94a7b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\compression">
+      <UniqueIdentifier>{b88002e9-185e-4e64-49f5-2d8989ce87f6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\debug">
+      <UniqueIdentifier>{7f23789d-f18a-2a2d-60fe-a87dc656f539}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\http">
+      <UniqueIdentifier>{748c8078-2027-8641-f485-1d4c66466e79}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\iomgr">
+      <UniqueIdentifier>{bb1a1cf2-6824-08f0-a9bd-3fafcaf13042}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\json">
+      <UniqueIdentifier>{681cdaeb-c47f-8853-d985-bf13c2873947}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\surface">
+      <UniqueIdentifier>{506dc3b3-d884-2b59-0dfa-57ed6affa2d3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\transport">
+      <UniqueIdentifier>{6c3394d1-27e9-003e-19ed-8116d210f7cc}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\plugin_registry">
+      <UniqueIdentifier>{babf0a90-e934-f599-5475-e6937d9580fe}</UniqueIdentifier>
     </Filter>
     <Filter Include="third_party">
       <UniqueIdentifier>{025c051e-8eba-125b-67f9-173f95176eb2}</UniqueIdentifier>
diff --git a/vsprojects/vcxproj/test/boringssl/boringssl_x509_test/boringssl_x509_test.vcxproj b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test/boringssl_x509_test.vcxproj
new file mode 100644
index 0000000..2bf7f71
--- /dev/null
+++ b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test/boringssl_x509_test.vcxproj
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{0E1472A5-A857-7680-45C6-7C4DD2F6BE48}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>boringssl_x509_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>boringssl_x509_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/boringssl\boringssl_x509_test_lib\boringssl_x509_test_lib.vcxproj">
+      <Project>{62DBB3BA-05D6-D2CF-7EC5-253F2AC25892}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\boringssl_test_util\boringssl_test_util.vcxproj">
+      <Project>{427037B1-B51B-D6F1-5025-AD12B200266A}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\boringssl\boringssl.vcxproj">
+      <Project>{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/boringssl/boringssl_x509_test/boringssl_x509_test.vcxproj.filters b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test/boringssl_x509_test.vcxproj.filters
new file mode 100644
index 0000000..00e4276
--- /dev/null
+++ b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test/boringssl_x509_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/boringssl/boringssl_x509_test_lib/boringssl_x509_test_lib.vcxproj b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test_lib/boringssl_x509_test_lib.vcxproj
new file mode 100644
index 0000000..f8b0e7a
--- /dev/null
+++ b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test_lib/boringssl_x509_test_lib.vcxproj
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{62DBB3BA-05D6-D2CF-7EC5-253F2AC25892}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>boringssl_x509_test_lib</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>boringssl_x509_test_lib</TargetName>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>false</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\x509\x509_test.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\boringssl_test_util\boringssl_test_util.vcxproj">
+      <Project>{427037B1-B51B-D6F1-5025-AD12B200266A}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\boringssl\boringssl.vcxproj">
+      <Project>{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/boringssl/boringssl_x509_test_lib/boringssl_x509_test_lib.vcxproj.filters b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test_lib/boringssl_x509_test_lib.vcxproj.filters
new file mode 100644
index 0000000..216a56f
--- /dev/null
+++ b/vsprojects/vcxproj/test/boringssl/boringssl_x509_test_lib/boringssl_x509_test_lib.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\third_party\boringssl\crypto\x509\x509_test.cc">
+      <Filter>third_party\boringssl\crypto\x509</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="third_party">
+      <UniqueIdentifier>{0a04403f-6935-8e9c-c271-cfcb728d6dd3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="third_party\boringssl">
+      <UniqueIdentifier>{8ffac2f8-0d1d-00df-018c-56100e9842f7}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="third_party\boringssl\crypto">
+      <UniqueIdentifier>{2d1857b4-2355-6af6-b6c8-b33f3ec27013}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="third_party\boringssl\crypto\x509">
+      <UniqueIdentifier>{615f50f9-1415-e8e4-49ec-987a5772c7ee}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/codegen_test/codegen_test.vcxproj b/vsprojects/vcxproj/test/codegen_test/codegen_test.vcxproj
deleted file mode 100644
index 7ba2a56..0000000
--- a/vsprojects/vcxproj/test/codegen_test/codegen_test.vcxproj
+++ /dev/null
@@ -1,240 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{07D92FF8-D0D1-CB1B-51D3-EBA0E5DEBDD7}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>codegen_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>codegen_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\control.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.grpc.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\control.grpc.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.grpc.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.grpc.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.grpc.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.grpc.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\services.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.grpc.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\services.grpc.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.grpc.pb.cc">
-    </ClCompile>
-    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.grpc.pb.h">
-    </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\codegen_test.cc">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_codegen_lib\grpc++_codegen_lib.vcxproj">
-      <Project>{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/codegen_test/codegen_test.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test/codegen_test.vcxproj.filters
deleted file mode 100644
index 980cf76..0000000
--- a/vsprojects/vcxproj/test/codegen_test/codegen_test.vcxproj.filters
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.proto">
-      <Filter>src\proto\grpc\testing</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.proto">
-      <Filter>src\proto\grpc\testing</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.proto">
-      <Filter>src\proto\grpc\testing</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.proto">
-      <Filter>src\proto\grpc\testing</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.proto">
-      <Filter>src\proto\grpc\testing</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.proto">
-      <Filter>src\proto\grpc\testing</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\codegen_test.cc">
-      <Filter>test\cpp\codegen</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="src">
-      <UniqueIdentifier>{a37f6960-8f92-51ed-9b99-d24970584bb2}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src\proto">
-      <UniqueIdentifier>{dc3f4032-f0dc-f8f0-e07a-78c0f628e9f5}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src\proto\grpc">
-      <UniqueIdentifier>{250aede7-067f-590b-42d7-15939da4a59d}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src\proto\grpc\testing">
-      <UniqueIdentifier>{57f4543e-acd0-a4a0-f3c3-8494e509b2b3}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test">
-      <UniqueIdentifier>{7337b395-7e96-f49b-0a4f-b8a70be23a57}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\cpp">
-      <UniqueIdentifier>{cf9e3404-0ab9-a301-9715-728febcece23}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\cpp\codegen">
-      <UniqueIdentifier>{d349ac75-02e7-cb63-92f1-1785a74c0561}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj
new file mode 100644
index 0000000..cd0b40c
--- /dev/null
+++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{C06E8406-E0B2-E532-526C-171569E0F2B6}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>codegen_test_full</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>codegen_test_full</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\control.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\control.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\services.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\services.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\codegen_test_full.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters
new file mode 100644
index 0000000..029b8ef
--- /dev/null
+++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\codegen_test_full.cc">
+      <Filter>test\cpp\codegen</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
+      <Filter>src\cpp\codegen</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h">
+      <Filter>include\grpc++\impl\codegen\security</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="include">
+      <UniqueIdentifier>{906b08b6-1c67-d4e6-dfe6-16aa91be8eb4}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc">
+      <UniqueIdentifier>{46618609-460b-ebe5-0b02-65a6afcea03b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++">
+      <UniqueIdentifier>{25436c6c-6d67-aba9-8d95-d7dd50e3a188}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl">
+      <UniqueIdentifier>{b0b279c5-88b4-b733-4d75-a003212c7e13}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen">
+      <UniqueIdentifier>{6b9a368a-8dba-441b-a31d-def53c3eb6cf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen\security">
+      <UniqueIdentifier>{12f7e55c-a6c1-b083-9017-135542012295}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl">
+      <UniqueIdentifier>{d4c65b16-f94b-557d-8cd2-b9c8c6659673}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl\codegen">
+      <UniqueIdentifier>{f2ddfc7f-8c95-bbfe-c40d-5737f28d8311}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src">
+      <UniqueIdentifier>{909027fc-be54-d7d9-3e0b-b034a6f7ff8f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\cpp">
+      <UniqueIdentifier>{0944bc3e-4288-3a9e-81df-b4eb0910e74f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\cpp\codegen">
+      <UniqueIdentifier>{88566202-70b0-f87e-2ce8-3cd61e5a57da}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto">
+      <UniqueIdentifier>{84c6b0c4-1143-abcf-cc7b-3ee6ef87f16a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc">
+      <UniqueIdentifier>{4da12131-db02-7cd7-361f-6f1c93af1d51}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\testing">
+      <UniqueIdentifier>{a8c9aa14-6237-2ecd-82b4-32f5f3347b35}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test">
+      <UniqueIdentifier>{5807e8ad-90b9-2dc6-447f-1c5e7b8fba47}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{0eaa7a87-86be-68a6-a8cf-a9039a9d61d6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\codegen">
+      <UniqueIdentifier>{6cac9a6e-b8c8-bef0-2895-9f732ff8c7ee}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
new file mode 100644
index 0000000..6d138fa
--- /dev/null
+++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
@@ -0,0 +1,291 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{87FCA32C-6ECF-5D95-7081-55F309EC6393}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>codegen_test_minimal</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>codegen_test_minimal</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\control.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\control.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\services.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\services.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\codegen_test_minimal.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters
new file mode 100644
index 0000000..dc3f0b2
--- /dev/null
+++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\control.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\payloads.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\perf_db.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\services.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\stats.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\codegen_test_minimal.cc">
+      <Filter>test\cpp\codegen</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
+      <Filter>src\cpp\codegen</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h">
+      <Filter>include\grpc++\impl\codegen\security</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_win32.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="include">
+      <UniqueIdentifier>{d7e3a4ab-12fd-702a-0f38-f390a3a498ee}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc">
+      <UniqueIdentifier>{af7d5949-f89a-c3d7-b61c-4f6eb53add9d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++">
+      <UniqueIdentifier>{871b80f5-04bd-85d1-7c3c-dad152f2d17b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl">
+      <UniqueIdentifier>{cb2776d8-357e-4807-8804-b07a35caf468}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen">
+      <UniqueIdentifier>{034ecb5b-5ea9-82eb-c7de-3318074530d2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen\security">
+      <UniqueIdentifier>{1eefd7f9-c93b-eb01-9ec6-e654a34a562e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl">
+      <UniqueIdentifier>{2ba3ef0f-e274-7ddd-20df-902d8d75f690}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl\codegen">
+      <UniqueIdentifier>{e161f3e2-2652-ca2f-adfd-0c58107a026f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src">
+      <UniqueIdentifier>{0d44e24d-bdd6-798d-096d-2201e0a9fd53}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\cpp">
+      <UniqueIdentifier>{13a5f072-c1d8-5794-d743-7f8cc295c8ef}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\cpp\codegen">
+      <UniqueIdentifier>{afa9b626-4df3-6192-b0b0-82986d31e915}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto">
+      <UniqueIdentifier>{85c80929-0814-efc5-9457-f80a00b4bcae}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc">
+      <UniqueIdentifier>{c7a2927d-c3a6-bf01-327d-d4d3e49682ba}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\testing">
+      <UniqueIdentifier>{9c363e7c-a9fc-0915-250a-5ba46bd8caf7}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test">
+      <UniqueIdentifier>{ea047246-affd-99d8-e39b-268b3ebba747}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{e09ae1ab-897c-30d8-bdd8-86cdbb7e3b57}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\codegen">
+      <UniqueIdentifier>{9ee5c585-b102-0eb7-69e4-9f084beeac31}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/h2_ssl_cert_test/h2_ssl_cert_test.vcxproj b/vsprojects/vcxproj/test/end2end/fixtures/h2_ssl_cert_test/h2_ssl_cert_test.vcxproj
new file mode 100644
index 0000000..d64c317
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end/fixtures/h2_ssl_cert_test/h2_ssl_cert_test.vcxproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{B3B7D225-3C04-72F9-4C2C-1C3F3136FE58}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_ssl_cert_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_ssl_cert_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_ssl_cert.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/end2end/tests\end2end_tests\end2end_tests.vcxproj">
+      <Project>{1F1F9084-2A93-B80E-364F-5754894AFAB4}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/h2_ssl_cert_test/h2_ssl_cert_test.vcxproj.filters b/vsprojects/vcxproj/test/end2end/fixtures/h2_ssl_cert_test/h2_ssl_cert_test.vcxproj.filters
new file mode 100644
index 0000000..532b0ae
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end/fixtures/h2_ssl_cert_test/h2_ssl_cert_test.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_ssl_cert.c">
+      <Filter>test\core\end2end\fixtures</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{2ad9c3be-3600-2475-3705-8927bd57651b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{5d5ee434-b892-585d-97ca-ae595eecbd0b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end">
+      <UniqueIdentifier>{903c738d-3c85-534d-d26e-01138f2e96c6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end\fixtures">
+      <UniqueIdentifier>{f5bca83d-8278-22b4-7999-c50cea11b90b}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_nosec_test/h2_uchannel_nosec_test.vcxproj b/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_nosec_test/h2_uchannel_nosec_test.vcxproj
deleted file mode 100644
index 76a9e56..0000000
--- a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_nosec_test/h2_uchannel_nosec_test.vcxproj
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{BD79A629-4181-DB5E-C28F-44EB280A6F91}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>h2_uchannel_nosec_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>h2_uchannel_nosec_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_uchannel.c">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/end2end/tests\end2end_nosec_tests\end2end_nosec_tests.vcxproj">
-      <Project>{47C2CB41-4E9F-58B6-F606-F6FAED5D00ED}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
-      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
-      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_nosec_test/h2_uchannel_nosec_test.vcxproj.filters b/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_nosec_test/h2_uchannel_nosec_test.vcxproj.filters
deleted file mode 100644
index c9adeee..0000000
--- a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_nosec_test/h2_uchannel_nosec_test.vcxproj.filters
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_uchannel.c">
-      <Filter>test\core\end2end\fixtures</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{549b9d3c-70c0-f3de-36d6-5b2ce5fb098c}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{d37f19b6-6893-6a90-09d2-e50d891899ff}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\end2end">
-      <UniqueIdentifier>{bde36bf9-4894-e85b-4a35-f7b1abe9387f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\end2end\fixtures">
-      <UniqueIdentifier>{e16ce654-bd8c-2527-1077-e6cd2639c1cb}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_test/h2_uchannel_test.vcxproj b/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_test/h2_uchannel_test.vcxproj
deleted file mode 100644
index 1564608..0000000
--- a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_test/h2_uchannel_test.vcxproj
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{E39D59C4-F5CB-7D68-DA6B-C6BC93843435}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>h2_uchannel_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>h2_uchannel_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_uchannel.c">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/end2end/tests\end2end_tests\end2end_tests.vcxproj">
-      <Project>{1F1F9084-2A93-B80E-364F-5754894AFAB4}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_test/h2_uchannel_test.vcxproj.filters b/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_test/h2_uchannel_test.vcxproj.filters
deleted file mode 100644
index 611a643..0000000
--- a/vsprojects/vcxproj/test/end2end/fixtures/h2_uchannel_test/h2_uchannel_test.vcxproj.filters
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_uchannel.c">
-      <Filter>test\core\end2end\fixtures</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{0e4c3b3f-4d89-039d-c4d2-3bd39bb5701f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{75084bcc-1809-7f7a-8989-d8fe2d5d404f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\end2end">
-      <UniqueIdentifier>{9e123c51-0a8c-f222-f2f9-3cee19f2f99e}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\end2end\fixtures">
-      <UniqueIdentifier>{999ee744-f147-9430-9a09-a16f69ecfa2a}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
index 2f3b591..22cd102 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
@@ -179,12 +179,16 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\graceful_server_shutdown.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\high_initial_seqno.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\hpack_size.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\idempotent_request.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\large_metadata.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
index c63ebe7..1bb208b 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
@@ -43,6 +43,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\graceful_server_shutdown.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
@@ -52,6 +55,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\hpack_size.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\idempotent_request.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
index f3b311b..bfd437e 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
@@ -181,12 +181,16 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\graceful_server_shutdown.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\high_initial_seqno.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\hpack_size.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\idempotent_request.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\large_metadata.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
index c30054a..61c065f 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
@@ -46,6 +46,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\graceful_server_shutdown.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
@@ -55,6 +58,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\hpack_size.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\idempotent_request.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj b/vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj
new file mode 100644
index 0000000..fb10f95
--- /dev/null
+++ b/vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{23DF0572-DBF1-08DA-8EAD-8508354C90A4}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>head_of_line_blocking_bad_client_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>head_of_line_blocking_bad_client_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\bad_client\tests\head_of_line_blocking.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/bad_client\bad_client_test\bad_client_test.vcxproj">
+      <Project>{BA67B418-B699-E41A-9CC4-0279C49481A5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj.filters b/vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj.filters
new file mode 100644
index 0000000..c3609f0
--- /dev/null
+++ b/vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\bad_client\tests\head_of_line_blocking.c">
+      <Filter>test\core\bad_client\tests</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{c7d7f2b5-9afd-5668-b11f-ceb3a3503569}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{3175d310-96bd-0c78-72e3-b5985873fa82}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\bad_client">
+      <UniqueIdentifier>{d7e592e2-acda-4572-59b7-20845fb05bd5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\bad_client\tests">
+      <UniqueIdentifier>{1fa3207b-dc88-d316-7c13-9ac70ddc850e}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/http_parser_test/http_parser_test.vcxproj b/vsprojects/vcxproj/test/http_parser_test/http_parser_test.vcxproj
new file mode 100644
index 0000000..bd5cf12
--- /dev/null
+++ b/vsprojects/vcxproj/test/http_parser_test/http_parser_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{49D7E690-BDA1-5236-1ABF-3D81C1559DF7}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>http_parser_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>http_parser_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\http\parser_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/http_parser_test/http_parser_test.vcxproj.filters b/vsprojects/vcxproj/test/http_parser_test/http_parser_test.vcxproj.filters
new file mode 100644
index 0000000..4353c3b
--- /dev/null
+++ b/vsprojects/vcxproj/test/http_parser_test/http_parser_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\http\parser_test.c">
+      <Filter>test\core\http</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{1d07f09d-a0ec-d684-3589-bff02afbe830}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{eedab59d-9f19-9172-cf0e-83a839217afc}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\http">
+      <UniqueIdentifier>{1fcac48f-3718-00ea-6c0c-aafa1a4de528}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj b/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj
index 97f14f6..5515349 100644
--- a/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj
+++ b/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj
@@ -158,7 +158,7 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\httpcli\format_request_test.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\http\format_request_test.c">
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
diff --git a/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj.filters b/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj.filters
index c54ded5..6f941f4 100644
--- a/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj.filters
+++ b/vsprojects/vcxproj/test/httpcli_format_request_test/httpcli_format_request_test.vcxproj.filters
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\httpcli\format_request_test.c">
-      <Filter>test\core\httpcli</Filter>
+    <ClCompile Include="$(SolutionDir)\..\test\core\http\format_request_test.c">
+      <Filter>test\core\http</Filter>
     </ClCompile>
   </ItemGroup>
 
@@ -13,8 +13,8 @@
     <Filter Include="test\core">
       <UniqueIdentifier>{f033cf49-b830-5698-3989-6ec75817333b}</UniqueIdentifier>
     </Filter>
-    <Filter Include="test\core\httpcli">
-      <UniqueIdentifier>{75330e6a-521e-5f90-defd-652a4591dbe9}</UniqueIdentifier>
+    <Filter Include="test\core\http">
+      <UniqueIdentifier>{51615bc9-b61d-8d7d-9abb-5409276c04ec}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
 </Project>
diff --git a/vsprojects/vcxproj/test/httpcli_parser_test/httpcli_parser_test.vcxproj b/vsprojects/vcxproj/test/httpcli_parser_test/httpcli_parser_test.vcxproj
deleted file mode 100644
index 6f97630..0000000
--- a/vsprojects/vcxproj/test/httpcli_parser_test/httpcli_parser_test.vcxproj
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{B6F60D1C-D4F3-0F1A-4A2F-9134629B7848}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>httpcli_parser_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>httpcli_parser_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\httpcli\parser_test.c">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/httpcli_parser_test/httpcli_parser_test.vcxproj.filters b/vsprojects/vcxproj/test/httpcli_parser_test/httpcli_parser_test.vcxproj.filters
deleted file mode 100644
index 1cdc32f..0000000
--- a/vsprojects/vcxproj/test/httpcli_parser_test/httpcli_parser_test.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\httpcli\parser_test.c">
-      <Filter>test\core\httpcli</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{f3562e8b-3020-c79a-4e3b-c895f9e49f44}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{db527686-b5c7-68df-a106-bd919f60742a}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\httpcli">
-      <UniqueIdentifier>{8e60d460-93de-c6e1-b67b-bfae71bd9bca}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj b/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj
new file mode 100644
index 0000000..11d89a0
--- /dev/null
+++ b/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>internal_api_canary_iomgr_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>internal_api_canary_iomgr_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj.filters b/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj.filters
new file mode 100644
index 0000000..f1ee82d
--- /dev/null
+++ b/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
+      <Filter>test\core\internal_api_canaries</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{881986d1-d1fe-b377-cf26-b3377af95009}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{4f9a544e-5680-18ee-30d7-38179bf82cee}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\internal_api_canaries">
+      <UniqueIdentifier>{6ab29f78-ec9d-d63a-8e8f-0d7552b3edd4}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj b/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj
new file mode 100644
index 0000000..59092dc
--- /dev/null
+++ b/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{D53575C6-713C-E6E3-FD74-E65F20916498}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>internal_api_canary_support_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>internal_api_canary_support_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj.filters b/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj.filters
new file mode 100644
index 0000000..f7f4e32
--- /dev/null
+++ b/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
+      <Filter>test\core\internal_api_canaries</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{a6c31cba-af9d-78ea-8980-8b77c9fc4485}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{d84283b8-4529-6c09-18bf-20a69f14f7ab}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\internal_api_canaries">
+      <UniqueIdentifier>{ea379f93-9285-7180-0d69-24a56da2b201}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj b/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj
new file mode 100644
index 0000000..110f7e3
--- /dev/null
+++ b/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{ED24E700-964E-B426-6A6A-1944E2EF7BCB}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>internal_api_canary_transport_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>internal_api_canary_transport_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj.filters b/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj.filters
new file mode 100644
index 0000000..1e0b4c5
--- /dev/null
+++ b/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
+      <Filter>test\core\internal_api_canaries</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{38e59e26-aad9-60fd-a1a7-c8fd9b606e2f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{79aad60f-59b8-09e2-2cad-5b5e083ac008}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\internal_api_canaries">
+      <UniqueIdentifier>{e4f0214e-e3ec-b5b8-c00b-2932b5ec2422}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj b/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj
new file mode 100644
index 0000000..34507b6
--- /dev/null
+++ b/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{91678827-DAEF-2E2F-9CD1-1F5E5DD54842}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>json_run_localhost</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>json_run_localhost</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\json_run_localhost.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
+      <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj.filters b/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj.filters
new file mode 100644
index 0000000..84c5d1e
--- /dev/null
+++ b/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\json_run_localhost.cc">
+      <Filter>test\cpp\qps</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{6a0e8372-94ed-67cd-edda-56ba97debf76}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{2a065f28-e35d-1a75-6e12-fd86e7b99443}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\qps">
+      <UniqueIdentifier>{6eec400a-a3a2-2904-8b49-92aeb69c4448}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/qps_json_driver/qps_json_driver.vcxproj b/vsprojects/vcxproj/test/qps_json_driver/qps_json_driver.vcxproj
new file mode 100644
index 0000000..3884c10
--- /dev/null
+++ b/vsprojects/vcxproj/test/qps_json_driver/qps_json_driver.vcxproj
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{79B45023-E5EB-4DF4-BBED-525CC0ACD832}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>qps_json_driver</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>qps_json_driver</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\parse_json.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\parse_json.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\qps_json_driver.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\qps\qps.vcxproj">
+      <Project>{8423B0C5-2428-CA10-82EF-7B5C1F3D8011}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
+      <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/qps_json_driver/qps_json_driver.vcxproj.filters b/vsprojects/vcxproj/test/qps_json_driver/qps_json_driver.vcxproj.filters
new file mode 100644
index 0000000..cde967f
--- /dev/null
+++ b/vsprojects/vcxproj/test/qps_json_driver/qps_json_driver.vcxproj.filters
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\parse_json.cc">
+      <Filter>test\cpp\qps</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\qps_json_driver.cc">
+      <Filter>test\cpp\qps</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\parse_json.h">
+      <Filter>test\cpp\qps</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{51cad99a-2bf1-0e37-a1be-0c9ad02355d3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{f8692949-7450-0a31-11fc-a17ea63b6357}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\qps">
+      <UniqueIdentifier>{73b4c157-7352-ba56-4790-66e27fa90451}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/qps_worker/qps_worker.vcxproj b/vsprojects/vcxproj/test/qps_worker/qps_worker.vcxproj
new file mode 100644
index 0000000..0ed96fc
--- /dev/null
+++ b/vsprojects/vcxproj/test/qps_worker/qps_worker.vcxproj
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{89ACCD5A-8411-634E-BF28-7115F46A807D}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>qps_worker</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>qps_worker</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\client.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\server.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\worker.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\qps\qps.vcxproj">
+      <Project>{8423B0C5-2428-CA10-82EF-7B5C1F3D8011}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
+      <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/qps_worker/qps_worker.vcxproj.filters b/vsprojects/vcxproj/test/qps_worker/qps_worker.vcxproj.filters
new file mode 100644
index 0000000..a1f2390
--- /dev/null
+++ b/vsprojects/vcxproj/test/qps_worker/qps_worker.vcxproj.filters
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\worker.cc">
+      <Filter>test\cpp\qps</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\client.h">
+      <Filter>test\cpp\qps</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\server.h">
+      <Filter>test\cpp\qps</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{bc4b8555-fcc7-4f70-96d9-581f535382e1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{79b85b26-c29a-b8a0-06a4-d4e44f2350aa}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\qps">
+      <UniqueIdentifier>{1c2b326f-ab54-97da-d40e-b0e99dd76de6}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+